1 package com.atlassian.plugin.web.descriptors;
2
3 import java.util.Iterator;
4 import java.util.List;
5
6 import com.atlassian.plugin.Plugin;
7 import com.atlassian.plugin.PluginParseException;
8 import com.atlassian.plugin.hostcontainer.HostContainer;
9 import com.atlassian.plugin.loaders.LoaderUtils;
10 import com.atlassian.plugin.util.Assertions;
11 import com.atlassian.plugin.web.Condition;
12 import com.atlassian.plugin.web.conditions.AbstractCompositeCondition;
13 import com.atlassian.plugin.web.conditions.AndCompositeCondition;
14 import com.atlassian.plugin.web.conditions.ConditionLoadingException;
15 import com.atlassian.plugin.web.conditions.InvertedCondition;
16 import com.atlassian.plugin.web.conditions.OrCompositeCondition;
17
18 import org.dom4j.Element;
19
20
21
22
23
24
25
26
27
28
29
30 public class ConditionElementParser
31 {
32 public static class CompositeType
33 {
34 public static final int OR = 0;
35 public static final int AND = 1;
36
37 public static int parse(final String type) throws PluginParseException
38 {
39 if ("or".equalsIgnoreCase(type))
40 {
41 return CompositeType.OR;
42 } else if ("and".equalsIgnoreCase(type))
43 {
44 return CompositeType.AND;
45 } else
46 {
47 throw new PluginParseException("Invalid condition type specified. type = " + type);
48 }
49 }
50 }
51
52
53
54
55 public static interface ConditionFactory
56 {
57 Condition create(String className, Plugin plugin) throws ConditionLoadingException;
58 }
59
60 private final ConditionFactory conditionFactory;
61
62 public ConditionElementParser(ConditionFactory conditionFactory)
63 {
64 this.conditionFactory = conditionFactory;
65 }
66
67
68
69
70
71
72
73
74
75 @SuppressWarnings("unchecked")
76 public Condition makeConditions(final Plugin plugin, final Element element, final int type) throws PluginParseException
77 {
78 Assertions.notNull("plugin == null", plugin);
79
80
81 final List<Element> singleConditionElements = element.elements("condition");
82 Condition singleConditions = null;
83 if ((singleConditionElements != null) && !singleConditionElements.isEmpty())
84 {
85 singleConditions = makeConditions(plugin, singleConditionElements, type);
86 }
87
88
89
90 final List<Element> nestedConditionsElements = element.elements("conditions");
91 AbstractCompositeCondition nestedConditions = null;
92 if ((nestedConditionsElements != null) && !nestedConditionsElements.isEmpty())
93 {
94 nestedConditions = getCompositeCondition(type);
95 for (final Iterator<Element> iterator = nestedConditionsElements.iterator(); iterator.hasNext(); )
96 {
97 final Element nestedElement = iterator.next();
98 nestedConditions.addCondition(makeConditions(plugin, nestedElement, CompositeType
99 .parse(nestedElement.attributeValue("type"))));
100 }
101 }
102
103 if ((singleConditions != null) && (nestedConditions != null))
104 {
105
106 final AbstractCompositeCondition compositeCondition = getCompositeCondition(type);
107 compositeCondition.addCondition(singleConditions);
108 compositeCondition.addCondition(nestedConditions);
109 return compositeCondition;
110 } else if (singleConditions != null)
111 {
112 return singleConditions;
113 } else if (nestedConditions != null)
114 {
115 return nestedConditions;
116 }
117
118 return null;
119 }
120
121 public Condition makeConditions(final Plugin plugin, final List<Element> elements, final int type) throws PluginParseException
122 {
123 if (elements.isEmpty())
124 {
125 return null;
126 } else if (elements.size() == 1)
127 {
128 return makeCondition(plugin, elements.get(0));
129 } else
130 {
131 final AbstractCompositeCondition compositeCondition = getCompositeCondition(type);
132 for (final Iterator<Element> it = elements.iterator(); it.hasNext(); )
133 {
134 final Element element = it.next();
135 compositeCondition.addCondition(makeCondition(plugin, element));
136 }
137
138 return compositeCondition;
139 }
140 }
141
142 public Condition makeCondition(final Plugin plugin, final Element element) throws PluginParseException
143 {
144 try
145 {
146 String conditionClassName = element.attributeValue("class");
147 if (conditionClassName == null)
148 {
149 throw new PluginParseException("Condition element must specify a class attribute");
150 }
151 final Condition condition = conditionFactory.create(conditionClassName, plugin);
152 condition.init(LoaderUtils.getParams(element));
153
154 if ((element.attribute("invert") != null) && "true".equals(element.attributeValue("invert")))
155 {
156 return new InvertedCondition(condition);
157 }
158
159 return condition;
160 } catch (final ClassCastException e)
161 {
162 throw new PluginParseException("Configured condition class does not implement the Condition interface", e);
163 } catch (final ConditionLoadingException cle)
164 {
165 throw new PluginParseException("Unable to load the module's display conditions: " + cle.getMessage(), cle);
166 }
167 }
168
169 private AbstractCompositeCondition getCompositeCondition(final int type) throws PluginParseException
170 {
171 switch (type)
172 {
173 case CompositeType.OR:
174 return new OrCompositeCondition();
175 case CompositeType.AND:
176 return new AndCompositeCondition();
177 default:
178 throw new PluginParseException("Invalid condition type specified. type = " + type);
179 }
180 }
181 }