View Javadoc

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   * An abstract convenience class for web fragment descriptors.
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       * Create a condition for when this web fragment should be displayed
65       * @param element Element of web-section or web-item
66       * @param type logical operator type {@link #getCompositeType}
67       * @throws PluginParseException
68       */
69      protected Condition makeConditions(final Element element, final int type) throws PluginParseException
70      {
71          //make single conditions (all Anded together)
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          //make composite conditions (logical operator can be specified by "type")
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              //Join together the single and composite conditions by this type
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         // this was moved to the enabled() method because spring beans declared
214         // by the plugin are not available for injection during the init() phase
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             // is there a better exception to throw?
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 }