Coverage Report - org.kuali.rice.kns.service.impl.DictionaryValidationServiceImpl
 
Classes in this File Line Coverage Branch Coverage Complexity
DictionaryValidationServiceImpl
0%
0/114
0%
0/76
10.4
 
 1  
 /**
 2  
  * Copyright 2005-2011 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 org.apache.commons.beanutils.PropertyUtils;
 19  
 import org.apache.commons.lang.StringUtils;
 20  
 import org.kuali.rice.core.api.CoreApiServiceLocator;
 21  
 import org.kuali.rice.core.api.util.RiceKeyConstants;
 22  
 import org.kuali.rice.core.framework.persistence.jdbc.sql.SQLUtils;
 23  
 import org.kuali.rice.core.web.format.DateFormatter;
 24  
 import org.kuali.rice.kns.datadictionary.MaintenanceDocumentEntry;
 25  
 import org.kuali.rice.kns.datadictionary.validation.MaintenanceDocumentAttributeValueReader;
 26  
 import org.kuali.rice.kns.service.DictionaryValidationService;
 27  
 import org.kuali.rice.krad.bo.BusinessObject;
 28  
 import org.kuali.rice.krad.datadictionary.control.ControlDefinition;
 29  
 import org.kuali.rice.krad.document.Document;
 30  
 import org.kuali.rice.krad.service.KRADServiceLocatorWeb;
 31  
 import org.kuali.rice.krad.util.GlobalVariables;
 32  
 import org.kuali.rice.krad.util.KRADConstants;
 33  
 
 34  
 import java.lang.reflect.Method;
 35  
 import java.math.BigDecimal;
 36  
 import java.util.List;
 37  
 import java.util.regex.Pattern;
 38  
 
 39  
 /**
 40  
  * @author Kuali Rice Team (rice.collab@kuali.org)
 41  
  */
 42  
 @Deprecated
 43  0
 public class DictionaryValidationServiceImpl extends org.kuali.rice.krad.service.impl.DictionaryValidationServiceImpl implements DictionaryValidationService {
 44  0
     private static org.apache.log4j.Logger LOG =
 45  
             org.apache.log4j.Logger.getLogger(DictionaryValidationServiceImpl.class);
 46  
 
 47  
     /**
 48  
      * @see org.kuali.rice.krad.service.DictionaryValidationService#validateDocumentRecursively
 49  
      */
 50  
     @Deprecated
 51  
     public void validateDocumentRecursively(Document document, int depth) {
 52  
         // validate primitives of document
 53  0
         validateDocument(document);
 54  
 
 55  
         // call method to recursively find business objects and validate
 56  0
         validateBusinessObjectsFromDescriptors(document, PropertyUtils.getPropertyDescriptors(document.getClass()),
 57  
                 depth);
 58  0
     }
 59  
 
 60  
     /**
 61  
      * @see org.kuali.rice.krad.service.DictionaryValidationService#validateBusinessObjectOnMaintenanceDocument(org.kuali.rice.krad.bo.BusinessObject,
 62  
      *      java.lang.String)
 63  
      * @deprecated since 1.1
 64  
      */
 65  
     @Deprecated
 66  
     public void validateBusinessObjectOnMaintenanceDocument(BusinessObject businessObject, String docTypeName) {
 67  
 
 68  0
         MaintenanceDocumentEntry entry = (MaintenanceDocumentEntry)
 69  
                 KRADServiceLocatorWeb.getDocumentDictionaryService().getMaintenanceDocumentEntry(docTypeName);
 70  0
         validate(new MaintenanceDocumentAttributeValueReader(businessObject, docTypeName, entry,
 71  
                 persistenceStructureService), true);
 72  0
     }
 73  
 
 74  
 //        protected void validateBusinessObjectOnMaintenanceDocumentHelper(BusinessObject businessObject, List<? extends MaintainableItemDefinition> itemDefinitions, String errorPrefix) {
 75  
 //
 76  
 //                for (MaintainableItemDefinition itemDefinition : itemDefinitions) {
 77  
 //                        if (itemDefinition instanceof MaintainableFieldDefinition) {
 78  
 //                        if (getDataDictionaryService().isAttributeDefined(businessObject.getClass(), itemDefinition.getName())) {
 79  
 //                            Object value = ObjectUtils.getPropertyValue(businessObject, itemDefinition.getName());
 80  
 //                            if (value != null && StringUtils.isNotBlank(value.toString())) {
 81  
 //                                    Class propertyType = ObjectUtils.getPropertyType(businessObject, itemDefinition.getName(), persistenceStructureService);
 82  
 //                                    if (TypeUtils.isStringClass(propertyType) || TypeUtils.isIntegralClass(propertyType) || TypeUtils.isDecimalClass(propertyType) || TypeUtils.isTemporalClass(propertyType)) {
 83  
 //                                        // check value format against dictionary
 84  
 //                                    if (!TypeUtils.isTemporalClass(propertyType)) {
 85  
 //                                        validateAttributeFormat(businessObject.getClass().getName(), itemDefinition.getName(), value.toString(), errorPrefix + itemDefinition.getName());
 86  
 //                                    }
 87  
 //                                    }
 88  
 //                            }
 89  
 //                        }
 90  
 //                        }
 91  
 //                        /*
 92  
 //                        TODO: reenable when we come up with a strategy to handle fields that are not editable
 93  
 //                        else if (itemDefinition instanceof MaintainableCollectionDefinition) {
 94  
 //                                MaintainableCollectionDefinition collectionDefinition = (MaintainableCollectionDefinition) itemDefinition;
 95  
 //                                Collection<BusinessObject> c = (Collection<BusinessObject>) ObjectUtils.getPropertyValue(businessObject, itemDefinition.getName());
 96  
 //                                if (c != null) {
 97  
 //                                        int i = 0;
 98  
 //                                        for (BusinessObject o : c) {
 99  
 //                                                String newErrorPrefix = errorPrefix + itemDefinition.getName() + "[" + i + "].";
 100  
 //                                                validateBusinessObjectOnMaintenanceDocumentHelper(o, collectionDefinition.getMaintainableCollections(), newErrorPrefix);
 101  
 //                                                validateBusinessObjectOnMaintenanceDocumentHelper(o, collectionDefinition.getMaintainableFields(), newErrorPrefix);
 102  
 //                                                i++;
 103  
 //                                        }
 104  
 //                                }
 105  
 //                        }*/
 106  
 //                }
 107  
 //        }
 108  
 
 109  
     /**
 110  
      * @see org.kuali.rice.krad.service.DictionaryValidationService#validateAttributeFormat
 111  
      *      objectClassName is the docTypeName
 112  
      * @deprecated since 1.1
 113  
      */
 114  
     @Deprecated
 115  
     public void validateAttributeFormat(String objectClassName, String attributeName, String attributeInValue,
 116  
             String errorKey) {
 117  
         // 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.
 118  0
         String attributeDataType = null;
 119  
         try {
 120  0
             attributeDataType = getWorkflowAttributePropertyResolutionService().determineFieldDataType(
 121  
                     (Class<? extends BusinessObject>) Class.forName(
 122  
                             getDataDictionaryService().getDataDictionary().getDictionaryObjectEntry(objectClassName)
 123  
                                     .getFullClassName()), attributeName);
 124  0
         } catch (ClassNotFoundException e) {
 125  0
             attributeDataType = KRADConstants.DATA_TYPE_STRING;
 126  0
         } catch (NullPointerException e) {
 127  0
             attributeDataType = KRADConstants.DATA_TYPE_STRING;
 128  0
         }
 129  
 
 130  0
         validateAttributeFormat(objectClassName, attributeName, attributeInValue, attributeDataType, errorKey);
 131  0
     }
 132  
 
 133  
     /**
 134  
      * The attributeDataType parameter should be one of the data types specified by the SearchableAttribute
 135  
      * interface;
 136  
      * will
 137  
      * default to DATA_TYPE_STRING if a data type other than the ones from SearchableAttribute is specified.
 138  
      *
 139  
      * @see org.kuali.rice.krad.service.DictionaryValidationService#validateAttributeFormat(java.lang.String,
 140  
      *      java.lang.String, java.lang.String, java.lang.String, java.lang.String)
 141  
      *      objectClassName is the docTypeName
 142  
      * @deprecated since 1.1
 143  
      */
 144  
     @Deprecated
 145  
     public void validateAttributeFormat(String objectClassName, String attributeName, String attributeInValue,
 146  
             String attributeDataType, String errorKey) {
 147  0
         boolean checkDateBounds = false; // this is used so we can check date bounds
 148  0
         Class<?> formatterClass = null;
 149  
 
 150  0
         if (LOG.isDebugEnabled()) {
 151  0
             LOG.debug("(bo, attributeName, attributeValue) = (" + objectClassName + "," + attributeName + "," +
 152  
                     attributeInValue + ")");
 153  
         }
 154  
 
 155  
         /*
 156  
         *  This will return a list of searchable attributes. so if the value is
 157  
         *  12/07/09 .. 12/08/09 it will return [12/07/09,12/08/09]
 158  
         */
 159  
 
 160  0
         final List<String> attributeValues = SQLUtils.getCleanedSearchableValues(attributeInValue, attributeDataType);
 161  
 
 162  0
         if (attributeValues == null || attributeValues.isEmpty()) {
 163  0
             return;
 164  
         }
 165  
 
 166  0
         for (String attributeValue : attributeValues) {
 167  
 
 168  
             // FIXME: JLR : Replacing this logic with KS-style validation is trickier, since KS validation requires a DataProvider object that can
 169  
             // look back and find other attribute values aside from the one we're working on.
 170  
             // Also - the date stuff below is implemented very differently.
 171  
             //validator.validateAttributeField(businessObject, fieldName);
 172  
 
 173  0
             if (StringUtils.isNotBlank(attributeValue)) {
 174  0
                 Integer minLength = getDataDictionaryService().getAttributeMinLength(objectClassName, attributeName);
 175  0
                 if ((minLength != null) && (minLength.intValue() > attributeValue.length())) {
 176  0
                     String errorLabel =
 177  
                             getDataDictionaryService().getAttributeErrorLabel(objectClassName, attributeName);
 178  0
                     GlobalVariables.getMessageMap().putError(errorKey, RiceKeyConstants.ERROR_MIN_LENGTH,
 179  
                             new String[]{errorLabel, minLength.toString()});
 180  0
                     return;
 181  
                 }
 182  0
                 Integer maxLength = getDataDictionaryService().getAttributeMaxLength(objectClassName, attributeName);
 183  0
                 if ((maxLength != null) && (maxLength.intValue() < attributeValue.length())) {
 184  0
                     String errorLabel =
 185  
                             getDataDictionaryService().getAttributeErrorLabel(objectClassName, attributeName);
 186  0
                     GlobalVariables.getMessageMap().putError(errorKey, RiceKeyConstants.ERROR_MAX_LENGTH,
 187  
                             new String[]{errorLabel, maxLength.toString()});
 188  0
                     return;
 189  
                 }
 190  0
                 Pattern validationExpression =
 191  
                         getDataDictionaryService().getAttributeValidatingExpression(objectClassName, attributeName);
 192  0
                 if (validationExpression != null && !validationExpression.pattern().equals(".*")) {
 193  0
                     if (LOG.isDebugEnabled()) {
 194  0
                         LOG.debug("(bo, attributeName, validationExpression) = (" + objectClassName + "," +
 195  
                                 attributeName + "," + validationExpression + ")");
 196  
                     }
 197  
 
 198  0
                     if (!validationExpression.matcher(attributeValue).matches()) {
 199  
                         // Retrieving formatter class
 200  0
                         if (formatterClass == null) {
 201  
                             // this is just a cache check... all dates ranges get called twice
 202  0
                             formatterClass =
 203  
                                     getDataDictionaryService().getAttributeFormatter(objectClassName, attributeName);
 204  
                         }
 205  
 
 206  0
                         if (formatterClass != null) {
 207  0
                             boolean valuesAreValid = true;
 208  0
                             boolean isError = true;
 209  0
                             String errorKeyPrefix = "";
 210  
                             try {
 211  
 
 212  
                                 // this is a special case for date ranges in order to set the proper error message
 213  0
                                 if (DateFormatter.class.isAssignableFrom(formatterClass)) {
 214  0
                                     String[] values = attributeInValue.split("\\.\\."); // is it a range
 215  0
                                     if (values.length == 2 &&
 216  
                                             attributeValues.size() == 2) { // make sure it's not like a .. b | c
 217  0
                                         checkDateBounds = true; // now we need to check that a <= b
 218  0
                                         if (attributeValues.indexOf(attributeValue) ==
 219  
                                                 0) { // only care about lower bound
 220  0
                                             errorKeyPrefix = KRADConstants.LOOKUP_RANGE_LOWER_BOUND_PROPERTY_PREFIX;
 221  
                                         }
 222  
                                     }
 223  
                                 }
 224  
 
 225  0
                                 Method validatorMethod =
 226  
                                         formatterClass.getDeclaredMethod(VALIDATE_METHOD, new Class<?>[]{String.class});
 227  0
                                 Object o = validatorMethod.invoke(formatterClass.newInstance(), attributeValue);
 228  0
                                 if (o instanceof Boolean) {
 229  0
                                     isError = !((Boolean) o).booleanValue();
 230  
                                 }
 231  0
                                 valuesAreValid &= !isError;
 232  0
                             } catch (Exception e) {
 233  0
                                 if (LOG.isDebugEnabled()) {
 234  0
                                     LOG.debug(e.getMessage(), e);
 235  
                                 }
 236  0
                                 isError = true;
 237  0
                                 valuesAreValid = false;
 238  0
                             }
 239  0
                             if (isError) {
 240  0
                                 checkDateBounds = false; // it's already invalid, no need to check date bounds
 241  0
                                 String errorMessageKey = getDataDictionaryService()
 242  
                                         .getAttributeValidatingErrorMessageKey(objectClassName, attributeName);
 243  0
                                 String[] errorMessageParameters = getDataDictionaryService()
 244  
                                         .getAttributeValidatingErrorMessageParameters(objectClassName, attributeName);
 245  0
                                 GlobalVariables.getMessageMap()
 246  
                                         .putError(errorKeyPrefix + errorKey, errorMessageKey, errorMessageParameters);
 247  
                             }
 248  0
                         } else {
 249  
                             // if it fails the default validation and has no formatter class then it's still a std failure.
 250  0
                             String errorMessageKey = getDataDictionaryService()
 251  
                                     .getAttributeValidatingErrorMessageKey(objectClassName, attributeName);
 252  0
                             String[] errorMessageParameters = getDataDictionaryService()
 253  
                                     .getAttributeValidatingErrorMessageParameters(objectClassName, attributeName);
 254  0
                             GlobalVariables.getMessageMap().putError(errorKey, errorMessageKey, errorMessageParameters);
 255  
                         }
 256  
                     }
 257  
                 }
 258  
                 /*BigDecimal*/
 259  0
                 String exclusiveMin =
 260  
                         getDataDictionaryService().getAttributeExclusiveMin(objectClassName, attributeName);
 261  0
                 if (exclusiveMin != null) {
 262  
                     try {
 263  0
                         BigDecimal exclusiveMinBigDecimal = new BigDecimal(exclusiveMin);
 264  0
                         if (exclusiveMinBigDecimal.compareTo(new BigDecimal(attributeValue)) >= 0) {
 265  0
                             String errorLabel =
 266  
                                     getDataDictionaryService().getAttributeErrorLabel(objectClassName, attributeName);
 267  0
                             GlobalVariables.getMessageMap().putError(errorKey, RiceKeyConstants.ERROR_EXCLUSIVE_MIN,
 268  
                                     // todo: Formatter for currency?
 269  
                                     new String[]{errorLabel, exclusiveMin.toString()});
 270  0
                             return;
 271  
                         }
 272  0
                     } catch (NumberFormatException e) {
 273  
                         // quash; this indicates that the DD contained a min for a non-numeric attribute
 274  0
                     }
 275  
                 }
 276  
                 /*BigDecimal*/
 277  0
                 String inclusiveMax =
 278  
                         getDataDictionaryService().getAttributeInclusiveMax(objectClassName, attributeName);
 279  0
                 if (inclusiveMax != null) {
 280  
                     try {
 281  0
                         BigDecimal inclusiveMaxBigDecimal = new BigDecimal(inclusiveMax);
 282  0
                         if (inclusiveMaxBigDecimal.compareTo(new BigDecimal(attributeValue)) < 0) {
 283  0
                             String errorLabel =
 284  
                                     getDataDictionaryService().getAttributeErrorLabel(objectClassName, attributeName);
 285  0
                             GlobalVariables.getMessageMap().putError(errorKey, RiceKeyConstants.ERROR_INCLUSIVE_MAX,
 286  
                                     // todo: Formatter for currency?
 287  
                                     new String[]{errorLabel, inclusiveMax.toString()});
 288  0
                             return;
 289  
                         }
 290  0
                     } catch (NumberFormatException e) {
 291  
                         // quash; this indicates that the DD contained a max for a non-numeric attribute
 292  0
                     }
 293  
                 }
 294  0
             }
 295  
         }
 296  
 
 297  0
         if (checkDateBounds) {
 298  
             // this means that we only have 2 values and it's a date range.
 299  0
             java.sql.Timestamp lVal = null;
 300  0
             java.sql.Timestamp uVal = null;
 301  
             try {
 302  0
                 lVal = CoreApiServiceLocator.getDateTimeService().convertToSqlTimestamp(attributeValues.get(0));
 303  0
                 uVal = CoreApiServiceLocator.getDateTimeService().convertToSqlTimestamp(attributeValues.get(1));
 304  0
             } catch (Exception ex) {
 305  
                 // this shouldn't happen because the tests passed above.
 306  0
                 String errorMessageKey = getDataDictionaryService()
 307  
                         .getAttributeValidatingErrorMessageKey(objectClassName, attributeName);
 308  0
                 String[] errorMessageParameters = getDataDictionaryService()
 309  
                         .getAttributeValidatingErrorMessageParameters(objectClassName, attributeName);
 310  0
                 GlobalVariables.getMessageMap()
 311  
                         .putError(KRADConstants.LOOKUP_RANGE_LOWER_BOUND_PROPERTY_PREFIX + errorKey, errorMessageKey,
 312  
                                 errorMessageParameters);
 313  0
             }
 314  
 
 315  0
             if (lVal != null && lVal.compareTo(uVal) > 0) { // check the bounds
 316  0
                 String errorMessageKey = getDataDictionaryService()
 317  
                         .getAttributeValidatingErrorMessageKey(objectClassName, attributeName);
 318  0
                 String[] errorMessageParameters = getDataDictionaryService()
 319  
                         .getAttributeValidatingErrorMessageParameters(objectClassName, attributeName);
 320  0
                 GlobalVariables.getMessageMap()
 321  
                         .putError(KRADConstants.LOOKUP_RANGE_LOWER_BOUND_PROPERTY_PREFIX + errorKey,
 322  
                                 errorMessageKey + ".range", errorMessageParameters);
 323  
             }
 324  
         }
 325  0
     }
 326  
 
 327  
     /**
 328  
      * @see org.kuali.rice.krad.service.DictionaryValidationService#validateAttributeRequired
 329  
      */
 330  
     // FIXME: JLR - this is now redundant and should be using the same code as the required processing elsewhere, but the control definition stuff doesn't really fit
 331  
     // it doesn't seem to be used anywhere
 332  
     @Deprecated
 333  
     public void validateAttributeRequired(String objectClassName, String attributeName, Object attributeValue,
 334  
             Boolean forMaintenance, String errorKey) {
 335  
         // check if field is a required field for the business object
 336  0
         if (attributeValue == null ||
 337  
                 (attributeValue instanceof String && StringUtils.isBlank((String) attributeValue))) {
 338  0
             Boolean required = getDataDictionaryService().isAttributeRequired(objectClassName, attributeName);
 339  0
             ControlDefinition controlDef =
 340  
                     getDataDictionaryService().getAttributeControlDefinition(objectClassName, attributeName);
 341  
 
 342  0
             if (required != null && required.booleanValue() && !(controlDef != null && controlDef.isHidden())) {
 343  
 
 344  
                 // get label of attribute for message
 345  0
                 String errorLabel = getDataDictionaryService().getAttributeErrorLabel(objectClassName, attributeName);
 346  0
                 GlobalVariables.getMessageMap().putError(errorKey, RiceKeyConstants.ERROR_REQUIRED, errorLabel);
 347  
             }
 348  
         }
 349  0
     }
 350  
 }