Repository: struts Updated Branches: refs/heads/master bbd4a9e8c -> 0314ddcb5
WW-4795 Implements @LongRangeFieldValidator annotation Project: http://git-wip-us.apache.org/repos/asf/struts/repo Commit: http://git-wip-us.apache.org/repos/asf/struts/commit/0314ddcb Tree: http://git-wip-us.apache.org/repos/asf/struts/tree/0314ddcb Diff: http://git-wip-us.apache.org/repos/asf/struts/diff/0314ddcb Branch: refs/heads/master Commit: 0314ddcb5c8badb8c216735f318fe75ffe56d6b5 Parents: bbd4a9e Author: Lukasz Lenart <lukaszlen...@apache.org> Authored: Tue May 9 10:33:35 2017 +0200 Committer: Lukasz Lenart <lukaszlen...@apache.org> Committed: Tue May 9 10:33:35 2017 +0200 ---------------------------------------------------------------------- ...nnotationValidationConfigurationBuilder.java | 52 +++++ .../annotations/LongRangeFieldValidator.java | 194 +++++++++++++++++++ .../validator/annotations/Validations.java | 4 + .../xwork2/validator/validators/default.xml | 1 + .../template/xhtml/form-close-validate.ftl | 2 +- .../validator/AnnotationValidationAction.java | 3 + ...ationValidationConfigurationBuilderTest.java | 15 +- core/src/test/resources/validators.xml | 2 + 8 files changed, 271 insertions(+), 2 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/struts/blob/0314ddcb/core/src/main/java/com/opensymphony/xwork2/validator/AnnotationValidationConfigurationBuilder.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/com/opensymphony/xwork2/validator/AnnotationValidationConfigurationBuilder.java b/core/src/main/java/com/opensymphony/xwork2/validator/AnnotationValidationConfigurationBuilder.java index b2764ca..f0f3e12 100644 --- a/core/src/main/java/com/opensymphony/xwork2/validator/AnnotationValidationConfigurationBuilder.java +++ b/core/src/main/java/com/opensymphony/xwork2/validator/AnnotationValidationConfigurationBuilder.java @@ -146,6 +146,14 @@ public class AnnotationValidationConfigurationBuilder { result.add(temp); } } + // Process LongRangeFieldValidator + else if (a instanceof LongRangeFieldValidator) { + LongRangeFieldValidator v = (LongRangeFieldValidator) a; + ValidatorConfig temp = processLongRangeFieldValidatorAnnotation(v, fieldName, methodName); + if (temp != null) { + result.add(temp); + } + } // Process ShortRangeFieldValidator else if (a instanceof ShortRangeFieldValidator) { ShortRangeFieldValidator v = (ShortRangeFieldValidator) a; @@ -298,6 +306,15 @@ public class AnnotationValidationConfigurationBuilder { } } } + LongRangeFieldValidator[] lrfv = validations.longRangeFields(); + if (irfv != null) { + for (LongRangeFieldValidator v : lrfv) { + ValidatorConfig temp = processLongRangeFieldValidatorAnnotation(v, fieldName, methodName); + if (temp != null) { + result.add(temp); + } + } + } RegexFieldValidator[] rfv = validations.regexFields(); if (rfv != null) { for (RegexFieldValidator v : rfv) { @@ -672,6 +689,41 @@ public class AnnotationValidationConfigurationBuilder { .build(); } + private ValidatorConfig processLongRangeFieldValidatorAnnotation(LongRangeFieldValidator v, String fieldName, String methodName) { + String validatorType = "long"; + + Map<String, Object> params = new HashMap<>(); + + if (fieldName != null) { + params.put("fieldName", fieldName); + } else if (StringUtils.isNotEmpty(v.fieldName())) { + params.put("fieldName", v.fieldName()); + } + + if (v.min() != null && v.min().length() > 0) { + params.put("min", v.min()); + } + if (v.max() != null && v.max().length() > 0) { + params.put("max", v.max()); + } + if (StringUtils.isNotEmpty(v.maxExpression())) { + params.put("maxExpression", v.maxExpression()); + } + if (StringUtils.isNotEmpty(v.minExpression())) { + params.put("minExpression", v.minExpression()); + } + + validatorFactory.lookupRegisteredValidatorType(validatorType); + return new ValidatorConfig.Builder(validatorType) + .addParams(params) + .addParam("methodName", methodName) + .shortCircuit(v.shortCircuit()) + .defaultMessage(v.message()) + .messageKey(v.key()) + .messageParams(v.messageParams()) + .build(); + } + private ValidatorConfig processShortRangeFieldValidatorAnnotation(ShortRangeFieldValidator v, String fieldName, String methodName) { String validatorType = "short"; http://git-wip-us.apache.org/repos/asf/struts/blob/0314ddcb/core/src/main/java/com/opensymphony/xwork2/validator/annotations/LongRangeFieldValidator.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/com/opensymphony/xwork2/validator/annotations/LongRangeFieldValidator.java b/core/src/main/java/com/opensymphony/xwork2/validator/annotations/LongRangeFieldValidator.java new file mode 100644 index 0000000..1886164 --- /dev/null +++ b/core/src/main/java/com/opensymphony/xwork2/validator/annotations/LongRangeFieldValidator.java @@ -0,0 +1,194 @@ +/* + * Copyright 2002-2006,2009 The Apache Software Foundation. + * + * Licensed 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. + */ + +package com.opensymphony.xwork2.validator.annotations; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * <!-- START SNIPPET: description --> + * This validator checks that a numeric field has a value within a specified range. + * If neither min nor max is set, nothing will be done. + * <!-- END SNIPPET: description --> + * + * <p><u>Annotation usage:</u></p> + * + * <!-- START SNIPPET: usage --> + * <p>The annotation must be applied at method level.</p> + * <!-- END SNIPPET: usage --> + * + * <p><u>Annotation parameters:</u></p> + * + * <!-- START SNIPPET: parameters --> + * <table class='confluenceTable' summary=''> + * <tr> + * <th class='confluenceTh'> Parameter </th> + * <th class='confluenceTh'> Required </th> + * <th class='confluenceTh'> Default </th> + * <th class='confluenceTh'> Notes </th> + * </tr> + * <tr> + * <td class='confluenceTd'>message</td> + * <td class='confluenceTd'>yes</td> + * <td class='confluenceTd'> </td> + * <td class='confluenceTd'>field error message</td> + * </tr> + * <tr> + * <td class='confluenceTd'>key</td> + * <td class='confluenceTd'>no</td> + * <td class='confluenceTd'> </td> + * <td class='confluenceTd'>i18n key from language specific properties file.</td> + * </tr> + * <tr> + * <td class='confluenceTd'>messageParams</td> + * <td class='confluenceTd'>no</td> + * <td class='confluenceTd'> </td> + * <td class='confluenceTd'>Additional params to be used to customize message - will be evaluated against the Value Stack</td> + * </tr> + * <tr> + * <td class='confluenceTd'>fieldName</td> + * <td class='confluenceTd'>no</td> + * <td class='confluenceTd'> </td> + * <td class='confluenceTd'> </td> + * </tr> + * <tr> + * <td class='confluenceTd'>shortCircuit</td> + * <td class='confluenceTd'>no</td> + * <td class='confluenceTd'>false</td> + * <td class='confluenceTd'>If this validator should be used as shortCircuit.</td> + * </tr> + * <tr> + * <td class='confluenceTd'>type</td> + * <td class='confluenceTd'>yes</td> + * <td class='confluenceTd'>ValidatorType.FIELD</td> + * <td class='confluenceTd'>Enum value from ValidatorType. Either FIELD or SIMPLE can be used here.</td> + * </tr> + * <tr> + * <td class='confluenceTd'> min </td> + * <td class='confluenceTd'> no </td> + * <td class='confluenceTd'> </td> + * <td class='confluenceTd'> Integer property. The minimum the number must be.</td> + * </tr> + * <tr> + * <td class='confluenceTd'> minExpression </td> + * <td class='confluenceTd'> no </td> + * <td class='confluenceTd'> </td> + * <td class='confluenceTd'>OGNL expression used to obtain the minimum the number must be.</td> + * </tr> + * <tr> + * <td class='confluenceTd'> max </td> + * <td class='confluenceTd'> no </td> + * <td class='confluenceTd'> </td> + * <td class='confluenceTd'> Integer property. The maximum number can be. Can be an expression.!</td> + * </tr> + * <tr> + * <td class='confluenceTd'> maxExpression </td> + * <td class='confluenceTd'> no </td> + * <td class='confluenceTd'> </td> + * <td class='confluenceTd'>OGNL expression used to obtain the maximum number can be.</td> + * </tr> + * <tr> + * <td class='confluenceTd'>parse</td> + * <td class='confluenceTd'>no</td> + * <td class='confluenceTd'>false</td> + * <td class='confluenceTd'>Enable parsing of min/max value.</td> + * </tr> + * </table> + * + * <p>If neither <em>min</em> nor <em>max</em> is set, nothing will be done.</p> + * + * <p>The values for min and max must be inserted as String values so that "0" can be handled as a possible value.</p> + * <!-- END SNIPPET: parameters --> + * + * <p><u>Example code:</u></p> + * + * <pre> + * <!-- START SNIPPET: example --> + * @LongRangeFieldValidator(message = "Default message", key = "i18n.key", shortCircuit = true, min = "0", max = "42") + * + * @LongRangeFieldValidator(message = "Default message", key = "i18n.key", shortCircuit = true, minExpression = "${minValue}", maxExpression = "${maxValue}") + * <!-- END SNIPPET: example --> + * </pre> + * + * + * @author Rainer Hermanns + */ +@Target({ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +public @interface LongRangeFieldValidator { + + /** + * Long property. + * + * @return The minimum the number must be. + */ + String min() default ""; + + /** + * @return The minimum number can be defined as an expression + */ + String minExpression() default ""; + + /** + * Long property. + * + * @return The maximum number can be. + */ + String max() default ""; + + /** + * @return The maximum number can be defined as an expression + */ + String maxExpression() default ""; + + /** + * @return The default error message for this validator. + * NOTE: It is required to set a message, if you are not using the message key for 18n lookup! + */ + String message() default ""; + + /** + * @return The message key to lookup for i18n. + */ + String key() default ""; + + /** + * @return Additional params to be used to customize message - will be evaluated against the Value Stack + */ + String[] messageParams() default {}; + + /** + * @return The optional fieldName for SIMPLE validator types. + */ + String fieldName() default ""; + + /** + * If this is activated, the validator will be used as short-circuit. + * + * Adds the short-circuit='true' attribute value if <tt>true</tt>. + * + * @return true if validator will be used as short-circuit. Default is false. + */ + boolean shortCircuit() default false; + + /** + * @return The validation type for this field/method. + */ + ValidatorType type() default ValidatorType.FIELD; +} http://git-wip-us.apache.org/repos/asf/struts/blob/0314ddcb/core/src/main/java/com/opensymphony/xwork2/validator/annotations/Validations.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/com/opensymphony/xwork2/validator/annotations/Validations.java b/core/src/main/java/com/opensymphony/xwork2/validator/annotations/Validations.java index bdf5a75..2b5c0b9 100644 --- a/core/src/main/java/com/opensymphony/xwork2/validator/annotations/Validations.java +++ b/core/src/main/java/com/opensymphony/xwork2/validator/annotations/Validations.java @@ -129,6 +129,8 @@ import java.lang.annotation.Target; * {@StringLengthFieldValidator(type = ValidatorType.SIMPLE, trim = true, minLength="10" , maxLength = "12", fieldName = "needstringlength", message = "You must enter a stringlength.")}, * intRangeFields = * { @IntRangeFieldValidator(type = ValidatorType.SIMPLE, fieldName = "intfield", min = "6", max = "10", message = "bar must be between ${min} and ${max}, current value is ${bar}.")}, + * longRangeFields = + * { @LongRangeFieldValidator(type = ValidatorType.SIMPLE, fieldName = "intfield", min = "6", max = "10", message = "bar must be between ${min} and ${max}, current value is ${bar}.")}, * shortRangeFields = * { @ShortRangeFieldValidator(type = ValidatorType.SIMPLE, fieldName = "shortfield", min = "1", max = "128", message = "bar must be between ${min} and ${max}, current value is ${bar}.")}, * dateRangeFields = @@ -173,6 +175,8 @@ public @interface Validations { IntRangeFieldValidator[] intRangeFields() default {}; + LongRangeFieldValidator[] longRangeFields() default {}; + RequiredFieldValidator[] requiredFields() default {}; RequiredStringValidator[] requiredStrings() default {}; http://git-wip-us.apache.org/repos/asf/struts/blob/0314ddcb/core/src/main/resources/com/opensymphony/xwork2/validator/validators/default.xml ---------------------------------------------------------------------- diff --git a/core/src/main/resources/com/opensymphony/xwork2/validator/validators/default.xml b/core/src/main/resources/com/opensymphony/xwork2/validator/validators/default.xml index fa8e742..ed7f2f8 100644 --- a/core/src/main/resources/com/opensymphony/xwork2/validator/validators/default.xml +++ b/core/src/main/resources/com/opensymphony/xwork2/validator/validators/default.xml @@ -15,6 +15,7 @@ <validator name="expression" class="com.opensymphony.xwork2.validator.validators.ExpressionValidator"/> <validator name="fieldexpression" class="com.opensymphony.xwork2.validator.validators.FieldExpressionValidator"/> <validator name="email" class="com.opensymphony.xwork2.validator.validators.EmailValidator"/> + <validator name="creditcard" class="com.opensymphony.xwork2.validator.validators.CreditCardValidator"/> <validator name="url" class="com.opensymphony.xwork2.validator.validators.URLValidator"/> <validator name="visitor" class="com.opensymphony.xwork2.validator.validators.VisitorFieldValidator"/> <validator name="conversion" class="com.opensymphony.xwork2.validator.validators.ConversionErrorFieldValidator"/> http://git-wip-us.apache.org/repos/asf/struts/blob/0314ddcb/core/src/main/resources/template/xhtml/form-close-validate.ftl ---------------------------------------------------------------------- diff --git a/core/src/main/resources/template/xhtml/form-close-validate.ftl b/core/src/main/resources/template/xhtml/form-close-validate.ftl index 3ffc3bf..cc42cfa 100644 --- a/core/src/main/resources/template/xhtml/form-close-validate.ftl +++ b/core/src/main/resources/template/xhtml/form-close-validate.ftl @@ -125,7 +125,7 @@ END SNIPPET: supported-validators errors = true; <#if validator.shortCircuit>continueValidation = false;</#if> } - <#elseif validator.validatorType = "int" || validator.validatorType = "short"> + <#elseif validator.validatorType = "int" || validator.validatorType = "short" || validator.validatorType = "long"> if (continueValidation && fieldValue !== null) { if (<#if validator.min??>parseInt(fieldValue) < ${validator.min?c}<#else>false</#if> || http://git-wip-us.apache.org/repos/asf/struts/blob/0314ddcb/core/src/test/java/com/opensymphony/xwork2/validator/AnnotationValidationAction.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/com/opensymphony/xwork2/validator/AnnotationValidationAction.java b/core/src/test/java/com/opensymphony/xwork2/validator/AnnotationValidationAction.java index 9e95dde..0bc44cd 100644 --- a/core/src/test/java/com/opensymphony/xwork2/validator/AnnotationValidationAction.java +++ b/core/src/test/java/com/opensymphony/xwork2/validator/AnnotationValidationAction.java @@ -11,6 +11,7 @@ import com.opensymphony.xwork2.validator.annotations.EmailValidator; import com.opensymphony.xwork2.validator.annotations.ExpressionValidator; import com.opensymphony.xwork2.validator.annotations.FieldExpressionValidator; import com.opensymphony.xwork2.validator.annotations.IntRangeFieldValidator; +import com.opensymphony.xwork2.validator.annotations.LongRangeFieldValidator; import com.opensymphony.xwork2.validator.annotations.RegexFieldValidator; import com.opensymphony.xwork2.validator.annotations.RequiredFieldValidator; import com.opensymphony.xwork2.validator.annotations.RequiredStringValidator; @@ -54,6 +55,8 @@ public class AnnotationValidationAction extends ActionSupport { messageParams = {"one", "two", "three"}, shortCircuit = true) @IntRangeFieldValidator(fieldName = "foo", key = "int.key", message = "Foo is out of range!", max = "10", min = "1", messageParams = {"one", "two", "three"}, shortCircuit = true) + @LongRangeFieldValidator(fieldName = "foo", key = "int.key", message = "Foo is out of range!", max = "10", min = "1", + messageParams = {"one", "two", "three"}, shortCircuit = true) @RequiredFieldValidator(fieldName = "foo", key = "required.key", message = "Foo is required!", messageParams = {"one", "two", "three"}, shortCircuit = true) @RequiredStringValidator(fieldName = "foo", key = "requiredstring.key", message = "Foo is required!", http://git-wip-us.apache.org/repos/asf/struts/blob/0314ddcb/core/src/test/java/com/opensymphony/xwork2/validator/AnnotationValidationConfigurationBuilderTest.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/com/opensymphony/xwork2/validator/AnnotationValidationConfigurationBuilderTest.java b/core/src/test/java/com/opensymphony/xwork2/validator/AnnotationValidationConfigurationBuilderTest.java index 1bc0564..5ac49ab 100644 --- a/core/src/test/java/com/opensymphony/xwork2/validator/AnnotationValidationConfigurationBuilderTest.java +++ b/core/src/test/java/com/opensymphony/xwork2/validator/AnnotationValidationConfigurationBuilderTest.java @@ -24,6 +24,7 @@ import com.opensymphony.xwork2.validator.validators.EmailValidator; import com.opensymphony.xwork2.validator.validators.ExpressionValidator; import com.opensymphony.xwork2.validator.validators.FieldExpressionValidator; import com.opensymphony.xwork2.validator.validators.IntRangeFieldValidator; +import com.opensymphony.xwork2.validator.validators.LongRangeFieldValidator; import com.opensymphony.xwork2.validator.validators.RegexFieldValidator; import com.opensymphony.xwork2.validator.validators.RequiredFieldValidator; import com.opensymphony.xwork2.validator.validators.RequiredStringValidator; @@ -51,7 +52,7 @@ public class AnnotationValidationConfigurationBuilderTest extends XWorkTestCase List<Validator> validators = manager.getValidators(AnnotationValidationAction.class, null); // then - assertEquals(validators.size(), 17); + assertEquals(validators.size(), 18); for (Validator validator : validators) { validate(validator); } @@ -98,6 +99,8 @@ public class AnnotationValidationConfigurationBuilderTest extends XWorkTestCase validateFieldExpressionValidator((FieldExpressionValidator) validator); } else if (validator.getValidatorType().equals("int")) { validateIntRangeFieldValidator((IntRangeFieldValidator) validator); + } else if (validator.getValidatorType().equals("long")) { + validateLongRangeFieldValidator((LongRangeFieldValidator) validator); } else if (validator.getValidatorType().equals("required")) { validateRequiredFieldValidator((RequiredFieldValidator) validator); } else if (validator.getValidatorType().equals("requiredstring")) { @@ -178,6 +181,16 @@ public class AnnotationValidationConfigurationBuilderTest extends XWorkTestCase assertEquals(Integer.valueOf(1), validator.getMin()); } + private void validateLongRangeFieldValidator(LongRangeFieldValidator validator) { + assertEquals("foo", validator.getFieldName()); + assertEquals("int.key", validator.getMessageKey()); + assertEquals("Foo is out of range!", validator.getDefaultMessage()); + assertTrue(Arrays.equals(new String[]{"one", "two", "three"}, validator.getMessageParameters())); + assertEquals(true, validator.isShortCircuit()); + assertEquals(Long.valueOf(10), validator.getMax()); + assertEquals(Long.valueOf(1), validator.getMin()); + } + private void validateFieldExpressionValidator(FieldExpressionValidator validator) { assertEquals("foo", validator.getFieldName()); assertEquals("It is not true!", validator.getDefaultMessage()); http://git-wip-us.apache.org/repos/asf/struts/blob/0314ddcb/core/src/test/resources/validators.xml ---------------------------------------------------------------------- diff --git a/core/src/test/resources/validators.xml b/core/src/test/resources/validators.xml index 5eff925..96242be 100644 --- a/core/src/test/resources/validators.xml +++ b/core/src/test/resources/validators.xml @@ -6,6 +6,8 @@ <validator name="required" class="com.opensymphony.xwork2.validator.validators.RequiredFieldValidator"/> <validator name="requiredstring" class="com.opensymphony.xwork2.validator.validators.RequiredStringValidator"/> <validator name="int" class="com.opensymphony.xwork2.validator.validators.IntRangeFieldValidator"/> + <validator name="long" class="com.opensymphony.xwork2.validator.validators.LongRangeFieldValidator"/> + <validator name="short" class="com.opensymphony.xwork2.validator.validators.ShortRangeFieldValidator"/> <validator name="double" class="com.opensymphony.xwork2.validator.validators.DoubleRangeFieldValidator"/> <validator name="date" class="com.opensymphony.xwork2.validator.validators.DateRangeFieldValidator"/> <validator name="expression" class="com.opensymphony.xwork2.validator.validators.ExpressionValidator"/>