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