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