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.ArrayUtils;
19 import org.apache.commons.lang.StringUtils;
20 import org.kuali.rice.krad.uif.component.Component;
21 import org.kuali.rice.krad.uif.element.Message;
22 import org.kuali.rice.krad.uif.lifecycle.ViewLifecycle;
23 import org.kuali.rice.krad.uif.lifecycle.ViewPostMetadata;
24 import org.kuali.rice.krad.uif.view.View;
25 import org.kuali.rice.krad.util.KRADConstants;
26
27 import java.util.ArrayList;
28 import java.util.Arrays;
29 import java.util.List;
30
31
32
33
34
35
36 public class MessageStructureUtils {
37
38
39
40
41
42
43
44
45
46
47 public static String translateStringMessage(String messageText) {
48 if (!StringUtils.isEmpty(messageText)) {
49 List<Component> components = MessageStructureUtils.parseMessage(null, messageText, null, null, false);
50
51 if (!components.isEmpty()) {
52 Component message = components.get(0);
53
54 if (message instanceof Message) {
55 messageText = ((Message) message).getMessageText();
56 }
57 }
58 }
59
60 return messageText;
61 }
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106 public static List<Component> parseMessage(String messageId, String messageText, List<Component> componentList,
107 View view, boolean parseComponents) {
108 messageText = messageText.replace("\\" + KRADConstants.MessageParsing.LEFT_TOKEN,
109 KRADConstants.MessageParsing.LEFT_BRACKET);
110 messageText = messageText.replace("\\" + KRADConstants.MessageParsing.RIGHT_TOKEN,
111 KRADConstants.MessageParsing.RIGHT_BRACKET);
112 messageText = messageText.replace(KRADConstants.MessageParsing.RIGHT_TOKEN,
113 KRADConstants.MessageParsing.RIGHT_TOKEN_PLACEHOLDER);
114 String[] messagePieces = messageText.split("[\\" + KRADConstants.MessageParsing.LEFT_TOKEN +
115 "|\\" + KRADConstants.MessageParsing.RIGHT_TOKEN + "]");
116
117 List<Component> messageComponentStructure = new ArrayList<Component>();
118
119
120
121 Message currentMessageComponent = null;
122
123 for (String messagePiece : messagePieces) {
124 if (messagePiece.endsWith(KRADConstants.MessageParsing.RIGHT_TOKEN_MARKER)) {
125 messagePiece = StringUtils.removeEnd(messagePiece, KRADConstants.MessageParsing.RIGHT_TOKEN_MARKER);
126
127 if (StringUtils.startsWithIgnoreCase(messagePiece, KRADConstants.MessageParsing.COMPONENT_BY_ID + "=")
128 && parseComponents) {
129
130 currentMessageComponent = processIdComponentContent(messagePiece, messageComponentStructure,
131 currentMessageComponent, view);
132 } else if (messagePiece.matches("^[0-9]+( .+=.+)*$") && parseComponents) {
133
134 currentMessageComponent = processIndexComponentContent(messagePiece, componentList,
135 messageComponentStructure, currentMessageComponent, view, messageId);
136 } else if (StringUtils.startsWithIgnoreCase(messagePiece, KRADConstants.MessageParsing.COLOR + "=")
137 || StringUtils.startsWithIgnoreCase(messagePiece, "/" + KRADConstants.MessageParsing.COLOR)) {
138
139 currentMessageComponent = processColorContent(messagePiece, currentMessageComponent, view);
140 } else if (StringUtils.startsWithIgnoreCase(messagePiece,
141 KRADConstants.MessageParsing.CSS_CLASSES + "=") || StringUtils.startsWithIgnoreCase(
142 messagePiece, "/" + KRADConstants.MessageParsing.CSS_CLASSES)) {
143
144 currentMessageComponent = processCssClassContent(messagePiece, currentMessageComponent, view);
145 } else if (StringUtils.startsWithIgnoreCase(messagePiece, KRADConstants.MessageParsing.LINK + "=")
146 || StringUtils.startsWithIgnoreCase(messagePiece, "/" + KRADConstants.MessageParsing.LINK)) {
147
148 currentMessageComponent = processLinkContent(messagePiece, currentMessageComponent, view);
149 } else if (StringUtils.startsWithIgnoreCase(messagePiece,
150 KRADConstants.MessageParsing.ACTION_LINK + "=") || StringUtils.startsWithIgnoreCase(
151 messagePiece, "/" + KRADConstants.MessageParsing.ACTION_LINK)) {
152
153 currentMessageComponent = processActionLinkContent(messagePiece, currentMessageComponent, view);
154 } else if (messagePiece.equals("")) {
155
156 } else {
157
158 currentMessageComponent = processHtmlContent(messagePiece, currentMessageComponent, view);
159 }
160 } else {
161
162 messagePiece = addBlanks(messagePiece);
163 currentMessageComponent = concatenateStringMessageContent(currentMessageComponent, messagePiece, view);
164 }
165 }
166
167 if (currentMessageComponent != null && StringUtils.isNotEmpty(currentMessageComponent.getMessageText())) {
168 messageComponentStructure.add(currentMessageComponent);
169 currentMessageComponent = null;
170 }
171
172 return messageComponentStructure;
173 }
174
175
176
177
178
179
180
181
182
183
184 private static Message concatenateStringMessageContent(Message currentMessageComponent, String messagePiece,
185 View view) {
186 if (currentMessageComponent == null) {
187 currentMessageComponent = ComponentFactory.getMessage();
188 currentMessageComponent.setMessageText(messagePiece);
189 currentMessageComponent.setRenderWrapperTag(false);
190 } else {
191 currentMessageComponent.setMessageText(currentMessageComponent.getMessageText() + messagePiece);
192 }
193
194 return currentMessageComponent;
195 }
196
197
198
199
200
201
202
203
204
205
206
207 private static Component processAdditionalProperties(Component component, String[] tagParts) {
208 String componentString = tagParts[0];
209 tagParts = (String[]) ArrayUtils.remove(tagParts, 0);
210
211 for (String part : tagParts) {
212 String[] propertyValue = part.split("=");
213
214 if (propertyValue.length == 2) {
215 String path = propertyValue[0];
216 String value = propertyValue[1].trim();
217 value = StringUtils.removeStart(value, "'");
218 value = StringUtils.removeEnd(value, "'");
219 ObjectPropertyUtils.setPropertyValue(component, path, value);
220 } else {
221 throw new RuntimeException(
222 "Invalid Message structure for component defined as " + componentString + " around " + part);
223 }
224 }
225
226 return component;
227 }
228
229
230
231
232
233
234
235
236 public static String addBlanks(String text) {
237 if (StringUtils.startsWithIgnoreCase(text, " ")) {
238 text = " " + StringUtils.removeStart(text, " ");
239 }
240
241 if (text.endsWith(" ")) {
242 text = StringUtils.removeEnd(text, " ") + " ";
243 }
244
245 return text;
246 }
247
248
249
250
251
252
253
254
255
256
257 private static Message processIdComponentContent(String messagePiece, List<Component> messageComponentStructure,
258 Message currentMessageComponent, View view) {
259
260 String[] parts = messagePiece.trim().trim().split("([ ]+(?=([^']*'[^']*')*[^']*$))");
261 messagePiece = parts[0];
262
263
264
265 if (currentMessageComponent != null && StringUtils.isNotEmpty(currentMessageComponent.getMessageText())) {
266 messageComponentStructure.add(currentMessageComponent);
267 currentMessageComponent = null;
268 }
269
270
271 messagePiece = StringUtils.remove(messagePiece, "'");
272 messagePiece = StringUtils.remove(messagePiece, "\"");
273 Component component = ComponentFactory.getNewComponentInstance(StringUtils.removeStart(messagePiece,
274 KRADConstants.MessageParsing.COMPONENT_BY_ID + "="));
275
276 if (component != null) {
277 component.addStyleClass(KRADConstants.MessageParsing.INLINE_COMP_CLASS);
278
279 if (parts.length > 1) {
280 component = processAdditionalProperties(component, parts);
281 }
282 messageComponentStructure.add(component);
283 }
284
285 return currentMessageComponent;
286 }
287
288
289
290
291
292
293
294
295
296
297
298
299
300 private static Message processIndexComponentContent(String messagePiece, List<Component> componentList,
301 List<Component> messageComponentStructure, Message currentMessageComponent, View view, String messageId) {
302
303 String[] parts = messagePiece.trim().trim().split("([ ]+(?=([^']*'[^']*')*[^']*$))");
304 messagePiece = parts[0];
305
306
307
308 if (currentMessageComponent != null && StringUtils.isNotEmpty(currentMessageComponent.getMessageText())) {
309 messageComponentStructure.add(currentMessageComponent);
310 currentMessageComponent = null;
311 }
312
313
314 int cIndex = Integer.parseInt(messagePiece);
315
316 if (componentList != null && cIndex < componentList.size() && !componentList.isEmpty()) {
317 Component component = componentList.get(cIndex);
318
319 if (component != null) {
320 if (parts.length > 1) {
321 component = processAdditionalProperties(component, parts);
322 }
323
324 component.addStyleClass(KRADConstants.MessageParsing.INLINE_COMP_CLASS);
325 messageComponentStructure.add(component);
326 }
327 } else {
328 throw new RuntimeException("Component with index " + cIndex +
329 " does not exist in inlineComponents of the message component with id " + messageId);
330 }
331
332 return currentMessageComponent;
333 }
334
335
336
337
338
339
340
341
342
343
344 private static Message processColorContent(String messagePiece, Message currentMessageComponent, View view) {
345 if (!StringUtils.startsWithIgnoreCase(messagePiece, "/")) {
346 messagePiece = StringUtils.remove(messagePiece, "'");
347 messagePiece = StringUtils.remove(messagePiece, "\"");
348 messagePiece = "<span style='color: " + StringUtils.removeStart(messagePiece,
349 KRADConstants.MessageParsing.COLOR + "=") + ";'>";
350 } else {
351 messagePiece = "</span>";
352 }
353
354 return concatenateStringMessageContent(currentMessageComponent, messagePiece, view);
355 }
356
357
358
359
360
361
362
363
364
365
366 private static Message processCssClassContent(String messagePiece, Message currentMessageComponent, View view) {
367 if (!StringUtils.startsWithIgnoreCase(messagePiece, "/")) {
368 messagePiece = StringUtils.remove(messagePiece, "'");
369 messagePiece = StringUtils.remove(messagePiece, "\"");
370 messagePiece = "<span class='" + StringUtils.removeStart(messagePiece,
371 KRADConstants.MessageParsing.CSS_CLASSES + "=") + "'>";
372 } else {
373 messagePiece = "</span>";
374 }
375
376 return concatenateStringMessageContent(currentMessageComponent, messagePiece, view);
377 }
378
379
380
381
382
383
384
385
386
387
388 private static Message processLinkContent(String messagePiece, Message currentMessageComponent, View view) {
389 if (!StringUtils.startsWithIgnoreCase(messagePiece, "/")) {
390
391 messagePiece = StringUtils.removeStart(messagePiece, KRADConstants.MessageParsing.LINK + "=");
392 messagePiece = StringUtils.removeStart(messagePiece, "'");
393 messagePiece = StringUtils.removeEnd(messagePiece, "'");
394 messagePiece = StringUtils.removeStart(messagePiece, "\"");
395 messagePiece = StringUtils.removeEnd(messagePiece, "\"");
396
397 messagePiece = "<a href='" + messagePiece + "' target='_blank'>";
398 } else {
399 messagePiece = "</a>";
400 }
401
402 return concatenateStringMessageContent(currentMessageComponent, messagePiece, view);
403 }
404
405
406
407
408
409
410
411
412
413
414
415 private static Message processActionLinkContent(String messagePiece, Message currentMessageComponent, View view) {
416 if (!StringUtils.startsWithIgnoreCase(messagePiece, "/")) {
417 messagePiece = StringUtils.removeStart(messagePiece, KRADConstants.MessageParsing.ACTION_LINK + "=");
418 String[] splitData = messagePiece.split(KRADConstants.MessageParsing.ACTION_DATA + "=");
419
420 String[] params = splitData[0].trim().split("([,]+(?=([^']*'[^']*')*[^']*$))");
421 String methodToCall = ((params.length >= 1) ? params[0] : "");
422 String validate = ((params.length >= 2) ? params[1] : "true");
423 String ajaxSubmit = ((params.length >= 3) ? params[2] : "true");
424 String successCallback = ((params.length >= 4) ? params[3] : "null");
425
426 String submitData = "null";
427
428 if (splitData.length > 1) {
429 submitData = splitData[1].trim();
430 }
431
432 methodToCall = StringUtils.remove(methodToCall, "'");
433 methodToCall = StringUtils.remove(methodToCall, "\"");
434
435 messagePiece = "<a href=\"javascript:void(null)\" onclick=\"submitForm(" +
436 "'" +
437 methodToCall +
438 "'," +
439 submitData +
440 "," +
441 validate +
442 "," +
443 ajaxSubmit +
444 "," +
445 successCallback +
446 "); return false;\">";
447
448 ViewPostMetadata viewPostMetadata = ViewLifecycle.getViewPostMetadata();
449 if (viewPostMetadata != null) {
450 viewPostMetadata.addAccessibleMethodToCall(methodToCall);
451 viewPostMetadata.addAvailableMethodToCall(methodToCall);
452 }
453 } else {
454 messagePiece = "</a>";
455 }
456
457 return concatenateStringMessageContent(currentMessageComponent, messagePiece, view);
458 }
459
460
461
462
463
464
465
466
467
468
469 private static Message processHtmlContent(String messagePiece, Message currentMessageComponent, View view) {
470
471 messagePiece = messagePiece.trim();
472
473 if (StringUtils.startsWithAny(messagePiece, KRADConstants.MessageParsing.UNALLOWED_HTML) || StringUtils
474 .endsWithAny(messagePiece, KRADConstants.MessageParsing.UNALLOWED_HTML)) {
475 throw new RuntimeException("The following html is not allowed in Messages: " + Arrays.toString(
476 KRADConstants.MessageParsing.UNALLOWED_HTML));
477 }
478
479 messagePiece = "<" + messagePiece + ">";
480
481 return concatenateStringMessageContent(currentMessageComponent, messagePiece, view);
482 }
483 }