1 package com.atlassian.plugin.web.descriptors;
2
3 import java.util.Iterator;
4 import java.util.List;
5
6 import org.dom4j.Element;
7
8 import com.atlassian.plugin.Plugin;
9 import com.atlassian.plugin.PluginParseException;
10 import com.atlassian.plugin.StateAware;
11 import com.atlassian.plugin.descriptors.AbstractModuleDescriptor;
12 import com.atlassian.plugin.loaders.LoaderUtils;
13 import com.atlassian.plugin.web.Condition;
14 import com.atlassian.plugin.web.ContextProvider;
15 import com.atlassian.plugin.web.WebInterfaceManager;
16 import com.atlassian.plugin.web.conditions.AbstractCompositeCondition;
17 import com.atlassian.plugin.web.conditions.AndCompositeCondition;
18 import com.atlassian.plugin.web.conditions.InvertedCondition;
19 import com.atlassian.plugin.web.conditions.OrCompositeCondition;
20 import com.atlassian.plugin.web.model.DefaultWebLabel;
21 import com.atlassian.plugin.web.model.DefaultWebParam;
22 import com.atlassian.plugin.web.model.WebLabel;
23 import com.atlassian.plugin.web.model.WebParam;
24
25
26
27
28 public abstract class AbstractWebFragmentModuleDescriptor extends AbstractModuleDescriptor implements StateAware, WebFragmentModuleDescriptor
29 {
30 protected WebInterfaceManager webInterfaceManager;
31 protected Element element;
32 protected int weight;
33
34 protected Condition condition;
35 protected ContextProvider contextProvider;
36 protected DefaultWebLabel label;
37 protected DefaultWebLabel tooltip;
38 protected WebParam params;
39
40 protected AbstractWebFragmentModuleDescriptor(WebInterfaceManager webInterfaceManager)
41 {
42 this.webInterfaceManager = webInterfaceManager;
43 }
44
45 public AbstractWebFragmentModuleDescriptor()
46 {
47 }
48
49 public void init(Plugin plugin, Element element) throws PluginParseException
50 {
51 super.init(plugin, element);
52
53 this.element = element;
54 weight = 1000;
55 try
56 {
57 weight = Integer.parseInt(element.attributeValue("weight"));
58 }
59 catch (NumberFormatException e)
60 {
61 }
62 }
63
64
65
66
67
68
69
70 protected Condition makeConditions(Element element, int type) throws PluginParseException
71 {
72
73 List singleConditionElements = element.elements("condition");
74 Condition singleConditions = null;
75 if (singleConditionElements != null && !singleConditionElements.isEmpty())
76 {
77 singleConditions = makeConditions(singleConditionElements, type);
78 }
79
80
81 List nestedConditionsElements = element.elements("conditions");
82 AbstractCompositeCondition nestedConditions = null;
83 if (nestedConditionsElements != null && !nestedConditionsElements.isEmpty())
84 {
85 nestedConditions = getCompositeCondition(type);
86 for (Iterator iterator = nestedConditionsElements.iterator(); iterator.hasNext();)
87 {
88 Element nestedElement = (Element) iterator.next();
89 nestedConditions.addCondition(makeConditions(nestedElement, getCompositeType(nestedElement.attributeValue("type"))));
90 }
91 }
92
93 if (singleConditions != null && nestedConditions != null)
94 {
95
96 AbstractCompositeCondition compositeCondition = getCompositeCondition(type);
97 compositeCondition.addCondition(singleConditions);
98 compositeCondition.addCondition(nestedConditions);
99 return compositeCondition;
100 }
101 else if (singleConditions != null)
102 {
103 return singleConditions;
104 }
105 else if (nestedConditions != null)
106 {
107 return nestedConditions;
108 }
109
110 return null;
111 }
112
113 protected Condition makeConditions(List elements, int type) throws PluginParseException
114 {
115 if (elements.size() == 0)
116 {
117 return null;
118 }
119 else if (elements.size() == 1)
120 {
121 return makeCondition((Element) elements.get(0));
122 }
123 else
124 {
125 AbstractCompositeCondition compositeCondition = getCompositeCondition(type);
126 for (Iterator it = elements.iterator(); it.hasNext();)
127 {
128 Element element = (Element) it.next();
129 compositeCondition.addCondition(makeCondition(element));
130 }
131
132 return compositeCondition;
133 }
134 }
135
136 protected Condition makeCondition(Element element) throws PluginParseException
137 {
138 try
139 {
140 Condition condition = webInterfaceManager.getWebFragmentHelper().loadCondition(element.attributeValue("class"), plugin);
141 condition.init(LoaderUtils.getParams(element));
142
143 if (element.attribute("invert") != null && "true".equals(element.attributeValue("invert")))
144 {
145 return new InvertedCondition(condition);
146 }
147
148 return condition;
149 }
150 catch (ClassCastException e)
151 {
152 throw new PluginParseException("Configured condition class does not implement the Condition interface");
153 }
154 catch (Throwable t)
155 {
156 throw new PluginParseException(t);
157 }
158 }
159
160 protected ContextProvider makeContextProvider(Element element) throws PluginParseException
161 {
162 try
163 {
164 ContextProvider context = webInterfaceManager.getWebFragmentHelper().loadContextProvider(element.attributeValue("class"), plugin);
165 context.init(LoaderUtils.getParams(element));
166
167 return context;
168 }
169 catch (ClassCastException e)
170 {
171 throw new PluginParseException("Configured context-provider class does not implement the ContextProvider interface");
172 }
173 catch (Throwable t)
174 {
175 throw new PluginParseException(t);
176 }
177 }
178
179 private int getCompositeType(String type) throws PluginParseException
180 {
181 if ("or".equalsIgnoreCase(type))
182 {
183 return COMPOSITE_TYPE_OR;
184 }
185 else if ("and".equalsIgnoreCase(type))
186 {
187 return COMPOSITE_TYPE_AND;
188 }
189 throw new PluginParseException("Invalid condition type specified. type = " + type);
190 }
191
192 private AbstractCompositeCondition getCompositeCondition(int type) throws PluginParseException
193 {
194 switch (type)
195 {
196 case COMPOSITE_TYPE_OR:
197 {
198 return new OrCompositeCondition();
199 }
200 case COMPOSITE_TYPE_AND:
201 {
202 return new AndCompositeCondition();
203 }
204 }
205 throw new PluginParseException("Invalid condition type specified. type = " + type);
206 }
207
208 public void enabled()
209 {
210
211
212 try
213 {
214 if (element.element("context-provider") != null)
215 {
216 contextProvider = makeContextProvider(element.element("context-provider"));
217 }
218
219 if (element.element("label") != null)
220 {
221 label = new DefaultWebLabel(element.element("label"), webInterfaceManager.getWebFragmentHelper(), contextProvider, this);
222 }
223
224 if (element.element("tooltip") != null)
225 {
226 tooltip = new DefaultWebLabel(element.element("tooltip"), webInterfaceManager.getWebFragmentHelper(), contextProvider, this);
227 }
228
229 if (getParams() != null)
230 {
231 params = new DefaultWebParam(getParams(), webInterfaceManager.getWebFragmentHelper(), contextProvider, this);
232 }
233
234 condition = makeConditions(element, COMPOSITE_TYPE_AND);
235 }
236 catch (PluginParseException e)
237 {
238
239 throw new RuntimeException("Unable to enable web fragment", e);
240 }
241
242 webInterfaceManager.refresh();
243 }
244
245 public void disabled()
246 {
247 webInterfaceManager.refresh();
248 }
249
250 public int getWeight()
251 {
252 return weight;
253 }
254
255 public Object getModule()
256 {
257 return null;
258 }
259
260 public WebLabel getWebLabel()
261 {
262 return label;
263 }
264
265 public WebLabel getTooltip()
266 {
267 return tooltip;
268 }
269
270 public void setWebInterfaceManager(WebInterfaceManager webInterfaceManager)
271 {
272 this.webInterfaceManager = webInterfaceManager;
273 }
274
275 public Condition getCondition()
276 {
277 return condition;
278 }
279
280 public ContextProvider getContextProvider()
281 {
282 return contextProvider;
283 }
284
285 public WebParam getWebParams()
286 {
287 return params;
288 }
289 }