/*
* The Kuali Financial System, a comprehensive financial management system for higher education.
*
* Copyright 2005-2014 The Kuali Foundation
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.kuali.kfs.sys.document.validation.impl;
import java.util.Collection;
import java.util.Iterator;
import org.kuali.kfs.sys.document.validation.Validation;
import org.kuali.kfs.sys.document.validation.event.AttributedDocumentEvent;
import org.kuali.rice.krad.rules.rule.event.KualiDocumentEvent;
import org.kuali.rice.krad.util.GlobalVariables;
import org.kuali.rice.krad.util.ObjectUtils;
/**
* A validation that runs a list of child validations over each member of a collection.
*/
public class CollectionValidation extends CompositeValidation {
protected String collectionProperty;
protected boolean removeCollectionPropretyPluralization = true;
/**
* Iterates over each member of the collection, which is assumed to be the property of the validation event named by the given collectionProperty
* @see org.kuali.kfs.sys.document.validation.impl.CompositeValidation#validate(java.lang.Object[])
*/
@Override
public boolean validate(AttributedDocumentEvent event) {
boolean result = true;
if (collectionProperty == null) {
throw new IllegalStateException("collectionProperty must not be null");
}
Iterator iter = getCollection(event).iterator();
// hold on to any existing iteration subject until after we're done doing our thing
Object parentIterationSubject = event.getIterationSubject();
int count = 0;
while (iter.hasNext()) {
result &= validateEachObject(event, iter.next(), count);
count += 1;
}
event.setIterationSubject(parentIterationSubject); // or back to null if the event didn't have an iteration subject in the first place
return result;
}
/**
* Validates each object in the collection
* @param event the event to validate against
* @param objectToValidate the object from the collection which is being validated
* @return true if object passed all child sub-validations, false otherwise
*/
protected boolean validateEachObject(AttributedDocumentEvent event, Object objectToValidate, int count) {
boolean result = true;
String errorPath = buildPropertyName(count);
GlobalVariables.getMessageMap().addToErrorPath(errorPath);
boolean currentResult = true;
event.setIterationSubject(objectToValidate);
for (Validation validation: getValidations()) {
currentResult = validation.stageValidation(event);
result &= currentResult;
if (!currentResult && validation.shouldQuitOnFail()) {
break;
}
}
GlobalVariables.getMessageMap().removeFromErrorPath(errorPath);
return result;
}
/**
* Here's a hack for all my homies: this method builds the property name of a specific item in a collection by chopping the presumed "s" at the end of collectionProperties,
* and then attaches array/list syntax to it to hold the count. It'll work for most stuff, won't it? If it doesn't, set removeCollectionPropretyPluralization to false
* @params count the count of the current item in the collection
* @return
*/
protected String buildPropertyName(int count) {
String collectionProp = collectionProperty;
if (isRemoveCollectionPropretyPluralization()) {
collectionProp = collectionProperty.substring(0, collectionProperty.length()-1);
}
return new StringBuilder().append(collectionProp).append('[').append(count).append(']').toString();
}
/**
* Based on the collection property, finds the events
* @param event
* @return
*/
protected Collection getCollection(KualiDocumentEvent event) {
return (Collection)ObjectUtils.getPropertyValue(event, collectionProperty);
}
/**
* Gets the collectionProperty attribute.
* @return Returns the collectionProperty.
*/
public String getCollectionProperty() {
return collectionProperty;
}
/**
* Sets the collectionProperty attribute value.
* @param collectionProperty The collectionProperty to set.
*/
public void setCollectionProperty(String collectionProperty) {
this.collectionProperty = collectionProperty;
}
public boolean isRemoveCollectionPropretyPluralization() {
return removeCollectionPropretyPluralization;
}
public void setRemoveCollectionPropretyPluralization(boolean removeCollectionPropretyPluralization) {
this.removeCollectionPropretyPluralization = removeCollectionPropretyPluralization;
}
}