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/03/06 17:04:52 UTC

bval git commit: more TCK satisfaction

Repository: bval
Updated Branches:
  refs/heads/bv2 8689861e0 -> 4c1e1e0b3


more TCK satisfaction


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

Branch: refs/heads/bv2
Commit: 4c1e1e0b34151d1a3101959a74ce15e26fec1801
Parents: 8689861
Author: Matt Benson <mb...@apache.org>
Authored: Tue Mar 6 11:04:45 2018 -0600
Committer: Matt Benson <mb...@apache.org>
Committed: Tue Mar 6 11:04:45 2018 -0600

----------------------------------------------------------------------
 .../apache/bval/jsr/descriptor/PropertyD.java   |  8 +-
 .../apache/bval/jsr/job/ValidateProperty.java   | 10 +--
 .../bval/jsr/job/ValidateReturnValue.java       |  2 +-
 .../org/apache/bval/jsr/job/ValidationJob.java  | 43 ++++++++--
 .../bval/jsr/metadata/ContainerElementKey.java  | 51 +++++++-----
 .../jsr/metadata/ContainerElementKeyTest.java   | 86 ++++++++++++++++++++
 6 files changed, 161 insertions(+), 39 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/bval/blob/4c1e1e0b/bval-jsr/src/main/java/org/apache/bval/jsr/descriptor/PropertyD.java
----------------------------------------------------------------------
diff --git a/bval-jsr/src/main/java/org/apache/bval/jsr/descriptor/PropertyD.java b/bval-jsr/src/main/java/org/apache/bval/jsr/descriptor/PropertyD.java
index c7c2eff..54a69f0 100644
--- a/bval-jsr/src/main/java/org/apache/bval/jsr/descriptor/PropertyD.java
+++ b/bval-jsr/src/main/java/org/apache/bval/jsr/descriptor/PropertyD.java
@@ -20,14 +20,13 @@ import java.lang.reflect.AnnotatedElement;
 import java.lang.reflect.Field;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
-import java.util.function.Supplier;
 import java.util.stream.Stream;
 
 import javax.validation.metadata.PropertyDescriptor;
 
 import org.apache.bval.jsr.GraphContext;
 import org.apache.bval.jsr.util.Methods;
-import org.apache.bval.jsr.util.NodeImpl;
+import org.apache.bval.jsr.util.PathImpl;
 import org.apache.bval.util.reflection.Reflection;
 import org.apache.commons.weaver.privilizer.Privilizing;
 import org.apache.commons.weaver.privilizer.Privilizing.CallTo;
@@ -97,9 +96,10 @@ public abstract class PropertyD<E extends AnnotatedElement> extends CascadableCo
 
     @Override
     protected Stream<GraphContext> readImpl(GraphContext context) throws Exception {
-        final Supplier<NodeImpl> propertyNode = () -> new NodeImpl.PropertyNodeImpl(getPropertyName());
         final Object value = getValue(context.getValue());
-        return Stream.of(context.child(propertyNode.get(), value));
+        final PathImpl p = PathImpl.copy(context.getPath());
+        p.addProperty(getPropertyName());
+        return Stream.of(context.child(p, value));
     }
 
     public abstract Object getValue(Object parent) throws Exception;

http://git-wip-us.apache.org/repos/asf/bval/blob/4c1e1e0b/bval-jsr/src/main/java/org/apache/bval/jsr/job/ValidateProperty.java
----------------------------------------------------------------------
diff --git a/bval-jsr/src/main/java/org/apache/bval/jsr/job/ValidateProperty.java b/bval-jsr/src/main/java/org/apache/bval/jsr/job/ValidateProperty.java
index e3ec306..fa7e0f5 100644
--- a/bval-jsr/src/main/java/org/apache/bval/jsr/job/ValidateProperty.java
+++ b/bval-jsr/src/main/java/org/apache/bval/jsr/job/ValidateProperty.java
@@ -20,14 +20,15 @@ package org.apache.bval.jsr.job;
 
 import java.lang.reflect.Array;
 import java.lang.reflect.Type;
+import java.lang.reflect.TypeVariable;
 import java.util.Arrays;
+import java.util.Collection;
 import java.util.List;
 import java.util.Map;
 import java.util.Optional;
 import java.util.Set;
 import java.util.function.BiConsumer;
 import java.util.function.Consumer;
-import java.util.function.Predicate;
 
 import javax.validation.ConstraintViolation;
 import javax.validation.Path;
@@ -231,12 +232,11 @@ public final class ValidateProperty<T> extends ValidationJob<T> {
             if (containerElements.size() == 1) {
                 element = containerElements.iterator().next();
             } else {
-                final Predicate<ContainerElementKey> wellKnown =
-                    k -> k.represents(MAP_VALUE) || k.represents(ITERABLE_ELEMENT);
+                final Collection<TypeVariable<?>> wellKnown = Arrays.asList(MAP_VALUE, ITERABLE_ELEMENT);
 
                 final Optional<ContainerElementTypeD> found =
-                    containerElements.stream().map(ContainerElementTypeD.class::cast)
-                        .filter(d -> d.getKey().getAssignableKeys().stream().anyMatch(wellKnown)).findFirst();
+                    containerElements.stream().<ContainerElementTypeD> map(ContainerElementTypeD.class::cast)
+                        .filter(d -> wellKnown.stream().anyMatch(d.getKey()::represents)).findFirst();
 
                 if (!found.isPresent()) {
                     return null;

http://git-wip-us.apache.org/repos/asf/bval/blob/4c1e1e0b/bval-jsr/src/main/java/org/apache/bval/jsr/job/ValidateReturnValue.java
----------------------------------------------------------------------
diff --git a/bval-jsr/src/main/java/org/apache/bval/jsr/job/ValidateReturnValue.java b/bval-jsr/src/main/java/org/apache/bval/jsr/job/ValidateReturnValue.java
index 21126a6..eedb27c 100644
--- a/bval-jsr/src/main/java/org/apache/bval/jsr/job/ValidateReturnValue.java
+++ b/bval-jsr/src/main/java/org/apache/bval/jsr/job/ValidateReturnValue.java
@@ -111,7 +111,7 @@ public abstract class ValidateReturnValue<E extends Executable, T> extends Valid
 
     @Override
     protected Frame<?> computeBaseFrame() {
-        final PathImpl path = PathImpl.create();
+        final PathImpl path = createBasePath();
         path.addNode(new NodeImpl.ReturnValueNodeImpl());
 
         return new SproutFrame<ReturnValueD<?, ?>>((ReturnValueD<?, ?>) describe().getReturnValueDescriptor(),

http://git-wip-us.apache.org/repos/asf/bval/blob/4c1e1e0b/bval-jsr/src/main/java/org/apache/bval/jsr/job/ValidationJob.java
----------------------------------------------------------------------
diff --git a/bval-jsr/src/main/java/org/apache/bval/jsr/job/ValidationJob.java b/bval-jsr/src/main/java/org/apache/bval/jsr/job/ValidationJob.java
index 88fd40c..070bdc6 100644
--- a/bval-jsr/src/main/java/org/apache/bval/jsr/job/ValidationJob.java
+++ b/bval-jsr/src/main/java/org/apache/bval/jsr/job/ValidationJob.java
@@ -21,6 +21,8 @@ package org.apache.bval.jsr.job;
 import java.lang.reflect.Array;
 import java.lang.reflect.Type;
 import java.lang.reflect.TypeVariable;
+import java.util.Arrays;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.Comparator;
 import java.util.LinkedHashSet;
@@ -33,6 +35,7 @@ import java.util.concurrent.ConcurrentMap;
 import java.util.concurrent.ConcurrentSkipListSet;
 import java.util.function.BiConsumer;
 import java.util.function.Consumer;
+import java.util.function.Predicate;
 import java.util.function.Supplier;
 import java.util.stream.Collectors;
 import java.util.stream.IntStream;
@@ -55,9 +58,9 @@ import org.apache.bval.jsr.ApacheFactoryContext;
 import org.apache.bval.jsr.ConstraintViolationImpl;
 import org.apache.bval.jsr.GraphContext;
 import org.apache.bval.jsr.descriptor.BeanD;
-import org.apache.bval.jsr.descriptor.CascadableContainerD;
 import org.apache.bval.jsr.descriptor.ComposedD;
 import org.apache.bval.jsr.descriptor.ConstraintD;
+import org.apache.bval.jsr.descriptor.ContainerElementTypeD;
 import org.apache.bval.jsr.descriptor.ElementD;
 import org.apache.bval.jsr.descriptor.PropertyD;
 import org.apache.bval.jsr.groups.Group;
@@ -68,6 +71,7 @@ import org.apache.bval.jsr.util.Proxies;
 import org.apache.bval.util.Exceptions;
 import org.apache.bval.util.Lazy;
 import org.apache.bval.util.ObjectUtils;
+import org.apache.bval.util.ObjectWrapper;
 import org.apache.bval.util.Validate;
 import org.apache.bval.util.reflection.TypeUtils;
 
@@ -239,9 +243,12 @@ public abstract class ValidationJob<T> {
             final TraversableResolver traversableResolver = validatorContext.getTraversableResolver();
 
             final Stream<PropertyD<?>> reachableProperties =
-                properties.filter(d -> traversableResolver.isReachable(context.getValue(),
-                    new NodeImpl.PropertyNodeImpl(d.getPropertyName()), getRootBeanClass(), context.getPath(),
-                    d.getElementType()));
+                    properties.filter(d -> {
+                        final PathImpl p = PathImpl.copy(context.getPath());
+                        p.addProperty(d.getPropertyName());
+                        return traversableResolver.isReachable(context.getValue(), p.removeLeafNode(), getRootBeanClass(),
+                            p, d.getElementType());
+                    });
 
             return reachableProperties.flatMap(
                 d -> d.read(context).filter(context -> !context.isRecursive()).map(child -> propertyFrame(d, child)))
@@ -262,14 +269,32 @@ public abstract class ValidationJob<T> {
         @Override
         void recurse(Class<?> group, Consumer<ConstraintViolation<T>> sink) {
             @SuppressWarnings({ "unchecked", "rawtypes" })
-            final Stream<CascadableContainerD<?, ?>> containerElements =
-                descriptor.getConstrainedContainerElementTypes().stream()
-                    .flatMap(d -> ComposedD.unwrap(d, (Class) CascadableContainerD.class));
+            final Stream<ContainerElementTypeD> containerElements =
+            descriptor.getConstrainedContainerElementTypes().stream()
+                .flatMap(d -> ComposedD.unwrap(d, (Class) ContainerElementTypeD.class));
+            
+            final ObjectWrapper<Boolean> effectiveCascade =
+                new ObjectWrapper<>(Boolean.valueOf(descriptor.isCascaded()));
 
-            containerElements.flatMap(d -> d.read(context).map(child -> new SproutFrame<>(this, d, child)))
+            // cascade legacy containers the old way by filtering them out here:
+
+            final Collection<TypeVariable<?>> wellKnown = Arrays.asList(ITERABLE_ELEMENT, MAP_VALUE);
+
+            final Predicate<? super ContainerElementTypeD> isNotLegacyContainer = d -> {
+                final boolean cascadedLegacyContainer =
+                    d.isCascaded() && wellKnown.stream().anyMatch(d.getKey()::represents);
+
+                if (cascadedLegacyContainer) {
+                    effectiveCascade.accept(Boolean.TRUE);
+                }
+                return !cascadedLegacyContainer;
+            };
+
+            containerElements.filter(isNotLegacyContainer)
+                .flatMap(d -> d.read(context).map(child -> new SproutFrame<>(this, d, child)))
                 .forEach(f -> f.process(group, sink));
 
-            if (!descriptor.isCascaded()) {
+            if (!effectiveCascade.get().booleanValue()) {
                 return;
             }
             if (descriptor instanceof PropertyDescriptor) {

http://git-wip-us.apache.org/repos/asf/bval/blob/4c1e1e0b/bval-jsr/src/main/java/org/apache/bval/jsr/metadata/ContainerElementKey.java
----------------------------------------------------------------------
diff --git a/bval-jsr/src/main/java/org/apache/bval/jsr/metadata/ContainerElementKey.java b/bval-jsr/src/main/java/org/apache/bval/jsr/metadata/ContainerElementKey.java
index 322a4ef..59cc90e 100644
--- a/bval-jsr/src/main/java/org/apache/bval/jsr/metadata/ContainerElementKey.java
+++ b/bval-jsr/src/main/java/org/apache/bval/jsr/metadata/ContainerElementKey.java
@@ -27,6 +27,7 @@ import java.util.LinkedHashSet;
 import java.util.Objects;
 import java.util.Optional;
 import java.util.Set;
+import java.util.function.Consumer;
 import java.util.logging.Logger;
 import java.util.stream.IntStream;
 import java.util.stream.Stream;
@@ -143,30 +144,40 @@ public class ContainerElementKey implements Comparable<ContainerElementKey> {
 
     public Set<ContainerElementKey> getAssignableKeys() {
         final Lazy<Set<ContainerElementKey>> result = new Lazy<>(LinkedHashSet::new);
-
-        if (typeArgumentIndex != null) {
-            final TypeVariable<?> var = containerClass.getTypeParameters()[typeArgumentIndex.intValue()];
-
-            Stream
-                .concat(Stream.of(containerClass.getAnnotatedSuperclass()),
-                    Stream.of(containerClass.getAnnotatedInterfaces()))
-                .filter(AnnotatedParameterizedType.class::isInstance).map(AnnotatedParameterizedType.class::cast)
-                .forEach(t -> {
-                    final AnnotatedType[] args = t.getAnnotatedActualTypeArguments();
-
-                    for (int i = 0; i < args.length; i++) {
-                        if (args[i].getType().equals(var)) {
-                            result.get().add(new ContainerElementKey(t, Integer.valueOf(i)));
-                        }
-                    }
-                });
-        }
+        hierarchy(result.consumer(Set::add));
         return result.optional().map(Collections::unmodifiableSet).orElseGet(Collections::emptySet);
     }
 
     public boolean represents(TypeVariable<?> var) {
-        return Optional.ofNullable(typeArgumentIndex)
-            .map(index -> getContainerClass().getTypeParameters()[index.intValue()]).filter(var::equals).isPresent();
+        return Stream.concat(Stream.of(this), getAssignableKeys().stream())
+            .anyMatch(cek -> cek.typeArgumentIndex != null
+                && cek.containerClass.getTypeParameters()[cek.typeArgumentIndex.intValue()].equals(var));
+    }
+
+    private void hierarchy(Consumer<ContainerElementKey> sink) {
+        if (typeArgumentIndex == null) {
+            return;
+        }
+        final TypeVariable<?> var = containerClass.getTypeParameters()[typeArgumentIndex.intValue()];
+
+        final Lazy<Set<ContainerElementKey>> round = new Lazy<>(LinkedHashSet::new);
+        Stream
+            .concat(Stream.of(containerClass.getAnnotatedSuperclass()),
+                Stream.of(containerClass.getAnnotatedInterfaces()))
+            .filter(AnnotatedParameterizedType.class::isInstance).map(AnnotatedParameterizedType.class::cast)
+            .forEach(t -> {
+                final AnnotatedType[] args = ((AnnotatedParameterizedType) t).getAnnotatedActualTypeArguments();
+                for (int i = 0; i < args.length; i++) {
+                    if (args[i].getType().equals(var)) {
+                        round.get().add(new ContainerElementKey(t, Integer.valueOf(i)));
+                    }
+                }
+            });
+
+        round.optional().ifPresent(s -> {
+            s.forEach(sink);
+            s.forEach(k -> k.hierarchy(sink));
+        });
     }
 
     private String containerClassName() {

http://git-wip-us.apache.org/repos/asf/bval/blob/4c1e1e0b/bval-jsr/src/test/java/org/apache/bval/jsr/metadata/ContainerElementKeyTest.java
----------------------------------------------------------------------
diff --git a/bval-jsr/src/test/java/org/apache/bval/jsr/metadata/ContainerElementKeyTest.java b/bval-jsr/src/test/java/org/apache/bval/jsr/metadata/ContainerElementKeyTest.java
new file mode 100644
index 0000000..b33b928
--- /dev/null
+++ b/bval-jsr/src/test/java/org/apache/bval/jsr/metadata/ContainerElementKeyTest.java
@@ -0,0 +1,86 @@
+/*
+ * 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.
+ */
+package org.apache.bval.jsr.metadata;
+
+import static org.junit.Assert.*;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.TypeVariable;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+
+import org.junit.Before;
+import org.junit.Test;
+
+public class ContainerElementKeyTest {
+    public static abstract class HasList {
+        public List<String> strings;
+    }
+
+    private Field stringsField;
+
+    @Before
+    public void setup() throws Exception {
+        stringsField = HasList.class.getField("strings");
+    }
+
+    @Test
+    public void testBasic() {
+        final ContainerElementKey containerElementKey =
+            new ContainerElementKey(stringsField.getAnnotatedType(), Integer.valueOf(0));
+
+        assertEquals(List.class, containerElementKey.getContainerClass());
+        assertEquals(0, containerElementKey.getTypeArgumentIndex().intValue());
+        assertEquals(String.class, containerElementKey.getAnnotatedType().getType());
+    }
+
+    @Test
+    public void testAssignableKeys() {
+        final ContainerElementKey containerElementKey =
+            new ContainerElementKey(stringsField.getAnnotatedType(), Integer.valueOf(0));
+
+        final Iterator<ContainerElementKey> iterator = containerElementKey.getAssignableKeys().iterator();
+        {
+            assertTrue(iterator.hasNext());
+            final ContainerElementKey assignableKey = iterator.next();
+            assertEquals(Collection.class, assignableKey.getContainerClass());
+            assertEquals(0, assignableKey.getTypeArgumentIndex().intValue());
+            assertTrue(assignableKey.getAnnotatedType().getType() instanceof TypeVariable<?>);
+        }
+        {
+            assertTrue(iterator.hasNext());
+            final ContainerElementKey assignableKey = iterator.next();
+            assertEquals(Iterable.class, assignableKey.getContainerClass());
+            assertEquals(0, assignableKey.getTypeArgumentIndex().intValue());
+            assertTrue(assignableKey.getAnnotatedType().getType() instanceof TypeVariable<?>);
+        }
+        assertFalse(iterator.hasNext());
+    }
+
+    @Test
+    public void testTypeVariableInheritance() {
+        final ContainerElementKey containerElementKey =
+            new ContainerElementKey(stringsField.getAnnotatedType(), Integer.valueOf(0));
+
+        assertTrue(containerElementKey.represents(List.class.getTypeParameters()[0]));
+        assertTrue(containerElementKey.represents(Collection.class.getTypeParameters()[0]));
+        assertTrue(containerElementKey.represents(Iterable.class.getTypeParameters()[0]));
+    }
+}