Skip to content
Permalink
Browse files
value extraction work
  • Loading branch information
mbenson committed Oct 16, 2018
1 parent ac87772 commit be34559cfffa49a893fd7acf147d2b2ae44bab67
Show file tree
Hide file tree
Showing 15 changed files with 275 additions and 203 deletions.
@@ -18,11 +18,19 @@
*/
package org.apache.bval.jsr;

import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.util.Map;

import javax.validation.Path;
import javax.validation.ValidationException;

import org.apache.bval.jsr.metadata.ContainerElementKey;
import org.apache.bval.jsr.util.NodeImpl;
import org.apache.bval.jsr.util.PathImpl;
import org.apache.bval.util.Exceptions;
import org.apache.bval.util.Validate;
import org.apache.bval.util.reflection.TypeUtils;

public class GraphContext {

@@ -64,9 +72,9 @@ public GraphContext child(NodeImpl node, Object value) {

public GraphContext child(Path p, Object value) {
Validate.notNull(p, "Path");
final PathImpl impl = PathImpl.copy(p);
final PathImpl impl = PathImpl.of(p);
Validate.isTrue(impl.isSubPathOf(path), "%s is not a subpath of %s", p, path);
return new GraphContext(validatorContext, impl, value, this);
return new GraphContext(validatorContext, impl == p ? PathImpl.copy(impl) : impl, value, this);
}

public boolean isRoot() {
@@ -92,4 +100,31 @@ public GraphContext getParent() {
public String toString() {
return String.format("%s: %s at '%s'", getClass().getSimpleName(), value, path);
}

public ContainerElementKey runtimeKey(ContainerElementKey key) {
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 ContainerElementKey.forTypeVariable(var);
}
}
}
return key;
}
}
@@ -20,18 +20,14 @@

import java.lang.reflect.AnnotatedElement;
import java.util.Set;
import java.util.stream.Stream;

import javax.validation.ValidationException;
import javax.validation.metadata.CascadableDescriptor;
import javax.validation.metadata.ContainerDescriptor;
import javax.validation.metadata.ContainerElementTypeDescriptor;
import javax.validation.metadata.GroupConversionDescriptor;

import org.apache.bval.jsr.GraphContext;
import org.apache.bval.jsr.groups.GroupConversion;
import org.apache.bval.jsr.util.ToUnmodifiable;
import org.apache.bval.util.Validate;
import org.apache.bval.util.reflection.TypeUtils;

public abstract class CascadableContainerD<P extends ElementD<?, ?>, E extends AnnotatedElement> extends
@@ -69,20 +65,4 @@ public Set<ContainerElementTypeDescriptor> getConstrainedContainerElementTypes()
return containerElementTypes.stream().filter(DescriptorManager::isConstrained)
.collect(ToUnmodifiable.set());
}

public final Stream<GraphContext> read(GraphContext context) {
Validate.notNull(context);
if (context.getValue() == null) {
return Stream.empty();
}
try {
return readImpl(context);
} catch (Exception e) {
throw e instanceof ValidationException ? (ValidationException) e : new ValidationException(e);
}
}

protected Stream<GraphContext> readImpl(GraphContext context) throws Exception {
throw new UnsupportedOperationException();
}
}
@@ -19,33 +19,15 @@
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,
@@ -67,44 +49,4 @@ public Integer getTypeArgumentIndex() {
public ContainerElementKey getKey() {
return key;
}

@Override
protected Stream<GraphContext> readImpl(GraphContext context) throws Exception {
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,11 +22,13 @@
import java.lang.reflect.Method;
import java.util.stream.Stream;

import javax.validation.ValidationException;
import javax.validation.metadata.PropertyDescriptor;

import org.apache.bval.jsr.GraphContext;
import org.apache.bval.jsr.util.Methods;
import org.apache.bval.jsr.util.PathImpl;
import org.apache.bval.util.Validate;
import org.apache.bval.util.reflection.Reflection;
import org.apache.commons.weaver.privilizer.Privilizing;
import org.apache.commons.weaver.privilizer.Privilizing.CallTo;
@@ -94,12 +96,19 @@ protected PropertyD(MetadataReader.ForContainer<E> reader, BeanD<?> parent) {
this.host = reader.meta.getHost();
}

@Override
protected Stream<GraphContext> readImpl(GraphContext context) throws Exception {
final Object value = getValue(context.getValue());
final PathImpl p = PathImpl.copy(context.getPath());
p.addProperty(getPropertyName());
return Stream.of(context.child(p, value));
public final Stream<GraphContext> read(GraphContext context) {
Validate.notNull(context);
if (context.getValue() == null) {
return Stream.empty();
}
try {
final Object value = getValue(context.getValue());
final PathImpl p = PathImpl.copy(context.getPath());
p.addProperty(getPropertyName());
return Stream.of(context.child(p, value));
} catch (Exception e) {
throw e instanceof ValidationException ? (ValidationException) e : new ValidationException(e);
}
}

public abstract Object getValue(Object parent) throws Exception;
@@ -165,7 +165,7 @@ public <U> U unwrap(Class<U> type) {
}

@SuppressWarnings({ "unchecked", "rawtypes" })
public void addError(String messageTemplate, Path propertyPath) {
public void addError(String messageTemplate, PathImpl propertyPath) {
violations.get().add(((ValidationJob) frame.getJob()).createViolation(messageTemplate, this, propertyPath));
}

@@ -18,8 +18,6 @@
*/
package org.apache.bval.jsr.job;

import javax.validation.Path;

import org.apache.bval.jsr.ApacheFactoryContext;
import org.apache.bval.jsr.ConstraintViolationImpl;
import org.apache.bval.jsr.GraphContext;
@@ -50,7 +48,7 @@ protected Class<T> getRootBeanClass() {

@Override
ConstraintViolationImpl<T> createViolation(String messageTemplate, String message,
ConstraintValidatorContextImpl<T> context, Path propertyPath) {
ConstraintValidatorContextImpl<T> context, PathImpl propertyPath) {
return new ConstraintViolationImpl<>(messageTemplate, message, bean,
context.getFrame().getBean(), propertyPath, context.getFrame().context.getValue(),
context.getConstraintDescriptor(), getRootBeanClass(),
@@ -28,7 +28,6 @@

import javax.validation.ConstraintViolation;
import javax.validation.ParameterNameProvider;
import javax.validation.Path;
import javax.validation.constraintvalidation.ValidationTarget;
import javax.validation.metadata.ExecutableDescriptor;

@@ -181,7 +180,7 @@ protected boolean hasWork() {

@Override
ConstraintViolationImpl<T> createViolation(String messageTemplate, String message,
ConstraintValidatorContextImpl<T> context, Path propertyPath) {
ConstraintValidatorContextImpl<T> context, PathImpl propertyPath) {
return new ConstraintViolationImpl<T>(messageTemplate, message, getRootBean(), context.getFrame().getBean(),
propertyPath, context.getFrame().context.getValue(), context.getConstraintDescriptor(), getRootBeanClass(),
context.getConstraintDescriptor().unwrap(ConstraintD.class).getDeclaredOn(), null, parameterValues);
@@ -31,7 +31,6 @@
import java.util.function.Consumer;

import javax.validation.ConstraintViolation;
import javax.validation.Path;
import javax.validation.metadata.BeanDescriptor;
import javax.validation.metadata.CascadableDescriptor;
import javax.validation.metadata.ContainerDescriptor;
@@ -515,7 +514,7 @@ protected Class<T> getRootBeanClass() {

@Override
ConstraintViolationImpl<T> createViolation(String messageTemplate, String message,
ConstraintValidatorContextImpl<T> context, Path propertyPath) {
ConstraintValidatorContextImpl<T> context, PathImpl propertyPath) {
return new ConstraintViolationImpl<>(messageTemplate, message, rootBean, context.getFrame().getBean(),
propertyPath, context.getFrame().context.getValue(), context.getConstraintDescriptor(), rootBeanClass,
context.getConstraintDescriptor().unwrap(ConstraintD.class).getDeclaredOn(), null, null);
@@ -21,8 +21,6 @@
import java.lang.reflect.Method;
import java.lang.reflect.Type;

import javax.validation.Path;

import org.apache.bval.jsr.ApacheFactoryContext;
import org.apache.bval.jsr.ConstraintViolationImpl;
import org.apache.bval.jsr.GraphContext;
@@ -125,7 +123,7 @@ Object getBean() {

@Override
ConstraintViolationImpl<T> createViolation(String messageTemplate, String message,
ConstraintValidatorContextImpl<T> context, Path propertyPath) {
ConstraintValidatorContextImpl<T> context, PathImpl propertyPath) {
return new ConstraintViolationImpl<>(messageTemplate, message, getRootBean(), context.getFrame().getBean(),
propertyPath, context.getFrame().context.getValue(), context.getConstraintDescriptor(), getRootBeanClass(),
context.getConstraintDescriptor().unwrap(ConstraintD.class).getDeclaredOn(), returnValue, null);

0 comments on commit be34559

Please sign in to comment.