Skip to content
Permalink
Browse files
use runtime type to find valueExtractor for container element keys
  • Loading branch information
mbenson committed Oct 16, 2018
1 parent f5124e2 commit e00c369067beeb8a77d15df5e683f71e9e0031b1
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 3 deletions.
@@ -19,21 +19,33 @@
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;

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 ContainerElementKey getKey() {

@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;
}
}
@@ -22,6 +22,7 @@
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 ValueExtractor<?> find(ContainerElementKey key) {
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;

0 comments on commit e00c369

Please sign in to comment.