Author: tv Date: Sat May 12 13:55:26 2007 New Revision: 537514 URL: http://svn.apache.org/viewvc?view=rev&rev=537514 Log: Added two examples for inter-field dependency validators to Intake
Added: jakarta/turbine/core/branches/TURBINE_2_3_BRANCH/src/java/org/apache/turbine/services/intake/validator/CompareCallback.java jakarta/turbine/core/branches/TURBINE_2_3_BRANCH/src/java/org/apache/turbine/services/intake/validator/FieldReference.java jakarta/turbine/core/branches/TURBINE_2_3_BRANCH/src/java/org/apache/turbine/services/intake/validator/IntegerRangeValidator.java Modified: jakarta/turbine/core/branches/TURBINE_2_3_BRANCH/conf/test/intake.xml jakarta/turbine/core/branches/TURBINE_2_3_BRANCH/src/java/org/apache/turbine/services/intake/model/FileItemField.java jakarta/turbine/core/branches/TURBINE_2_3_BRANCH/src/test/org/apache/turbine/services/intake/IntakeServiceTest.java Modified: jakarta/turbine/core/branches/TURBINE_2_3_BRANCH/conf/test/intake.xml URL: http://svn.apache.org/viewvc/jakarta/turbine/core/branches/TURBINE_2_3_BRANCH/conf/test/intake.xml?view=diff&rev=537514&r1=537513&r2=537514 ============================================================================== --- jakarta/turbine/core/branches/TURBINE_2_3_BRANCH/conf/test/intake.xml (original) +++ jakarta/turbine/core/branches/TURBINE_2_3_BRANCH/conf/test/intake.xml Sat May 12 13:55:26 2007 @@ -29,4 +29,28 @@ <rule value="true" name="required">ValidValue</rule> </field> </group> + <group name="DateRangeTest" key="rt"> + <field name="DateMin" key="dmin" type="DateString"> + <rule value="MM/dd/yyyy" name="format">Invalid format</rule> + </field> + <field name="DateMax" key="dmax" type="DateString" + validator="DateRangeValidator"> + <rule value="MM/dd/yyyy" name="format">Invalid format</rule> + <rule value="DateMin" name="greater-than">Value must be greater than DateMin</rule> + </field> + <field name="DateMax2" key="dmax2" type="DateString" + validator="DateRangeValidator"> + <rule value="MM/dd/yyyy" name="format">Invalid format</rule> + <rule value="DateMin" name="less-than">Value must be less than DateMin</rule> + </field> + </group> + <group name="IntRangeTest" key="irt"> + <field name="IntMin" key="imin" type="int" /> + <field name="IntMax" key="imax" type="int" validator="IntegerRangeValidator"> + <rule value="IntMin" name="greater-than-or-equal">Value must be greater than or equal to IntMin</rule> + </field> + <field name="IntMax2" key="imax2" type="int" validator="IntegerRangeValidator"> + <rule value="IntMin" name="less-than-or-equal">Value must be less than or equal to IntMin</rule> + </field> + </group> </input-data> Modified: jakarta/turbine/core/branches/TURBINE_2_3_BRANCH/src/java/org/apache/turbine/services/intake/model/FileItemField.java URL: http://svn.apache.org/viewvc/jakarta/turbine/core/branches/TURBINE_2_3_BRANCH/src/java/org/apache/turbine/services/intake/model/FileItemField.java?view=diff&rev=537514&r1=537513&r2=537514 ============================================================================== --- jakarta/turbine/core/branches/TURBINE_2_3_BRANCH/src/java/org/apache/turbine/services/intake/model/FileItemField.java (original) +++ jakarta/turbine/core/branches/TURBINE_2_3_BRANCH/src/java/org/apache/turbine/services/intake/model/FileItemField.java Sat May 12 13:55:26 2007 @@ -146,7 +146,7 @@ * * @return the valid flag */ - protected boolean validate() + public boolean validate() { ParameterParser pp = (ParameterParser) super.parser; if (isMultiValued) Added: jakarta/turbine/core/branches/TURBINE_2_3_BRANCH/src/java/org/apache/turbine/services/intake/validator/CompareCallback.java URL: http://svn.apache.org/viewvc/jakarta/turbine/core/branches/TURBINE_2_3_BRANCH/src/java/org/apache/turbine/services/intake/validator/CompareCallback.java?view=auto&rev=537514 ============================================================================== --- jakarta/turbine/core/branches/TURBINE_2_3_BRANCH/src/java/org/apache/turbine/services/intake/validator/CompareCallback.java (added) +++ jakarta/turbine/core/branches/TURBINE_2_3_BRANCH/src/java/org/apache/turbine/services/intake/validator/CompareCallback.java Sat May 12 13:55:26 2007 @@ -0,0 +1,41 @@ +package org.apache.turbine.services.intake.validator; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +/** + * Interface to define the compare operation betwen two field values + * + * @author <a href="mailto:[EMAIL PROTECTED]">Thomas Vandahl</a> + * @version $Id: DateStringValidator.java 534527 2007-05-02 16:10:59Z tv $ + */ +public interface CompareCallback +{ + /** + * Compare the given values using the compare operation provided + * + * @param compare type of compare operation + * @param thisValue value of this field + * @param refValue value of the reference field + * + * @return the result of the comparison + */ + public boolean compareValues(int compare, Object thisValue, Object refValue) + throws ClassCastException; +} Added: jakarta/turbine/core/branches/TURBINE_2_3_BRANCH/src/java/org/apache/turbine/services/intake/validator/FieldReference.java URL: http://svn.apache.org/viewvc/jakarta/turbine/core/branches/TURBINE_2_3_BRANCH/src/java/org/apache/turbine/services/intake/validator/FieldReference.java?view=auto&rev=537514 ============================================================================== --- jakarta/turbine/core/branches/TURBINE_2_3_BRANCH/src/java/org/apache/turbine/services/intake/validator/FieldReference.java (added) +++ jakarta/turbine/core/branches/TURBINE_2_3_BRANCH/src/java/org/apache/turbine/services/intake/validator/FieldReference.java Sat May 12 13:55:26 2007 @@ -0,0 +1,250 @@ +package org.apache.turbine.services.intake.validator; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import java.util.Iterator; +import java.util.List; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.turbine.services.intake.IntakeException; +import org.apache.turbine.services.intake.model.Field; +import org.apache.turbine.services.intake.model.Group; + +/** + * Helper Class to manage relations between fields. The following + * comparisons are supported: + * + * <table> + * <tr> + * <th>Name</th><th>Valid Values</th><th>Default Value</th> + * </tr> + * <tr> + * <td>less-than</td> + * <td><name of other field></td> + * <td> </td> + * </tr> + * <tr> + * <td>greater-than</td> + * <td><name of other field></td> + * <td> </td> + * </tr> + * <tr> + * <td>less-than-or-equal</td> + * <td><name of other field></td> + * <td> </td> + * </tr> + * <tr> + * <td>greater-than-or-equal</td> + * <td><name of other field></td> + * <td> </td> + * </tr> + * </table> + * + * @author <a href="mailto:[EMAIL PROTECTED]">Thomas Vandahl</a> + * @version $Id: DateStringValidator.java 534527 2007-05-02 16:10:59Z tv $ + */ +public class FieldReference +{ + /** a local logger */ + protected static final Log log = LogFactory.getLog(FieldReference.class); + + /** Rule name for "<" comparison */ + public static final String RANGE_LT = "less-than"; + + /** Rule name for ">" comparison */ + public static final String RANGE_GT = "greater-than"; + + /** Rule name for "<=" comparison */ + public static final String RANGE_LTE = "less-than-or-equal"; + + /** Rule name for ">=" comparison */ + public static final String RANGE_GTE = "greater-than-or-equal"; + + /** Integer value for "<" comparison */ + public static final int COMPARE_LT = 1; + + /** Integer value for ">" comparison */ + public static final int COMPARE_GT = 2; + + /** Integer value for "<=" comparison */ + public static final int COMPARE_LTE = 3; + + /** Integer value for ">=" comparison */ + public static final int COMPARE_GTE = 4; + + /** Numeric comparison */ + private int compare = 0; + + /** Name of referenced field */ + private String fieldName = null; + + /** Error message */ + private String message = null; + + /** + * Constructor + */ + public FieldReference() + { + } + + /** + * @return the comparison type + */ + public int getCompare() + { + return compare; + } + + /** + * @param compare the comparison type to set + */ + public void setCompare(int compare) + { + this.compare = compare; + } + + /** + * @return the field name + */ + public String getFieldName() + { + return fieldName; + } + + /** + * @param fieldName the field name to set + */ + public void setFieldName(String fieldName) + { + this.fieldName = fieldName; + } + + /** + * @return the message + */ + public String getMessage() + { + return message; + } + + /** + * @param message the message to set + */ + public void setMessage(String message) + { + this.message = message; + } + + /** + * Map the comparison strings to their numeric counterparts + * + * @param key the + * @return + */ + public static int getCompareType(String key) + { + int compareType = 0; + + if (key.equals(RANGE_LT)) + { + compareType = COMPARE_LT; + } + else if (key.equals(RANGE_LTE)) + { + compareType = COMPARE_LTE; + } + else if (key.equals(RANGE_GT)) + { + compareType = COMPARE_GT; + } + else if (key.equals(RANGE_GTE)) + { + compareType = COMPARE_GTE; + } + + return compareType; + } + + /** + * Check the parsed value against the referenced fields + * + * @param fieldReferences List of field references to check + * @param compareCallback Callback to the actual compare operation + * @param value the parsed value of the related field + * @param group the group the related field belongs to + * + * @throws ValidationException + */ + public static void checkReferences(List fieldReferences, CompareCallback compareCallback, + Object value, Group group) + throws ValidationException + { + for (Iterator i = fieldReferences.iterator(); i.hasNext();) + { + FieldReference ref = (FieldReference)i.next(); + boolean comp_true = true; + + try + { + Field refField = group.get(ref.getFieldName()); + + if (refField.isSet()) + { + /* + * Fields are processed in sequence so that our + * reference field might have been set but not + * yet validated. We check this here. + */ + if (!refField.isValidated()) + { + refField.validate(); + } + + if (refField.isValid()) + { + try + { + comp_true = compareCallback.compareValues(ref.getCompare(), + value, + refField.getValue()); + } + catch (ClassCastException e) + { + throw new IntakeException("Type mismatch comparing " + + value + " with " + refField.getValue(), e); + } + } + } + } + catch (IntakeException e) + { + log.error("Validate operation failed.", e); + throw new ValidationException(ref.getMessage()); + } + + if (comp_true == false) + { + throw new ValidationException(ref.getMessage()); + } + } + } +} Added: jakarta/turbine/core/branches/TURBINE_2_3_BRANCH/src/java/org/apache/turbine/services/intake/validator/IntegerRangeValidator.java URL: http://svn.apache.org/viewvc/jakarta/turbine/core/branches/TURBINE_2_3_BRANCH/src/java/org/apache/turbine/services/intake/validator/IntegerRangeValidator.java?view=auto&rev=537514 ============================================================================== --- jakarta/turbine/core/branches/TURBINE_2_3_BRANCH/src/java/org/apache/turbine/services/intake/validator/IntegerRangeValidator.java (added) +++ jakarta/turbine/core/branches/TURBINE_2_3_BRANCH/src/java/org/apache/turbine/services/intake/validator/IntegerRangeValidator.java Sat May 12 13:55:26 2007 @@ -0,0 +1,229 @@ +package org.apache.turbine.services.intake.validator; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import org.apache.commons.lang.StringUtils; +import org.apache.turbine.services.intake.IntakeException; +import org.apache.turbine.services.intake.model.Field; +import org.apache.turbine.services.intake.model.Group; + +/** + * Validates an int field in dependency on another int field. + * + * <table> + * <tr> + * <th>Name</th><th>Valid Values</th><th>Default Value</th> + * </tr> + * <tr> + * <td>less-than</td> + * <td><name of other field></td> + * <td> </td> + * </tr> + * <tr> + * <td>greater-than</td> + * <td><name of other field></td> + * <td> </td> + * </tr> + * <tr> + * <td>less-than-or-equal</td> + * <td><name of other field></td> + * <td> </td> + * </tr> + * <tr> + * <td>greater-than-or-equal</td> + * <td><name of other field></td> + * <td> </td> + * </tr> + * </table> + * + * @author <a href="mailto:[EMAIL PROTECTED]">Thomas Vandahl</a> + * @version $Id: DateStringValidator.java 534527 2007-05-02 16:10:59Z tv $ + */ +public class IntegerRangeValidator + extends IntegerValidator +{ + /** List of FieldReferences for multiple comparisons */ + List fieldReferences; + + /** Callback for the actual compare operation */ + CompareCallback compareCallback; + + public IntegerRangeValidator(final Map paramMap) + throws IntakeException + { + init(paramMap); + } + + /** + * Default constructor + */ + public IntegerRangeValidator() + { + super(); + } + + /** + * Constructor to use when initialising Object + * + * @param paramMap + * @throws InvalidMaskException + */ + public void init(final Map paramMap) + throws InvalidMaskException + { + super.init(paramMap); + + compareCallback = new CompareCallback() + { + /** + * Compare the given values using the compare operation provided + * + * @param compare type of compare operation + * @param thisValue value of this field + * @param refValue value of the reference field + * + * @return the result of the comparison + */ + public boolean compareValues(int compare, Object thisValue, Object refValue) + throws ClassCastException + { + boolean result = true; + + Integer thisInt = (Integer)thisValue; + Integer otherInt = (Integer)refValue; + + switch (compare) + { + case FieldReference.COMPARE_LT: + result = thisInt.compareTo(otherInt) < 0; + break; + + case FieldReference.COMPARE_LTE: + result = thisInt.compareTo(otherInt) <= 0; + break; + + case FieldReference.COMPARE_GT: + result = thisInt.compareTo(otherInt) > 0; + break; + + case FieldReference.COMPARE_GTE: + result = thisInt.compareTo(otherInt) >= 0; + break; + } + + return result; + } + }; + + fieldReferences = new ArrayList(10); + + for (Iterator i = paramMap.entrySet().iterator(); i.hasNext();) + { + Map.Entry entry = (Map.Entry)i.next(); + String key = (String)entry.getKey(); + Constraint constraint = (Constraint)entry.getValue(); + + int compare = FieldReference.getCompareType(key); + + if (compare != 0) + { + // found matching constraint + FieldReference fieldref = new FieldReference(); + fieldref.setCompare(compare); + fieldref.setFieldName(constraint.getValue()); + fieldref.setMessage(constraint.getMessage()); + + fieldReferences.add(fieldref); + } + } + + if (fieldReferences.isEmpty()) + { + log.warn("No reference field rules have been found."); + } + } + + /** + * Determine whether a testValue meets the criteria specified + * in the constraints defined for this validator + * + * @param testField a <code>Field</code> to be tested + * @exception ValidationException containing an error message if the + * testValue did not pass the validation tests. + */ + public void assertValidity(final Field testField) + throws ValidationException + { + super.assertValidity(testField); + + Group thisGroup = testField.getGroup(); + + if (testField.isMultiValued()) + { + String[] stringValues = (String[])testField.getTestValue(); + + for (int i = 0; i < stringValues.length; i++) + { + assertValidity(stringValues[i], thisGroup); + } + } + else + { + String testValue = (String)testField.getTestValue(); + + assertValidity(testValue, thisGroup); + } + } + + /** + * Determine whether a testValue meets the criteria specified + * in the constraints defined for this validator + * + * @param testValue a <code>String</code> to be tested + * @param group the group this field belongs to + * + * @exception ValidationException containing an error message if the + * testValue did not pass the validation tests. + */ + public void assertValidity(final String testValue, final Group group) + throws ValidationException + { + if (required || StringUtils.isNotEmpty(testValue)) + { + Integer testInt = new Integer(testValue); + + try + { + FieldReference.checkReferences(fieldReferences, compareCallback, + testInt, group); + } + catch (ValidationException e) + { + errorMessage = e.getMessage(); + throw e; + } + } + } +} Modified: jakarta/turbine/core/branches/TURBINE_2_3_BRANCH/src/test/org/apache/turbine/services/intake/IntakeServiceTest.java URL: http://svn.apache.org/viewvc/jakarta/turbine/core/branches/TURBINE_2_3_BRANCH/src/test/org/apache/turbine/services/intake/IntakeServiceTest.java?view=diff&rev=537514&r1=537513&r2=537514 ============================================================================== --- jakarta/turbine/core/branches/TURBINE_2_3_BRANCH/src/test/org/apache/turbine/services/intake/IntakeServiceTest.java (original) +++ jakarta/turbine/core/branches/TURBINE_2_3_BRANCH/src/test/org/apache/turbine/services/intake/IntakeServiceTest.java Sat May 12 13:55:26 2007 @@ -26,13 +26,19 @@ import org.apache.turbine.services.intake.model.Field; import org.apache.turbine.services.intake.model.Group; import org.apache.turbine.services.intake.validator.BooleanValidator; +import org.apache.turbine.services.intake.validator.DateRangeValidator; +import org.apache.turbine.services.intake.validator.IntegerRangeValidator; import org.apache.turbine.test.BaseTurbineTest; +import org.apache.turbine.util.parser.DefaultParameterParser; +import org.apache.turbine.util.parser.ParameterParser; public class IntakeServiceTest extends BaseTurbineTest { Group booleanTestGroup = null; + Group rangeTestGroup = null; + Group integerRangeTestGroup = null; public IntakeServiceTest(String name) throws Exception { @@ -41,6 +47,8 @@ ServiceManager serviceManager = TurbineServices.getInstance(); IntakeService intakeService = (IntakeService) serviceManager.getService(IntakeService.SERVICE_NAME); booleanTestGroup = intakeService.getGroup("BooleanTest"); + rangeTestGroup = intakeService.getGroup("DateRangeTest"); + integerRangeTestGroup = intakeService.getGroup("IntRangeTest"); } @@ -63,6 +71,38 @@ Field booleanField = booleanTestGroup.get("RequiredBooleanTestField"); assertTrue("The Default Validator of an intake Field type boolean should be BooleanValidator", (booleanField.getValidator() instanceof BooleanValidator)); assertTrue("An intake Field type boolean, which is required, should be required", booleanField.isRequired()); + } + + public void testDateRangeValidator() throws IntakeException + { + ParameterParser pp = new DefaultParameterParser(); + pp.add("rt_0dmin", "05/11/2007"); + pp.add("rt_0dmax", "05/12/2007"); + pp.add("rt_0dmax2", "05/11/2007"); + rangeTestGroup.init(Group.NEW, pp); + + Field dmax = rangeTestGroup.get("DateMax"); + Field dmax2 = rangeTestGroup.get("DateMax2"); + + assertTrue("The Validator of the field DateMax should be a DateRangeValidator", (dmax.getValidator() instanceof DateRangeValidator)); + assertTrue("The date range should be valid", dmax.isValid()); + assertFalse("The date range should not be valid", dmax2.isValid()); + } + + public void testIntegerRangeValidator() throws IntakeException + { + ParameterParser pp = new DefaultParameterParser(); + pp.add("irt_0imin", "1"); + pp.add("irt_0imax", "3"); + pp.add("irt_0imax2", "2"); + integerRangeTestGroup.init(Group.NEW, pp); + + Field imax = integerRangeTestGroup.get("IntMax"); + Field imax2 = integerRangeTestGroup.get("IntMax2"); + + assertTrue("The Validator of the field IntMax should be an IntegerRangeValidator", (imax.getValidator() instanceof IntegerRangeValidator)); + assertTrue("The integer range should be valid", imax.isValid()); + assertFalse("The integer range should not be valid", imax2.isValid()); } /** --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]