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/27 22:58:40 UTC
[2/2] bval git commit: use runtime type to find valueExtractor for
container element keys
use runtime type to find valueExtractor for container element keys
Project: http://git-wip-us.apache.org/repos/asf/bval/repo
Commit: http://git-wip-us.apache.org/repos/asf/bval/commit/f69d9b97
Tree: http://git-wip-us.apache.org/repos/asf/bval/tree/f69d9b97
Diff: http://git-wip-us.apache.org/repos/asf/bval/diff/f69d9b97
Branch: refs/heads/bv2
Commit: f69d9b97398866f7b0348b52319b73b55da022ad
Parents: 85ea6c6
Author: Matt Benson <mb...@apache.org>
Authored: Tue Mar 27 17:58:23 2018 -0500
Committer: Matt Benson <mb...@apache.org>
Committed: Tue Mar 27 17:58:23 2018 -0500
----------------------------------------------------------------------
.../jsr/descriptor/ContainerElementTypeD.java | 44 +++++++++++++++++++-
.../jsr/valueextraction/ValueExtractors.java | 5 ++-
2 files changed, 46 insertions(+), 3 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/bval/blob/f69d9b97/bval-jsr/src/main/java/org/apache/bval/jsr/descriptor/ContainerElementTypeD.java
----------------------------------------------------------------------
diff --git a/bval-jsr/src/main/java/org/apache/bval/jsr/descriptor/ContainerElementTypeD.java b/bval-jsr/src/main/java/org/apache/bval/jsr/descriptor/ContainerElementTypeD.java
index ef00edc..fc97df8 100644
--- a/bval-jsr/src/main/java/org/apache/bval/jsr/descriptor/ContainerElementTypeD.java
+++ b/bval-jsr/src/main/java/org/apache/bval/jsr/descriptor/ContainerElementTypeD.java
@@ -19,9 +19,13 @@
package org.apache.bval.jsr.descriptor;
import java.lang.reflect.AnnotatedType;
+import java.lang.reflect.Type;
+import java.lang.reflect.TypeVariable;
+import java.util.Map;
import java.util.stream.Stream;
import javax.validation.ConstraintDeclarationException;
+import javax.validation.ValidationException;
import javax.validation.metadata.ContainerElementTypeDescriptor;
import javax.validation.valueextraction.ValueExtractor;
@@ -29,11 +33,19 @@ import org.apache.bval.jsr.GraphContext;
import org.apache.bval.jsr.metadata.ContainerElementKey;
import org.apache.bval.jsr.valueextraction.ExtractValues;
import org.apache.bval.util.Exceptions;
+import org.apache.bval.util.ObjectUtils;
import org.apache.bval.util.Validate;
+import org.apache.bval.util.reflection.TypeUtils;
public class ContainerElementTypeD extends CascadableContainerD<CascadableContainerD<?, ?>, AnnotatedType>
implements ContainerElementTypeDescriptor {
+ private static ContainerElementKey toContainerElementKey(TypeVariable<?> var) {
+ final Class<?> container = (Class<?>) var.getGenericDeclaration();
+ final int argIndex = ObjectUtils.indexOf(container.getTypeParameters(), var);
+ return new ContainerElementKey(container, Integer.valueOf(argIndex));
+ }
+
private final ContainerElementKey key;
ContainerElementTypeD(ContainerElementKey key, MetadataReader.ForContainer<AnnotatedType> reader,
@@ -58,11 +70,41 @@ public class ContainerElementTypeD extends CascadableContainerD<CascadableContai
@Override
protected Stream<GraphContext> readImpl(GraphContext context) throws Exception {
- final ValueExtractor<?> valueExtractor = context.getValidatorContext().getValueExtractors().find(key);
+ final ContainerElementKey runtimeKey = runtimeKey(context.getValue());
+ final ValueExtractor<?> valueExtractor =
+ context.getValidatorContext().getValueExtractors().find(runtimeKey);
+
if (valueExtractor == null) {
Exceptions.raise(ConstraintDeclarationException::new, "No %s found for %s",
ValueExtractor.class.getSimpleName(), key);
}
return ExtractValues.extract(context, key, valueExtractor).stream();
}
+
+ private ContainerElementKey runtimeKey(Object value) {
+ final Class<?> containerClass = key.getContainerClass();
+ final Class<? extends Object> runtimeType = value.getClass();
+ if (!runtimeType.equals(containerClass)) {
+ Exceptions.raiseUnless(containerClass.isAssignableFrom(runtimeType), ValidationException::new,
+ "Value %s is not assignment-compatible with %s", value, containerClass);
+
+ if (key.getTypeArgumentIndex() == null) {
+ return new ContainerElementKey(runtimeType, null);
+ }
+ final Map<TypeVariable<?>, Type> typeArguments = TypeUtils.getTypeArguments(runtimeType, containerClass);
+
+ Type type = typeArguments.get(containerClass.getTypeParameters()[key.getTypeArgumentIndex().intValue()]);
+
+ while (type instanceof TypeVariable<?>) {
+ final TypeVariable<?> var = (TypeVariable<?>) type;
+ final Type nextType = typeArguments.get(var);
+ if (nextType instanceof TypeVariable<?>) {
+ type = nextType;
+ } else {
+ return toContainerElementKey(var);
+ }
+ }
+ }
+ return key;
+ }
}
http://git-wip-us.apache.org/repos/asf/bval/blob/f69d9b97/bval-jsr/src/main/java/org/apache/bval/jsr/valueextraction/ValueExtractors.java
----------------------------------------------------------------------
diff --git a/bval-jsr/src/main/java/org/apache/bval/jsr/valueextraction/ValueExtractors.java b/bval-jsr/src/main/java/org/apache/bval/jsr/valueextraction/ValueExtractors.java
index ca45701..2ebc2c7 100644
--- a/bval-jsr/src/main/java/org/apache/bval/jsr/valueextraction/ValueExtractors.java
+++ b/bval-jsr/src/main/java/org/apache/bval/jsr/valueextraction/ValueExtractors.java
@@ -22,6 +22,7 @@ import java.lang.reflect.Type;
import java.lang.reflect.WildcardType;
import java.util.Collections;
import java.util.HashMap;
+import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Optional;
import java.util.Properties;
@@ -223,8 +224,8 @@ public class ValueExtractors {
return null;
}
final Map<ContainerElementKey, ValueExtractor<?>> candidateMap =
- assignableKeys.stream().filter(allValueExtractors::containsKey)
- .collect(Collectors.toMap(Function.identity(), allValueExtractors::get));
+ assignableKeys.stream().filter(allValueExtractors::containsKey).collect(
+ Collectors.toMap(Function.identity(), allValueExtractors::get, (quid, quo) -> quo, LinkedHashMap::new));
if (candidateMap.isEmpty()) {
return null;