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