This is an automated email from the ASF dual-hosted git repository.

adelbene pushed a commit to branch WICKET-6662
in repository https://gitbox.apache.org/repos/asf/wicket.git

commit 8340b1009f84292fbec3523de79aca1751883a81
Author: Sven Meier <[email protected]>
AuthorDate: Fri Apr 19 09:56:39 2019 +0200

    WICKET-6656 allow bean validation to handle required annotations
    
    and updated dependencies; this closes #353
---
 .../validation/BeanValidationConfiguration.java    |  44 ++++++++-
 .../bean/validation/BeanValidationContext.java     |  14 +++
 .../wicket/bean/validation/PropertyValidator.java  | 110 +++++++--------------
 wicket-examples/pom.xml                            |   6 --
 .../constraint/ValidPasswordValidator.java         |   6 +-
 5 files changed, 97 insertions(+), 83 deletions(-)

diff --git 
a/wicket-bean-validation/src/main/java/org/apache/wicket/bean/validation/BeanValidationConfiguration.java
 
b/wicket-bean-validation/src/main/java/org/apache/wicket/bean/validation/BeanValidationConfiguration.java
index d705a63..7971c84 100644
--- 
a/wicket-bean-validation/src/main/java/org/apache/wicket/bean/validation/BeanValidationConfiguration.java
+++ 
b/wicket-bean-validation/src/main/java/org/apache/wicket/bean/validation/BeanValidationConfiguration.java
@@ -1,6 +1,8 @@
 package org.apache.wicket.bean.validation;
 
 import java.lang.annotation.Annotation;
+import java.util.ArrayList;
+import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
@@ -8,7 +10,10 @@ import java.util.concurrent.CopyOnWriteArrayList;
 import java.util.function.Supplier;
 
 import javax.validation.Validator;
+import javax.validation.constraints.NotEmpty;
+import javax.validation.constraints.NotNull;
 import javax.validation.constraints.Size;
+import javax.validation.metadata.ConstraintDescriptor;
 
 import org.apache.wicket.Application;
 import org.apache.wicket.MetaDataKey;
@@ -27,6 +32,28 @@ public class BeanValidationConfiguration implements 
BeanValidationContext
        {
        };
 
+       /**
+        * Default list of annotations that make a component required.
+        */
+       static final List<Class<? extends Annotation>> REQUIRED_ANNOTATIONS;
+       static
+       {
+               List<Class<? extends Annotation>> tmp = new ArrayList<>();
+               tmp.add(NotNull.class);
+               try
+               {
+                       
tmp.add(Class.forName("javax.validation.constraints.NotBlank")
+                               .asSubclass(Annotation.class));
+                       
tmp.add(Class.forName("javax.validation.constraints.NotEmpty")
+                               .asSubclass(Annotation.class));
+               }
+               catch (ClassNotFoundException e)
+               {
+                       // ignore exception, we are using bean validation 1.1
+               }
+               REQUIRED_ANNOTATIONS = Collections.unmodifiableList(tmp);
+       }
+
        private Supplier<Validator> validatorProvider = new 
DefaultValidatorProvider();
 
        private IViolationTranslator violationTranslator = new 
DefaultViolationTranslator();
@@ -61,7 +88,6 @@ public class BeanValidationConfiguration implements 
BeanValidationContext
                return this;
        }
 
-
        @Override
        @SuppressWarnings("unchecked")
        public <T extends Annotation> ITagModifier<T> getTagModifier(Class<T> 
annotationType)
@@ -131,8 +157,8 @@ public class BeanValidationConfiguration implements 
BeanValidationContext
         * Registers a violation translator
         *
         * @param violationTranslator
-        *          A violation translator that will convert {@link 
javax.validation.ConstraintViolation}s
-        *          into Wicket's {@link 
org.apache.wicket.validation.ValidationError}s
+        *            A violation translator that will convert {@link 
javax.validation.ConstraintViolation}s into Wicket's
+        *            {@link org.apache.wicket.validation.ValidationError}s
         */
        public void setViolationTranslator(IViolationTranslator 
violationTranslator)
        {
@@ -171,4 +197,16 @@ public class BeanValidationConfiguration implements 
BeanValidationContext
                }
                return null;
        }
+
+       /**
+        * By default {@link NotNull} and {@link NotEmpty} constraints make a 
component required.
+        * 
+        * @param constraint
+        *            constraint 
+        */
+       @Override
+       public boolean isRequiredConstraint(ConstraintDescriptor<?> constraint)
+       {
+               return 
REQUIRED_ANNOTATIONS.contains(constraint.getAnnotation().annotationType());
+       }
 }
diff --git 
a/wicket-bean-validation/src/main/java/org/apache/wicket/bean/validation/BeanValidationContext.java
 
b/wicket-bean-validation/src/main/java/org/apache/wicket/bean/validation/BeanValidationContext.java
index dd5c4a0..8f1f8b9 100644
--- 
a/wicket-bean-validation/src/main/java/org/apache/wicket/bean/validation/BeanValidationContext.java
+++ 
b/wicket-bean-validation/src/main/java/org/apache/wicket/bean/validation/BeanValidationContext.java
@@ -3,6 +3,7 @@ package org.apache.wicket.bean.validation;
 import java.lang.annotation.Annotation;
 
 import javax.validation.Validator;
+import javax.validation.metadata.ConstraintDescriptor;
 
 import org.apache.wicket.markup.html.form.FormComponent;
 
@@ -36,6 +37,19 @@ public interface BeanValidationContext extends 
IPropertyResolver
         */
        IViolationTranslator getViolationTranslator();
 
+       /**
+        * Resolve the property for a component.
+        * 
+        * @param component component
+        */
        @Override
        Property resolveProperty(FormComponent<?> component);
+       
+       /**
+        * Does the given constraint make a component required.
+        * 
+        * @param constraint constraint
+        * @return <code>true</code> if required
+        */
+       boolean isRequiredConstraint(ConstraintDescriptor<?> constraint);
 }
\ No newline at end of file
diff --git 
a/wicket-bean-validation/src/main/java/org/apache/wicket/bean/validation/PropertyValidator.java
 
b/wicket-bean-validation/src/main/java/org/apache/wicket/bean/validation/PropertyValidator.java
index 9cee8f8..437c04a 100644
--- 
a/wicket-bean-validation/src/main/java/org/apache/wicket/bean/validation/PropertyValidator.java
+++ 
b/wicket-bean-validation/src/main/java/org/apache/wicket/bean/validation/PropertyValidator.java
@@ -1,17 +1,12 @@
 package org.apache.wicket.bean.validation;
 
-import java.lang.annotation.Annotation;
-import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.Collections;
 import java.util.HashSet;
 import java.util.Iterator;
-import java.util.List;
 import java.util.Set;
 
 import javax.validation.ConstraintViolation;
 import javax.validation.Validator;
-import javax.validation.constraints.NotNull;
 import javax.validation.groups.Default;
 import javax.validation.metadata.ConstraintDescriptor;
 
@@ -21,8 +16,8 @@ import org.apache.wicket.markup.ComponentTag;
 import org.apache.wicket.markup.html.form.FormComponent;
 import org.apache.wicket.model.IModel;
 import org.apache.wicket.model.PropertyModel;
+import org.apache.wicket.validation.INullAcceptingValidator;
 import org.apache.wicket.validation.IValidatable;
-import org.apache.wicket.validation.IValidator;
 
 /**
  * Validator that delegates to the bean validation framework. The integration 
has to be first
@@ -57,33 +52,16 @@ import org.apache.wicket.validation.IValidator;
  * 
  * @param <T>
  */
-public class PropertyValidator<T> extends Behavior implements IValidator<T>
+public class PropertyValidator<T> extends Behavior implements 
INullAcceptingValidator<T>
 {
        private static final Class<?>[] EMPTY = new Class<?>[0];
-       private static final List<Class<? extends Annotation>> 
NOT_NULL_ANNOTATIONS;
-       static
-       {
-               List<Class<? extends Annotation>> tmp = new ArrayList<>();
-               tmp.add(NotNull.class);
-               try
-               {
-                       
tmp.add(Class.forName("javax.validation.constraints.NotBlank")
-                               .asSubclass(Annotation.class));
-                       
tmp.add(Class.forName("javax.validation.constraints.NotEmpty")
-                               .asSubclass(Annotation.class));
-               }
-               catch (ClassNotFoundException e)
-               {
-                       // ignore exception, we are using bean validation 1.1
-               }
-               NOT_NULL_ANNOTATIONS = Collections.unmodifiableList(tmp);
-       }
 
        private FormComponent<T> component;
 
        // the trailing underscore means that these members should not be used
        // directly. ALWAYS use the respective getter instead.
        private Property property_;
+
        private final IModel<Class<?>[]> groups_;
 
        /**
@@ -114,14 +92,17 @@ public class PropertyValidator<T> extends Behavior 
implements IValidator<T>
 
        /**
         * To support debugging, trying to provide useful information where 
possible
+        * 
         * @return
         */
-       private String createUnresolvablePropertyMessage(FormComponent<T> 
component) {
+       private String createUnresolvablePropertyMessage(FormComponent<T> 
component)
+       {
                String baseMessage = "Could not resolve Bean Property from 
component: " + component
-                               + ". (Hints:) Possible causes are a typo in the 
PropertyExpression, a null reference or a model that does not work in 
combination with a "
-                               + IPropertyResolver.class.getSimpleName() + ".";
-        IModel<?> model = 
ValidationModelResolver.resolvePropertyModelFrom(component);
-               if (model != null) {
+                       + ". (Hints:) Possible causes are a typo in the 
PropertyExpression, a null reference or a model that does not work in 
combination with a "
+                       + IPropertyResolver.class.getSimpleName() + ".";
+               IModel<?> model = 
ValidationModelResolver.resolvePropertyModelFrom(component);
+               if (model != null)
+               {
                        baseMessage += " Model : " + model;
                }
                return baseMessage;
@@ -157,15 +138,14 @@ public class PropertyValidator<T> extends Behavior 
implements IValidator<T>
                if (this.component != null)
                {
                        throw new IllegalStateException( //
-                               "This validator has already been added to 
component: "
-                                       + this.component
+                               "This validator has already been added to 
component: " + this.component
                                        + ". This validator does not support 
reusing instances, please create a new one");
                }
 
                if (!(component instanceof FormComponent))
                {
-                       throw new 
IllegalStateException(getClass().getSimpleName()
-                               + " can only be added to FormComponents");
+                       throw new IllegalStateException(
+                               getClass().getSimpleName() + " can only be 
added to FormComponents");
                }
 
                // TODO add a validation key that appends the type so we can 
have
@@ -187,6 +167,7 @@ public class PropertyValidator<T> extends Behavior 
implements IValidator<T>
                        // that model object is accessible (i.e. component is 
already added
                        // in a page).
                        requiredFlagSet = true;
+
                        if (isRequired())
                        {
                                this.component.setRequired(true);
@@ -204,55 +185,38 @@ public class PropertyValidator<T> extends Behavior 
implements IValidator<T>
                }
        }
 
-       private List<ConstraintDescriptor<?>> 
findNotNullConstraints(List<Class<? extends Annotation>> notNullAnnotationTypes)
+       /**
+        * Should this property make the owning component required.
+        * 
+        * @return <code>true</code> if required
+        * 
+        * @see BeanValidationContext#isRequiredConstraint(ConstraintDescriptor)
+        */
+       protected boolean isRequired()
        {
                BeanValidationContext config = 
BeanValidationConfiguration.get();
-               Validator validator = config.getValidator();
-               Property property = getProperty();
-
-               List<ConstraintDescriptor<?>> constraints = new ArrayList<>();
 
-               Iterator<ConstraintDescriptor<?>> it = new 
ConstraintIterator(validator, property);
+               HashSet<Class<?>> groups = new 
HashSet<Class<?>>(Arrays.asList(getGroups()));
 
+               Iterator<ConstraintDescriptor<?>> it = new 
ConstraintIterator(config.getValidator(), getProperty());
                while (it.hasNext())
                {
-                       ConstraintDescriptor<?> desc = it.next();
-                       Annotation annotation = desc.getAnnotation();
-                       Class<? extends Annotation> annotationType = 
annotation.annotationType();
-                       if (notNullAnnotationTypes.contains(annotationType))
-                       {
-                               constraints.add(desc);
-                       }
-               }
-
-               return constraints;
-       }
-
-       boolean isRequired()
-       {
-               List<ConstraintDescriptor<?>> constraints = 
findNotNullConstraints(NOT_NULL_ANNOTATIONS);
-
-               if (constraints.isEmpty())
-               {
-                       return false;
-               }
-
-               Set<Class<?>> validatorGroups = new HashSet<>();
-               validatorGroups.addAll(Arrays.asList(getGroups()));
-
-               for (ConstraintDescriptor<?> constraint : constraints)
-               {
-                       if (canApplyToDefaultGroup(constraint) && 
validatorGroups.isEmpty())
-                       {
-                               return true;
-                       }
-
-                       for (Class<?> constraintGroup : constraint.getGroups())
+                       ConstraintDescriptor<?> constraint = it.next();
+                       
+                       if (config.isRequiredConstraint(constraint))
                        {
-                               if (validatorGroups.contains(constraintGroup))
+                               if (canApplyToDefaultGroup(constraint) && 
groups.size() == 0)
                                {
                                        return true;
                                }
+               
+                               for (Class<?> constraintGroup : 
constraint.getGroups())
+                               {
+                                       if (groups.contains(constraintGroup))
+                                       {
+                                               return true;
+                                       }
+                               }
                        }
                }
 
diff --git a/wicket-examples/pom.xml b/wicket-examples/pom.xml
index faf9962..65e6bfd 100644
--- a/wicket-examples/pom.xml
+++ b/wicket-examples/pom.xml
@@ -56,11 +56,6 @@
                                <groupId>org.codelibs</groupId>
                                <artifactId>jhighlight</artifactId>
                                <version>1.0.3</version>
-                               
-                       </dependency>
-                       <dependency>
-                               <groupId>org.hibernate.validator</groupId>
-                               <artifactId>hibernate-validator</artifactId>
                        </dependency>
                </dependencies>
        </dependencyManagement>
@@ -145,7 +140,6 @@
                <dependency>
                        <groupId>org.hibernate.validator</groupId>
                        <artifactId>hibernate-validator</artifactId>
-                       <version>6.0.13.Final</version>
                        <scope>compile</scope>
                </dependency>
                <dependency>
diff --git 
a/wicket-examples/src/main/java/org/apache/wicket/examples/bean/validation/constraint/ValidPasswordValidator.java
 
b/wicket-examples/src/main/java/org/apache/wicket/examples/bean/validation/constraint/ValidPasswordValidator.java
index 1b68dd3..f392501 100644
--- 
a/wicket-examples/src/main/java/org/apache/wicket/examples/bean/validation/constraint/ValidPasswordValidator.java
+++ 
b/wicket-examples/src/main/java/org/apache/wicket/examples/bean/validation/constraint/ValidPasswordValidator.java
@@ -38,7 +38,11 @@ public class ValidPasswordValidator implements 
ConstraintValidator<ValidPassword
        {
                boolean validationResult = true;
 
-               if (!CONTENT.matcher(value).matches())
+               if (value == null)
+               {
+                       validationResult = false; 
+               }
+               else if (!CONTENT.matcher(value).matches())
                {
                        validationResult = false;
                }

Reply via email to