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.util.RiceKeyConstants; 019import org.kuali.rice.krad.datadictionary.exception.AttributeValidationException; 020import org.kuali.rice.krad.datadictionary.validation.AttributeValueReader; 021import org.kuali.rice.krad.datadictionary.validation.DictionaryObjectAttributeValueReader; 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.ExistenceConstraint; 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 * @author Kuali Rice Team (rice.collab@kuali.org) 031 */ 032public class ExistenceConstraintProcessor extends OptionalElementConstraintProcessor<ExistenceConstraint> { 033 034 private static final String CONSTRAINT_NAME = "existence constraint"; 035 036 /** 037 * @see org.kuali.rice.krad.datadictionary.validation.processor.ConstraintProcessor#process(org.kuali.rice.krad.datadictionary.validation.result.DictionaryValidationResult, 038 * Object, org.kuali.rice.krad.datadictionary.validation.constraint.Constraint, 039 * org.kuali.rice.krad.datadictionary.validation.AttributeValueReader) \ 040 */ 041 @Override 042 public ProcessorResult process(DictionaryValidationResult result, Object value, ExistenceConstraint constraint, 043 AttributeValueReader attributeValueReader) throws AttributeValidationException { 044 045 // To accommodate the needs of other processors, the ConstraintProcessor.process() method returns a list of ConstraintValidationResult objects 046 // but since a definition that is existence constrained only provides a single isRequired field, there is effectively a single constraint 047 // being imposed. 048 return new ProcessorResult(processSingleExistenceConstraint(result, value, constraint, attributeValueReader)); 049 } 050 051 @Override 052 public String getName() { 053 return CONSTRAINT_NAME; 054 } 055 056 /** 057 * @see org.kuali.rice.krad.datadictionary.validation.processor.ConstraintProcessor#getConstraintType() 058 */ 059 @Override 060 public Class<? extends Constraint> getConstraintType() { 061 return ExistenceConstraint.class; 062 } 063 064 protected ConstraintValidationResult processSingleExistenceConstraint(DictionaryValidationResult result, 065 Object value, ExistenceConstraint constraint, 066 AttributeValueReader attributeValueReader) throws AttributeValidationException { 067 // If it's not set, then there's no constraint 068 if (constraint.isRequired() == null) { 069 return result.addNoConstraint(attributeValueReader, CONSTRAINT_NAME); 070 } 071 072 if (constraint.isRequired().booleanValue() && !skipConstraint(attributeValueReader)) { 073 // If this attribute is required and the value is null then 074 if (ValidationUtils.isNullOrEmpty(value)) { 075 String errorParameter = attributeValueReader.getLabel(attributeValueReader.getAttributeName()); 076 if (ValidationUtils.isNullOrEmpty(errorParameter)) { 077 errorParameter = attributeValueReader.getAttributeName(); 078 } 079 return result.addError(attributeValueReader, CONSTRAINT_NAME, RiceKeyConstants.ERROR_REQUIRED, 080 errorParameter); 081 } 082 return result.addSuccess(attributeValueReader, CONSTRAINT_NAME); 083 } 084 085 return result.addSkipped(attributeValueReader, CONSTRAINT_NAME); 086 } 087 088 /** 089 * Checks to see if existence constraint should be skipped. Required constraint should be skipped if it is an 090 * attribute of a complex 091 * attribute and the complex attribute is not required. 092 * 093 * @param attributeValueReader 094 * @return true if the constraint should be skipped 095 */ 096 private boolean skipConstraint(AttributeValueReader attributeValueReader) { 097 boolean skipConstraint = false; 098 if (attributeValueReader instanceof DictionaryObjectAttributeValueReader) { 099 DictionaryObjectAttributeValueReader dictionaryValueReader = 100 (DictionaryObjectAttributeValueReader) attributeValueReader; 101 skipConstraint = dictionaryValueReader.isNestedAttribute() && dictionaryValueReader.isParentAttributeNull(); 102 } 103 return skipConstraint; 104 } 105 106}