Skip to content

Commit

Permalink
revamp custom constraint building code for TCK progress/spec compliance
Browse files Browse the repository at this point in the history
  • Loading branch information
mbenson committed Oct 16, 2018
1 parent 860ff19 commit 54dab69
Show file tree
Hide file tree
Showing 13 changed files with 173 additions and 207 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import javax.validation.ClockProvider;
import javax.validation.ConstraintValidatorContext;
import javax.validation.ConstraintViolation;
import javax.validation.ElementKind;
import javax.validation.MessageInterpolator;
import javax.validation.ValidationException;
import javax.validation.metadata.ConstraintDescriptor;
Expand All @@ -43,10 +44,12 @@
import org.apache.bval.util.Validate;

public class ConstraintValidatorContextImpl<T> implements ConstraintValidatorContext, MessageInterpolator.Context {
private class ConstraintViolationBuilderImpl implements ConstraintValidatorContext.ConstraintViolationBuilder {
public class ConstraintViolationBuilderImpl implements ConstraintValidatorContext.ConstraintViolationBuilder {
private final String template;
private final PathImpl path;

private boolean complete;

ConstraintViolationBuilderImpl(String template, PathImpl path) {
this.template = template;
this.path = path;
Expand All @@ -57,29 +60,22 @@ private class ConstraintViolationBuilderImpl implements ConstraintValidatorConte
*/
@Override
public NodeBuilderDefinedContext addNode(String name) {
PathImpl p;
if (path.isRootPath()) {
p = PathImpl.create();
p.getLeafNode().setName(name);
} else {
p = PathImpl.copy(path);
p.addNode(new NodeImpl.PropertyNodeImpl(name));
}
return new NodeBuilderDefinedContextImpl(ConstraintValidatorContextImpl.this, template, p);
return new NodeBuilderDefinedContextImpl(extensiblePath().addProperty(name), this);
}

@Override
public NodeBuilderCustomizableContext addPropertyNode(String name) {
return new NodeBuilderCustomizableContextImpl(ConstraintValidatorContextImpl.this, template, path, name);
return new NodeBuilderCustomizableContextImpl(extensiblePath(), name, this);
}

@Override
public LeafNodeBuilderCustomizableContext addBeanNode() {
return new LeafNodeBuilderCustomizableContextImpl(ConstraintValidatorContextImpl.this, template, path);
return new LeafNodeBuilderCustomizableContextImpl(extensiblePath(), this);
}

@Override
public NodeBuilderDefinedContext addParameterNode(int index) {
ofLegalState();
Exceptions.raiseUnless(frame.descriptor instanceof CrossParameterDescriptor, ValidationException::new,
"Cannot add parameter node for %s", f -> f.args(frame.descriptor.getClass().getName()));

Expand All @@ -88,28 +84,52 @@ public NodeBuilderDefinedContext addParameterNode(int index) {

final String parameterName = crossParameter.getParent().getParameterDescriptors().get(index).getName();

final NodeImpl node = new NodeImpl.ParameterNodeImpl(parameterName, index);
if (!path.isRootPath()) {
path.removeLeafNode();
}
path.addNode(node);
return new NodeBuilderDefinedContextImpl(ConstraintValidatorContextImpl.this, template, path);
path.removeLeafNode();
return new NodeBuilderDefinedContextImpl(path.addNode(new NodeImpl.ParameterNodeImpl(parameterName, index)),
this);
}

/**
* {@inheritDoc}
*/
@Override
public ConstraintValidatorContext addConstraintViolation() {
addError(template, path);
return addConstraintViolation(path);
}

public synchronized ConstraintViolationBuilderImpl ofLegalState() {
Validate.validState(!complete, "#addConstraintViolation() already called");
return this;
}

public ConstraintValidatorContext addConstraintViolation(PathImpl p) {
synchronized (this) {
ofLegalState();
complete = true;
}
addError(template, p);
return ConstraintValidatorContextImpl.this;
}

@Override
public ContainerElementNodeBuilderCustomizableContext addContainerElementNode(String name,
Class<?> containerType, Integer typeArgumentIndex) {
return new ContainerElementNodeBuilderCustomizableContextImpl(ConstraintValidatorContextImpl.this, template,
path, name, containerType, typeArgumentIndex);
ofLegalState();
return new ContainerElementNodeBuilderCustomizableContextImpl(extensiblePath(), name,
containerType, typeArgumentIndex, this);
}

private PathImpl extensiblePath() {
if (path.isRootPath()) {
return PathImpl.create();
}
final PathImpl result = PathImpl.copy(path);
final NodeImpl leafNode = result.getLeafNode();
if (leafNode.getKind() == ElementKind.BEAN
&& !(leafNode.isInIterable() || leafNode.getContainerClass() != null)) {
result.removeLeafNode();
}
return result;
}
}

Expand Down Expand Up @@ -153,11 +173,6 @@ public <U> U unwrap(Class<U> type) {
}
}

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

ValidationJob<T>.Frame<?> getFrame() {
return frame;
}
Expand All @@ -181,4 +196,9 @@ public ConstraintDescriptor<?> getConstraintDescriptor() {
public Object getValidatedValue() {
return frame.context.getValue();
}

@SuppressWarnings({ "unchecked", "rawtypes" })
private void addError(String messageTemplate, PathImpl propertyPath) {
violations.get().add(((ValidationJob) frame.getJob()).createViolation(messageTemplate, this, propertyPath));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -162,9 +162,8 @@ Object getBean() {

@Override
protected Frame<?> computeBaseFrame() {
final PathImpl cp = createBasePath();
cp.addNode(new NodeImpl.CrossParameterNodeImpl());
return new ParametersFrame(describe(), new GraphContext(validatorContext, cp, parameterValues));
return new ParametersFrame(describe(), new GraphContext(validatorContext,
createBasePath().addNode(new NodeImpl.CrossParameterNodeImpl()), parameterValues));
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -130,11 +130,8 @@ Object getBean() {

@Override
protected Frame<?> computeBaseFrame() {
final PathImpl path = createBasePath();
path.addNode(new NodeImpl.ReturnValueNodeImpl());

return createBaseFrame((ReturnValueD<?, ?>) describe().getReturnValueDescriptor(),
new GraphContext(validatorContext, path, returnValue));
return createBaseFrame((ReturnValueD<?, ?>) describe().getReturnValueDescriptor(), new GraphContext(
validatorContext, createBasePath().addNode(new NodeImpl.ReturnValueNodeImpl()), returnValue));
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -252,13 +252,16 @@ private Stream<Class<?>> expand(Class<?> group) {
}

public class BeanFrame<B> extends Frame<BeanD<B>> {
private final GraphContext realContext;

BeanFrame(GraphContext context) {
this(null, context);
}

BeanFrame(Frame<?> parent, GraphContext context) {
super(parent, getBeanDescriptor(context.getValue()), context);
super(parent, getBeanDescriptor(context.getValue()),
context.child(context.getPath().addBean(), context.getValue()));
this.realContext = context;
}

@Override
Expand All @@ -282,7 +285,7 @@ private Stream<Frame<?>> propertyFrames() {
final TraversableResolver traversableResolver = validatorContext.getTraversableResolver();

final Stream<PropertyD<?>> reachableProperties = properties.filter(d -> {
final PathImpl p = context.getPath();
final PathImpl p = realContext.getPath();
p.addProperty(d.getPropertyName());
try {
return traversableResolver.isReachable(context.getValue(), p.removeLeafNode(), getRootBeanClass(),
Expand All @@ -294,7 +297,7 @@ private Stream<Frame<?>> propertyFrames() {
}
});
return reachableProperties.flatMap(
d -> d.read(context).filter(context -> !context.isRecursive()).map(child -> propertyFrame(d, child)));
d -> d.read(realContext).filter(context -> !context.isRecursive()).map(child -> propertyFrame(d, child)));
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,50 +28,40 @@

public class ContainerElementNodeBuilderCustomizableContextImpl
implements ContainerElementNodeBuilderCustomizableContext {
private final ConstraintValidatorContextImpl<?> context;
private final String template;
private final PathImpl path;
private NodeImpl node;
private final ConstraintValidatorContextImpl<?>.ConstraintViolationBuilderImpl builder;

public ContainerElementNodeBuilderCustomizableContextImpl(ConstraintValidatorContextImpl<?> context, String template,
PathImpl path, String name, Class<?> containerType, Integer typeArgumentIndex) {
public ContainerElementNodeBuilderCustomizableContextImpl(PathImpl path, String name, Class<?> containerType,
Integer typeArgumentIndex, ConstraintValidatorContextImpl<?>.ConstraintViolationBuilderImpl builder) {
super();
this.context = context;
this.path = path;
this.template = template;
this.node = new NodeImpl.ContainerElementNodeImpl(name, containerType, typeArgumentIndex);
this.builder = builder.ofLegalState();
this.path = path.addNode(new NodeImpl.ContainerElementNodeImpl(name, containerType, typeArgumentIndex));
}

@Override
public ContainerElementNodeContextBuilder inIterable() {
node.setInIterable(true);
return new ContainerElementNodeContextBuilderImpl(context, template, path, node);
return new ContainerElementNodeContextBuilderImpl(path, builder);
}

@Override
public NodeBuilderCustomizableContext addPropertyNode(String name) {
path.addNode(node);
return new NodeBuilderCustomizableContextImpl(context, template, path, name);
return new NodeBuilderCustomizableContextImpl(path, name, builder);
}

@Override
public LeafNodeBuilderCustomizableContext addBeanNode() {
path.addNode(node);
return new LeafNodeBuilderCustomizableContextImpl(context, template, path);
return new LeafNodeBuilderCustomizableContextImpl(path, builder);
}

@Override
public ContainerElementNodeBuilderCustomizableContext addContainerElementNode(String name, Class<?> containerType,
Integer typeArgumentIndex) {
path.addNode(node);
node = new NodeImpl.ContainerElementNodeImpl(name, containerType, typeArgumentIndex);
path.addNode(new NodeImpl.ContainerElementNodeImpl(name, containerType, typeArgumentIndex));
return this;
}

@Override
public ConstraintValidatorContext addConstraintViolation() {
path.addNode(node);
context.addError(template, path);
return context;
return builder.addConstraintViolation(path);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,39 +27,35 @@
import org.apache.bval.jsr.job.ConstraintValidatorContextImpl;

public class ContainerElementNodeBuilderDefinedContextImpl implements ContainerElementNodeBuilderDefinedContext {
private final ConstraintValidatorContextImpl<?> context;
private final String template;
private final ConstraintValidatorContextImpl<?>.ConstraintViolationBuilderImpl builder;
private final PathImpl path;

ContainerElementNodeBuilderDefinedContextImpl(ConstraintValidatorContextImpl<?> context, String template,
PathImpl path) {
ContainerElementNodeBuilderDefinedContextImpl(PathImpl path,
ConstraintValidatorContextImpl<?>.ConstraintViolationBuilderImpl builder) {
super();
this.context = context;
this.template = template;
this.path = path;
this.builder = builder.ofLegalState();
}

@Override
public NodeBuilderCustomizableContext addPropertyNode(String name) {
return new NodeBuilderCustomizableContextImpl(context, template, path, name);
return new NodeBuilderCustomizableContextImpl(path, name, builder);
}

@Override
public LeafNodeBuilderCustomizableContext addBeanNode() {
return new LeafNodeBuilderCustomizableContextImpl(context, template, path);
return new LeafNodeBuilderCustomizableContextImpl(path, builder);
}

@Override
public ContainerElementNodeBuilderCustomizableContext addContainerElementNode(String name, Class<?> containerType,
Integer typeArgumentIndex) {
return new ContainerElementNodeBuilderCustomizableContextImpl(context, name, path, name, containerType,
typeArgumentIndex);
return new ContainerElementNodeBuilderCustomizableContextImpl(path, name, containerType, typeArgumentIndex,
builder);
}

@Override
public ConstraintValidatorContext addConstraintViolation() {
context.addError(template, path);
return context;
return builder.addConstraintViolation(path);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -28,58 +28,48 @@
import org.apache.bval.jsr.job.ConstraintValidatorContextImpl;

public class ContainerElementNodeContextBuilderImpl implements ContainerElementNodeContextBuilder {
private final ConstraintValidatorContextImpl<?> context;
private final String template;
private final PathImpl path;
private final NodeImpl node;
private ConstraintValidatorContextImpl<?>.ConstraintViolationBuilderImpl builder;

ContainerElementNodeContextBuilderImpl(ConstraintValidatorContextImpl<?> context, String template,
PathImpl path, NodeImpl node) {
ContainerElementNodeContextBuilderImpl(PathImpl path,
ConstraintValidatorContextImpl<?>.ConstraintViolationBuilderImpl builder) {
super();
this.context = context;
this.template = template;
this.builder = builder.ofLegalState();
this.path = path;
this.node = node;
path.getLeafNode().inIterable();
}

@Override
public ContainerElementNodeBuilderDefinedContext atKey(Object key) {
node.setKey(key);
path.addNode(node);
return new ContainerElementNodeBuilderDefinedContextImpl(context, template, path);
path.getLeafNode().setKey(key);
return new ContainerElementNodeBuilderDefinedContextImpl(path, builder);
}

@Override
public ContainerElementNodeBuilderDefinedContext atIndex(Integer index) {
node.setIndex(index);
path.addNode(node);
return new ContainerElementNodeBuilderDefinedContextImpl(context, template, path);
path.getLeafNode().setIndex(index);
return new ContainerElementNodeBuilderDefinedContextImpl(path, builder);
}

@Override
public NodeBuilderCustomizableContext addPropertyNode(String name) {
path.addNode(node);
return new NodeBuilderCustomizableContextImpl(context, name, path, name);
return new NodeBuilderCustomizableContextImpl(path, name, builder);
}

@Override
public LeafNodeBuilderCustomizableContext addBeanNode() {
path.addNode(node);
return new LeafNodeBuilderCustomizableContextImpl(context, template, path);
return new LeafNodeBuilderCustomizableContextImpl(path, builder);
}

@Override
public ContainerElementNodeBuilderCustomizableContext addContainerElementNode(String name, Class<?> containerType,
Integer typeArgumentIndex) {
path.addNode(node);
return new ContainerElementNodeBuilderCustomizableContextImpl(context, template, path, name, containerType,
typeArgumentIndex);
return new ContainerElementNodeBuilderCustomizableContextImpl(path, name, containerType, typeArgumentIndex,
builder);
}

@Override
public ConstraintValidatorContext addConstraintViolation() {
context.addError(template, path);
return context;
return builder.addConstraintViolation(path);
}

}
Loading

0 comments on commit 54dab69

Please sign in to comment.