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