Coverage Report - org.kuali.rice.kns.service.impl.DictionaryValidationServiceImpl
 
Classes in this File Line Coverage Branch Coverage Complexity
DictionaryValidationServiceImpl
0%
0/389
0%
0/262
4.951
 
 1  
 /*
 2  
  * Copyright 2005-2007 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.kns.service.impl;
 17  
 
 18  
 import java.beans.PropertyDescriptor;
 19  
 import java.lang.reflect.InvocationTargetException;
 20  
 import java.lang.reflect.Method;
 21  
 import java.math.BigDecimal;
 22  
 import java.util.Collection;
 23  
 import java.util.Iterator;
 24  
 import java.util.List;
 25  
 import java.util.Map;
 26  
 import java.util.Set;
 27  
 import java.util.regex.Pattern;
 28  
 
 29  
 import org.apache.commons.beanutils.PropertyUtils;
 30  
 import org.apache.commons.lang.ArrayUtils;
 31  
 import org.apache.commons.lang.StringUtils;
 32  
 import org.hibernate.util.IdentitySet;
 33  
 import org.kuali.rice.core.jdbc.SqlBuilder;
 34  
 import org.kuali.rice.kew.docsearch.SearchableAttribute;
 35  
 import org.kuali.rice.kns.bo.BusinessObject;
 36  
 import org.kuali.rice.kns.bo.Inactivateable;
 37  
 import org.kuali.rice.kns.bo.PersistableBusinessObject;
 38  
 import org.kuali.rice.kns.datadictionary.ApcRuleDefinition;
 39  
 import org.kuali.rice.kns.datadictionary.MaintainableFieldDefinition;
 40  
 import org.kuali.rice.kns.datadictionary.MaintainableItemDefinition;
 41  
 import org.kuali.rice.kns.datadictionary.MaintainableSectionDefinition;
 42  
 import org.kuali.rice.kns.datadictionary.MaintenanceDocumentEntry;
 43  
 import org.kuali.rice.kns.datadictionary.ReferenceDefinition;
 44  
 import org.kuali.rice.kns.datadictionary.control.ControlDefinition;
 45  
 import org.kuali.rice.kns.document.Document;
 46  
 import org.kuali.rice.kns.document.TransactionalDocument;
 47  
 import org.kuali.rice.kns.exception.InfrastructureException;
 48  
 import org.kuali.rice.kns.exception.ObjectNotABusinessObjectRuntimeException;
 49  
 import org.kuali.rice.kns.service.BusinessObjectService;
 50  
 import org.kuali.rice.kns.service.DataDictionaryService;
 51  
 import org.kuali.rice.kns.service.DictionaryValidationService;
 52  
 import org.kuali.rice.kns.service.KNSServiceLocator;
 53  
 import org.kuali.rice.kns.service.MaintenanceDocumentDictionaryService;
 54  
 import org.kuali.rice.kns.service.PersistenceService;
 55  
 import org.kuali.rice.kns.service.PersistenceStructureService;
 56  
 import org.kuali.rice.kns.service.TransactionalDocumentDictionaryService;
 57  
 import org.kuali.rice.kns.util.GlobalVariables;
 58  
 import org.kuali.rice.kns.util.KNSConstants;
 59  
 import org.kuali.rice.kns.util.MessageMap;
 60  
 import org.kuali.rice.kns.util.ObjectUtils;
 61  
 import org.kuali.rice.kns.util.RiceKeyConstants;
 62  
 import org.kuali.rice.kns.util.TypeUtils;
 63  
 import org.kuali.rice.kns.web.format.DateFormatter;
 64  
 import org.kuali.rice.kns.workflow.service.WorkflowAttributePropertyResolutionService;
 65  
 
 66  
 /**
 67  
  * Validates Documents, Business Objects, and Attributes against the data dictionary. Including min, max lengths, and validating
 68  
  * expressions. This is the default, Kuali delivered implementation.
 69  
  * 
 70  
  * KULRICE - 3355 Modified to prevent infinite looping (to maxDepth) scenario when a parent references a child which references a parent
 71  
  */
 72  
 //@Transactional
 73  0
 public class DictionaryValidationServiceImpl implements DictionaryValidationService {
 74  0
     private static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(DictionaryValidationServiceImpl.class);
 75  
 
 76  
     /**
 77  
      * Constant defines a validation method for an attribute value.
 78  
      * <p>Value is "validate"
 79  
      */
 80  
     public static final String VALIDATE_METHOD="validate";
 81  
     
 82  
     private DataDictionaryService dataDictionaryService;
 83  
     private BusinessObjectService businessObjectService;
 84  
     private MaintenanceDocumentDictionaryService maintenanceDocumentDictionaryService;
 85  
     private TransactionalDocumentDictionaryService transactionalDocumentDictionaryService;
 86  
     private PersistenceService persistenceService;
 87  
     private WorkflowAttributePropertyResolutionService workflowAttributePropertyResolutionService;
 88  
 
 89  
     private PersistenceStructureService persistenceStructureService;
 90  
     
 91  
     /** 
 92  
      * creates a new IdentitySet.
 93  
      * @return a new Set
 94  
      */
 95  
     @SuppressWarnings("unchecked")
 96  
     private static Set<BusinessObject> newIdentitySet() {
 97  
         //using Hibernate's IdentitySet because Java 5 doesn't have a good way to create one
 98  0
         return new IdentitySet();
 99  
         //in Java 6
 100  
         //return java.util.Collections.newSetFromMap(new java.util.IdentityHashMap<BusinessObject, Boolean>());
 101  
     }
 102  
     
 103  
     /**
 104  
      * @see org.kuali.rice.kns.service.DictionaryValidationService#validateDocument(org.kuali.rice.kns.document.Document)
 105  
      */
 106  
     public void validateDocument(Document document) {
 107  0
         String documentEntryName = document.getDocumentHeader().getWorkflowDocument().getDocumentType();
 108  
 
 109  
         // validate primitive values
 110  0
         validatePrimitivesFromDescriptors(documentEntryName, document, PropertyUtils.getPropertyDescriptors(document.getClass()), "", true);
 111  0
     }
 112  
 
 113  
 
 114  
     /**
 115  
      * @see org.kuali.rice.kns.service.DictionaryValidationService#validateDocumentAttribute(org.kuali.rice.kns.document.Document,
 116  
      *      java.lang.String,java.lang.String)
 117  
      */
 118  
     public void validateDocumentAttribute(Document document, String attributeName, String errorPrefix) {
 119  0
         String documentEntryName = document.getDocumentHeader().getWorkflowDocument().getDocumentType();
 120  
 
 121  
         try {
 122  0
             PropertyDescriptor attributeDescriptor = PropertyUtils.getPropertyDescriptor(document, attributeName);
 123  0
             validatePrimitiveFromDescriptor(documentEntryName, document, attributeDescriptor, errorPrefix, true);
 124  
         }
 125  0
         catch (NoSuchMethodException e) {
 126  0
             throw new InfrastructureException("unable to find propertyDescriptor for property '" + attributeName + "'", e);
 127  
         }
 128  0
         catch (IllegalAccessException e) {
 129  0
             throw new InfrastructureException("unable to access propertyDescriptor for property '" + attributeName + "'", e);
 130  
         }
 131  0
         catch (InvocationTargetException e) {
 132  0
             throw new InfrastructureException("unable to invoke methods for property '" + attributeName + "'", e);
 133  0
         }
 134  0
     }
 135  
 
 136  
     /**
 137  
      * @see org.kuali.rice.kns.service.DictionaryValidationService#validateDocumentRecursively
 138  
      */
 139  
     public void validateDocumentRecursively(Document document, int depth) {
 140  
         // validate primitives of document
 141  0
         validateDocument(document);
 142  
 
 143  
         // call method to recursively find business objects and validate
 144  0
         validateBusinessObjectsFromDescriptors(document, PropertyUtils.getPropertyDescriptors(document.getClass()), depth);
 145  0
     }
 146  
 
 147  
     public void validateDocumentAndUpdatableReferencesRecursively(Document document, int maxDepth, boolean validateRequired) {
 148  0
             validateDocumentAndUpdatableReferencesRecursively(document, maxDepth, validateRequired, false);
 149  0
     }
 150  
     
 151  
     public void validateDocumentAndUpdatableReferencesRecursively(Document document, int maxDepth, boolean validateRequired, boolean chompLastLetterSFromCollectionName) {
 152  0
         String documentEntryName = document.getDocumentHeader().getWorkflowDocument().getDocumentType();
 153  
         // validate primitive values of the document
 154  0
         validatePrimitivesFromDescriptors(documentEntryName, document, PropertyUtils.getPropertyDescriptors(document.getClass()), "", validateRequired);
 155  
         
 156  0
         if (maxDepth > 0) {
 157  0
             validateUpdatabableReferencesRecursively(document, maxDepth - 1, validateRequired, chompLastLetterSFromCollectionName,  newIdentitySet());
 158  
         }
 159  0
     }
 160  
     
 161  
     private void validateUpdatabableReferencesRecursively(BusinessObject businessObject, int maxDepth, boolean validateRequired, boolean chompLastLetterSFromCollectionName, Set<BusinessObject> processedBOs) {
 162  
             // if null or already processed, return
 163  0
             if (ObjectUtils.isNull(businessObject) || processedBOs.contains(businessObject)) {
 164  0
                     return;
 165  
             }
 166  0
         processedBOs.add(businessObject);  // add bo to list to prevent excessive looping
 167  0
             Map<String, Class> references = persistenceStructureService.listReferenceObjectFields(businessObject.getClass());
 168  0
             for (String referenceName : references.keySet()) {
 169  0
                     if (persistenceStructureService.isReferenceUpdatable(businessObject.getClass(), referenceName)) {
 170  0
                             Object referenceObj = ObjectUtils.getPropertyValue(businessObject, referenceName);
 171  
 
 172  0
                             if (ObjectUtils.isNull(referenceObj) || !(referenceObj instanceof PersistableBusinessObject)) {
 173  0
                                     continue;
 174  
                             }
 175  
 
 176  0
                             BusinessObject referenceBusinessObject = (BusinessObject) referenceObj;
 177  0
                             GlobalVariables.getMessageMap().addToErrorPath(referenceName);
 178  0
                             validateBusinessObject(referenceBusinessObject, validateRequired);
 179  0
                             if (maxDepth > 0) {
 180  0
                                     validateUpdatabableReferencesRecursively(referenceBusinessObject, maxDepth - 1, validateRequired, chompLastLetterSFromCollectionName, processedBOs);
 181  
                             }
 182  0
                             GlobalVariables.getMessageMap().removeFromErrorPath(referenceName);
 183  
 
 184  0
                     }
 185  
             }
 186  0
             Map<String, Class> collections = persistenceStructureService.listCollectionObjectTypes(businessObject.getClass());
 187  0
             for (String collectionName : collections.keySet()) {
 188  0
                     if (persistenceStructureService.isCollectionUpdatable(businessObject.getClass(), collectionName)) {
 189  0
                             Object listObj = ObjectUtils.getPropertyValue(businessObject, collectionName);
 190  
 
 191  0
                             if (ObjectUtils.isNull(listObj)) {
 192  0
                                     continue;
 193  
                             }
 194  
 
 195  0
                             if (!(listObj instanceof List)) {
 196  0
                                         if ( LOG.isInfoEnabled() ) {
 197  0
                                                 LOG.info("The reference named " + collectionName + " of BO class " + businessObject.getClass().getName() + " should be of type java.util.List to be validated properly.");
 198  
                                         }
 199  
                                     continue;
 200  
                             }
 201  
 
 202  0
                             List list = (List) listObj;
 203  
                             
 204  
                             //should we materialize the proxied collection or just skip validation here assuming an unmaterialized objects are valid?
 205  0
                             ObjectUtils.materializeObjects(list);
 206  
                             
 207  0
                             for (int i = 0; i < list.size(); i++) {
 208  0
                                     final Object o = list.get(i);
 209  0
                                     if (ObjectUtils.isNotNull(o) && o instanceof PersistableBusinessObject) {
 210  0
                                             final BusinessObject element = (BusinessObject) o;
 211  
                                             
 212  
                                             final String errorPathAddition;
 213  0
                                             if (chompLastLetterSFromCollectionName) {
 214  0
                                                     errorPathAddition = StringUtils.chomp(collectionName, "s") + "[" + Integer.toString(i) + "]";
 215  
                                             } else {
 216  0
                                                     errorPathAddition = collectionName + "[" + Integer.toString(i) + "]";
 217  
                                             }
 218  
 
 219  0
                                             GlobalVariables.getMessageMap().addToErrorPath(errorPathAddition);
 220  0
                                             validateBusinessObject(element, validateRequired);
 221  0
                                             if (maxDepth > 0) {
 222  0
                                                     validateUpdatabableReferencesRecursively(element, maxDepth - 1, validateRequired, chompLastLetterSFromCollectionName, processedBOs);
 223  
                                             }
 224  0
                                             GlobalVariables.getMessageMap().removeFromErrorPath(errorPathAddition);
 225  
                                     }
 226  
                             }
 227  0
                     }
 228  
             }
 229  0
     }
 230  
 
 231  
     /**
 232  
      * @see org.kuali.rice.kns.service.DictionaryValidationService#validateBusinessObject(org.kuali.rice.kns.bo.BusinessObject)
 233  
      */
 234  
     public void validateBusinessObject(BusinessObject businessObject) {
 235  0
         validateBusinessObject(businessObject, true);
 236  0
     }
 237  
 
 238  
     /**
 239  
      * @see org.kuali.rice.kns.service.DictionaryValidationService#validateBusinessObject(org.kuali.rice.kns.bo.BusinessObject,boolean)
 240  
      */
 241  
     public void validateBusinessObject(BusinessObject businessObject, boolean validateRequired) {
 242  0
         if (ObjectUtils.isNull(businessObject)) {
 243  0
             return;
 244  
         }
 245  
         try {
 246  
                 // validate the primitive attributes of the bo
 247  0
                 validatePrimitivesFromDescriptors(businessObject.getClass().getName(), businessObject, PropertyUtils.getPropertyDescriptors(businessObject.getClass()), "", validateRequired);
 248  0
         } catch(RuntimeException e) {
 249  0
                 LOG.error(String.format("Exception while validating %s", businessObject.getClass().getName()), e);
 250  0
                 throw e;
 251  0
         }
 252  0
     }
 253  
 
 254  
     /**
 255  
          * @see org.kuali.rice.kns.service.DictionaryValidationService#validateBusinessObjectOnMaintenanceDocument(org.kuali.rice.kns.bo.BusinessObject, java.lang.String)
 256  
          */
 257  
         public void validateBusinessObjectOnMaintenanceDocument(BusinessObject businessObject, String docTypeName) {
 258  0
                 MaintenanceDocumentEntry entry = KNSServiceLocator.getMaintenanceDocumentDictionaryService().getMaintenanceDocumentEntry(docTypeName);
 259  0
                 for (MaintainableSectionDefinition sectionDefinition : entry.getMaintainableSections()) {
 260  0
                         validateBusinessObjectOnMaintenanceDocumentHelper(businessObject, sectionDefinition.getMaintainableItems(), "");
 261  
                 }
 262  0
         }
 263  
         
 264  
         protected void validateBusinessObjectOnMaintenanceDocumentHelper(BusinessObject businessObject, List<? extends MaintainableItemDefinition> itemDefinitions, String errorPrefix) {
 265  0
                 for (MaintainableItemDefinition itemDefinition : itemDefinitions) {
 266  0
                         if (itemDefinition instanceof MaintainableFieldDefinition) {
 267  0
                         if (getDataDictionaryService().isAttributeDefined(businessObject.getClass(), itemDefinition.getName())) {
 268  0
                             Object value = ObjectUtils.getPropertyValue(businessObject, itemDefinition.getName());
 269  0
                             if (value != null && StringUtils.isNotBlank(value.toString())) {
 270  0
                                     Class propertyType = ObjectUtils.getPropertyType(businessObject, itemDefinition.getName(), persistenceStructureService);
 271  0
                                     if (TypeUtils.isStringClass(propertyType) || TypeUtils.isIntegralClass(propertyType) || TypeUtils.isDecimalClass(propertyType) || TypeUtils.isTemporalClass(propertyType)) {
 272  
                                         // check value format against dictionary
 273  0
                                     if (!TypeUtils.isTemporalClass(propertyType)) {
 274  0
                                         validateAttributeFormat(businessObject.getClass().getName(), itemDefinition.getName(), value.toString(), errorPrefix + itemDefinition.getName());
 275  
                                     }
 276  
                                     }
 277  
                             }
 278  0
                         }
 279  
                         }
 280  
                         /*
 281  
                         TODO: reenable when we come up with a strategy to handle fields that are not editable
 282  
                         else if (itemDefinition instanceof MaintainableCollectionDefinition) {
 283  
                                 MaintainableCollectionDefinition collectionDefinition = (MaintainableCollectionDefinition) itemDefinition;
 284  
                                 Collection<BusinessObject> c = (Collection<BusinessObject>) ObjectUtils.getPropertyValue(businessObject, itemDefinition.getName());
 285  
                                 if (c != null) {
 286  
                                         int i = 0;
 287  
                                         for (BusinessObject o : c) {
 288  
                                                 String newErrorPrefix = errorPrefix + itemDefinition.getName() + "[" + i + "].";
 289  
                                                 validateBusinessObjectOnMaintenanceDocumentHelper(o, collectionDefinition.getMaintainableCollections(), newErrorPrefix);
 290  
                                                 validateBusinessObjectOnMaintenanceDocumentHelper(o, collectionDefinition.getMaintainableFields(), newErrorPrefix);
 291  
                                                 i++;
 292  
                                         }
 293  
                                 }
 294  
                         }*/
 295  
                 }
 296  0
         }
 297  
 
 298  
 
 299  
         /**
 300  
      * @see org.kuali.rice.kns.service.DictionaryValidationService#isBusinessObjectValid(org.kuali.rice.kns.bo.BusinessObject)
 301  
      */
 302  
     public boolean isBusinessObjectValid(BusinessObject businessObject) {
 303  0
         return isBusinessObjectValid(businessObject, null);
 304  
     }
 305  
 
 306  
     /**
 307  
      * @see org.kuali.rice.kns.service.DictionaryValidationService#isBusinessObjectValid(org.kuali.rice.kns.bo.BusinessObject, String)
 308  
      */
 309  
     public boolean isBusinessObjectValid(BusinessObject businessObject, String prefix) {
 310  0
         final MessageMap errorMap = GlobalVariables.getMessageMap();
 311  0
         int originalErrorCount = errorMap.getErrorCount();
 312  
 
 313  0
         errorMap.addToErrorPath(prefix);
 314  0
         validateBusinessObject(businessObject);
 315  0
         errorMap.removeFromErrorPath(prefix);
 316  
 
 317  0
         return errorMap.getErrorCount() == originalErrorCount;
 318  
     }
 319  
 
 320  
 
 321  
     /**
 322  
      * @param businessObject - business object to validate
 323  
      */
 324  
     public void validateBusinessObjectsRecursively(BusinessObject businessObject, int depth) {
 325  0
         if (ObjectUtils.isNull(businessObject)) {
 326  0
             return;
 327  
         }
 328  
 
 329  
         // validate primitives and any specific bo validation
 330  0
         validateBusinessObject(businessObject);
 331  
 
 332  
         // call method to recursively find business objects and validate
 333  0
         validateBusinessObjectsFromDescriptors(businessObject, PropertyUtils.getPropertyDescriptors(businessObject.getClass()), depth);
 334  0
     }
 335  
 
 336  
 
 337  
     /**
 338  
      * @see org.kuali.rice.kns.service.DictionaryValidationService#validateAttributeFormat
 339  
      * objectClassName is the docTypeName
 340  
      */
 341  
     public void validateAttributeFormat(String objectClassName, String attributeName, String attributeInValue, String errorKey) {
 342  
         // Retrieve the field's data type, or set to the string data type if an exception occurs when retrieving the class or the DD entry.
 343  0
         String attributeDataType = null;
 344  
         try {
 345  0
                 attributeDataType = getWorkflowAttributePropertyResolutionService().determineFieldDataType((Class<? extends BusinessObject>)Class.forName(
 346  
                                 getDataDictionaryService().getDataDictionary().getDictionaryObjectEntry(objectClassName).getFullClassName()), attributeName);
 347  0
         } catch(ClassNotFoundException e) {
 348  0
                 attributeDataType = SearchableAttribute.DATA_TYPE_STRING;
 349  0
         } catch (NullPointerException e) {
 350  0
                 attributeDataType = SearchableAttribute.DATA_TYPE_STRING;
 351  0
         }
 352  
         
 353  0
         validateAttributeFormat(objectClassName, attributeName, attributeInValue, attributeDataType, errorKey);
 354  0
     }
 355  
 
 356  
     /**
 357  
      * The attributeDataType parameter should be one of the data types specified by the SearchableAttribute interface; will
 358  
      * default to DATA_TYPE_STRING if a data type other than the ones from SearchableAttribute is specified.
 359  
      * 
 360  
      * @see org.kuali.rice.kns.service.DictionaryValidationService#validateAttributeFormat(java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String)
 361  
      * objectClassName is the docTypeName
 362  
      */
 363  
         public void validateAttributeFormat(String objectClassName, String attributeName, String attributeInValue, String attributeDataType, String errorKey) {
 364  0
         boolean checkDateBounds = false; // this is used so we can check date bounds
 365  0
         Class<?> formatterClass = null;
 366  
 
 367  0
         if ( LOG.isDebugEnabled() ) {
 368  0
         LOG.debug("(bo, attributeName, attributeValue) = (" + objectClassName + "," + attributeName + "," + attributeInValue + ")");
 369  
         }
 370  
 
 371  
         /*
 372  
          *  This will return a list of searchable attributes. so if the value is
 373  
          *  12/07/09 .. 12/08/09 it will return [12/07/09,12/08/09]
 374  
          */
 375  
 
 376  0
         List<String> attributeValues = SqlBuilder.getCleanedSearchableValues(attributeInValue, attributeDataType);
 377  
 
 378  0
         if(attributeValues == null || attributeValues.isEmpty()) {
 379  0
                         return;
 380  
                 }
 381  
 
 382  0
         for(String attributeValue : attributeValues){
 383  0
         if (StringUtils.isNotBlank(attributeValue)) {
 384  0
             Integer maxLength = getDataDictionaryService().getAttributeMaxLength(objectClassName, attributeName);
 385  0
             if ((maxLength != null) && (maxLength.intValue() < attributeValue.length())) {
 386  0
                         String errorLabel = getDataDictionaryService().getAttributeErrorLabel(objectClassName, attributeName);
 387  0
                 GlobalVariables.getMessageMap().putError(errorKey, RiceKeyConstants.ERROR_MAX_LENGTH, new String[] { errorLabel, maxLength.toString() });
 388  0
                 return;
 389  
             }
 390  0
             Pattern validationExpression = getDataDictionaryService().getAttributeValidatingExpression(objectClassName, attributeName);
 391  0
             if (validationExpression != null && !validationExpression.pattern().equals(".*")) {
 392  0
                             if ( LOG.isDebugEnabled() ) {
 393  0
                 LOG.debug("(bo, attributeName, validationExpression) = (" + objectClassName + "," + attributeName + "," + validationExpression + ")");
 394  
                             }
 395  
 
 396  0
                     if (!validationExpression.matcher(attributeValue).matches()) {
 397  
                             // Retrieving formatter class
 398  0
                                     if(formatterClass == null){
 399  
                                             // this is just a cache check... all dates ranges get called twice
 400  0
                                             formatterClass=getDataDictionaryService().getAttributeFormatter(
 401  
                             objectClassName, attributeName);
 402  
                                     }
 403  
 
 404  0
                     if (formatterClass != null) {
 405  0
                             boolean valuesAreValid = true;
 406  0
                                     boolean isError=true;
 407  0
                                     String errorKeyPrefix = "";
 408  
                                     try {
 409  
                             
 410  
                                             // this is a special case for date ranges in order to set the proper error message
 411  0
                         if (DateFormatter.class.isAssignableFrom(formatterClass)) {
 412  0
                                                     String[] values = attributeInValue.split("\\.\\."); // is it a range
 413  0
                                                     if(values.length == 2 && attributeValues.size() == 2){ // make sure it's not like a .. b | c
 414  0
                                                             checkDateBounds = true; // now we need to check that a <= b
 415  0
                                                             if(attributeValues.indexOf(attributeValue) == 0){ // only care about lower bound
 416  0
                                                                     errorKeyPrefix = KNSConstants.LOOKUP_RANGE_LOWER_BOUND_PROPERTY_PREFIX;
 417  
                                                             }
 418  
                             }
 419  
                         }
 420  
                         
 421  0
                                             Method validatorMethod=formatterClass.getDeclaredMethod(
 422  
                                                             VALIDATE_METHOD, new Class<?>[] {String.class});
 423  0
                                         Object o=validatorMethod.invoke(
 424  
                                                         formatterClass.newInstance(), attributeValue);
 425  0
                                         if (o instanceof Boolean) {
 426  0
                                                 isError = !((Boolean)o).booleanValue();
 427  
                                         }
 428  0
                                         valuesAreValid &= !isError;
 429  0
                                     } catch (Exception e) {
 430  0
                                             if ( LOG.isDebugEnabled() ) {
 431  0
                                             LOG.debug(e.getMessage(), e);
 432  
                                             }
 433  0
                                             isError =true;
 434  0
                                             valuesAreValid = false;
 435  0
                                     }
 436  0
                                     if (isError) {
 437  0
                                             checkDateBounds = false; // it's already invalid, no need to check date bounds
 438  0
                                             String errorMessageKey = getDataDictionaryService().getAttributeValidatingErrorMessageKey(objectClassName, attributeName);
 439  0
                                             String[] errorMessageParameters = getDataDictionaryService().getAttributeValidatingErrorMessageParameters(objectClassName, attributeName);
 440  0
                                             GlobalVariables.getMessageMap().putError(errorKeyPrefix + errorKey, errorMessageKey, errorMessageParameters);
 441  
                                     }
 442  0
                     } else {
 443  
                                     // if it fails the default validation and has no formatter class then it's still a std failure.
 444  0
                             String errorMessageKey = getDataDictionaryService().getAttributeValidatingErrorMessageKey(objectClassName, attributeName);
 445  0
                                     String[] errorMessageParameters = getDataDictionaryService().getAttributeValidatingErrorMessageParameters(objectClassName, attributeName);
 446  0
                                     GlobalVariables.getMessageMap().putError(errorKey, errorMessageKey, errorMessageParameters);
 447  
                     }
 448  
                 }
 449  
 
 450  
             }
 451  0
             BigDecimal exclusiveMin = getDataDictionaryService().getAttributeExclusiveMin(objectClassName, attributeName);
 452  0
             if (exclusiveMin != null) {
 453  
                 try {
 454  0
                     if (exclusiveMin.compareTo(new BigDecimal(attributeValue)) >= 0) {
 455  0
                                 String errorLabel = getDataDictionaryService().getAttributeErrorLabel(objectClassName, attributeName);
 456  0
                         GlobalVariables.getMessageMap().putError(errorKey, RiceKeyConstants.ERROR_EXCLUSIVE_MIN,
 457  
                         // todo: Formatter for currency?
 458  
                                 new String[] { errorLabel, exclusiveMin.toString() });
 459  0
                         return;
 460  
                     }
 461  
                 }
 462  0
                 catch (NumberFormatException e) {
 463  
                     // quash; this indicates that the DD contained a min for a non-numeric attribute
 464  0
                 }
 465  
             }
 466  0
             BigDecimal inclusiveMax = getDataDictionaryService().getAttributeInclusiveMax(objectClassName, attributeName);
 467  0
             if (inclusiveMax != null) {
 468  
                 try {
 469  0
                     if (inclusiveMax.compareTo(new BigDecimal(attributeValue)) < 0) {
 470  0
                                 String errorLabel = getDataDictionaryService().getAttributeErrorLabel(objectClassName, attributeName);
 471  0
                         GlobalVariables.getMessageMap().putError(errorKey, RiceKeyConstants.ERROR_INCLUSIVE_MAX,
 472  
                         // todo: Formatter for currency?
 473  
                                 new String[] { errorLabel, inclusiveMax.toString() });
 474  0
                         return;
 475  
                     }
 476  
                 }
 477  0
                 catch (NumberFormatException e) {
 478  
                     // quash; this indicates that the DD contained a max for a non-numeric attribute
 479  0
                 }
 480  
             }
 481  0
         }
 482  
     }
 483  
 
 484  0
         if(checkDateBounds){
 485  
                 // this means that we only have 2 values and it's a date range.
 486  0
                 java.sql.Timestamp lVal = null;
 487  0
                     java.sql.Timestamp uVal = null;
 488  
                     try{
 489  0
                             lVal = KNSServiceLocator.getDateTimeService().convertToSqlTimestamp(attributeValues.get(0));
 490  0
                             uVal = KNSServiceLocator.getDateTimeService().convertToSqlTimestamp(attributeValues.get(1));
 491  0
                     }catch(Exception ex){
 492  
                             // this shouldn't happen because the tests passed above.
 493  0
                             String errorMessageKey = getDataDictionaryService().getAttributeValidatingErrorMessageKey(objectClassName, attributeName);
 494  0
                             String[] errorMessageParameters = getDataDictionaryService().getAttributeValidatingErrorMessageParameters(objectClassName, attributeName);
 495  0
                             GlobalVariables.getMessageMap().putError(KNSConstants.LOOKUP_RANGE_LOWER_BOUND_PROPERTY_PREFIX + errorKey, errorMessageKey, errorMessageParameters);
 496  0
                     }
 497  
 
 498  0
                     if(lVal != null && lVal.compareTo(uVal) > 0){ // check the bounds
 499  0
                             String errorMessageKey = getDataDictionaryService().getAttributeValidatingErrorMessageKey(objectClassName, attributeName);
 500  0
                             String[] errorMessageParameters = getDataDictionaryService().getAttributeValidatingErrorMessageParameters(objectClassName, attributeName);
 501  0
                             GlobalVariables.getMessageMap().putError(KNSConstants.LOOKUP_RANGE_LOWER_BOUND_PROPERTY_PREFIX + errorKey, errorMessageKey + ".range", errorMessageParameters);
 502  
                     }
 503  
         }
 504  0
     }
 505  
 
 506  
     /**
 507  
      * @see org.kuali.rice.kns.service.DictionaryValidationService#validateAttributeRequired
 508  
      */
 509  
     public void validateAttributeRequired(String objectClassName, String attributeName, Object attributeValue, Boolean forMaintenance, String errorKey) {
 510  
         // check if field is a required field for the business object
 511  0
         if (attributeValue == null || (attributeValue instanceof String && StringUtils.isBlank((String) attributeValue))) {
 512  0
             Boolean required = getDataDictionaryService().isAttributeRequired(objectClassName, attributeName);
 513  0
             ControlDefinition controlDef = getDataDictionaryService().getAttributeControlDefinition(objectClassName, attributeName);
 514  
 
 515  0
             if (required != null && required.booleanValue() && !(controlDef != null && controlDef.isHidden())) {
 516  
 
 517  
                 // get label of attribute for message
 518  0
                 String errorLabel = getDataDictionaryService().getAttributeErrorLabel(objectClassName, attributeName);
 519  0
                 GlobalVariables.getMessageMap().putError(errorKey, RiceKeyConstants.ERROR_REQUIRED, errorLabel);
 520  
             }
 521  
         }
 522  0
     }
 523  
 
 524  
     /**
 525  
      * iterates through the property discriptors looking for business objects or lists of business objects. calls validate method
 526  
      * for each bo found
 527  
      * 
 528  
      * @param object
 529  
      * @param propertyDescriptors
 530  
      */
 531  
     private void validateBusinessObjectsFromDescriptors(Object object, PropertyDescriptor[] propertyDescriptors, int depth) {
 532  0
         for (PropertyDescriptor propertyDescriptor : propertyDescriptors) {
 533  
             // validate the properties that are descended from BusinessObject
 534  0
             if (propertyDescriptor.getPropertyType() != null && PersistableBusinessObject.class.isAssignableFrom(propertyDescriptor.getPropertyType()) && ObjectUtils.getPropertyValue(object, propertyDescriptor.getName()) != null) {
 535  0
                 BusinessObject bo = (BusinessObject) ObjectUtils.getPropertyValue(object, propertyDescriptor.getName());
 536  0
                 if (depth == 0) {
 537  0
                     GlobalVariables.getMessageMap().addToErrorPath(propertyDescriptor.getName());
 538  0
                     validateBusinessObject(bo);
 539  0
                     GlobalVariables.getMessageMap().removeFromErrorPath(propertyDescriptor.getName());
 540  
                 }
 541  
                 else {
 542  0
                     validateBusinessObjectsRecursively(bo, depth - 1);
 543  
                 }
 544  0
             }
 545  
 
 546  
             /*
 547  
              * if property is a List, then walk the list and do the validation on each contained object that is a descendent of
 548  
              * BusinessObject
 549  
              */
 550  0
             else if (propertyDescriptor.getPropertyType() != null && (List.class).isAssignableFrom(propertyDescriptor.getPropertyType()) && ObjectUtils.getPropertyValue(object, propertyDescriptor.getName()) != null) {
 551  0
                 List propertyList = (List) ObjectUtils.getPropertyValue(object, propertyDescriptor.getName());
 552  0
                 for (int j = 0; j < propertyList.size(); j++) {
 553  0
                     if (propertyList.get(j) != null && propertyList.get(j) instanceof PersistableBusinessObject) {
 554  0
                         if (depth == 0) {
 555  0
                             GlobalVariables.getMessageMap().addToErrorPath(StringUtils.chomp(propertyDescriptor.getName(), "s") + "[" + (new Integer(j)).toString() + "]");
 556  0
                             validateBusinessObject((BusinessObject) propertyList.get(j));
 557  0
                             GlobalVariables.getMessageMap().removeFromErrorPath(StringUtils.chomp(propertyDescriptor.getName(), "s") + "[" + (new Integer(j)).toString() + "]");
 558  
                         }
 559  
                         else {
 560  0
                             validateBusinessObjectsRecursively((BusinessObject) propertyList.get(j), depth - 1);
 561  
                         }
 562  
                     }
 563  
                 }
 564  
 
 565  
             }
 566  
         }
 567  0
     }
 568  
 
 569  
     /**
 570  
      * iterates through property descriptors looking for primitives types, calls validate format and required check
 571  
      * 
 572  
      * @param entryName
 573  
      * @param object
 574  
      * @param propertyDescriptors
 575  
      * @param errorPrefix
 576  
      */
 577  
     private void validatePrimitivesFromDescriptors(String entryName, Object object, PropertyDescriptor[] propertyDescriptors, String errorPrefix, boolean validateRequired) {
 578  0
         for (PropertyDescriptor propertyDescriptor : propertyDescriptors) {
 579  0
             validatePrimitiveFromDescriptor(entryName, object, propertyDescriptor, errorPrefix, validateRequired);
 580  
         }
 581  0
     }
 582  
 
 583  
     /**
 584  
      * calls validate format and required check for the given propertyDescriptor
 585  
      * 
 586  
      * @param entryName
 587  
      * @param object
 588  
      * @param propertyDescriptor
 589  
      * @param errorPrefix
 590  
      */
 591  
     public void validatePrimitiveFromDescriptor(String entryName, Object object, PropertyDescriptor propertyDescriptor, String errorPrefix, boolean validateRequired) {
 592  
         // validate the primitive attributes if defined in the dictionary
 593  0
         if (null != propertyDescriptor && getDataDictionaryService().isAttributeDefined(entryName, propertyDescriptor.getName())) {
 594  0
             Object value = ObjectUtils.getPropertyValue(object, propertyDescriptor.getName());
 595  0
             Class propertyType = propertyDescriptor.getPropertyType();
 596  
 
 597  0
             if (TypeUtils.isStringClass(propertyType) || TypeUtils.isIntegralClass(propertyType) || TypeUtils.isDecimalClass(propertyType) || TypeUtils.isTemporalClass(propertyType)) {
 598  
 
 599  
                 // check value format against dictionary
 600  0
                 if (value != null && StringUtils.isNotBlank(value.toString())) {
 601  0
                     if (!TypeUtils.isTemporalClass(propertyType)) {
 602  0
                         validateAttributeFormat(entryName, propertyDescriptor.getName(), value.toString(), errorPrefix + propertyDescriptor.getName());
 603  
                     }
 604  
                 }
 605  0
                 else if (validateRequired) {
 606  0
                     validateAttributeRequired(entryName, propertyDescriptor.getName(), value, Boolean.FALSE, errorPrefix + propertyDescriptor.getName());
 607  
                 }
 608  
             }
 609  
         }
 610  0
     }
 611  
 
 612  
     /**
 613  
      * @see org.kuali.rice.kns.service.DictionaryValidationService#validateReferenceExists(org.kuali.rice.kns.bo.BusinessObject,
 614  
      *      org.kuali.rice.kns.datadictionary.ReferenceDefinition)
 615  
      */
 616  
     public boolean validateReferenceExists(BusinessObject bo, ReferenceDefinition reference) {
 617  0
         return validateReferenceExists(bo, reference.getAttributeName());
 618  
     }
 619  
 
 620  
     /**
 621  
      * @see org.kuali.rice.kns.service.DictionaryValidationService#validateReferenceExists(org.kuali.rice.kns.bo.BusinessObject,
 622  
      *      java.lang.String)
 623  
      */
 624  
     public boolean validateReferenceExists(BusinessObject bo, String referenceName) {
 625  
 
 626  
         // attempt to retrieve the specified object from the db
 627  0
         BusinessObject referenceBo = businessObjectService.getReferenceIfExists(bo, referenceName);
 628  
 
 629  
         // if it isnt there, then it doesnt exist, return false
 630  0
         if (ObjectUtils.isNotNull(referenceBo)) {
 631  0
             return true;
 632  
         }
 633  
 
 634  
         // otherwise, it is there, return true
 635  
         else {
 636  0
             return false;
 637  
         }
 638  
 
 639  
     }
 640  
 
 641  
     /**
 642  
      * @see org.kuali.rice.kns.service.DictionaryValidationService#validateReferenceIsActive(org.kuali.rice.kns.bo.BusinessObject,
 643  
      *      org.kuali.rice.kns.datadictionary.ReferenceDefinition)
 644  
      */
 645  
     public boolean validateReferenceIsActive(BusinessObject bo, ReferenceDefinition reference) {
 646  0
         return validateReferenceIsActive(bo, reference.getAttributeName());
 647  
     }
 648  
 
 649  
     /**
 650  
      * @see org.kuali.rice.kns.service.DictionaryValidationService#validateReferenceIsActive(org.kuali.rice.kns.bo.BusinessObject,
 651  
      *      java.lang.String, java.lang.String, boolean)
 652  
      */
 653  
     public boolean validateReferenceIsActive(BusinessObject bo, String referenceName) {
 654  
 
 655  
         // attempt to retrieve the specified object from the db
 656  0
         BusinessObject referenceBo = businessObjectService.getReferenceIfExists(bo, referenceName);
 657  0
         if (referenceBo == null) {
 658  0
                 return false;
 659  
         }
 660  0
         if (!(referenceBo instanceof Inactivateable) || ((Inactivateable) referenceBo).isActive()) {
 661  0
             return true;
 662  
         }else{
 663  0
                 return false;
 664  
         }
 665  
     }
 666  
 
 667  
     /**
 668  
      * @see org.kuali.rice.kns.service.DictionaryValidationService#validateReferenceExistsAndIsActive(org.kuali.rice.kns.bo.BusinessObject,
 669  
      *      org.kuali.rice.kns.datadictionary.ReferenceDefinition)
 670  
      */
 671  
     public boolean validateReferenceExistsAndIsActive(BusinessObject bo, ReferenceDefinition reference) {
 672  0
         boolean success = true;
 673  
         // intelligently use the fieldname from the reference, or get it out
 674  
         // of the dataDictionaryService
 675  
         String displayFieldName;
 676  0
         if (reference.isDisplayFieldNameSet()) {
 677  0
             displayFieldName = reference.getDisplayFieldName();
 678  
         }
 679  
         else {
 680  0
             Class boClass = reference.isCollectionReference() ? reference.getCollectionBusinessObjectClass() : bo.getClass();
 681  0
             displayFieldName = dataDictionaryService.getAttributeLabel(boClass, reference.getAttributeToHighlightOnFail());
 682  
         }
 683  
 
 684  0
         if (reference.isCollectionReference()) {
 685  0
             success = validateCollectionReferenceExistsAndIsActive(bo, reference, displayFieldName, StringUtils.split(reference.getCollection(), "."), null);
 686  
         }
 687  
         else {
 688  0
             success = validateReferenceExistsAndIsActive(bo, reference.getAttributeName(),reference.getAttributeToHighlightOnFail(), displayFieldName);
 689  
         }
 690  0
         return success;
 691  
     }
 692  
 
 693  
     /**
 694  
      * @param bo the object to get the collection from
 695  
      * @param reference the <code>ReferenceDefinition</code> of the collection to validate
 696  
      * @param displayFieldName the name of the field
 697  
      * @param intermediateCollections array containing the path to the collection as tokens
 698  
      * @param pathToAttribute the rebuilt path to the ReferenceDefinition.attributeToHighlightOnFail which includes the index of
 699  
      *        each subcollection
 700  
      * @return
 701  
      */
 702  
     private boolean validateCollectionReferenceExistsAndIsActive(BusinessObject bo, ReferenceDefinition reference, String displayFieldName, String[] intermediateCollections, String pathToAttributeI) {
 703  0
         boolean success = true;
 704  
         Collection<PersistableBusinessObject> referenceCollection;
 705  0
         String collectionName = intermediateCollections[0];
 706  
         // remove current collection from intermediates
 707  0
         intermediateCollections = (String[]) ArrayUtils.removeElement(intermediateCollections, collectionName);
 708  
         try {
 709  0
             referenceCollection = (Collection) PropertyUtils.getProperty(bo, collectionName);
 710  
         }
 711  0
         catch (Exception e) {
 712  0
             throw new RuntimeException(e);
 713  0
         }
 714  0
         int pos = 0;
 715  0
         Iterator<PersistableBusinessObject> iterator = referenceCollection.iterator();
 716  0
         while (iterator.hasNext()) {
 717  0
             String pathToAttribute = StringUtils.defaultString(pathToAttributeI) + collectionName + "[" + (pos++) + "].";
 718  
             // keep drilling down until we reach the nested collection we want
 719  0
             if (intermediateCollections.length > 0) {
 720  0
                 success &= validateCollectionReferenceExistsAndIsActive(iterator.next(), reference, displayFieldName, intermediateCollections, pathToAttribute);
 721  
             }
 722  
             else {
 723  0
                 String attributeToHighlightOnFail = pathToAttribute + reference.getAttributeToHighlightOnFail();
 724  0
                 success &= validateReferenceExistsAndIsActive(iterator.next(), reference.getAttributeName(), attributeToHighlightOnFail, displayFieldName);
 725  
             }
 726  0
         }
 727  
 
 728  0
         return success;
 729  
 
 730  
     }
 731  
 
 732  
     /**
 733  
      * @see org.kuali.rice.kns.service.DictionaryValidationService#validateReferenceExistsAndIsActive(org.kuali.rice.kns.bo.BusinessObject,
 734  
      *      java.lang.String, java.lang.String, boolean, boolean, java.lang.String, java.lang.String)
 735  
      */
 736  
 
 737  
     public boolean validateReferenceExistsAndIsActive(BusinessObject bo, String referenceName, String attributeToHighlightOnFail, String displayFieldName) {
 738  
             
 739  
             // if we're dealing with a nested attribute, we need to resolve down to the BO where the primitive attribute is located
 740  
             // this is primarily to deal with the case of a defaultExistenceCheck that uses an "extension", i.e referenceName
 741  
             // would be extension.attributeName
 742  0
             if (ObjectUtils.isNestedAttribute(referenceName)) {
 743  0
                     String nestedAttributePrefix = ObjectUtils.getNestedAttributePrefix(referenceName);
 744  0
                     String nestedAttributePrimitive = ObjectUtils.getNestedAttributePrimitive(referenceName);
 745  0
                     Object nestedObject = ObjectUtils.getPropertyValue(bo, nestedAttributePrefix);
 746  0
                     if (!(nestedObject instanceof BusinessObject)) {
 747  0
                             throw new ObjectNotABusinessObjectRuntimeException("Attribute requested (" + nestedAttributePrefix + ") is of class: " + "'" + nestedObject.getClass().getName() + "' and is not a " + "descendent of BusinessObject.");
 748  
                     }
 749  0
                     return validateReferenceExistsAndIsActive((BusinessObject)nestedObject, nestedAttributePrimitive, attributeToHighlightOnFail, displayFieldName);
 750  
             }
 751  
             
 752  0
         boolean success = true;
 753  
         boolean exists;
 754  
         boolean active;
 755  
 
 756  0
         boolean fkFieldsPopulated = true;
 757  
         // need to check for DD relationship FKs
 758  0
         List<String> fkFields = getDataDictionaryService().getRelationshipSourceAttributes(bo.getClass().getName(), referenceName);
 759  0
         if (fkFields != null) {
 760  0
             for (String fkFieldName : fkFields) {
 761  0
                 Object fkFieldValue = null;
 762  
                 try {
 763  0
                     fkFieldValue = PropertyUtils.getProperty(bo, fkFieldName);
 764  
                 }
 765  
                 // if we cant retrieve the field value, then
 766  
                 // it doesnt have a value
 767  0
                 catch (IllegalAccessException e) {
 768  0
                     fkFieldsPopulated = false;
 769  
                 }
 770  0
                 catch (InvocationTargetException e) {
 771  0
                     fkFieldsPopulated = false;
 772  
                 }
 773  0
                 catch (NoSuchMethodException e) {
 774  0
                     fkFieldsPopulated = false;
 775  0
                 }
 776  
 
 777  
                 // test the value
 778  0
                 if (fkFieldValue == null) {
 779  0
                     fkFieldsPopulated = false;
 780  
                 }
 781  0
                 else if (String.class.isAssignableFrom(fkFieldValue.getClass())) {
 782  0
                     if (StringUtils.isBlank((String) fkFieldValue)) {
 783  0
                         fkFieldsPopulated = false;
 784  
                     }
 785  
                 }
 786  0
             }
 787  
         }
 788  0
         else if ( bo instanceof PersistableBusinessObject ) { // if no DD relationship exists, check the persistence service
 789  0
             fkFieldsPopulated = persistenceService.allForeignKeyValuesPopulatedForReference((PersistableBusinessObject)bo, referenceName);
 790  
         }
 791  
 
 792  
         // only bother if all the fk fields have values
 793  0
         if (fkFieldsPopulated) {
 794  
 
 795  
             // do the existence test
 796  0
             exists = validateReferenceExists(bo, referenceName);
 797  0
             if (exists) {
 798  
 
 799  
                 // do the active test, if appropriate
 800  0
                 if (!(bo instanceof Inactivateable) || ((Inactivateable) bo).isActive()) {
 801  0
                     active = validateReferenceIsActive(bo, referenceName);
 802  0
                     if (!active) {
 803  0
                         GlobalVariables.getMessageMap().putError(attributeToHighlightOnFail, RiceKeyConstants.ERROR_INACTIVE, displayFieldName);
 804  0
                         success &= false;
 805  
                     }
 806  
                 }
 807  
             }
 808  
             else {
 809  0
                 GlobalVariables.getMessageMap().putError(attributeToHighlightOnFail, RiceKeyConstants.ERROR_EXISTENCE, displayFieldName);
 810  0
                 success &= false;
 811  
             }
 812  
         }
 813  0
         return success;
 814  
     }
 815  
 
 816  
     /**
 817  
      * @see org.kuali.rice.kns.service.DictionaryValidationService#validateDefaultExistenceChecks(org.kuali.rice.kns.bo.BusinessObject)
 818  
      */
 819  
     public boolean validateDefaultExistenceChecks(BusinessObject bo) {
 820  
 
 821  0
         boolean success = true;
 822  
 
 823  
         // get a collection of all the referenceDefinitions setup for this object
 824  0
         Collection references = maintenanceDocumentDictionaryService.getDefaultExistenceChecks(bo.getClass());
 825  
 
 826  
         // walk through the references, doing the tests on each
 827  0
         for (Iterator iter = references.iterator(); iter.hasNext();) {
 828  0
             ReferenceDefinition reference = (ReferenceDefinition) iter.next();
 829  
 
 830  
             // do the existence and validation testing
 831  0
             success &= validateReferenceExistsAndIsActive(bo, reference);
 832  0
         }
 833  0
         return success;
 834  
     }
 835  
     
 836  
     /**
 837  
      * @see org.kuali.rice.kns.service.DictionaryValidationService#validateDefaultExistenceChecksForNewCollectionItem(org.kuali.rice.kns.bo.BusinessObject, org.kuali.rice.kns.bo.BusinessObject, java.lang.String)
 838  
      */
 839  
         public boolean validateDefaultExistenceChecksForNewCollectionItem(BusinessObject bo, BusinessObject newCollectionItem,
 840  
                         String collectionName) {
 841  0
         boolean success = true;
 842  
         
 843  0
         if (StringUtils.isNotBlank(collectionName)) {
 844  
                 // get a collection of all the referenceDefinitions setup for this object
 845  0
                 Collection references = maintenanceDocumentDictionaryService.getDefaultExistenceChecks(bo.getClass());
 846  
         
 847  
                 // walk through the references, doing the tests on each
 848  0
                 for (Iterator iter = references.iterator(); iter.hasNext();) {
 849  0
                     ReferenceDefinition reference = (ReferenceDefinition) iter.next();
 850  0
                                 if(collectionName != null && collectionName.equals(reference.getCollection())){
 851  
                                         String displayFieldName;
 852  0
                             if (reference.isDisplayFieldNameSet()) {
 853  0
                                 displayFieldName = reference.getDisplayFieldName();
 854  
                             }
 855  
                             else {
 856  0
                                 Class boClass = reference.isCollectionReference() ? reference.getCollectionBusinessObjectClass() : bo.getClass();
 857  0
                                 displayFieldName = dataDictionaryService.getAttributeLabel(boClass, reference.getAttributeToHighlightOnFail());
 858  
                             }
 859  
                 
 860  0
                             success &= validateReferenceExistsAndIsActive(newCollectionItem, reference.getAttributeName(), reference.getAttributeToHighlightOnFail(), displayFieldName);
 861  
                                 }
 862  0
                 }
 863  
         }
 864  
         
 865  0
         return success;
 866  
         }
 867  
 
 868  
         /**
 869  
          * This overridden method ...
 870  
          * 
 871  
          * @see org.kuali.rice.kns.service.DictionaryValidationService#validateDefaultExistenceChecksForTransDoc(org.kuali.rice.kns.document.TransactionalDocument)
 872  
          */
 873  
         public boolean validateDefaultExistenceChecksForTransDoc(TransactionalDocument document) {
 874  0
         boolean success = true;
 875  
 
 876  
         // get a collection of all the referenceDefinitions setup for this object
 877  0
         Collection references = transactionalDocumentDictionaryService.getDefaultExistenceChecks(document);
 878  
 
 879  
         // walk through the references, doing the tests on each
 880  0
         for (Iterator iter = references.iterator(); iter.hasNext();) {
 881  0
             ReferenceDefinition reference = (ReferenceDefinition) iter.next();
 882  
 
 883  
             // do the existence and validation testing
 884  0
             success &= validateReferenceExistsAndIsActive(document.getDocumentBusinessObject(), reference);
 885  0
         }
 886  0
         return success;
 887  
         }
 888  
 
 889  
 
 890  
         /**
 891  
          * This overridden method ...
 892  
          * 
 893  
          * @see org.kuali.rice.kns.service.DictionaryValidationService#validateDefaultExistenceChecksForNewCollectionItem(org.kuali.rice.kns.document.TransactionalDocument, org.kuali.rice.kns.bo.PersistableBusinessObject)
 894  
          */
 895  
         public boolean validateDefaultExistenceChecksForNewCollectionItem(
 896  
                         TransactionalDocument document,
 897  
                         BusinessObject newCollectionItem, String collectionName) {
 898  0
         boolean success = true;
 899  0
         if (StringUtils.isNotBlank(collectionName)) {
 900  
                 // get a collection of all the referenceDefinitions setup for this object
 901  0
                 Collection references = transactionalDocumentDictionaryService.getDefaultExistenceChecks(document);
 902  
         
 903  
                 // walk through the references, doing the tests on each
 904  0
                 for (Iterator iter = references.iterator(); iter.hasNext();) {
 905  0
                     ReferenceDefinition reference = (ReferenceDefinition) iter.next();
 906  0
                                 if(collectionName != null && collectionName.equals(reference.getCollection())){
 907  
                                         String displayFieldName;
 908  0
                             if (reference.isDisplayFieldNameSet()) {
 909  0
                                 displayFieldName = reference.getDisplayFieldName();
 910  
                             }
 911  
                             else {
 912  0
                                 Class boClass = reference.isCollectionReference() ? reference.getCollectionBusinessObjectClass() : document.getDocumentBusinessObject().getClass();
 913  0
                                 displayFieldName = dataDictionaryService.getAttributeLabel(boClass, reference.getAttributeToHighlightOnFail());
 914  
                             }
 915  
                 
 916  0
                             success &= validateReferenceExistsAndIsActive(newCollectionItem, reference.getAttributeName(), reference.getAttributeToHighlightOnFail(), displayFieldName);
 917  
                                 }
 918  0
                 }
 919  
         }
 920  0
         return success;
 921  
         }
 922  
 
 923  
         /**
 924  
      * @see org.kuali.rice.kns.service.DictionaryValidationService#validateApcRule(org.kuali.rice.kns.bo.BusinessObject,
 925  
      *      org.kuali.rice.kns.datadictionary.ApcRuleDefinition)
 926  
      */
 927  
     public boolean validateApcRule(BusinessObject bo, ApcRuleDefinition apcRule) {
 928  0
         boolean success = true;
 929  
         Object attrValue;
 930  
         try {
 931  0
             attrValue = PropertyUtils.getSimpleProperty(bo, apcRule.getAttributeName());
 932  
             // if the value we get back is null that means that the user didn't fill anything in
 933  
             // so the rule shouldn't fail because of this
 934  0
             if (StringUtils.isEmpty((String) attrValue)) {
 935  0
                 return success;
 936  
             }
 937  
         }
 938  0
         catch (Exception e) {
 939  0
             throw new RuntimeException(e);
 940  0
         }
 941  
 
 942  0
         String attrValueStr = attrValue.toString();
 943  0
         if (!KNSServiceLocator.getParameterService().getParameterEvaluator(apcRule.getParameterNamespace(), apcRule.getParameterDetailType(), apcRule.getParameterName(), attrValueStr).evaluationSucceeds()) {
 944  
         //if (!configService.evaluateConstrainedValue(apcRule.getParameterNamespace(), apcRule.getParameterDetailType(), apcRule.getParameterName(),attrValueStr)) {
 945  0
             success &= false;
 946  0
             GlobalVariables.getMessageMap().putError(apcRule.getAttributeName(), apcRule.getErrorMessage());
 947  
         }
 948  
 
 949  0
         return success;
 950  
     }
 951  
 
 952  
     /**
 953  
      * @see org.kuali.rice.kns.service.DictionaryValidationService#validateApcRules(org.kuali.rice.kns.bo.BusinessObject)
 954  
      */
 955  
     public boolean validateApcRules(BusinessObject bo) {
 956  0
         boolean success = true;
 957  
 
 958  
         // get a collection of all the apcRuleDefinitions setup for this object
 959  0
         Collection rules = maintenanceDocumentDictionaryService.getApplyApcRules(bo.getClass());
 960  
 
 961  
         // walk through the rules, doing the tests on each
 962  0
         for (Iterator iter = rules.iterator(); iter.hasNext();) {
 963  0
             ApcRuleDefinition rule = (ApcRuleDefinition) iter.next();
 964  
 
 965  
             // do the existence and validation testing
 966  0
             success &= validateApcRule(bo, rule);
 967  0
         }
 968  0
         return success;
 969  
     }
 970  
 
 971  
 
 972  
     /**
 973  
      * @return Returns the dataDictionaryService.
 974  
      */
 975  
     public DataDictionaryService getDataDictionaryService() {
 976  0
         return dataDictionaryService;
 977  
     }
 978  
 
 979  
     /**
 980  
      * @param dataDictionaryService The dataDictionaryService to set.
 981  
      */
 982  
     public void setDataDictionaryService(DataDictionaryService dataDictionaryService) {
 983  0
         this.dataDictionaryService = dataDictionaryService;
 984  0
     }
 985  
 
 986  
     /**
 987  
      * Sets the businessObjectService attribute value.
 988  
      * 
 989  
      * @param businessObjectService The businessObjectService to set.
 990  
      */
 991  
     public void setBusinessObjectService(BusinessObjectService businessObjectService) {
 992  0
         this.businessObjectService = businessObjectService;
 993  0
     }
 994  
 
 995  
     /**
 996  
      * Sets the maintenanceDocumentDictionaryService attribute value.
 997  
      * 
 998  
      * @param maintenanceDocumentDictionaryService The maintenanceDocumentDictionaryService to set.
 999  
      */
 1000  
     public void setMaintenanceDocumentDictionaryService(MaintenanceDocumentDictionaryService maintenanceDocumentDictionaryService) {
 1001  0
         this.maintenanceDocumentDictionaryService = maintenanceDocumentDictionaryService;
 1002  0
     }
 1003  
 
 1004  
 
 1005  
     /**
 1006  
          * @param transactionalDocumentDictionaryService the transactionalDocumentDictionaryService to set
 1007  
          */
 1008  
         public void setTransactionalDocumentDictionaryService(
 1009  
                         TransactionalDocumentDictionaryService transactionalDocumentDictionaryService) {
 1010  0
                 this.transactionalDocumentDictionaryService = transactionalDocumentDictionaryService;
 1011  0
         }
 1012  
 
 1013  
 
 1014  
         /**
 1015  
      * Sets the persistenceService attribute value.
 1016  
      * 
 1017  
      * @param persistenceService The persistenceService to set.
 1018  
      */
 1019  
     public void setPersistenceService(PersistenceService persistenceService) {
 1020  0
         this.persistenceService = persistenceService;
 1021  0
     }
 1022  
 
 1023  
     public void setPersistenceStructureService(PersistenceStructureService persistenceStructureService) {
 1024  0
         this.persistenceStructureService = persistenceStructureService;
 1025  0
     }
 1026  
 
 1027  
     private WorkflowAttributePropertyResolutionService getWorkflowAttributePropertyResolutionService() {
 1028  0
             if (workflowAttributePropertyResolutionService == null) {
 1029  0
                     workflowAttributePropertyResolutionService = KNSServiceLocator.getWorkflowAttributePropertyResolutionService();
 1030  
             }
 1031  0
             return workflowAttributePropertyResolutionService;
 1032  
     }
 1033  
 }