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'>&nbsp;</td>
+ * <td class='confluenceTd'>field error message</td>
+ * </tr>
+ * <tr>
+ * <td class='confluenceTd'>key</td>
+ * <td class='confluenceTd'>no</td>
+ * <td class='confluenceTd'>&nbsp;</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'>&nbsp;</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'>&nbsp;</td>
+ * <td class='confluenceTd'>&nbsp;</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'>&nbsp;</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'>&nbsp;</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'>&nbsp;</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'>&nbsp;</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 -->
+ * &#64;LongRangeFieldValidator(message = "Default message", key = "i18n.key", 
shortCircuit = true, min = "0", max = "42")
+ *
+ * &#64;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;
  *                   {&#64;StringLengthFieldValidator(type = 
ValidatorType.SIMPLE, trim = true, minLength="10" , maxLength = "12", fieldName 
= "needstringlength", message = "You must enter a stringlength.")},
  *           intRangeFields =
  *                   { &#64;IntRangeFieldValidator(type = 
ValidatorType.SIMPLE, fieldName = "intfield", min = "6", max = "10", message = 
"bar must be between ${min} and ${max}, current value is ${bar}.")},
+ *           longRangeFields =
+ *                   { &#64;LongRangeFieldValidator(type = 
ValidatorType.SIMPLE, fieldName = "intfield", min = "6", max = "10", message = 
"bar must be between ${min} and ${max}, current value is ${bar}.")},
  *           shortRangeFields =
  *                   { &#64;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"/>

Reply via email to