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