1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.rice.krad.util;
17
18 import org.apache.commons.lang.StringEscapeUtils;
19 import org.apache.commons.lang.StringUtils;
20 import org.apache.commons.lang.builder.EqualsBuilder;
21 import org.apache.commons.lang.builder.HashCodeBuilder;
22 import org.apache.commons.lang.builder.ToStringBuilder;
23 import org.springframework.util.AutoPopulatingList;
24
25 import java.io.Serializable;
26 import java.util.ArrayList;
27 import java.util.Collections;
28 import java.util.Iterator;
29 import java.util.LinkedHashMap;
30 import java.util.List;
31 import java.util.Map;
32 import java.util.Set;
33
34
35
36
37
38
39
40
41
42
43
44
45 public class MessageMap implements Serializable {
46 private static final long serialVersionUID = -2328635367656516150L;
47
48 private final List<String> errorPath;
49
50 private final Map<String, List<ErrorMessage>> errorMessages;
51 private final Map<String, List<ErrorMessage>> warningMessages;
52 private final Map<String, List<ErrorMessage>> infoMessages;
53 private final List<GrowlMessage> growlMessages;
54
55 public MessageMap() {
56 errorPath = Collections.synchronizedList(new ArrayList<String>());
57 errorMessages = Collections.synchronizedMap(new LinkedHashMap<String, List<ErrorMessage>>());
58 warningMessages = Collections.synchronizedMap(new LinkedHashMap<String, List<ErrorMessage>>());
59 infoMessages = Collections.synchronizedMap(new LinkedHashMap<String, List<ErrorMessage>>());
60 growlMessages = Collections.synchronizedList(new AutoPopulatingList<GrowlMessage>(GrowlMessage.class));
61 }
62
63 public MessageMap(MessageMap messageMap) {
64 this.errorPath = messageMap.errorPath;
65 this.errorMessages = messageMap.errorMessages;
66 this.warningMessages = messageMap.warningMessages;
67 this.infoMessages = messageMap.infoMessages;
68
69 growlMessages = Collections.synchronizedList(new AutoPopulatingList<GrowlMessage>(GrowlMessage.class));
70 }
71
72 public void merge(MessageMap messageMap) {
73 if (messageMap != null) {
74 if (messageMap.hasErrors()) {
75 merge(messageMap.getErrorMessages(), errorMessages);
76 }
77 if (messageMap.hasInfo()) {
78 merge(messageMap.getInfoMessages(), infoMessages);
79 }
80 if (messageMap.hasWarnings()) {
81 merge(messageMap.getWarningMessages(), warningMessages);
82 }
83 if (messageMap.getGrowlMessages() != null) {
84 growlMessages.addAll(messageMap.getGrowlMessages());
85 }
86 }
87
88 }
89
90
91
92
93
94
95
96
97 public void merge(Map<String, List<ErrorMessage>> messagesFrom,
98 Map<String, List<ErrorMessage>> messagesTo) {
99 for (String key : messagesFrom.keySet()) {
100
101 if (messagesTo.containsKey(key)) {
102
103 List<ErrorMessage> tal = messagesFrom.get(key);
104 List<ErrorMessage> parentList = messagesTo.get(key);
105
106 for (Object o : tal) {
107
108 if (!parentList.contains(o)) {
109 parentList.add((ErrorMessage) o);
110 }
111 }
112
113 } else {
114 messagesTo.put(key, messagesFrom.get(key));
115 }
116
117 }
118 }
119
120 public List<ErrorMessage> putError(String propertyName, String errorKey, String... errorParameters) {
121 ErrorMessage message = new ErrorMessage(errorKey, errorParameters);
122 return putMessageInMap(errorMessages, propertyName, message, true, true);
123 }
124
125 public List<ErrorMessage> putWarning(String propertyName, String messageKey,
126 String... messageParameters) {
127 ErrorMessage message = new ErrorMessage(messageKey, messageParameters);
128 return putMessageInMap(warningMessages, propertyName, message, true, true);
129 }
130
131 public List<ErrorMessage> putInfo(String propertyName, String messageKey,
132 String... messageParameters) {
133 ErrorMessage message = new ErrorMessage(messageKey, messageParameters);
134 return putMessageInMap(infoMessages, propertyName, message, true, true);
135 }
136
137 public List<ErrorMessage> putError(String propertyName, ErrorMessage message) {
138 return putMessageInMap(errorMessages, propertyName, message, true, true);
139 }
140
141 public List<ErrorMessage> putWarning(String propertyName, ErrorMessage message) {
142 return putMessageInMap(warningMessages, propertyName, message, true, true);
143 }
144
145 public List<ErrorMessage> putInfo(String propertyName, ErrorMessage message) {
146 return putMessageInMap(infoMessages, propertyName, message, true, true);
147 }
148
149 public List<ErrorMessage> putErrorWithoutFullErrorPath(String propertyName, String errorKey,
150 String... errorParameters) {
151 ErrorMessage message = new ErrorMessage(errorKey, errorParameters);
152 return putMessageInMap(errorMessages, propertyName, message, false, true);
153 }
154
155 public List<ErrorMessage> putWarningWithoutFullErrorPath(String propertyName, String messageKey,
156 String... messageParameters) {
157 ErrorMessage message = new ErrorMessage(messageKey, messageParameters);
158 return putMessageInMap(warningMessages, propertyName, message, false, true);
159 }
160
161 public List<ErrorMessage> putInfoWithoutFullErrorPath(String propertyName, String messageKey,
162 String... messageParameters) {
163 ErrorMessage message = new ErrorMessage(messageKey, messageParameters);
164 return putMessageInMap(infoMessages, propertyName, message, false, true);
165 }
166
167 public List<ErrorMessage> putErrorWithoutFullErrorPath(String propertyName, ErrorMessage message) {
168 return putMessageInMap(errorMessages, propertyName, message, false, true);
169 }
170
171 public List<ErrorMessage> putWarningWithoutFullErrorPath(String propertyName, ErrorMessage message) {
172 return putMessageInMap(warningMessages, propertyName, message, false, true);
173 }
174
175 public List<ErrorMessage> putInfoWithoutFullErrorPath(String propertyName, ErrorMessage message) {
176 return putMessageInMap(infoMessages, propertyName, message, false, true);
177 }
178
179 public List<ErrorMessage> putErrorForSectionId(String sectionId, String errorKey,
180 String... errorParameters) {
181 return putErrorWithoutFullErrorPath(sectionId, errorKey, errorParameters);
182 }
183
184 public List<ErrorMessage> putWarningForSectionId(String sectionId, String messageKey,
185 String... messageParameters) {
186 return putWarningWithoutFullErrorPath(sectionId, messageKey, messageParameters);
187 }
188
189 public List<ErrorMessage> putInfoForSectionId(String sectionId, String messageKey,
190 String... messageParameters) {
191 return putInfoWithoutFullErrorPath(sectionId, messageKey, messageParameters);
192 }
193
194 public List<ErrorMessage> putErrorForSectionId(String sectionId, ErrorMessage message) {
195 return putErrorWithoutFullErrorPath(sectionId, message);
196 }
197
198 public List<ErrorMessage> putWarningForSectionId(String sectionId, ErrorMessage message) {
199 return putWarningWithoutFullErrorPath(sectionId, message);
200 }
201
202 public List<ErrorMessage> putInfoForSectionId(String sectionId, ErrorMessage message) {
203 return putInfoWithoutFullErrorPath(sectionId, message);
204 }
205
206
207
208
209
210
211
212
213 public void addGrowlMessage(String growlTitle, String messageKey, String... messageParameters) {
214 GrowlMessage growl = new GrowlMessage();
215
216 growl.setTitle(growlTitle);
217 growl.setMessageKey(messageKey);
218 growl.setMessageParameters(messageParameters);
219
220 growlMessages.add(growl);
221 }
222
223
224
225
226
227
228 public void addGrowlMessage(GrowlMessage growl) {
229 growlMessages.add(growl);
230 }
231
232
233
234
235
236
237
238
239
240
241
242
243 protected List<ErrorMessage> putMessageInMap(Map<String, List<ErrorMessage>> messagesMap,
244 String propertyName, ErrorMessage errorMessage, boolean prependFullErrorPath,
245 boolean escapeHtmlMessageParameters) {
246 if (StringUtils.isBlank(propertyName)) {
247 throw new IllegalArgumentException("invalid (blank) propertyName");
248 }
249 if (StringUtils.isBlank(errorMessage.getErrorKey())) {
250 throw new IllegalArgumentException("invalid (blank) errorKey");
251 }
252
253
254 List<ErrorMessage> errorList = null;
255 String propertyKey = getKeyPath(propertyName, prependFullErrorPath);
256 if (messagesMap.containsKey(propertyKey)) {
257 errorList = messagesMap.get(propertyKey);
258 } else {
259 errorList = Collections.synchronizedList(new AutoPopulatingList<ErrorMessage>(ErrorMessage.class));
260 }
261
262 if (escapeHtmlMessageParameters) {
263 if (errorMessage.getMessageParameters() != null) {
264 String[] filteredMessageParameters = new String[errorMessage.getMessageParameters().length];
265 for (int i = 0; i < errorMessage.getMessageParameters().length; i++) {
266 filteredMessageParameters[i] = StringEscapeUtils.escapeHtml(errorMessage.getMessageParameters()[i]);
267 }
268 errorMessage.setMessageParameters(filteredMessageParameters);
269 }
270
271 if (errorMessage.getMessagePrefixParameters() != null) {
272 String[] filteredMessageParameters = new String[errorMessage.getMessagePrefixParameters().length];
273 for (int i = 0; i < errorMessage.getMessagePrefixParameters().length; i++) {
274 filteredMessageParameters[i] = StringEscapeUtils.escapeHtml(
275 errorMessage.getMessagePrefixParameters()[i]);
276 }
277 errorMessage.setMessagePrefixParameters(filteredMessageParameters);
278 }
279
280 if (errorMessage.getMessageSuffixParameters() != null) {
281 String[] filteredMessageParameters = new String[errorMessage.getMessageSuffixParameters().length];
282 for (int i = 0; i < errorMessage.getMessageSuffixParameters().length; i++) {
283 filteredMessageParameters[i] = StringEscapeUtils.escapeHtml(
284 errorMessage.getMessageSuffixParameters()[i]);
285 }
286 errorMessage.setMessageSuffixParameters(filteredMessageParameters);
287 }
288 }
289
290
291 boolean alreadyAdded = false;
292 for (ErrorMessage e : errorList) {
293 if (e.equals(errorMessage)) {
294 alreadyAdded = true;
295 break;
296 }
297 }
298 if (!alreadyAdded) {
299 errorList.add(errorMessage);
300 }
301
302 return messagesMap.put(propertyKey, errorList);
303 }
304
305
306
307
308
309
310
311
312
313
314
315 public boolean replaceError(String propertyName, String targetKey, String replaceKey, String... replaceParameters) {
316 return replaceError(propertyName, targetKey, true, replaceKey, replaceParameters);
317 }
318
319
320
321
322
323
324
325
326
327
328
329
330 public boolean replaceErrorWithoutFullErrorPath(String propertyName, String targetKey, String replaceKey,
331 String... replaceParameters) {
332 return replaceError(propertyName, targetKey, false, replaceKey, replaceParameters);
333 }
334
335
336
337
338
339
340
341
342
343
344
345 private boolean replaceError(String propertyName, String targetKey, boolean withFullErrorPath, String replaceKey,
346 String... replaceParameters) {
347 boolean replaced = false;
348
349 if (StringUtils.isBlank(propertyName)) {
350 throw new IllegalArgumentException("invalid (blank) propertyName");
351 }
352 if (StringUtils.isBlank(targetKey)) {
353 throw new IllegalArgumentException("invalid (blank) targetKey");
354 }
355 if (StringUtils.isBlank(replaceKey)) {
356 throw new IllegalArgumentException("invalid (blank) replaceKey");
357 }
358
359
360 List<ErrorMessage> errorList = null;
361 String propertyKey = getKeyPath(propertyName, withFullErrorPath);
362 if (errorMessages.containsKey(propertyKey)) {
363 errorList = errorMessages.get(propertyKey);
364
365
366 for (int i = 0; i < errorList.size(); ++i) {
367 ErrorMessage em = errorList.get(i);
368
369
370 if (em.getErrorKey().equals(targetKey)) {
371 ErrorMessage rm = new ErrorMessage(replaceKey, replaceParameters);
372 errorList.set(i, rm);
373 replaced = true;
374 }
375 }
376 }
377
378 return replaced;
379 }
380
381
382
383
384
385
386
387
388 public boolean fieldHasMessage(String fieldName, String errorKey) {
389 boolean found = false;
390
391 List<ErrorMessage> fieldMessages = errorMessages.get(fieldName);
392 if (fieldMessages != null) {
393 for (Iterator<ErrorMessage> i = fieldMessages.iterator(); !found && i.hasNext(); ) {
394 ErrorMessage errorMessage = i.next();
395 found = errorMessage.getErrorKey().equals(errorKey);
396 }
397 }
398
399 return found;
400 }
401
402
403
404
405
406
407
408 public int countFieldMessages(String fieldName) {
409 int count = 0;
410
411 List<ErrorMessage> fieldMessages = errorMessages.get(fieldName);
412 if (fieldMessages != null) {
413 count = fieldMessages.size();
414 }
415
416 return count;
417 }
418
419
420
421
422 public boolean containsMessageKey(String messageKey) {
423 ErrorMessage foundMessage = null;
424
425 if (!hasNoErrors()) {
426 for (Iterator<Map.Entry<String, List<ErrorMessage>>> i =
427 getAllPropertiesAndErrors().iterator(); (foundMessage == null) && i.hasNext(); ) {
428 Map.Entry<String, List<ErrorMessage>> e = i.next();
429 List<ErrorMessage> entryErrorList = e.getValue();
430 for (Iterator<ErrorMessage> j = entryErrorList.iterator(); j.hasNext(); ) {
431 ErrorMessage em = j.next();
432 if (messageKey.equals(em.getErrorKey())) {
433 foundMessage = em;
434 }
435 }
436 }
437 }
438
439 return (foundMessage != null);
440 }
441
442 private int getMessageCount(Map<String, List<ErrorMessage>> messageMap) {
443 int messageCount = 0;
444 for (Iterator<String> iter = messageMap.keySet().iterator(); iter.hasNext(); ) {
445 String errorKey = iter.next();
446 List<ErrorMessage> errors = messageMap.get(errorKey);
447 messageCount += errors.size();
448 }
449
450 return messageCount;
451 }
452
453
454
455
456
457
458 public int getErrorCount() {
459 return getMessageCount(errorMessages);
460 }
461
462
463
464
465
466
467 public int getWarningCount() {
468 return getMessageCount(warningMessages);
469 }
470
471
472
473
474
475
476 public int getInfoCount() {
477 return getMessageCount(infoMessages);
478 }
479
480
481
482
483
484 public List<ErrorMessage> getMessages(String path) {
485 return errorMessages.get(path);
486 }
487
488
489
490
491
492
493 public void addToErrorPath(String parentName) {
494 errorPath.add(parentName);
495 }
496
497
498
499
500
501
502 public List<String> getErrorPath() {
503 return errorPath;
504 }
505
506
507
508
509
510
511
512 public boolean removeFromErrorPath(String parentName) {
513 return errorPath.remove(parentName);
514 }
515
516
517
518
519 public void clearErrorPath() {
520 errorPath.clear();
521 }
522
523
524
525
526
527
528
529
530
531
532 public String getKeyPath(String propertyName, boolean prependFullErrorPath) {
533 String keyPath = "";
534
535 if (KRADConstants.GLOBAL_ERRORS.equals(propertyName)) {
536 return KRADConstants.GLOBAL_ERRORS;
537 }
538
539 if (!errorPath.isEmpty() && prependFullErrorPath) {
540 keyPath = StringUtils.join(errorPath.iterator(), ".");
541 keyPath += (keyPath != null && keyPath.endsWith(".")) ? propertyName : "." + propertyName;
542 } else {
543 keyPath = propertyName;
544 }
545
546 return keyPath;
547 }
548
549
550
551
552 public List<String> getPropertiesWithErrors() {
553 List<String> properties = new ArrayList<String>();
554
555 for (Iterator<String> iter = errorMessages.keySet().iterator(); iter.hasNext(); ) {
556 properties.add(iter.next());
557 }
558
559 return properties;
560 }
561
562
563
564
565 public List<String> getPropertiesWithWarnings() {
566 List<String> properties = new ArrayList<String>(warningMessages.keySet());
567 return properties;
568 }
569
570
571
572
573 public List<String> getPropertiesWithInfo() {
574 List<String> properties = new ArrayList<String>(infoMessages.keySet());
575 return properties;
576 }
577
578 public void clearErrorMessages() {
579 errorMessages.clear();
580 }
581
582 public boolean doesPropertyHaveError(String key) {
583 return errorMessages.containsKey(key);
584 }
585
586
587
588
589 public boolean containsKeyMatchingPattern(String pattern) {
590 List<String> simplePatterns = new ArrayList<String>();
591 List<String> wildcardPatterns = new ArrayList<String>();
592 String[] patterns = pattern.split(",");
593 for (int i = 0; i < patterns.length; i++) {
594 String s = patterns[i];
595 if (s.endsWith("*")) {
596 wildcardPatterns.add(s.substring(0, s.length() - 1));
597 } else {
598 simplePatterns.add(s);
599 }
600 }
601 for (Iterator<String> keys = errorMessages.keySet().iterator(); keys.hasNext(); ) {
602 String key = keys.next();
603 if (simplePatterns.contains(key)) {
604 return true;
605 }
606 for (Iterator<String> wildcardIterator = wildcardPatterns.iterator(); wildcardIterator.hasNext(); ) {
607 String wildcard = wildcardIterator.next();
608 if (key.startsWith(wildcard)) {
609 return true;
610 }
611 }
612 }
613 return false;
614 }
615
616 public Set<Map.Entry<String, List<ErrorMessage>>> getAllPropertiesAndErrors() {
617 return errorMessages.entrySet();
618 }
619
620 public List<ErrorMessage> getErrorMessagesForProperty(String propertyName) {
621 return errorMessages.get(propertyName);
622 }
623
624 public List<ErrorMessage> getWarningMessagesForProperty(String propertyName) {
625 return warningMessages.get(propertyName);
626 }
627
628 public List<ErrorMessage> getInfoMessagesForProperty(String propertyName) {
629 return infoMessages.get(propertyName);
630 }
631
632
633
634
635
636
637
638
639
640
641
642
643 public List<List<ErrorMessage>> getErrorMessagesForProperty(String propertyName,
644 boolean allowWildcard) {
645 List<List<ErrorMessage>> foundMessages = new ArrayList<List<ErrorMessage>>();
646 if (allowWildcard) {
647 boolean wildcard = false;
648 if (propertyName.endsWith("*")) {
649 wildcard = true;
650 propertyName = propertyName.substring(0, propertyName.length() - 1);
651 }
652 for (Iterator<String> keys = errorMessages.keySet().iterator(); keys.hasNext(); ) {
653 String key = keys.next();
654 if (!wildcard && propertyName.equals(key)) {
655 foundMessages.add(errorMessages.get(key));
656 break;
657 } else if (wildcard && key.startsWith(propertyName)) {
658 foundMessages.add(errorMessages.get(key));
659 }
660 }
661 } else {
662 foundMessages.add(getErrorMessagesForProperty(propertyName));
663 }
664
665 return foundMessages;
666 }
667
668
669
670
671
672
673
674
675
676
677
678
679 public List<List<ErrorMessage>> getWarningMessagesForProperty(String propertyName,
680 boolean allowWildcard) {
681 List<List<ErrorMessage>> foundMessages = new ArrayList<List<ErrorMessage>>();
682 if (allowWildcard) {
683 boolean wildcard = false;
684 if (propertyName.endsWith("*")) {
685 wildcard = true;
686 propertyName = propertyName.substring(0, propertyName.length() - 1);
687 }
688 for (Iterator<String> keys = warningMessages.keySet().iterator(); keys.hasNext(); ) {
689 String key = keys.next();
690 if (!wildcard && propertyName.equals(key)) {
691 foundMessages.add(warningMessages.get(key));
692 break;
693 } else if (wildcard && key.startsWith(propertyName)) {
694 foundMessages.add(warningMessages.get(key));
695 }
696 }
697 } else {
698 foundMessages.add(getWarningMessagesForProperty(propertyName));
699 }
700
701 return foundMessages;
702 }
703
704
705
706
707
708
709
710
711
712
713
714
715 public List<List<ErrorMessage>> getInfoMessagesForProperty(String propertyName,
716 boolean allowWildcard) {
717 List<List<ErrorMessage>> foundMessages = new ArrayList<List<ErrorMessage>>();
718 if (allowWildcard) {
719 boolean wildcard = false;
720 if (propertyName.endsWith("*")) {
721 wildcard = true;
722 propertyName = propertyName.substring(0, propertyName.length() - 1);
723 }
724 for (Iterator<String> keys = infoMessages.keySet().iterator(); keys.hasNext(); ) {
725 String key = keys.next();
726 if (!wildcard && propertyName.equals(key)) {
727 foundMessages.add(infoMessages.get(key));
728 break;
729 } else if (wildcard && key.startsWith(propertyName)) {
730 foundMessages.add(infoMessages.get(key));
731 }
732 }
733 } else {
734 foundMessages.add(getInfoMessagesForProperty(propertyName));
735 }
736
737 return foundMessages;
738 }
739
740 public boolean hasErrors() {
741 return !errorMessages.isEmpty();
742 }
743
744 public boolean hasNoErrors() {
745 return errorMessages.isEmpty();
746 }
747
748 public boolean hasWarnings() {
749 return !warningMessages.isEmpty();
750 }
751
752 public boolean hasNoWarnings() {
753 return warningMessages.isEmpty();
754 }
755
756 public boolean hasInfo() {
757 return !infoMessages.isEmpty();
758 }
759
760 public boolean hasNoInfo() {
761 return infoMessages.isEmpty();
762 }
763
764 public boolean hasMessages() {
765 if (!errorMessages.isEmpty() || !warningMessages.isEmpty() || !infoMessages.isEmpty()) {
766 return true;
767 }
768 return false;
769 }
770
771 public boolean hasNoMessages() {
772 if (errorMessages.isEmpty() && warningMessages.isEmpty() && infoMessages.isEmpty()) {
773 return true;
774 }
775 return false;
776 }
777
778 public Set<String> getAllPropertiesWithErrors() {
779 return errorMessages.keySet();
780 }
781
782 public Set<String> getAllPropertiesWithWarnings() {
783 return warningMessages.keySet();
784 }
785
786 public Set<String> getAllPropertiesWithInfo() {
787 return infoMessages.keySet();
788 }
789
790 public List<ErrorMessage> removeAllErrorMessagesForProperty(String property) {
791 return errorMessages.remove(property);
792 }
793
794 public List<ErrorMessage> removeAllWarningMessagesForProperty(String property) {
795 return warningMessages.remove(property);
796 }
797
798 public List<ErrorMessage> removeAllInfoMessagesForProperty(String property) {
799 return infoMessages.remove(property);
800 }
801
802 public int getNumberOfPropertiesWithErrors() {
803 return errorMessages.size();
804 }
805
806 public Map<String, List<ErrorMessage>> getErrorMessages() {
807 return this.errorMessages;
808 }
809
810 public Map<String, List<ErrorMessage>> getWarningMessages() {
811 return this.warningMessages;
812 }
813
814 public Map<String, List<ErrorMessage>> getInfoMessages() {
815 return this.infoMessages;
816 }
817
818
819
820
821
822
823
824 public List<GrowlMessage> getGrowlMessages() {
825 return this.growlMessages;
826 }
827
828 @Override
829 public boolean equals(Object o) {
830 return EqualsBuilder.reflectionEquals(this, o);
831 }
832
833 @Override
834 public int hashCode() {
835 return HashCodeBuilder.reflectionHashCode(this);
836 }
837
838 @Override
839 public String toString() {
840 return ToStringBuilder.reflectionToString(this);
841 }
842 }