Coverage Report - org.kuali.rice.krad.util.MessageMap
 
Classes in this File Line Coverage Branch Coverage Complexity
MessageMap
0%
0/239
0%
0/148
2.25
 
 1  
 /*
 2  
  * Copyright 2005-2009 The Kuali Foundation
 3  
  *
 4  
  * Licensed under the Educational Community License, Version 2.0 (the "License");
 5  
  * you may not use this file except in compliance with the License.
 6  
  * You may obtain a copy of the License at
 7  
  *
 8  
  * http://www.opensource.org/licenses/ecl2.php
 9  
  *
 10  
  * Unless required by applicable law or agreed to in writing, software
 11  
  * distributed under the License is distributed on an "AS IS" BASIS,
 12  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 13  
  * See the License for the specific language governing permissions and
 14  
  * limitations under the License.
 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.*;
 28  
 
 29  
 
 30  
 /**
 31  
  * Holds errors due to validation. Keys of map represent property paths, and value is a AutoPopulatingList that contains resource string
 32  
  * keys (to retrieve the error message).
 33  
  *
 34  
  * Note, prior to rice 0.9.4, this class implemented {@link java.util.Map}.  The implements has been removed as of rice 0.9.4
 35  
  */
 36  
 public class MessageMap implements Serializable {
 37  
         
 38  
     private static final long serialVersionUID = -2328635367656516150L;
 39  
     
 40  0
     private List<String> errorPath = new ArrayList<String>();
 41  0
     private Map<String, AutoPopulatingList<ErrorMessage>> errorMessages = new LinkedHashMap<String, AutoPopulatingList<ErrorMessage>>();
 42  0
     private Map<String, AutoPopulatingList<ErrorMessage>> warningMessages = new LinkedHashMap<String, AutoPopulatingList<ErrorMessage>>();
 43  0
     private Map<String, AutoPopulatingList<ErrorMessage>> infoMessages = new LinkedHashMap<String, AutoPopulatingList<ErrorMessage>>();
 44  
 
 45  0
     public MessageMap() {}
 46  
 
 47  0
     public MessageMap(MessageMap messageMap) {
 48  0
             this.errorPath = messageMap.errorPath;
 49  0
             this.errorMessages = messageMap.errorMessages;
 50  0
             this.warningMessages = messageMap.warningMessages;
 51  0
             this.infoMessages = messageMap.infoMessages;
 52  0
     }
 53  
 
 54  
 
 55  
     public void merge(MessageMap messageMap){
 56  0
             if(messageMap != null){
 57  0
                     if(messageMap.hasErrors()){
 58  0
                             merge(messageMap.getErrorMessages(), errorMessages);
 59  
                     }
 60  0
                     if(messageMap.hasInfo()){
 61  0
                             merge(messageMap.getInfoMessages(), infoMessages);
 62  
                     }
 63  0
                     if(messageMap.hasWarnings()){
 64  0
                             merge(messageMap.getWarningMessages(), warningMessages);
 65  
                     }
 66  
 
 67  
             }
 68  
 
 69  0
     }
 70  
 
 71  
     /**
 72  
      *
 73  
      * This method takes one message map and merges it into another.  Makes sure there are no duplicates.
 74  
      *
 75  
      * @param messagesFrom
 76  
      * @param messagesTo
 77  
      */
 78  
     protected void merge(Map<String, AutoPopulatingList<ErrorMessage>> messagesFrom, Map<String, AutoPopulatingList<ErrorMessage>> messagesTo){
 79  0
             for(String key : messagesFrom.keySet()){
 80  
 
 81  0
                     if(messagesTo.containsKey(key)){
 82  
                             // now we need to merge the messages
 83  0
                             AutoPopulatingList<ErrorMessage> tal = messagesFrom.get(key);
 84  0
                             AutoPopulatingList<ErrorMessage> parentList = messagesTo.get(key);
 85  
 
 86  0
                             for(Object o :tal){
 87  
 
 88  0
                                      if ( !parentList.contains( o ) ) {
 89  0
                                              parentList.add((ErrorMessage)o);
 90  
                                  }
 91  
                             }
 92  
 
 93  0
                     }else{
 94  0
                             messagesTo.put(key, messagesFrom.get(key));
 95  
                     }
 96  
 
 97  
             }
 98  
 
 99  0
     }
 100  
     /**
 101  
      * Adds an error to the map under the given propertyName and adds an array of message parameters. This will fully prepend the
 102  
      * error key with any value in the errorPath list. This should be used when you do not want to add the error with the prepend
 103  
      * pre-built error path.
 104  
      *
 105  
      * @param propertyName name of the property to add error under
 106  
      * @param errorKey resource key used to retrieve the error text from the error message resource bundle
 107  
      * @param errorParameters zero or more string parameters for the displayed error message
 108  
      * @return AutoPopulatingList
 109  
      */
 110  
     public AutoPopulatingList<ErrorMessage> putError(String propertyName, String errorKey, String... errorParameters) {
 111  0
         return putMessageInMap(errorMessages, propertyName, errorKey, true, true, errorParameters);
 112  
     }
 113  
 
 114  
     public AutoPopulatingList<ErrorMessage> putWarning(String propertyName, String messageKey, String... messageParameters) {
 115  0
         return putMessageInMap(warningMessages, propertyName, messageKey, true, true, messageParameters);
 116  
     }
 117  
 
 118  
     public AutoPopulatingList<ErrorMessage> putInfo(String propertyName, String messageKey, String... messageParameters) {
 119  0
         return putMessageInMap(infoMessages, propertyName, messageKey, true, true, messageParameters);
 120  
     }
 121  
 
 122  
     /**
 123  
      * Adds an error to the map under the given propertyName and adds an array of message parameters. This will fully prepend the
 124  
      * error key with any value in the errorPath list.
 125  
      *
 126  
      * @param propertyName name of the property to add error under
 127  
      * @param errorKey resource key used to retrieve the error text from the error message resource bundle
 128  
      * @param errorParameters zero or more string parameters for the displayed error message
 129  
      * @return AutoPopulatingList
 130  
      */
 131  
     public AutoPopulatingList<ErrorMessage> putErrorWithoutFullErrorPath(String propertyName, String errorKey, String... errorParameters) {
 132  0
         return putMessageInMap(errorMessages, propertyName, errorKey, false, true, errorParameters);
 133  
     }
 134  
 
 135  
     public AutoPopulatingList<ErrorMessage> putWarningWithoutFullErrorPath(String propertyName, String messageKey, String... messageParameters) {
 136  0
         return putMessageInMap(warningMessages, propertyName, messageKey, false, true, messageParameters);
 137  
     }
 138  
 
 139  
     public AutoPopulatingList<ErrorMessage> putInfoWithoutFullErrorPath(String propertyName, String messageKey, String... messageParameters) {
 140  0
         return putMessageInMap(infoMessages, propertyName, messageKey, false, true, messageParameters);
 141  
     }
 142  
 
 143  
     /**
 144  
      * Adds an error related to a particular section identified by its section ID.  For maintenance documents, the section ID is identified
 145  
      * by calling {@link org.kuali.rice.kns.datadictionary.MaintainableSectionDefinition#getId()}
 146  
      *
 147  
      * @param sectionId
 148  
      * @param errorKey
 149  
      * @param errorParameters
 150  
      * @return
 151  
      */
 152  
     public AutoPopulatingList<ErrorMessage> putErrorForSectionId(String sectionId, String errorKey, String... errorParameters) {
 153  0
             return putErrorWithoutFullErrorPath(sectionId, errorKey, errorParameters);
 154  
     }
 155  
 
 156  
     public AutoPopulatingList<ErrorMessage> putWarningForSectionId(String sectionId, String messageKey, String... messageParameters) {
 157  0
             return putWarningWithoutFullErrorPath(sectionId, messageKey, messageParameters);
 158  
     }
 159  
 
 160  
     public AutoPopulatingList<ErrorMessage> putInfoForSectionId(String sectionId, String messageKey, String... messageParameters) {
 161  0
             return putInfoWithoutFullErrorPath(sectionId, messageKey, messageParameters);
 162  
     }
 163  
 
 164  
     /**
 165  
      * adds an error to the map under the given propertyName and adds an array of message parameters.
 166  
      *
 167  
      * @param propertyName name of the property to add error under
 168  
      * @param messageKey resource key used to retrieve the error text from the error message resource bundle
 169  
      * @param withFullErrorPath true if you want the whole parent error path appended, false otherwise
 170  
      * @param escapeHtmlMessageParameters whether to escape HTML characters in the message parameters, provides protection against XSS attacks
 171  
      * @param messageParameters zero or more string parameters for the displayed error message
 172  
      * @return TypeArrayList
 173  
      */
 174  
     private AutoPopulatingList<ErrorMessage> putMessageInMap(Map<String, AutoPopulatingList<ErrorMessage>> messagesMap, String propertyName, String messageKey, boolean withFullErrorPath, boolean escapeHtmlMessageParameters, String... messageParameters) {
 175  0
         if (StringUtils.isBlank(propertyName)) {
 176  0
             throw new IllegalArgumentException("invalid (blank) propertyName");
 177  
         }
 178  0
         if (StringUtils.isBlank(messageKey)) {
 179  0
             throw new IllegalArgumentException("invalid (blank) errorKey");
 180  
         }
 181  
 
 182  
         // check if we have previous errors for this property
 183  0
         AutoPopulatingList<ErrorMessage> errorList = null;
 184  0
         String propertyKey = getKeyPath(propertyName, withFullErrorPath);
 185  0
         if (messagesMap.containsKey(propertyKey)) {
 186  0
             errorList = messagesMap.get(propertyKey);
 187  
         }
 188  
         else {
 189  0
             errorList = new AutoPopulatingList<ErrorMessage>(ErrorMessage.class);
 190  
         }
 191  
 
 192  0
         if (escapeHtmlMessageParameters && messageParameters != null) {
 193  0
                 String[] filteredMessageParameters = new String[messageParameters.length];
 194  0
                 for (int i = 0; i < messageParameters.length; i++) {
 195  0
                         filteredMessageParameters[i] = StringEscapeUtils.escapeHtml(messageParameters[i]);
 196  
                 }
 197  0
                 messageParameters = filteredMessageParameters;
 198  
         }
 199  
 
 200  
         // add error to list
 201  0
         ErrorMessage errorMessage = new ErrorMessage(messageKey, messageParameters);
 202  
         // check if this error has already been added to the list
 203  0
         if ( !errorList.contains( errorMessage ) ) {
 204  0
             errorList.add(errorMessage);
 205  
         }
 206  
 
 207  0
         return messagesMap.put(propertyKey, errorList);
 208  
     }
 209  
 
 210  
     /**
 211  
      * If any error messages with the key targetKey exist in this ErrorMap for the named property, those ErrorMessages will be
 212  
      * replaced with a new ErrorMessage with the given replaceKey and replaceParameters.
 213  
      *
 214  
      * @param propertyName name of the property where existing error will be replaced
 215  
      * @param targetKey error key of message to be replaced
 216  
      * @paran replaceKey error key which will replace targetKey
 217  
      * @param replaceParameters zero or more string parameters for the replacement error message
 218  
      * @return true if the replacement occurred
 219  
      */
 220  
     public boolean replaceError(String propertyName, String targetKey, String replaceKey, String... replaceParameters) {
 221  0
         return replaceError(propertyName, targetKey, true, replaceKey, replaceParameters);
 222  
     }
 223  
 
 224  
     /**
 225  
      * If any error messages with the key targetKey exist in this ErrorMap for the named property, those ErrorMessages will be
 226  
      * replaced with a new ErrorMessage with the given replaceKey and replaceParameters. The targetKey and replaceKey will be
 227  
      * prepended with the current errorPath, if any.
 228  
      *
 229  
      *
 230  
      * @param propertyName name of the property where existing error will be replaced
 231  
      * @param targetKey error key of message to be replaced
 232  
      * @paran replaceKey error key which will replace targetKey
 233  
      * @param replaceParameters zero or more string parameters for the replacement error message
 234  
      * @return true if the replacement occurred
 235  
      */
 236  
     public boolean replaceErrorWithoutFullErrorPath(String propertyName, String targetKey, String replaceKey, String... replaceParameters) {
 237  0
         return replaceError(propertyName, targetKey, false, replaceKey, replaceParameters);
 238  
     }
 239  
 
 240  
 
 241  
     /**
 242  
      * If any error messages with the key targetKey exist in this ErrorMap for the named property, those ErrorMessages will be
 243  
      * replaced with a new ErrorMessage with the given replaceKey and replaceParameters.
 244  
      *
 245  
      * @param propertyName name of the property to add error under
 246  
      * @param targetKey resource key used to retrieve the error text
 247  
      * @param withFullErrorPath true if you want the whole parent error path appended, false otherwise
 248  
      * @param replaceParameters zero or more string parameters for the displayed error message
 249  
      * @return true if the replacement occurred
 250  
      */
 251  
     private boolean replaceError(String propertyName, String targetKey, boolean withFullErrorPath, String replaceKey, String... replaceParameters) {
 252  0
         boolean replaced = false;
 253  
 
 254  0
         if (StringUtils.isBlank(propertyName)) {
 255  0
             throw new IllegalArgumentException("invalid (blank) propertyName");
 256  
         }
 257  0
         if (StringUtils.isBlank(targetKey)) {
 258  0
             throw new IllegalArgumentException("invalid (blank) targetKey");
 259  
         }
 260  0
         if (StringUtils.isBlank(replaceKey)) {
 261  0
             throw new IllegalArgumentException("invalid (blank) replaceKey");
 262  
         }
 263  
 
 264  
         // check if we have previous errors for this property
 265  0
         AutoPopulatingList<ErrorMessage> errorList = null;
 266  0
         String propertyKey = getKeyPath(propertyName, withFullErrorPath);
 267  0
         if (errorMessages.containsKey(propertyKey)) {
 268  0
             errorList = errorMessages.get(propertyKey);
 269  
 
 270  
             // look for the specific targetKey
 271  0
             for (int i = 0; i < errorList.size(); ++i) {
 272  0
                 ErrorMessage em = errorList.get(i);
 273  
 
 274  
                 // replace matching messages
 275  0
                 if (em.getErrorKey().equals(targetKey)) {
 276  0
                     ErrorMessage rm = new ErrorMessage(replaceKey, replaceParameters);
 277  0
                     errorList.set(i, rm);
 278  0
                     replaced = true;
 279  
                 }
 280  
             }
 281  
         }
 282  
 
 283  0
         return replaced;
 284  
     }
 285  
 
 286  
 
 287  
     /**
 288  
      * Returns true if the named field has a message with the given errorKey
 289  
      *
 290  
      * @param errorKey
 291  
      * @param fieldName
 292  
      * @return boolean
 293  
      */
 294  
     public boolean fieldHasMessage(String fieldName, String errorKey) {
 295  0
         boolean found = false;
 296  
 
 297  0
         List<ErrorMessage> fieldMessages = errorMessages.get(fieldName);
 298  0
         if (fieldMessages != null) {
 299  0
             for (Iterator<ErrorMessage> i = fieldMessages.iterator(); !found && i.hasNext();) {
 300  0
                 ErrorMessage errorMessage = i.next();
 301  0
                 found = errorMessage.getErrorKey().equals(errorKey);
 302  0
             }
 303  
         }
 304  
 
 305  0
         return found;
 306  
     }
 307  
 
 308  
     /**
 309  
      * Returns the number of messages for the given field
 310  
      *
 311  
      * @param fieldName
 312  
      * @return int
 313  
      */
 314  
     public int countFieldMessages(String fieldName) {
 315  0
         int count = 0;
 316  
 
 317  0
         List<ErrorMessage> fieldMessages = errorMessages.get(fieldName);
 318  0
         if (fieldMessages != null) {
 319  0
             count = fieldMessages.size();
 320  
         }
 321  
 
 322  0
         return count;
 323  
     }
 324  
 
 325  
 
 326  
     /**
 327  
      * @return true if the given messageKey is associated with some property in this ErrorMap
 328  
      */
 329  
     public boolean containsMessageKey(String messageKey) {
 330  0
         ErrorMessage foundMessage = null;
 331  
 
 332  0
         if (!hasNoErrors()) {
 333  0
             for (Iterator<Map.Entry<String, AutoPopulatingList<ErrorMessage>>> i = getAllPropertiesAndErrors().iterator(); (foundMessage == null) && i.hasNext();) {
 334  0
                     Map.Entry<String, AutoPopulatingList<ErrorMessage>> e = i.next();
 335  0
                 AutoPopulatingList<ErrorMessage> entryErrorList = e.getValue();
 336  0
                 for (Iterator<ErrorMessage> j = entryErrorList.iterator(); j.hasNext();) {
 337  0
                     ErrorMessage em = j.next();
 338  0
                     if (messageKey.equals(em.getErrorKey())) {
 339  0
                         foundMessage = em;
 340  
                     }
 341  0
                 }
 342  0
             }
 343  
         }
 344  
 
 345  0
         return (foundMessage != null);
 346  
     }
 347  
 
 348  
 
 349  
     private int getMessageCount(Map<String, AutoPopulatingList<ErrorMessage>> messageMap) {
 350  0
         int messageCount = 0;
 351  0
         for (Iterator<String> iter = messageMap.keySet().iterator(); iter.hasNext();) {
 352  0
             String errorKey = iter.next();
 353  0
             List<ErrorMessage> errors = messageMap.get(errorKey);
 354  0
             messageCount += errors.size();
 355  0
         }
 356  
 
 357  0
         return messageCount;
 358  
     }
 359  
 
 360  
     /**
 361  
      * Counts the total number of error messages in the map
 362  
      *
 363  
      * @return returns an int for the total number of errors
 364  
      */
 365  
     public int getErrorCount() {
 366  0
             return getMessageCount(errorMessages);
 367  
     }
 368  
 
 369  
     /**
 370  
      * Counts the total number of warning messages in the map
 371  
      *
 372  
      * @return returns an int for the total number of warnings
 373  
      */
 374  
     public int getWarningCount() {
 375  0
             return getMessageCount(warningMessages);
 376  
     }
 377  
 
 378  
     /**
 379  
      * Counts the total number of info messages in the map
 380  
      *
 381  
      * @return returns an int for the total number of info
 382  
      */
 383  
     public int getInfoCount() {
 384  0
             return getMessageCount(infoMessages);
 385  
     }
 386  
 
 387  
     /**
 388  
      * @param path
 389  
      * @return Returns a List of ErrorMessages for the given path
 390  
      */
 391  
     public AutoPopulatingList<ErrorMessage> getMessages(String path) {
 392  0
         return errorMessages.get(path);
 393  
     }
 394  
 
 395  
     /**
 396  
      * Adds a string prefix to the error path.
 397  
      *
 398  
      * @param parentName
 399  
      */
 400  
     public void addToErrorPath(String parentName) {
 401  0
         errorPath.add(parentName);
 402  0
     }
 403  
 
 404  
     /**
 405  
      * This method returns the list that holds the error path values.
 406  
      *
 407  
      * @return List
 408  
      */
 409  
     public List<String> getErrorPath() {
 410  0
         return errorPath;
 411  
     }
 412  
 
 413  
     /**
 414  
      * Removes a string prefix from the error path.
 415  
      *
 416  
      * @param parentName
 417  
      * @return boolean Returns true if the parentName existed, false otherwise.
 418  
      */
 419  
     public boolean removeFromErrorPath(String parentName) {
 420  0
         return errorPath.remove(parentName);
 421  
     }
 422  
 
 423  
     /**
 424  
      * Clears the errorPath.
 425  
      */
 426  
     public void clearErrorPath() {
 427  0
         errorPath.clear();
 428  0
     }
 429  
 
 430  
     /**
 431  
      * This is what's prepended to the beginning of the key. This is built by iterating over all of the entries in the errorPath
 432  
      * list and concatenating them together witha "."
 433  
      *
 434  
      * @return String Returns the keyPath.
 435  
      * @param propertyName
 436  
      * @param prependFullErrorPath
 437  
      */
 438  
     public String getKeyPath(String propertyName, boolean prependFullErrorPath) {
 439  0
         String keyPath = "";
 440  
 
 441  0
         if (KRADConstants.GLOBAL_ERRORS.equals(propertyName)) {
 442  0
             return KRADConstants.GLOBAL_ERRORS;
 443  
         }
 444  
 
 445  0
         if (!errorPath.isEmpty() && prependFullErrorPath) {
 446  0
             keyPath = StringUtils.join(errorPath.iterator(), ".");
 447  0
             keyPath += (keyPath!=null && keyPath.endsWith("."))?propertyName:"." + propertyName;
 448  
         }
 449  
         else {
 450  0
             keyPath = propertyName;
 451  
         }
 452  
 
 453  0
         return keyPath;
 454  
     }
 455  
 
 456  
     /**
 457  
      * @return List of the property names that have errors.
 458  
      */
 459  
     public List<String> getPropertiesWithErrors() {
 460  0
         List<String> properties = new ArrayList<String>();
 461  
 
 462  0
         for (Iterator<String> iter = errorMessages.keySet().iterator(); iter.hasNext();) {
 463  0
             properties.add(iter.next());
 464  
         }
 465  
 
 466  0
         return properties;
 467  
     }
 468  
 
 469  
     /**
 470  
      * @return List of the property names that have warnings.
 471  
      */
 472  
     public List<String> getPropertiesWithWarnings() {
 473  0
         List<String> properties = new ArrayList<String>(warningMessages.keySet());
 474  0
         return properties;
 475  
     }
 476  
 
 477  
     /**
 478  
      * @return List of the property names that have info.
 479  
      */
 480  
     public List<String> getPropertiesWithInfo() {
 481  0
         List<String> properties = new ArrayList<String>(infoMessages.keySet());
 482  0
         return properties;
 483  
     }
 484  
 
 485  
     public void clearErrorMessages() {
 486  0
             errorMessages.clear();
 487  0
     }
 488  
 
 489  
     public boolean doesPropertyHaveError(String key) {
 490  0
             return errorMessages.containsKey(key);
 491  
     }
 492  
 
 493  
     /**
 494  
      * @param pattern comma separated list of keys, optionally ending with * wildcard
 495  
      */
 496  
     public boolean containsKeyMatchingPattern(String pattern) {
 497  0
         List<String> simplePatterns = new ArrayList<String>();
 498  0
         List<String> wildcardPatterns = new ArrayList<String>();
 499  0
         String[] patterns = pattern.split(",");
 500  0
         for (int i = 0; i < patterns.length; i++) {
 501  0
             String s = patterns[i];
 502  0
             if (s.endsWith("*")) {
 503  0
                 wildcardPatterns.add(s.substring(0, s.length() - 1));
 504  
             }
 505  
             else {
 506  0
                 simplePatterns.add(s);
 507  
             }
 508  
         }
 509  0
         for (Iterator<String> keys = errorMessages.keySet().iterator(); keys.hasNext();) {
 510  0
             String key = keys.next();
 511  0
             if (simplePatterns.contains(key)) {
 512  0
                 return true;
 513  
             }
 514  0
             for (Iterator<String> wildcardIterator = wildcardPatterns.iterator(); wildcardIterator.hasNext();) {
 515  0
                 String wildcard = wildcardIterator.next();
 516  0
                 if (key.startsWith(wildcard)) {
 517  0
                     return true;
 518  
                 }
 519  0
             }
 520  0
         }
 521  0
         return false;
 522  
     }
 523  
 
 524  
     public Set<Map.Entry<String, AutoPopulatingList<ErrorMessage>>> getAllPropertiesAndErrors() {
 525  0
             return errorMessages.entrySet();
 526  
     }
 527  
 
 528  
     public AutoPopulatingList<ErrorMessage> getErrorMessagesForProperty(String propertyName) {
 529  0
             return errorMessages.get(propertyName);
 530  
     }
 531  
 
 532  
     public AutoPopulatingList<ErrorMessage> getWarningMessagesForProperty(String propertyName) {
 533  0
             return warningMessages.get(propertyName);
 534  
     }
 535  
 
 536  
     public AutoPopulatingList<ErrorMessage> getInfoMessagesForProperty(String propertyName) {
 537  0
             return infoMessages.get(propertyName);
 538  
     }
 539  
     
 540  
         /**
 541  
          * Gets a list of lists that represent errors that matched by the
 542  
          * propertyName passed in (multiple lists because the wildcard can match
 543  
          * multiple keys). If wildcard is true, the propertyName ends with a
 544  
          * wildcard character. Otherwise, it will only match on the single key and
 545  
          * return a list with one list
 546  
          * 
 547  
          * @param propertyName
 548  
          * @param allowWildcard
 549  
          * @return
 550  
          */
 551  
         public List<AutoPopulatingList<ErrorMessage>> getErrorMessagesForProperty(
 552  
                         String propertyName, boolean allowWildcard) {
 553  0
                 List<AutoPopulatingList<ErrorMessage>> foundMessages = new ArrayList<AutoPopulatingList<ErrorMessage>>();
 554  0
                 if (allowWildcard) {
 555  0
                         boolean wildcard = false;
 556  0
                         if (propertyName.endsWith("*")) {
 557  0
                                 wildcard = true;
 558  0
                                 propertyName = propertyName.substring(0,
 559  
                                                 propertyName.length() - 1);
 560  
                         }
 561  0
                         for (Iterator<String> keys = errorMessages.keySet().iterator(); keys
 562  0
                                         .hasNext();) {
 563  0
                                 String key = keys.next();
 564  0
                                 if (!wildcard && propertyName.equals(key)) {
 565  0
                                         foundMessages.add(errorMessages.get(key));
 566  0
                                         break;
 567  0
                                 } else if (wildcard && key.startsWith(propertyName)) {
 568  0
                                         foundMessages.add(errorMessages.get(key));
 569  
                                 }
 570  0
                         }
 571  0
                 } else {
 572  0
                         foundMessages.add(getErrorMessagesForProperty(propertyName));
 573  
                 }
 574  
 
 575  0
                 return foundMessages;
 576  
         }
 577  
 
 578  
         /**
 579  
          * Gets a list of lists that represent warnings that matched by the
 580  
          * propertyName passed in (multiple lists because the wildcard can match
 581  
          * multiple keys). If wildcard is true, the propertyName ends with a
 582  
          * wildcard character. Otherwise, it will only match on the single key and
 583  
          * return a list with one list.
 584  
          * 
 585  
          * @param propertyName
 586  
          * @param allowWildcard
 587  
          * @return
 588  
          */
 589  
         public List<AutoPopulatingList<ErrorMessage>> getWarningMessagesForProperty(
 590  
                         String propertyName, boolean allowWildcard) {
 591  0
                 List<AutoPopulatingList<ErrorMessage>> foundMessages = new ArrayList<AutoPopulatingList<ErrorMessage>>();
 592  0
                 if (allowWildcard) {
 593  0
                         boolean wildcard = false;
 594  0
                         if (propertyName.endsWith("*")) {
 595  0
                                 wildcard = true;
 596  0
                                 propertyName = propertyName.substring(0,
 597  
                                                 propertyName.length() - 1);
 598  
                         }
 599  0
                         for (Iterator<String> keys = warningMessages.keySet().iterator(); keys
 600  0
                                         .hasNext();) {
 601  0
                                 String key = keys.next();
 602  0
                                 if (!wildcard && propertyName.equals(key)) {
 603  0
                                         foundMessages.add(warningMessages.get(key));
 604  0
                                         break;
 605  0
                                 } else if (wildcard && key.startsWith(propertyName)) {
 606  0
                                         foundMessages.add(warningMessages.get(key));
 607  
                                 }
 608  0
                         }
 609  0
                 } else {
 610  0
                         foundMessages.add(getWarningMessagesForProperty(propertyName));
 611  
                 }
 612  
 
 613  0
                 return foundMessages;
 614  
         }
 615  
 
 616  
         /**
 617  
          * Gets a list of lists that represent info messages that matched by the
 618  
          * propertyName passed in (multiple lists because the wildcard can match
 619  
          * multiple keys). If wildcard is true, the propertyName ends with a
 620  
          * wildcard character. If it is false, it will only match on the single key
 621  
          * and return a list with one list.
 622  
          * 
 623  
          * @param propertyName
 624  
          * @param allowWildcard
 625  
          * @return
 626  
          */
 627  
         public List<AutoPopulatingList<ErrorMessage>> getInfoMessagesForProperty(
 628  
                         String propertyName, boolean allowWildcard) {
 629  0
                 List<AutoPopulatingList<ErrorMessage>> foundMessages = new ArrayList<AutoPopulatingList<ErrorMessage>>();
 630  0
                 if (allowWildcard) {
 631  0
                         boolean wildcard = false;
 632  0
                         if (propertyName.endsWith("*")) {
 633  0
                                 wildcard = true;
 634  0
                                 propertyName = propertyName.substring(0,
 635  
                                                 propertyName.length() - 1);
 636  
                         }
 637  0
                         for (Iterator<String> keys = infoMessages.keySet().iterator(); keys
 638  0
                                         .hasNext();) {
 639  0
                                 String key = keys.next();
 640  0
                                 if (!wildcard && propertyName.equals(key)) {
 641  0
                                         foundMessages.add(infoMessages.get(key));
 642  0
                                         break;
 643  0
                                 } else if (wildcard && key.startsWith(propertyName)) {
 644  0
                                         foundMessages.add(infoMessages.get(key));
 645  
                                 }
 646  0
                         }
 647  0
                 } else {
 648  0
                         foundMessages.add(getInfoMessagesForProperty(propertyName));
 649  
                 }
 650  
 
 651  0
                 return foundMessages;
 652  
         }
 653  
 
 654  
     public boolean hasErrors() {
 655  0
             return !errorMessages.isEmpty();
 656  
     }
 657  
 
 658  
     public boolean hasNoErrors() {
 659  0
             return errorMessages.isEmpty();
 660  
     }
 661  
 
 662  
     public boolean hasWarnings() {
 663  0
             return !warningMessages.isEmpty();
 664  
     }
 665  
 
 666  
     public boolean hasNoWarnings() {
 667  0
             return warningMessages.isEmpty();
 668  
     }
 669  
 
 670  
     public boolean hasInfo() {
 671  0
             return !infoMessages.isEmpty();
 672  
     }
 673  
 
 674  
     public boolean hasNoInfo() {
 675  0
             return infoMessages.isEmpty();
 676  
     }
 677  
 
 678  
     public boolean hasMessages() {
 679  0
         if (!errorMessages.isEmpty()
 680  
                 || !warningMessages.isEmpty()
 681  
                 || !infoMessages.isEmpty()) {
 682  0
             return true;
 683  
         }
 684  0
         return false;
 685  
     }
 686  
 
 687  
     public boolean hasNoMessages() {
 688  0
         if (errorMessages.isEmpty()
 689  
                 && warningMessages.isEmpty()
 690  
                 && infoMessages.isEmpty()) {
 691  0
             return true;
 692  
         }
 693  0
         return false;
 694  
     }
 695  
 
 696  
     public Set<String> getAllPropertiesWithErrors() {
 697  0
             return errorMessages.keySet();
 698  
     }
 699  
 
 700  
     public Set<String> getAllPropertiesWithWarnings() {
 701  0
             return warningMessages.keySet();
 702  
     }
 703  
 
 704  
     public Set<String> getAllPropertiesWithInfo() {
 705  0
             return infoMessages.keySet();
 706  
     }
 707  
 
 708  
     public AutoPopulatingList<ErrorMessage> removeAllErrorMessagesForProperty(String property) {
 709  0
             return errorMessages.remove(property);
 710  
     }
 711  
 
 712  
     public AutoPopulatingList<ErrorMessage> removeAllWarningMessagesForProperty(String property) {
 713  0
             return warningMessages.remove(property);
 714  
     }
 715  
 
 716  
     public AutoPopulatingList<ErrorMessage> removeAllInfoMessagesForProperty(String property) {
 717  0
             return infoMessages.remove(property);
 718  
     }
 719  
 
 720  
     public int getNumberOfPropertiesWithErrors() {
 721  0
             return errorMessages.size();
 722  
     }
 723  
 
 724  
     public Map<String, AutoPopulatingList<ErrorMessage>> getErrorMessages() {
 725  0
         return this.errorMessages;
 726  
     }
 727  
 
 728  
     public Map<String, AutoPopulatingList<ErrorMessage>> getWarningMessages() {
 729  0
         return this.warningMessages;
 730  
     }
 731  
 
 732  
     public Map<String, AutoPopulatingList<ErrorMessage>> getInfoMessages() {
 733  0
         return this.infoMessages;
 734  
     }
 735  
 
 736  
     @Override
 737  
     public boolean equals(Object o) {
 738  0
         return EqualsBuilder.reflectionEquals(this, o);
 739  
     }
 740  
 
 741  
     @Override
 742  
     public int hashCode() {
 743  0
         return HashCodeBuilder.reflectionHashCode(this);
 744  
     }
 745  
 
 746  
     @Override
 747  
     public String toString() {
 748  0
         return ToStringBuilder.reflectionToString(this);
 749  
     }
 750  
 }