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]));
+ }
+}