1
2
3
4
5
6
7 package org.mule.expression;
8
9 import org.mule.api.MuleMessage;
10 import org.mule.api.expression.RequiredValueException;
11 import org.mule.api.transport.PropertyScope;
12 import org.mule.config.i18n.CoreMessages;
13 import org.mule.routing.filters.WildcardFilter;
14
15 import java.util.ArrayList;
16 import java.util.Collections;
17 import java.util.HashMap;
18 import java.util.List;
19 import java.util.Map;
20
21 import static org.mule.expression.ExpressionConstants.ALL_ARGUMENT;
22 import static org.mule.expression.ExpressionConstants.DELIM;
23 import static org.mule.expression.ExpressionConstants.OPTIONAL_ARGUMENT;
24
25
26
27
28 public final class ExpressionUtils
29 {
30 private ExpressionUtils()
31 {
32
33 }
34
35
36
37
38
39
40
41
42
43
44 public static Object getPropertyWithScope(String expression, MuleMessage msg)
45 {
46 return getPropertyWithScope(expression, msg, Object.class);
47 }
48
49
50
51
52
53
54
55
56
57
58
59
60
61 public static <T> T getPropertyWithScope(String expression, MuleMessage msg, Class<T> type)
62 {
63 return getPropertyInternal(expression, PropertyScope.OUTBOUND, true, msg, type);
64 }
65
66
67
68
69
70 public static Object getProperty(String expression, PropertyScope scope, MuleMessage msg)
71 {
72 return getProperty(expression, scope, msg, Object.class);
73 }
74
75
76
77
78
79
80
81
82
83 public static <T> T getProperty(String expression, PropertyScope scope, MuleMessage msg, Class<T> type)
84 {
85 return getPropertyInternal(expression, scope, false, msg, type);
86 }
87
88
89
90
91
92
93
94
95
96
97
98 @SuppressWarnings("unchecked")
99 protected static <T> T getPropertyInternal(String expression, PropertyScope scope, boolean parseScope, MuleMessage msg, Class<T> type)
100 {
101 if (parseScope)
102 {
103 PropertyScope tempScope = getScope(expression);
104 if (tempScope != null)
105 {
106
107 expression = expression.substring(tempScope.getScopeName().length() + 1);
108 scope = tempScope;
109 }
110 }
111
112 if (expression.contains(ALL_ARGUMENT))
113 {
114 WildcardFilter filter = new WildcardFilter(expression);
115 if (Map.class.isAssignableFrom(type))
116 {
117 Map<String, Object> props = new HashMap<String, Object>();
118 for (String name : msg.getPropertyNames(scope))
119 {
120 if (filter.accept(name))
121 {
122 props.put(name, msg.getProperty(name, scope));
123 }
124 }
125 return (T) returnMap(props, scope);
126 }
127 else if (List.class.isAssignableFrom(type))
128 {
129 List<Object> values = new ArrayList<Object>();
130 for (String name : msg.getPropertyNames(scope))
131 {
132 if (filter.accept(name))
133 {
134 values.add(msg.getProperty(name, scope));
135 }
136 }
137 return (T) returnList(values, scope);
138 }
139 else
140 {
141
142 throw new IllegalArgumentException("Type specified is not a collection type but '" + ALL_ARGUMENT + "' was specified for all properties. Type is: " + type);
143 }
144 }
145 else if (Map.class.isAssignableFrom(type))
146 {
147 String[] names = expression.split(DELIM);
148 Map<String, Object> props = new HashMap<String, Object>();
149 for (String name : names)
150 {
151 boolean required = true;
152 name = name.trim();
153 PropertyScope entryScope = scope;
154 if (parseScope)
155 {
156 entryScope = getScope(name);
157 if (entryScope != null)
158 {
159
160 name = name.substring(entryScope.getScopeName().length() + 1);
161 }
162 else
163 {
164 entryScope = scope;
165 }
166 }
167 if (name.endsWith(OPTIONAL_ARGUMENT))
168 {
169 name = name.substring(0, name.length() - OPTIONAL_ARGUMENT.length());
170 required = false;
171 }
172 Object value = msg.getProperty(name, entryScope);
173 if (value == null && required)
174 {
175 throw new RequiredValueException(CoreMessages.expressionEvaluatorReturnedNull("headers", entryScope.getScopeName() + ":" + name));
176 }
177 else if (value != null)
178 {
179 props.put(name, value);
180 }
181 }
182 return (T) returnMap(props, scope);
183 }
184 else if (List.class.isAssignableFrom(type))
185 {
186 String[] names = expression.split(DELIM);
187 List<Object> values = new ArrayList<Object>();
188 for (String name : names)
189 {
190 boolean required = true;
191 name = name.trim();
192 PropertyScope itemScope = scope;
193 if (parseScope)
194 {
195 itemScope = getScope(name);
196 if (itemScope != null)
197 {
198
199 name = name.substring(itemScope.getScopeName().length() + 1);
200 }
201 else
202 {
203 itemScope = scope;
204 }
205 }
206 if (name.endsWith(OPTIONAL_ARGUMENT))
207 {
208 name = name.substring(0, name.length() - OPTIONAL_ARGUMENT.length());
209 required = false;
210 }
211 name = name.trim();
212 Object value = msg.getProperty(name, itemScope);
213 if (value == null && required)
214 {
215 throw new RequiredValueException(CoreMessages.expressionEvaluatorReturnedNull("headers-list", itemScope.getScopeName() + ":" + name));
216 }
217 else if (value != null)
218 {
219 values.add(value);
220 }
221 }
222 return (T) returnList(values, scope);
223 }
224 else
225 {
226 boolean required = true;
227 if (expression.endsWith(OPTIONAL_ARGUMENT))
228 {
229 expression = expression.substring(0, expression.length() - OPTIONAL_ARGUMENT.length());
230 required = false;
231 }
232 Object result = msg.getProperty(expression.trim(), scope);
233 if (result == null && required)
234 {
235 throw new RequiredValueException(CoreMessages.expressionEvaluatorReturnedNull("header", scope.getScopeName() + ":" + expression));
236
237 }
238 return (T) result;
239 }
240 }
241
242 private static Map<String, Object> returnMap(Map<String, Object> props, PropertyScope scope)
243 {
244 Map<String, Object> p = (props.size() == 0 ? Collections.<String, Object>emptyMap() : props);
245 if (scope.equals(PropertyScope.INBOUND))
246 {
247 p = Collections.unmodifiableMap(p);
248 }
249 return p;
250 }
251
252 private static List<Object> returnList(List<Object> values, PropertyScope scope)
253 {
254 List<Object> l = (values.size() == 0 ? Collections.emptyList() : values);
255 if (scope.equals(PropertyScope.INBOUND))
256 {
257 l = Collections.unmodifiableList(l);
258 }
259 return l;
260 }
261
262 protected static PropertyScope getScope(String expression)
263 {
264
265 final String[] tokens = expression.split(":", 2);
266 PropertyScope scope;
267 if (tokens.length == 2)
268 {
269 final String candidate = tokens[0];
270 scope = PropertyScope.get(candidate.toLowerCase());
271 if (scope == null)
272 {
273 throw new IllegalArgumentException(String.format("'%s' is not a valid property scope.", candidate));
274 }
275
276 return scope;
277 }
278 return null;
279 }
280 }