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