You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@bval.apache.org by mb...@apache.org on 2018/04/04 16:43:37 UTC

[2/3] bval git commit: raise ConstraintDeclarationException if repeatable constraints and containers are specified together: TCK

raise ConstraintDeclarationException if repeatable constraints and containers are specified together: TCK


Project: http://git-wip-us.apache.org/repos/asf/bval/repo
Commit: http://git-wip-us.apache.org/repos/asf/bval/commit/733acddf
Tree: http://git-wip-us.apache.org/repos/asf/bval/tree/733acddf
Diff: http://git-wip-us.apache.org/repos/asf/bval/diff/733acddf

Branch: refs/heads/bv2
Commit: 733acddfe0086cd6c1f862f781d2db53a1c7c3b7
Parents: e076d2f
Author: Matt Benson <mb...@apache.org>
Authored: Wed Apr 4 11:42:39 2018 -0500
Committer: Matt Benson <mb...@apache.org>
Committed: Wed Apr 4 11:42:39 2018 -0500

----------------------------------------------------------------------
 .../bval/jsr/util/AnnotationsManager.java       | 49 +++++++++++++++++---
 1 file changed, 42 insertions(+), 7 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/bval/blob/733acddf/bval-jsr/src/main/java/org/apache/bval/jsr/util/AnnotationsManager.java
----------------------------------------------------------------------
diff --git a/bval-jsr/src/main/java/org/apache/bval/jsr/util/AnnotationsManager.java b/bval-jsr/src/main/java/org/apache/bval/jsr/util/AnnotationsManager.java
index 38d73e3..f0aa3a8 100644
--- a/bval-jsr/src/main/java/org/apache/bval/jsr/util/AnnotationsManager.java
+++ b/bval-jsr/src/main/java/org/apache/bval/jsr/util/AnnotationsManager.java
@@ -36,11 +36,14 @@ import java.util.Optional;
 import java.util.Set;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.function.Function;
+import java.util.function.Predicate;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
 
 import javax.validation.Constraint;
+import javax.validation.ConstraintDeclarationException;
 import javax.validation.ConstraintDefinitionException;
+import javax.validation.ConstraintTarget;
 import javax.validation.OverridesAttribute;
 import javax.validation.Payload;
 import javax.validation.ValidationException;
@@ -49,6 +52,7 @@ import javax.validation.constraintvalidation.ValidationTarget;
 import org.apache.bval.jsr.ApacheValidatorFactory;
 import org.apache.bval.jsr.ConfigurationImpl;
 import org.apache.bval.jsr.ConstraintAnnotationAttributes;
+import org.apache.bval.jsr.ConstraintAnnotationAttributes.Worker;
 import org.apache.bval.jsr.ConstraintCached.ConstraintValidatorInfo;
 import org.apache.bval.jsr.groups.Group;
 import org.apache.bval.jsr.groups.Groups;
@@ -105,6 +109,11 @@ public class AnnotationsManager {
     }
 
     private static class Composition {
+        static <A extends Annotation> Optional<ConstraintAnnotationAttributes.Worker<A>> validWorker(
+            ConstraintAnnotationAttributes attr, Class<A> type) {
+            return Optional.of(type).map(attr::analyze).filter(Worker::isValid);
+        }
+
         final Lazy<Map<OverriddenAnnotationSpecifier, Map<String, String>>> overrides = new Lazy<>(HashMap::new);
         final Annotation[] components;
 
@@ -161,6 +170,10 @@ public class AnnotationsManager {
             final Class<? extends Payload>[] payload =
                 ConstraintAnnotationAttributes.PAYLOAD.analyze(source.annotationType()).read(source);
 
+            final Optional<ConstraintTarget> constraintTarget =
+                validWorker(ConstraintAnnotationAttributes.VALIDATION_APPLIES_TO, source.annotationType())
+                    .map(w -> w.read(source));
+
             final Map<Class<? extends Annotation>, AtomicInteger> constraintCounts = new HashMap<>();
 
             return Stream.of(components).map(c -> {
@@ -172,6 +185,11 @@ public class AnnotationsManager {
                 proxyBuilder.setGroups(groups);
                 proxyBuilder.setPayload(payload);
 
+                if (constraintTarget.isPresent()
+                    && validWorker(ConstraintAnnotationAttributes.VALIDATION_APPLIES_TO, c.annotationType())
+                        .isPresent()) {
+                    proxyBuilder.setValidationAppliesTo(constraintTarget.get());
+                }
                 overrides.optional().map(o -> o.get(new OverriddenAnnotationSpecifier(c.annotationType(), index)))
                     .ifPresent(m -> {
                         final Map<String, Object> sourceAttributes = readAttributes(source);
@@ -265,14 +283,31 @@ public class AnnotationsManager {
     }
 
     private static Annotation[] getDeclaredConstraints(AnnotatedElement e) {
-        return Stream.of(e.getDeclaredAnnotations()).flatMap((Function<Annotation, Stream<Annotation>>) a -> {
-            final ConstraintAnnotationAttributes.Worker<? extends Annotation> analyzer =
-                ConstraintAnnotationAttributes.VALUE.analyze(a.annotationType());
-            if (analyzer.isValid()) {
-                return Stream.of(analyzer.<Annotation[]> read(a));
+        final Annotation[] declaredAnnotations = e.getDeclaredAnnotations();
+
+        // collect constraint explicitly nested into repeatable containers:
+        final Map<Class<? extends Annotation>, Annotation[]> repeated = new HashMap<>();
+
+        for (Annotation a : declaredAnnotations) {
+            final Class<? extends Annotation> annotationType = a.annotationType();
+            final Worker<? extends Annotation> w = ConstraintAnnotationAttributes.VALUE.analyze(annotationType);
+            if (w.isValid()
+                && ((Class<?>) w.getSpecificType()).getComponentType().isAnnotationPresent(Constraint.class)) {
+                repeated.put(annotationType, w.read(a));
             }
-            return Stream.of(a);
-        }).filter(a -> a.annotationType().isAnnotationPresent(Constraint.class)).toArray(Annotation[]::new);
+        }
+        final Set<Annotation> constraints = Stream.of(declaredAnnotations)
+            .filter((Predicate<Annotation>) a -> a.annotationType().isAnnotationPresent(Constraint.class))
+            .collect(Collectors.toSet());
+
+        Exceptions.raiseIf(
+            constraints.stream().map(Annotation::annotationType).filter(t -> t.isAnnotationPresent(Repeatable.class))
+                .map(rct -> rct.getAnnotation(Repeatable.class).value()).anyMatch(repeated::containsKey),
+            ConstraintDeclarationException::new,
+            "Simultaneous declaration of repeatable constraint and associated container on %s", e);
+
+        return Stream.concat(constraints.stream(), repeated.values().stream().flatMap(Stream::of))
+            .toArray(Annotation[]::new);
     }
 
     public static boolean declaresAttribute(Class<? extends Annotation> annotationType, String name) {