001/**
002 * Copyright 2005-2018 The Kuali Foundation
003 *
004 * Licensed under the Educational Community License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.opensource.org/licenses/ecl2.php
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016package org.kuali.rice.krad.datadictionary.validation.processor;
017
018import org.kuali.rice.core.api.data.DataType;
019import org.kuali.rice.core.api.util.RiceKeyConstants;
020import org.kuali.rice.krad.datadictionary.exception.AttributeValidationException;
021import org.kuali.rice.krad.datadictionary.validation.AttributeValueReader;
022import org.kuali.rice.krad.datadictionary.validation.ValidationUtils;
023import org.kuali.rice.krad.datadictionary.validation.constraint.Constraint;
024import org.kuali.rice.krad.datadictionary.validation.constraint.DataTypeConstraint;
025import org.kuali.rice.krad.datadictionary.validation.result.ConstraintValidationResult;
026import org.kuali.rice.krad.datadictionary.validation.result.DictionaryValidationResult;
027import org.kuali.rice.krad.datadictionary.validation.result.ProcessorResult;
028
029/**
030 * DataTypeConstraintProcessor processes constraints of type {@link DataTypeConstraint}
031 *
032 * @author Kuali Rice Team (rice.collab@kuali.org)
033 */
034public class DataTypeConstraintProcessor extends MandatoryElementConstraintProcessor<DataTypeConstraint> {
035
036    private static final String CONSTRAINT_NAME = "data type constraint";
037
038    /**
039     * @see org.kuali.rice.krad.datadictionary.validation.processor.ConstraintProcessor#process(org.kuali.rice.krad.datadictionary.validation.result.DictionaryValidationResult,
040     *      Object, org.kuali.rice.krad.datadictionary.validation.constraint.Constraint,
041     *      org.kuali.rice.krad.datadictionary.validation.AttributeValueReader)
042     */
043    @Override
044    public ProcessorResult process(DictionaryValidationResult result, Object value, DataTypeConstraint constraint,
045            AttributeValueReader attributeValueReader) throws AttributeValidationException {
046
047        DataType dataType = constraint.getDataType();
048
049        return new ProcessorResult(processDataTypeConstraint(result, dataType, value, attributeValueReader));
050    }
051
052    @Override
053    public String getName() {
054        return CONSTRAINT_NAME;
055    }
056
057    /**
058     * @see org.kuali.rice.krad.datadictionary.validation.processor.ConstraintProcessor#getConstraintType()
059     */
060    @Override
061    public Class<? extends Constraint> getConstraintType() {
062        return DataTypeConstraint.class;
063    }
064
065    /**
066     * validates the value provided using {@code DataTypeConstraint}
067     *
068     * @param result - a holder for any already run validation results
069     * @param dataType - the expected data type
070     * @param value - the value to validate
071     * @param attributeValueReader - provides access to the attribute being validated
072     * @return the passed in result, updated with the results of the processing
073     */
074    protected ConstraintValidationResult processDataTypeConstraint(DictionaryValidationResult result, DataType dataType,
075            Object value, AttributeValueReader attributeValueReader) {
076        if (dataType == null) {
077            return result.addNoConstraint(attributeValueReader, CONSTRAINT_NAME);
078        }
079
080        if (ValidationUtils.isNullOrEmpty(value)) {
081            return result.addSkipped(attributeValueReader, CONSTRAINT_NAME);
082        }
083
084        try {
085            ValidationUtils.convertToDataType(value, dataType, dateTimeService);
086        } catch (Exception e) {
087            switch (dataType) {
088                case BOOLEAN:
089                    return result.addError(attributeValueReader, CONSTRAINT_NAME, RiceKeyConstants.ERROR_BOOLEAN);
090                case INTEGER:
091                    return result.addError(attributeValueReader, CONSTRAINT_NAME, RiceKeyConstants.ERROR_INTEGER);
092                case LONG:
093                    return result.addError(attributeValueReader, CONSTRAINT_NAME, RiceKeyConstants.ERROR_LONG);
094                case DOUBLE:
095                    return result.addError(attributeValueReader, CONSTRAINT_NAME, RiceKeyConstants.ERROR_BIG_DECIMAL);
096                case FLOAT:
097                    return result.addError(attributeValueReader, CONSTRAINT_NAME, RiceKeyConstants.ERROR_BIG_DECIMAL);
098                case TRUNCATED_DATE:
099                case DATE:
100                    return result.addError(attributeValueReader, CONSTRAINT_NAME, RiceKeyConstants.ERROR_BIG_DECIMAL);
101                case STRING:
102            }
103        }
104
105        // If we get here then it was a success!
106        return result.addSuccess(attributeValueReader, CONSTRAINT_NAME);
107    }
108
109}