1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.rice.krad.uif.util;
17
18 import org.apache.commons.lang.StringUtils;
19 import org.kuali.rice.krad.uif.UifConstants;
20 import org.kuali.rice.krad.uif.UifPropertyPaths;
21 import org.kuali.rice.krad.uif.container.CollectionGroup;
22 import org.kuali.rice.krad.uif.field.DataField;
23 import org.kuali.rice.krad.uif.view.View;
24 import org.kuali.rice.krad.uif.component.BindingInfo;
25 import org.kuali.rice.krad.uif.component.Component;
26 import org.kuali.rice.krad.uif.layout.LayoutManager;
27
28 import java.util.HashMap;
29 import java.util.List;
30 import java.util.Map;
31
32
33
34
35
36
37 public class ExpressionUtils {
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55 public static void adjustPropertyExpressions(View view, Object object) {
56 if (object == null) {
57 return;
58 }
59
60
61 Map<String, String> propertyExpressions = new HashMap<String, String>();
62 if (Component.class.isAssignableFrom(object.getClass())) {
63 propertyExpressions = ((Component) object).getPropertyExpressions();
64 } else if (LayoutManager.class.isAssignableFrom(object.getClass())) {
65 propertyExpressions = ((LayoutManager) object).getPropertyExpressions();
66 } else if (BindingInfo.class.isAssignableFrom(object.getClass())) {
67 propertyExpressions = ((BindingInfo) object).getPropertyExpressions();
68 }
69
70 Map<String, String> adjustedPropertyExpressions = new HashMap<String, String>();
71 for (Map.Entry<String, String> propertyExpression : propertyExpressions.entrySet()) {
72 String propertyName = propertyExpression.getKey();
73 String expression = propertyExpression.getValue();
74
75
76 if (StringUtils.contains(propertyName, ".")) {
77 boolean expressionMoved = moveNestedPropertyExpression(object, propertyName, expression);
78
79
80 if (expressionMoved) {
81 continue;
82 }
83 }
84
85
86 String adjustedExpression = replaceBindingPrefixes(view, object, expression);
87
88 adjustedPropertyExpressions.put(propertyName, adjustedExpression);
89 }
90
91
92 ObjectPropertyUtils.setPropertyValue(object, UifPropertyPaths.PROPERTY_EXPRESSIONS,
93 adjustedPropertyExpressions);
94 }
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113 public static String replaceBindingPrefixes(View view, Object object, String expression) {
114 String adjustedExpression = StringUtils.replace(expression, UifConstants.NO_BIND_ADJUST_PREFIX, "");
115
116
117 if (object instanceof DataField) {
118
119
120 BindingInfo bindingInfo = ((DataField) object).getBindingInfo();
121 String fieldPath = bindingInfo.getBindingPath();
122
123
124 fieldPath = StringUtils.removeEnd(fieldPath, "." + bindingInfo.getBindingName());
125 adjustedExpression = StringUtils.replace(adjustedExpression, UifConstants.FIELD_PATH_BIND_ADJUST_PREFIX,
126 fieldPath + ".");
127 } else {
128 adjustedExpression = StringUtils.replace(adjustedExpression, UifConstants.FIELD_PATH_BIND_ADJUST_PREFIX,
129 "");
130 }
131
132
133 if (StringUtils.isNotBlank(view.getDefaultBindingObjectPath())) {
134 adjustedExpression = StringUtils.replace(adjustedExpression, UifConstants.DEFAULT_PATH_BIND_ADJUST_PREFIX,
135 view.getDefaultBindingObjectPath() + ".");
136
137 } else {
138 adjustedExpression = StringUtils.replace(adjustedExpression, UifConstants.DEFAULT_PATH_BIND_ADJUST_PREFIX,
139 "");
140 }
141
142
143 if (adjustedExpression.contains(UifConstants.LINE_PATH_BIND_ADJUST_PREFIX) && (object instanceof Component)) {
144 String linePath = getLinePathPrefixValue((Component) object);
145
146 adjustedExpression = StringUtils.replace(adjustedExpression, UifConstants.LINE_PATH_BIND_ADJUST_PREFIX,
147 linePath + ".");
148 }
149
150
151 if (adjustedExpression.contains(UifConstants.NODE_PATH_BIND_ADJUST_PREFIX) && (object instanceof Component)) {
152 String nodePath = "";
153
154 Map<String, Object> context = ((Component) object).getContext();
155 if (context.containsKey(UifConstants.ContextVariableNames.NODE_PATH)) {
156 nodePath = (String) context.get(UifConstants.ContextVariableNames.NODE_PATH);
157 }
158
159 adjustedExpression = StringUtils.replace(adjustedExpression, UifConstants.NODE_PATH_BIND_ADJUST_PREFIX,
160 nodePath + ".");
161 }
162
163 return adjustedExpression;
164 }
165
166
167
168
169
170
171
172
173 protected static String getLinePathPrefixValue(Component component) {
174 String linePath = "";
175
176 CollectionGroup collectionGroup = (CollectionGroup) (component.getContext().get(
177 UifConstants.ContextVariableNames.COLLECTION_GROUP));
178 if (collectionGroup == null) {
179 return linePath;
180 }
181
182 Object indexObj = component.getContext().get(UifConstants.ContextVariableNames.INDEX);
183 if (indexObj != null) {
184 int index = (Integer) indexObj;
185 boolean addLine = false;
186 Object addLineObj = component.getContext().get(UifConstants.ContextVariableNames.IS_ADD_LINE);
187
188 if (addLineObj != null) {
189 addLine = (Boolean) addLineObj;
190 }
191
192 if (addLine) {
193 linePath = collectionGroup.getAddLineBindingInfo().getBindingPath();
194 } else {
195 linePath = collectionGroup.getBindingInfo().getBindingPath() + "[" + index + "]";
196 }
197 }
198
199 return linePath;
200 }
201
202
203
204
205
206
207
208
209
210 protected static boolean moveNestedPropertyExpression(Object object, String propertyName, String expression) {
211 boolean moved = false;
212
213
214 String parentPropertyName = StringUtils.substringBeforeLast(propertyName, ".");
215 String propertyNameInParent = StringUtils.substringAfterLast(propertyName, ".");
216
217 Object parentObject = ObjectPropertyUtils.getPropertyValue(object, parentPropertyName);
218 if ((parentObject != null) && ObjectPropertyUtils.isReadableProperty(parentObject,
219 UifPropertyPaths.PROPERTY_EXPRESSIONS) && ((parentObject instanceof Component)
220 || (parentObject instanceof LayoutManager)
221 || (parentObject instanceof BindingInfo))) {
222 Map<String, String> propertyExpressions = ObjectPropertyUtils.getPropertyValue(parentObject,
223 UifPropertyPaths.PROPERTY_EXPRESSIONS);
224 if (propertyExpressions == null) {
225 propertyExpressions = new HashMap<String, String>();
226 }
227
228
229 propertyExpressions.put(propertyNameInParent, expression);
230 ObjectPropertyUtils.setPropertyValue(parentObject, UifPropertyPaths.PROPERTY_EXPRESSIONS,
231 propertyExpressions);
232 moved = true;
233 }
234
235 return moved;
236 }
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256 public static String parseExpression(String exp, List<String> controlNames) {
257
258 exp = exp.trim();
259 if (exp.startsWith("@{")) {
260 exp = StringUtils.removeStart(exp, "@{");
261 if (exp.endsWith("}")) {
262 exp = StringUtils.removeEnd(exp, "}");
263 }
264 }
265
266 exp = StringUtils.replace(exp, "!=", " != ");
267 exp = StringUtils.replace(exp, "==", " == ");
268 exp = StringUtils.replace(exp, ">", " > ");
269 exp = StringUtils.replace(exp, "<", " < ");
270 exp = StringUtils.replace(exp, "<=", " <= ");
271 exp = StringUtils.replace(exp, ">=", " >= ");
272
273 String conditionJs = exp;
274 String stack = "";
275
276 boolean expectingSingleQuote = false;
277 boolean ignoreNext = false;
278 for (int i = 0; i < exp.length(); i++) {
279 char c = exp.charAt(i);
280 if (!expectingSingleQuote && !ignoreNext && (c == '(' || c == ' ' || c == ')')) {
281 evaluateCurrentStack(stack.trim(), controlNames);
282
283 stack = "";
284 continue;
285 } else if (!ignoreNext && c == '\'') {
286 stack = stack + c;
287 expectingSingleQuote = !expectingSingleQuote;
288 } else if (c == '\\') {
289 stack = stack + c;
290 ignoreNext = !ignoreNext;
291 } else {
292 stack = stack + c;
293 ignoreNext = false;
294 }
295 }
296
297 if (StringUtils.isNotEmpty(stack)) {
298 evaluateCurrentStack(stack.trim(), controlNames);
299 }
300
301 conditionJs = conditionJs.replaceAll("\\s(?i:ne)\\s", " != ").replaceAll("\\s(?i:eq)\\s", " == ").replaceAll(
302 "\\s(?i:gt)\\s", " > ").replaceAll("\\s(?i:lt)\\s", " < ").replaceAll("\\s(?i:lte)\\s", " <= ")
303 .replaceAll("\\s(?i:gte)\\s", " >= ").replaceAll("\\s(?i:and)\\s", " && ").replaceAll("\\s(?i:or)\\s",
304 " || ").replaceAll("\\s(?i:not)\\s", " != ").replaceAll("\\s(?i:null)\\s?", " '' ").replaceAll(
305 "\\s?(?i:#empty)\\((.*?)\\)", "isValueEmpty($1)");
306
307 if (conditionJs.contains("matches")) {
308 conditionJs = conditionJs.replaceAll("\\s+(?i:matches)\\s+'.*'", ".match(/" + "$0" + "/) != null ");
309 conditionJs = conditionJs.replaceAll("\\(/\\s+(?i:matches)\\s+'", "(/");
310 conditionJs = conditionJs.replaceAll("'\\s*/\\)", "/)");
311 }
312
313 for (String propertyName : controlNames) {
314 conditionJs = conditionJs.replace(propertyName, "coerceValue(\"" + propertyName + "\")");
315 }
316
317 return conditionJs;
318 }
319
320
321
322
323
324
325
326
327 public static void evaluateCurrentStack(String stack, List<String> controlNames) {
328 if (StringUtils.isNotBlank(stack)) {
329 if (!(stack.equals("==")
330 || stack.equals("!=")
331 || stack.equals(">")
332 || stack.equals("<")
333 || stack.equals(">=")
334 || stack.equals("<=")
335 || stack.equalsIgnoreCase("ne")
336 || stack.equalsIgnoreCase("eq")
337 || stack.equalsIgnoreCase("gt")
338 || stack.equalsIgnoreCase("lt")
339 || stack.equalsIgnoreCase("lte")
340 || stack.equalsIgnoreCase("gte")
341 || stack.equalsIgnoreCase("matches")
342 || stack.equalsIgnoreCase("null")
343 || stack.equalsIgnoreCase("false")
344 || stack.equalsIgnoreCase("true")
345 || stack.equalsIgnoreCase("and")
346 || stack.equalsIgnoreCase("or")
347 || stack.contains("#empty")
348 || stack.startsWith("'")
349 || stack.endsWith("'"))) {
350
351 boolean isNumber = false;
352 if ((StringUtils.isNumeric(stack.substring(0, 1)) || stack.substring(0, 1).equals("-"))) {
353 try {
354 Double.parseDouble(stack);
355 isNumber = true;
356 } catch (NumberFormatException e) {
357 isNumber = false;
358 }
359 }
360
361 if (!(isNumber)) {
362 if (!controlNames.contains(stack)) {
363 controlNames.add(stack);
364 }
365 }
366 }
367 }
368 }
369
370 }