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 if (currentMessageComponent == null) {
184 currentMessageComponent = ComponentFactory.getMessage();
185 currentMessageComponent.setMessageText(messagePiece);
186 currentMessageComponent.setGenerateSpan(false);
187 } else {
188 currentMessageComponent.setMessageText(currentMessageComponent.getMessageText() + messagePiece);
189 }
190
191 return currentMessageComponent;
192 }
193
194
195
196
197
198
199
200
201
202
203
204 private static Component processAdditionalProperties(Component component, String[] tagParts) {
205 String componentString = tagParts[0];
206 tagParts = (String[]) ArrayUtils.remove(tagParts, 0);
207
208 for (String part : tagParts) {
209 String[] propertyValue = part.split("=");
210
211 if (propertyValue.length == 2) {
212 String path = propertyValue[0];
213 String value = propertyValue[1].trim();
214 value = StringUtils.removeStart(value, "'");
215 value = StringUtils.removeEnd(value, "'");
216 ObjectPropertyUtils.setPropertyValue(component, path, value);
217 } else {
218 throw new RuntimeException(
219 "Invalid Message structure for component defined as " + componentString + " around " + part);
220 }
221 }
222
223 return component;
224 }
225
226
227
228
229
230
231
232
233 public static String addBlanks(String text) {
234 if (StringUtils.startsWithIgnoreCase(text, " ")) {
235 text = " " + StringUtils.removeStart(text, " ");
236 }
237
238 if (text.endsWith(" ")) {
239 text = StringUtils.removeEnd(text, " ") + " ";
240 }
241
242 return text;
243 }
244
245
246
247
248
249
250
251
252
253
254 private static Message processIdComponentContent(String messagePiece, List<Component> messageComponentStructure,
255 Message currentMessageComponent, View view) {
256
257 String[] parts = messagePiece.trim().trim().split("([ ]+(?=([^']*'[^']*')*[^']*$))");
258 messagePiece = parts[0];
259
260
261
262 if (currentMessageComponent != null && StringUtils.isNotEmpty(currentMessageComponent.getMessageText())) {
263 messageComponentStructure.add(currentMessageComponent);
264 currentMessageComponent = null;
265 }
266
267
268 messagePiece = StringUtils.remove(messagePiece, "'");
269 messagePiece = StringUtils.remove(messagePiece, "\"");
270 Component component = ComponentFactory.getNewComponentInstance(StringUtils.removeStart(messagePiece,
271 KRADConstants.MessageParsing.COMPONENT_BY_ID + "="));
272
273 if (component != null) {
274 component.addStyleClass(KRADConstants.MessageParsing.INLINE_COMP_CLASS);
275
276 if (parts.length > 1) {
277 component = processAdditionalProperties(component, parts);
278 }
279 messageComponentStructure.add(component);
280 }
281
282 return currentMessageComponent;
283 }
284
285
286
287
288
289
290
291
292
293
294
295
296
297 private static Message processIndexComponentContent(String messagePiece, List<Component> componentList,
298 List<Component> messageComponentStructure, Message currentMessageComponent, View view, String messageId) {
299
300 String[] parts = messagePiece.trim().trim().split("([ ]+(?=([^']*'[^']*')*[^']*$))");
301 messagePiece = parts[0];
302
303
304
305 if (currentMessageComponent != null && StringUtils.isNotEmpty(currentMessageComponent.getMessageText())) {
306 messageComponentStructure.add(currentMessageComponent);
307 currentMessageComponent = null;
308 }
309
310
311 int cIndex = Integer.parseInt(messagePiece);
312
313 if (componentList != null && cIndex < componentList.size() && !componentList.isEmpty()) {
314 Component component = componentList.get(cIndex);
315
316 if (component != null) {
317 if (parts.length > 1) {
318 component = processAdditionalProperties(component, parts);
319 }
320
321 component.addStyleClass(KRADConstants.MessageParsing.INLINE_COMP_CLASS);
322 messageComponentStructure.add(component);
323 }
324 } else {
325 throw new RuntimeException("Component with index " + cIndex +
326 " does not exist in inlineComponents of the message component with id " + messageId);
327 }
328
329 return currentMessageComponent;
330 }
331
332
333
334
335
336
337
338
339
340
341 private static Message processColorContent(String messagePiece, Message currentMessageComponent, View view) {
342 if (!StringUtils.startsWithIgnoreCase(messagePiece, "/")) {
343 messagePiece = StringUtils.remove(messagePiece, "'");
344 messagePiece = StringUtils.remove(messagePiece, "\"");
345 messagePiece = "<span style='color: " + StringUtils.removeStart(messagePiece,
346 KRADConstants.MessageParsing.COLOR + "=") + ";'>";
347 } else {
348 messagePiece = "</span>";
349 }
350
351 return concatenateStringMessageContent(currentMessageComponent, messagePiece, view);
352 }
353
354
355
356
357
358
359
360
361
362
363 private static Message processCssClassContent(String messagePiece, Message currentMessageComponent, View view) {
364 if (!StringUtils.startsWithIgnoreCase(messagePiece, "/")) {
365 messagePiece = StringUtils.remove(messagePiece, "'");
366 messagePiece = StringUtils.remove(messagePiece, "\"");
367 messagePiece = "<span class='" + StringUtils.removeStart(messagePiece,
368 KRADConstants.MessageParsing.CSS_CLASSES + "=") + "'>";
369 } else {
370 messagePiece = "</span>";
371 }
372
373 return concatenateStringMessageContent(currentMessageComponent, messagePiece, view);
374 }
375
376
377
378
379
380
381
382
383
384
385 private static Message processLinkContent(String messagePiece, Message currentMessageComponent, View view) {
386 if (!StringUtils.startsWithIgnoreCase(messagePiece, "/")) {
387
388 messagePiece = StringUtils.removeStart(messagePiece, KRADConstants.MessageParsing.LINK + "=");
389 messagePiece = StringUtils.removeStart(messagePiece, "'");
390 messagePiece = StringUtils.removeEnd(messagePiece, "'");
391 messagePiece = StringUtils.removeStart(messagePiece, "\"");
392 messagePiece = StringUtils.removeEnd(messagePiece, "\"");
393
394 messagePiece = "<a href='" + messagePiece + "' target='_blank'>";
395 } else {
396 messagePiece = "</a>";
397 }
398
399 return concatenateStringMessageContent(currentMessageComponent, messagePiece, view);
400 }
401
402
403
404
405
406
407
408
409
410
411
412 private static Message processActionLinkContent(String messagePiece, Message currentMessageComponent, View view) {
413 if (!StringUtils.startsWithIgnoreCase(messagePiece, "/")) {
414 messagePiece = StringUtils.removeStart(messagePiece, KRADConstants.MessageParsing.ACTION_LINK + "=");
415 String[] splitData = messagePiece.split(KRADConstants.MessageParsing.ACTION_DATA + "=");
416
417 String[] params = splitData[0].trim().split("([,]+(?=([^']*'[^']*')*[^']*$))");
418 String methodToCall = ((params.length >= 1) ? params[0] : "");
419 String validate = ((params.length >= 2) ? params[1] : "true");
420 String ajaxSubmit = ((params.length >= 3) ? params[2] : "true");
421 String successCallback = ((params.length >= 4) ? params[3] : "null");
422
423 String submitData = "null";
424
425 if (splitData.length > 1) {
426 submitData = splitData[1].trim();
427 }
428
429 methodToCall = StringUtils.remove(methodToCall, "'");
430 methodToCall = StringUtils.remove(methodToCall, "\"");
431
432 messagePiece = "<a href=\"javascript:void(null)\" onclick=\"submitForm(" +
433 "'" +
434 methodToCall +
435 "'," +
436 submitData +
437 "," +
438 validate +
439 "," +
440 ajaxSubmit +
441 "," +
442 successCallback +
443 "); return false;\">";
444 } else {
445 messagePiece = "</a>";
446 }
447
448 return concatenateStringMessageContent(currentMessageComponent, messagePiece, view);
449 }
450
451
452
453
454
455
456
457
458
459
460 private static Message processHtmlContent(String messagePiece, Message currentMessageComponent, View view) {
461
462 messagePiece = messagePiece.trim();
463
464 if (StringUtils.startsWithAny(messagePiece, KRADConstants.MessageParsing.UNALLOWED_HTML) || StringUtils
465 .endsWithAny(messagePiece, KRADConstants.MessageParsing.UNALLOWED_HTML)) {
466 throw new RuntimeException("The following html is not allowed in Messages: " + Arrays.toString(
467 KRADConstants.MessageParsing.UNALLOWED_HTML));
468 }
469
470 messagePiece = "<" + messagePiece + ">";
471
472 return concatenateStringMessageContent(currentMessageComponent, messagePiece, view);
473 }
474 }