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