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 (object instanceof Component) {
144 String linePath = getLinePathPrefixValue((Component) object);
145
146 if (StringUtils.isNotEmpty(linePath)) {
147 adjustedExpression = StringUtils.replace(adjustedExpression, UifConstants.LINE_PATH_BIND_ADJUST_PREFIX,
148 linePath + ".");
149 }
150 }
151
152 return adjustedExpression;
153 }
154
155
156
157
158
159
160
161
162 protected static String getLinePathPrefixValue(Component component) {
163 String linePath = "";
164
165 CollectionGroup collectionGroup = (CollectionGroup) (component.getContext().get(
166 UifConstants.ContextVariableNames.COLLECTION_GROUP));
167 if (collectionGroup == null) {
168 return linePath;
169 }
170
171 Object indexObj = component.getContext().get(UifConstants.ContextVariableNames.INDEX);
172 if (indexObj != null) {
173 int index = (Integer) indexObj;
174 boolean addLine = false;
175 Object addLineObj = component.getContext().get(UifConstants.ContextVariableNames.IS_ADD_LINE);
176
177 if (addLineObj != null) {
178 addLine = (Boolean) addLineObj;
179 }
180
181 if (addLine) {
182 linePath = collectionGroup.getAddLineBindingInfo().getBindingPath();
183 } else {
184 linePath = collectionGroup.getBindingInfo().getBindingPath() + "[" + index + "]";
185 }
186 }
187
188 return linePath;
189 }
190
191
192
193
194
195
196
197
198
199 protected static boolean moveNestedPropertyExpression(Object object, String propertyName, String expression) {
200 boolean moved = false;
201
202
203 String parentPropertyName = StringUtils.substringBeforeLast(propertyName, ".");
204 String propertyNameInParent = StringUtils.substringAfterLast(propertyName, ".");
205
206 Object parentObject = ObjectPropertyUtils.getPropertyValue(object, parentPropertyName);
207 if ((parentObject != null) && ObjectPropertyUtils.isReadableProperty(parentObject,
208 UifPropertyPaths.PROPERTY_EXPRESSIONS) && ((parentObject instanceof Component)
209 || (parentObject instanceof LayoutManager)
210 || (parentObject instanceof BindingInfo))) {
211 Map<String, String> propertyExpressions = ObjectPropertyUtils.getPropertyValue(parentObject,
212 UifPropertyPaths.PROPERTY_EXPRESSIONS);
213 if (propertyExpressions == null) {
214 propertyExpressions = new HashMap<String, String>();
215 }
216
217
218 propertyExpressions.put(propertyNameInParent, expression);
219 ObjectPropertyUtils.setPropertyValue(parentObject, UifPropertyPaths.PROPERTY_EXPRESSIONS,
220 propertyExpressions);
221 moved = true;
222 }
223
224 return moved;
225 }
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245 public static String parseExpression(String exp, List<String> controlNames) {
246
247 exp = exp.trim();
248 if (exp.startsWith("@{")) {
249 exp = StringUtils.removeStart(exp, "@{");
250 if (exp.endsWith("}")) {
251 exp = StringUtils.removeEnd(exp, "}");
252 }
253 }
254
255 exp = StringUtils.replace(exp, "!=", " != ");
256 exp = StringUtils.replace(exp, "==", " == ");
257 exp = StringUtils.replace(exp, ">", " > ");
258 exp = StringUtils.replace(exp, "<", " < ");
259 exp = StringUtils.replace(exp, "<=", " <= ");
260 exp = StringUtils.replace(exp, ">=", " >= ");
261
262 String conditionJs = exp;
263 String stack = "";
264
265 boolean expectingSingleQuote = false;
266 boolean ignoreNext = false;
267 for (int i = 0; i < exp.length(); i++) {
268 char c = exp.charAt(i);
269 if (!expectingSingleQuote && !ignoreNext && (c == '(' || c == ' ' || c == ')')) {
270 evaluateCurrentStack(stack.trim(), controlNames);
271
272 stack = "";
273 continue;
274 } else if (!ignoreNext && c == '\'') {
275 stack = stack + c;
276 expectingSingleQuote = !expectingSingleQuote;
277 } else if (c == '\\') {
278 stack = stack + c;
279 ignoreNext = !ignoreNext;
280 } else {
281 stack = stack + c;
282 ignoreNext = false;
283 }
284 }
285
286 if (StringUtils.isNotEmpty(stack)) {
287 evaluateCurrentStack(stack.trim(), controlNames);
288 }
289
290 conditionJs = conditionJs.replaceAll("\\s(?i:ne)\\s", " != ").replaceAll("\\s(?i:eq)\\s", " == ").replaceAll(
291 "\\s(?i:gt)\\s", " > ").replaceAll("\\s(?i:lt)\\s", " < ").replaceAll("\\s(?i:lte)\\s", " <= ")
292 .replaceAll("\\s(?i:gte)\\s", " >= ").replaceAll("\\s(?i:and)\\s", " && ").replaceAll("\\s(?i:or)\\s",
293 " || ").replaceAll("\\s(?i:not)\\s", " != ").replaceAll("\\s(?i:null)\\s?", " '' ").replaceAll(
294 "\\s?(?i:#empty)\\((.*?)\\)", "isValueEmpty($1)");
295
296 if (conditionJs.contains("matches")) {
297 conditionJs = conditionJs.replaceAll("\\s+(?i:matches)\\s+'.*'", ".match(/" + "$0" + "/) != null ");
298 conditionJs = conditionJs.replaceAll("\\(/\\s+(?i:matches)\\s+'", "(/");
299 conditionJs = conditionJs.replaceAll("'\\s*/\\)", "/)");
300 }
301
302 for (String propertyName : controlNames) {
303 conditionJs = conditionJs.replace(propertyName, "coerceValue(\"" + propertyName + "\")");
304 }
305
306 return conditionJs;
307 }
308
309
310
311
312
313
314
315
316 public static void evaluateCurrentStack(String stack, List<String> controlNames) {
317 if (StringUtils.isNotBlank(stack)) {
318 if (!(stack.equals("==")
319 || stack.equals("!=")
320 || stack.equals(">")
321 || stack.equals("<")
322 || stack.equals(">=")
323 || stack.equals("<=")
324 || stack.equalsIgnoreCase("ne")
325 || stack.equalsIgnoreCase("eq")
326 || stack.equalsIgnoreCase("gt")
327 || stack.equalsIgnoreCase("lt")
328 || stack.equalsIgnoreCase("lte")
329 || stack.equalsIgnoreCase("gte")
330 || stack.equalsIgnoreCase("matches")
331 || stack.equalsIgnoreCase("null")
332 || stack.equalsIgnoreCase("false")
333 || stack.equalsIgnoreCase("true")
334 || stack.equalsIgnoreCase("and")
335 || stack.equalsIgnoreCase("or")
336 || stack.contains("#empty")
337 || stack.startsWith("'")
338 || stack.endsWith("'"))) {
339
340 boolean isNumber = false;
341 if ((StringUtils.isNumeric(stack.substring(0, 1)) || stack.substring(0, 1).equals("-"))) {
342 try {
343 Double.parseDouble(stack);
344 isNumber = true;
345 } catch (NumberFormatException e) {
346 isNumber = false;
347 }
348 }
349
350 if (!(isNumber)) {
351 if (!controlNames.contains(stack)) {
352 controlNames.add(stack);
353 }
354 }
355 }
356 }
357 }
358
359 }