1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.rice.krad.uif.service.impl;
17
18 import org.apache.commons.lang.StringUtils;
19 import org.kuali.rice.krad.datadictionary.uif.UifDictionaryBean;
20 import org.kuali.rice.krad.uif.UifConstants;
21 import org.kuali.rice.krad.uif.component.BindingInfo;
22 import org.kuali.rice.krad.uif.component.Component;
23 import org.kuali.rice.krad.uif.component.KeepExpression;
24 import org.kuali.rice.krad.uif.component.PropertyReplacer;
25 import org.kuali.rice.krad.uif.container.CollectionGroup;
26 import org.kuali.rice.krad.uif.field.DataField;
27 import org.kuali.rice.krad.uif.layout.LayoutManager;
28 import org.kuali.rice.krad.uif.service.ExpressionEvaluatorService;
29 import org.kuali.rice.krad.uif.util.CloneUtils;
30 import org.kuali.rice.krad.uif.util.ExpressionFunctions;
31 import org.kuali.rice.krad.uif.util.ObjectPropertyUtils;
32 import org.kuali.rice.krad.uif.view.View;
33 import org.springframework.expression.Expression;
34 import org.springframework.expression.ExpressionParser;
35 import org.springframework.expression.common.TemplateParserContext;
36 import org.springframework.expression.spel.standard.SpelExpressionParser;
37 import org.springframework.expression.spel.support.StandardEvaluationContext;
38
39 import java.util.Collection;
40 import java.util.List;
41 import java.util.Map;
42 import java.util.Map.Entry;
43
44
45
46
47
48
49 public class ExpressionEvaluatorServiceImpl implements ExpressionEvaluatorService {
50 private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(
51 ExpressionEvaluatorServiceImpl.class);
52
53
54
55
56
57
58 public void evaluateExpressionsOnConfigurable(View view, UifDictionaryBean expressionConfigurable,
59 Object contextObject, Map<String, Object> evaluationParameters) {
60 if ((expressionConfigurable instanceof Component) || (expressionConfigurable instanceof LayoutManager)) {
61 evaluatePropertyReplacers(view, expressionConfigurable, contextObject, evaluationParameters);
62 }
63 evaluatePropertyExpressions(view, expressionConfigurable, contextObject, evaluationParameters);
64 }
65
66
67
68
69
70 public String evaluateExpressionTemplate(Object contextObject, Map<String, Object> evaluationParameters,
71 String expressionTemplate) {
72 StandardEvaluationContext context = new StandardEvaluationContext(contextObject);
73 context.setVariables(evaluationParameters);
74 addCustomFunctions(context);
75
76 ExpressionParser parser = new SpelExpressionParser();
77
78 String result = null;
79 try {
80 Expression expression = null;
81 if (StringUtils.contains(expressionTemplate, UifConstants.EL_PLACEHOLDER_PREFIX)) {
82 expression = parser.parseExpression(expressionTemplate, new TemplateParserContext(
83 UifConstants.EL_PLACEHOLDER_PREFIX, UifConstants.EL_PLACEHOLDER_SUFFIX));
84 } else {
85 expression = parser.parseExpression(expressionTemplate);
86 }
87
88 result = expression.getValue(context, String.class);
89 } catch (Exception e) {
90 LOG.error("Exception evaluating expression: " + expressionTemplate);
91 throw new RuntimeException("Exception evaluating expression: " + expressionTemplate, e);
92 }
93
94 return result;
95 }
96
97
98
99
100
101 public Object evaluateExpression(Object contextObject, Map<String, Object> evaluationParameters,
102 String expressionStr) {
103 StandardEvaluationContext context = new StandardEvaluationContext(contextObject);
104 context.setVariables(evaluationParameters);
105 addCustomFunctions(context);
106
107
108 if (StringUtils.startsWith(expressionStr, UifConstants.EL_PLACEHOLDER_PREFIX) && StringUtils.endsWith(
109 expressionStr, UifConstants.EL_PLACEHOLDER_SUFFIX)) {
110 expressionStr = StringUtils.removeStart(expressionStr, UifConstants.EL_PLACEHOLDER_PREFIX);
111 expressionStr = StringUtils.removeEnd(expressionStr, UifConstants.EL_PLACEHOLDER_SUFFIX);
112 }
113
114 ExpressionParser parser = new SpelExpressionParser();
115 Object result = null;
116 try {
117 Expression expression = parser.parseExpression(expressionStr);
118
119 result = expression.getValue(context);
120 } catch (Exception e) {
121 LOG.error("Exception evaluating expression: " + expressionStr);
122 throw new RuntimeException("Exception evaluating expression: " + expressionStr, e);
123 }
124
125 return result;
126 }
127
128
129
130
131
132
133 protected void addCustomFunctions(StandardEvaluationContext context) {
134 try {
135
136 context.registerFunction("isAssignableFrom", ExpressionFunctions.class.getDeclaredMethod("isAssignableFrom",
137 new Class[]{Class.class, Class.class}));
138 context.registerFunction("empty", ExpressionFunctions.class.getDeclaredMethod("empty",
139 new Class[]{Object.class}));
140 context.registerFunction("emptyList", ExpressionFunctions.class.getDeclaredMethod("emptyList",
141 new Class[]{List.class}));
142 context.registerFunction("listContains", ExpressionFunctions.class.getDeclaredMethod("listContains",
143 new Class[]{List.class, Object[].class}));
144 context.registerFunction("getName", ExpressionFunctions.class.getDeclaredMethod("getName",
145 new Class[]{Class.class}));
146 context.registerFunction("getParm", ExpressionFunctions.class.getDeclaredMethod("getParm",
147 new Class[]{String.class, String.class, String.class}));
148 context.registerFunction("getParmInd", ExpressionFunctions.class.getDeclaredMethod("getParmInd",
149 new Class[]{String.class, String.class, String.class}));
150 context.registerFunction("hasPerm", ExpressionFunctions.class.getDeclaredMethod("hasPerm",
151 new Class[]{String.class, String.class}));
152 context.registerFunction("hasPermDtls", ExpressionFunctions.class.getDeclaredMethod("hasPermDtls",
153 new Class[]{String.class, String.class, Map.class, Map.class}));
154 context.registerFunction("hasPermTmpl", ExpressionFunctions.class.getDeclaredMethod("hasPermTmpl",
155 new Class[]{String.class, String.class, Map.class, Map.class}));
156 context.registerFunction("sequence", ExpressionFunctions.class.getDeclaredMethod("sequence",
157 new Class[]{String.class}));
158 } catch (NoSuchMethodException e) {
159 LOG.error("Custom function for el expressions not found: " + e.getMessage());
160 throw new RuntimeException("Custom function for el expressions not found: " + e.getMessage(), e);
161 }
162 }
163
164
165
166
167
168
169
170
171
172
173
174
175
176 protected void evaluatePropertyReplacers(View view, UifDictionaryBean expressionConfigurable, Object contextObject,
177 Map<String, Object> evaluationParameters) {
178 List<PropertyReplacer> replacers = null;
179 if (Component.class.isAssignableFrom(expressionConfigurable.getClass())) {
180 replacers = ((Component) expressionConfigurable).getPropertyReplacers();
181 } else if (LayoutManager.class.isAssignableFrom(expressionConfigurable.getClass())) {
182 replacers = ((LayoutManager) expressionConfigurable).getPropertyReplacers();
183 }
184
185 for (PropertyReplacer propertyReplacer : replacers) {
186 String expression = propertyReplacer.getCondition();
187 String adjustedExpression = replaceBindingPrefixes(view, expressionConfigurable, expression);
188
189 String conditionEvaluation = evaluateExpressionTemplate(contextObject, evaluationParameters,
190 adjustedExpression);
191 boolean conditionSuccess = Boolean.parseBoolean(conditionEvaluation);
192 if (conditionSuccess) {
193 ObjectPropertyUtils.setPropertyValue(expressionConfigurable, propertyReplacer.getPropertyName(),
194 propertyReplacer.getReplacement());
195 }
196 }
197 }
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213 protected void evaluatePropertyExpressions(View view, UifDictionaryBean expressionConfigurable,
214 Object contextObject, Map<String, Object> evaluationParameters) {
215 Map<String, String> propertyExpressions = expressionConfigurable.getPropertyExpressions();
216 for (Entry<String, String> propertyExpression : propertyExpressions.entrySet()) {
217 String propertyName = propertyExpression.getKey();
218 String expression = propertyExpression.getValue();
219
220
221 if (CloneUtils.fieldHasAnnotation(expressionConfigurable.getClass(), propertyName, KeepExpression.class)) {
222
223 ObjectPropertyUtils.setPropertyValue(expressionConfigurable, propertyName, expression);
224 continue;
225 }
226
227 Object propertyValue = null;
228
229
230 String adjustedExpression = replaceBindingPrefixes(view, expressionConfigurable, expression);
231
232
233 if (StringUtils.startsWith(adjustedExpression, UifConstants.EL_PLACEHOLDER_PREFIX) && StringUtils.endsWith(
234 adjustedExpression, UifConstants.EL_PLACEHOLDER_SUFFIX) && (StringUtils.countMatches(
235 adjustedExpression, UifConstants.EL_PLACEHOLDER_PREFIX) == 1)) {
236 propertyValue = evaluateExpression(contextObject, evaluationParameters, adjustedExpression);
237 } else {
238
239 propertyValue = evaluateExpressionTemplate(contextObject, evaluationParameters, adjustedExpression);
240 }
241
242
243
244 if (StringUtils.endsWith(propertyName, ExpressionEvaluatorService.EMBEDDED_PROPERTY_NAME_ADD_INDICATOR)) {
245 StringUtils.removeEnd(propertyName, ExpressionEvaluatorService.EMBEDDED_PROPERTY_NAME_ADD_INDICATOR);
246
247 Collection collectionValue = ObjectPropertyUtils.getPropertyValue(expressionConfigurable, propertyName);
248 if (collectionValue == null) {
249 throw new RuntimeException("Property name: "
250 + propertyName
251 + " with collection type was not initialized. Cannot add expression result");
252 }
253 collectionValue.add(propertyValue);
254 } else {
255 ObjectPropertyUtils.setPropertyValue(expressionConfigurable, propertyName, propertyValue);
256 }
257 }
258 }
259
260
261
262
263 public boolean containsElPlaceholder(String value) {
264 boolean containsElPlaceholder = false;
265
266 if (StringUtils.isNotBlank(value)) {
267 String elPlaceholder = StringUtils.substringBetween(value, UifConstants.EL_PLACEHOLDER_PREFIX,
268 UifConstants.EL_PLACEHOLDER_SUFFIX);
269 if (StringUtils.isNotBlank(elPlaceholder)) {
270 containsElPlaceholder = true;
271 }
272 }
273
274 return containsElPlaceholder;
275 }
276
277
278
279
280
281 public String replaceBindingPrefixes(View view, Object object, String expression) {
282 String adjustedExpression = StringUtils.replace(expression, UifConstants.NO_BIND_ADJUST_PREFIX, "");
283
284
285 if (object instanceof DataField) {
286
287
288 BindingInfo bindingInfo = ((DataField) object).getBindingInfo();
289 String fieldPath = bindingInfo.getBindingPath();
290
291
292 fieldPath = StringUtils.removeEnd(fieldPath, "." + bindingInfo.getBindingName());
293 adjustedExpression = StringUtils.replace(adjustedExpression, UifConstants.FIELD_PATH_BIND_ADJUST_PREFIX,
294 fieldPath + ".");
295 } else {
296 adjustedExpression = StringUtils.replace(adjustedExpression, UifConstants.FIELD_PATH_BIND_ADJUST_PREFIX,
297 "");
298 }
299
300
301 if (StringUtils.isNotBlank(view.getDefaultBindingObjectPath())) {
302 adjustedExpression = StringUtils.replace(adjustedExpression, UifConstants.DEFAULT_PATH_BIND_ADJUST_PREFIX,
303 view.getDefaultBindingObjectPath() + ".");
304
305 } else {
306 adjustedExpression = StringUtils.replace(adjustedExpression, UifConstants.DEFAULT_PATH_BIND_ADJUST_PREFIX,
307 "");
308 }
309
310
311 if (adjustedExpression.contains(UifConstants.LINE_PATH_BIND_ADJUST_PREFIX) && (object instanceof Component)) {
312 String linePath = getLinePathPrefixValue((Component) object);
313
314 adjustedExpression = StringUtils.replace(adjustedExpression, UifConstants.LINE_PATH_BIND_ADJUST_PREFIX,
315 linePath + ".");
316 }
317
318
319 if (adjustedExpression.contains(UifConstants.NODE_PATH_BIND_ADJUST_PREFIX) && (object instanceof Component)) {
320 String nodePath = "";
321
322 Map<String, Object> context = ((Component) object).getContext();
323 if (context.containsKey(UifConstants.ContextVariableNames.NODE_PATH)) {
324 nodePath = (String) context.get(UifConstants.ContextVariableNames.NODE_PATH);
325 }
326
327 adjustedExpression = StringUtils.replace(adjustedExpression, UifConstants.NODE_PATH_BIND_ADJUST_PREFIX,
328 nodePath + ".");
329 }
330
331 return adjustedExpression;
332 }
333
334
335
336
337
338
339
340
341
342 protected static String getLinePathPrefixValue(Component component) {
343 String linePath = "";
344
345 CollectionGroup collectionGroup = (CollectionGroup) (component.getContext().get(
346 UifConstants.ContextVariableNames.COLLECTION_GROUP));
347 if (collectionGroup == null) {
348 LOG.warn("collection group not found for " + component + "," + component.getId() + ", " + component
349 .getComponentTypeName());
350 return linePath;
351 }
352
353 Object indexObj = component.getContext().get(UifConstants.ContextVariableNames.INDEX);
354 if (indexObj != null) {
355 int index = (Integer) indexObj;
356 boolean addLine = false;
357 Object addLineObj = component.getContext().get(UifConstants.ContextVariableNames.IS_ADD_LINE);
358
359 if (addLineObj != null) {
360 addLine = (Boolean) addLineObj;
361 }
362
363 if (addLine) {
364 linePath = collectionGroup.getAddLineBindingInfo().getBindingPath();
365 } else {
366 linePath = collectionGroup.getBindingInfo().getBindingPath() + "[" + index + "]";
367 }
368 }
369
370 return linePath;
371 }
372
373 }