001/** 002 * Copyright 2005-2016 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.ErrorLevel; 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.MustOccurConstraint; 025import org.kuali.rice.krad.datadictionary.validation.constraint.PrerequisiteConstraint; 026import org.kuali.rice.krad.datadictionary.validation.result.ConstraintValidationResult; 027import org.kuali.rice.krad.datadictionary.validation.result.DictionaryValidationResult; 028import org.kuali.rice.krad.datadictionary.validation.result.ProcessorResult; 029 030import java.util.List; 031 032/** 033 * 034 * @author Kuali Rice Team (rice.collab@kuali.org) 035 */ 036public class MustOccurConstraintProcessor extends BasePrerequisiteConstraintProcessor<MustOccurConstraint> { 037 038 private static final String CONSTRAINT_NAME = "must occur constraint"; 039 040 /** 041 * @see org.kuali.rice.krad.datadictionary.validation.processor.ConstraintProcessor#process(org.kuali.rice.krad.datadictionary.validation.result.DictionaryValidationResult, Object, org.kuali.rice.krad.datadictionary.validation.constraint.Constraint, org.kuali.rice.krad.datadictionary.validation.AttributeValueReader) 042 */ 043 @Override 044 public ProcessorResult process(DictionaryValidationResult result, 045 Object value, MustOccurConstraint constraint, AttributeValueReader attributeValueReader) 046 throws AttributeValidationException { 047 048 if (ValidationUtils.isNullOrEmpty(value)) 049 return new ProcessorResult(result.addSkipped(attributeValueReader, CONSTRAINT_NAME)); 050 051 052 ConstraintValidationResult constraintValidationResult = new ConstraintValidationResult(CONSTRAINT_NAME); 053 constraintValidationResult.setConstraintLabelKey(constraint.getLabelKey()); 054 constraintValidationResult.setErrorParameters(constraint.getValidationMessageParamsArray()); 055 056 // If the processing of this constraint is not successful then it's an error 057 if (!processMustOccurConstraint(constraintValidationResult, constraint, attributeValueReader)) { 058 // if attributeName is null, use the entry name since we are processing a must occur constraint that may be referencing multiple attributes 059 if (attributeValueReader.getAttributeName() == null){ 060 constraintValidationResult.setAttributeName(attributeValueReader.getEntryName()); 061 } else{ 062 constraintValidationResult.setAttributeName(attributeValueReader.getAttributeName()); 063 constraintValidationResult.setAttributePath(attributeValueReader.getPath()); 064 } 065 constraintValidationResult.setError(RiceKeyConstants.ERROR_OCCURS); 066 } 067 068 // Store the label key (if one exists) for this constraint on the constraint validation result so it can be shown later 069 070 // Add it to the DictionaryValidationResult object 071 result.addConstraintValidationResult(attributeValueReader, constraintValidationResult); 072 073 return new ProcessorResult(constraintValidationResult); 074 075 } 076 077 @Override 078 public String getName() { 079 return CONSTRAINT_NAME; 080 } 081 082 /** 083 * @see org.kuali.rice.krad.datadictionary.validation.processor.ConstraintProcessor#getConstraintType() 084 */ 085 @Override 086 public Class<? extends Constraint> getConstraintType() { 087 return MustOccurConstraint.class; 088 } 089 090 protected boolean processMustOccurConstraint(ConstraintValidationResult topLevelResult, MustOccurConstraint constraint, AttributeValueReader attributeValueReader) throws AttributeValidationException { 091 092 boolean isSuccessful = false; 093 int trueCount = 0; 094 095 List<PrerequisiteConstraint> prerequisiteConstraints = constraint.getPrerequisiteConstraints(); 096 if (prerequisiteConstraints != null) { 097 for (PrerequisiteConstraint prerequisiteConstraint : prerequisiteConstraints) { 098 ConstraintValidationResult constraintValidationResult = processPrerequisiteConstraint(prerequisiteConstraint, attributeValueReader); 099 constraintValidationResult.setConstraintLabelKey(prerequisiteConstraint.getLabelKey()); 100 constraintValidationResult.setErrorParameters(prerequisiteConstraint.getValidationMessageParamsArray()); 101 // Add the result of each prerequisite constraint validation to the top level result object as a child 102 topLevelResult.addChild(constraintValidationResult); 103 trueCount += (constraintValidationResult.getStatus().getLevel() <= ErrorLevel.WARN.getLevel()) ? 1 : 0; 104 } 105 } 106 107 List<MustOccurConstraint> mustOccurConstraints = constraint.getMustOccurConstraints(); 108 if (mustOccurConstraints != null) { 109 for (MustOccurConstraint mustOccurConstraint : mustOccurConstraints) { 110 // Create a new constraint validation result for this must occur constraint and make it child of the top-level constraint, 111 // then pass it in to the recursive call so that prerequisite constraints can be placed under it 112 ConstraintValidationResult constraintValidationResult = new ConstraintValidationResult(CONSTRAINT_NAME); 113 constraintValidationResult.setConstraintLabelKey(mustOccurConstraint.getLabelKey()); 114 constraintValidationResult.setErrorParameters(mustOccurConstraint.getValidationMessageParamsArray()); 115 topLevelResult.addChild(constraintValidationResult); 116 trueCount += (processMustOccurConstraint(constraintValidationResult, mustOccurConstraint, attributeValueReader)) ? 1 : 0; 117 } 118 } 119 120 int minimum = constraint.getMin() != null ? constraint.getMin().intValue() : 0; 121 int maximum = constraint.getMax() != null ? constraint.getMax().intValue() : 0; 122 123 isSuccessful = (trueCount >= minimum && trueCount <= maximum) ? true : false; 124 125 return isSuccessful; 126 } 127 128}