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