http://git-wip-us.apache.org/repos/asf/bval/blob/a43c0b0c/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintDefaults.java ---------------------------------------------------------------------- diff --git a/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintDefaults.java b/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintDefaults.java index 3e3771e..07af5fe 100644 --- a/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintDefaults.java +++ b/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintDefaults.java @@ -80,28 +80,20 @@ public class ConstraintDefaults { private Map<String, Class<? extends ConstraintValidator<?, ?>>[]> loadDefaultConstraints(String resource) { final Properties constraintProperties = new Properties(); final ClassLoader classloader = getClassLoader(); - final InputStream stream = classloader.getResourceAsStream(resource); - if (stream == null) { - log.log(Level.WARNING, String.format("Cannot find %s", resource)); - } else { - try { + try (final InputStream stream = classloader.getResourceAsStream(resource)) { + if (stream == null) { + log.log(Level.WARNING, String.format("Cannot find %s", resource)); + } else { constraintProperties.load(stream); - } catch (IOException e) { - log.log(Level.SEVERE, String.format("Cannot load %s", resource), e); - } finally { - try { - stream.close(); - } catch (final IOException e) { - // no-op - } } + } catch (IOException e) { + log.log(Level.SEVERE, String.format("Cannot load %s", resource), e); } - final Map<String, Class<? extends ConstraintValidator<?, ?>>[]> loadedConstraints = - new HashMap<String, Class<? extends ConstraintValidator<?, ?>>[]>(); + final Map<String, Class<? extends ConstraintValidator<?, ?>>[]> loadedConstraints = new HashMap<>(); for (final Map.Entry<Object, Object> entry : constraintProperties.entrySet()) { - final List<Class<?>> classes = new LinkedList<Class<?>>(); + final List<Class<?>> classes = new LinkedList<>(); for (String className : StringUtils.split((String) entry.getValue(), ',')) { try { classes.add(Reflection.toClass(className.trim(), classloader));
http://git-wip-us.apache.org/repos/asf/bval/blob/a43c0b0c/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintDescriptorImpl.java ---------------------------------------------------------------------- diff --git a/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintDescriptorImpl.java b/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintDescriptorImpl.java index a56e1e1..c4c9d99 100644 --- a/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintDescriptorImpl.java +++ b/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintDescriptorImpl.java @@ -21,6 +21,7 @@ package org.apache.bval.jsr; import javax.validation.ConstraintTarget; import javax.validation.Payload; import javax.validation.metadata.ConstraintDescriptor; +import javax.validation.metadata.ValidateUnwrappedValue; import java.io.Serializable; import java.lang.annotation.Annotation; @@ -220,4 +221,16 @@ public class ConstraintDescriptorImpl<T extends Annotation> implements Constrain result = 31 * result + (template != null ? template.hashCode() : 0); return result; } + + @Override + public ValidateUnwrappedValue getValueUnwrapping() { + // TODO Auto-generated method stub + return null; + } + + @Override + public <U> U unwrap(Class<U> arg0) { + // TODO Auto-generated method stub + return null; + } } http://git-wip-us.apache.org/repos/asf/bval/blob/a43c0b0c/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintValidation.java ---------------------------------------------------------------------- diff --git a/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintValidation.java b/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintValidation.java index 5b51141..5ba14ca 100644 --- a/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintValidation.java +++ b/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintValidation.java @@ -39,6 +39,8 @@ import javax.validation.ValidationException; import javax.validation.constraintvalidation.SupportedValidationTarget; import javax.validation.constraintvalidation.ValidationTarget; import javax.validation.metadata.ConstraintDescriptor; +import javax.validation.metadata.ValidateUnwrappedValue; + import java.io.Serializable; import java.lang.annotation.Annotation; import java.lang.reflect.Array; @@ -54,6 +56,7 @@ import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.stream.Collectors; /** * Description: Adapter between Constraint (JSR303) and Validation (Core)<br/> @@ -328,10 +331,12 @@ public class ConstraintValidation<T extends Annotation> implements Validation, C throw new UnexpectedTypeException(message); } if (types.size() > 1) { - throw new UnexpectedTypeException( - String.format("Ambiguous validators for type %s. See: @%s at %s. Validators are: %s", - stringForType(targetType), anno.annotationType().getSimpleName(), stringForLocation(owner, access), - StringUtils.join(types, ", "))); + throw new UnexpectedTypeException(String.format( + "Ambiguous validators for type %s. See: @%s at %s. Validators are: %s", + stringForType(targetType), + anno.annotationType().getSimpleName(), + stringForLocation(owner, access), types.stream() + .map(Object::toString).collect(Collectors.joining(", ")))); } } @@ -524,9 +529,13 @@ public class ConstraintValidation<T extends Annotation> implements Validation, C * {@inheritDoc} */ @Override - @SuppressWarnings("unchecked") + @SuppressWarnings({ "unchecked", "rawtypes" }) public Set<ConstraintDescriptor<?>> getComposingConstraints() { - return composedConstraints == null ? Collections.EMPTY_SET : composedConstraints; + if (composedConstraints == null) { + return Collections.emptySet(); + } + final Set result = composedConstraints; + return result; } /** @@ -581,4 +590,16 @@ public class ConstraintValidation<T extends Annotation> implements Validation, C public void setValidated(final boolean validated) { this.validated = validated; } + + @Override + public ValidateUnwrappedValue getValueUnwrapping() { + // TODO Auto-generated method stub + return null; + } + + @Override + public <U> U unwrap(Class<U> arg0) { + // TODO Auto-generated method stub + return null; + } } http://git-wip-us.apache.org/repos/asf/bval/blob/a43c0b0c/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintValidatorContextImpl.java ---------------------------------------------------------------------- diff --git a/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintValidatorContextImpl.java b/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintValidatorContextImpl.java index 3599603..930170d 100644 --- a/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintValidatorContextImpl.java +++ b/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintValidatorContextImpl.java @@ -25,6 +25,7 @@ import org.apache.bval.jsr.util.NodeImpl; import org.apache.bval.jsr.util.PathImpl; import org.apache.bval.model.ValidationListener; +import javax.validation.ClockProvider; import javax.validation.ConstraintValidator; import javax.validation.ConstraintValidatorContext; import javax.validation.Path; @@ -38,7 +39,10 @@ import java.util.List; * Description: Short-lived {@link ConstraintValidatorContext} implementation passed by * a {@link ConstraintValidation} to its adapted {@link ConstraintValidator}. <br/> */ -public class ConstraintValidatorContextImpl implements ConstraintValidatorContext { +@Deprecated +public class ConstraintValidatorContextImpl + extends org.apache.bval.jsr.job.ConstraintValidatorContextImpl<Object> + implements ConstraintValidatorContext { private final List<ValidationListener.Error> errorMessages = new LinkedList<ValidationListener.Error>(); private final ConstraintValidation<?> constraintDescriptor; @@ -53,6 +57,7 @@ public class ConstraintValidatorContextImpl implements ConstraintValidatorContex */ public ConstraintValidatorContextImpl(GroupValidationContext<?> validationContext, ConstraintValidation<?> aConstraintValidation) { + super(); this.validationContext = validationContext; this.constraintDescriptor = aConstraintValidation; } @@ -154,6 +159,13 @@ public class ConstraintValidatorContextImpl implements ConstraintValidatorContex parent.addError(messageTemplate, propertyPath); return parent; } + + @Override + public ContainerElementNodeBuilderCustomizableContext addContainerElementNode( + String arg0, Class<?> arg1, Integer arg2) { + // TODO Auto-generated method stub + return null; + } } /** @@ -190,4 +202,10 @@ public class ConstraintValidatorContextImpl implements ConstraintValidatorContex public void addError(String messageTemplate, Path propertyPath) { errorMessages.add(new ValidationListener.Error(messageTemplate, propertyPath, null)); } + + @Override + public ClockProvider getClockProvider() { + // TODO Auto-generated method stub + return null; + } } http://git-wip-us.apache.org/repos/asf/bval/blob/a43c0b0c/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintViolationImpl.java ---------------------------------------------------------------------- diff --git a/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintViolationImpl.java b/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintViolationImpl.java index c367b8e..d510341 100644 --- a/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintViolationImpl.java +++ b/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintViolationImpl.java @@ -20,15 +20,19 @@ import javax.validation.ConstraintViolation; import javax.validation.Path; import javax.validation.ValidationException; import javax.validation.metadata.ConstraintDescriptor; + +import org.apache.bval.jsr.util.Exceptions; + import java.io.Serializable; import java.lang.annotation.ElementType; import java.util.Arrays; +import java.util.Objects; /** * Description: Describe a constraint validation defect.<br/> * From rootBean and propertyPath, it is possible to rebuild the context of the failure */ -class ConstraintViolationImpl<T> implements ConstraintViolation<T>, Serializable { +public class ConstraintViolationImpl<T> implements ConstraintViolation<T>, Serializable { /** Serialization version */ private static final long serialVersionUID = 1L; @@ -163,7 +167,7 @@ class ConstraintViolationImpl<T> implements ConstraintViolation<T>, Serializable if (type.isInstance(this)) { return type.cast(this); } - throw new ValidationException("Type " + type + " is not supported"); + throw Exceptions.create(ValidationException::new, "Type %s is not supported", type); } /** @@ -171,45 +175,28 @@ class ConstraintViolationImpl<T> implements ConstraintViolation<T>, Serializable */ @Override public String toString() { - return "ConstraintViolationImpl{" + "rootBean=" + rootBean + ", propertyPath='" + propertyPath + '\'' - + ", message='" + message + '\'' + ", leafBean=" + leafBean + ", value=" + value + '}'; + return String.format("%s{rootBean=%s, propertyPath='%s', message='%s', leafBean=%s, value=%s}", + ConstraintViolationImpl.class.getSimpleName(), rootBean, propertyPath, message, leafBean, value); } @Override public boolean equals(Object o) { - if (this == o) + if (this == o) { return true; - if (o == null || getClass() != o.getClass()) + } + if (o == null || !getClass().equals(o.getClass())) { return false; + } - ConstraintViolationImpl that = (ConstraintViolationImpl) o; - - if (constraintDescriptor != null ? !constraintDescriptor.equals(that.constraintDescriptor) - : that.constraintDescriptor != null) - return false; - if (elementType != that.elementType) - return false; - if (leafBean != null ? !leafBean.equals(that.leafBean) : that.leafBean != null) - return false; - if (message != null ? !message.equals(that.message) : that.message != null) - return false; - if (messageTemplate != null ? !messageTemplate.equals(that.messageTemplate) : that.messageTemplate != null) - return false; - // Probably incorrect - comparing Object[] arrays with Arrays.equals - if (!Arrays.equals(parameters, that.parameters)) - return false; - if (propertyPath != null ? !propertyPath.equals(that.propertyPath) : that.propertyPath != null) - return false; - if (returnValue != null ? !returnValue.equals(that.returnValue) : that.returnValue != null) - return false; - if (rootBean != null ? !rootBean.equals(that.rootBean) : that.rootBean != null) - return false; - if (rootBeanClass != null ? !rootBeanClass.equals(that.rootBeanClass) : that.rootBeanClass != null) - return false; - if (value != null ? !value.equals(that.value) : that.value != null) - return false; + @SuppressWarnings("rawtypes") + final ConstraintViolationImpl that = (ConstraintViolationImpl) o; - return true; + return Objects.equals(constraintDescriptor, that.constraintDescriptor) && elementType == that.elementType + && Objects.equals(leafBean, that.leafBean) && Objects.equals(message, that.message) + && Objects.equals(messageTemplate, that.messageTemplate) && Arrays.equals(parameters, that.parameters) + && Objects.equals(propertyPath, that.propertyPath) && Objects.equals(returnValue, that.returnValue) + && Objects.equals(rootBean, that.rootBean) && Objects.equals(rootBeanClass, that.rootBeanClass) + && Objects.equals(value, that.value); } @Override @@ -217,18 +204,10 @@ class ConstraintViolationImpl<T> implements ConstraintViolation<T>, Serializable return hashCode; } - public int computeHashCode() { - int result = messageTemplate != null ? messageTemplate.hashCode() : 0; - result = 31 * result + (message != null ? message.hashCode() : 0); - result = 31 * result + (rootBean != null ? rootBean.hashCode() : 0); - result = 31 * result + (rootBeanClass != null ? rootBeanClass.hashCode() : 0); - result = 31 * result + (leafBean != null ? leafBean.hashCode() : 0); - result = 31 * result + (value != null ? value.hashCode() : 0); - result = 31 * result + (propertyPath != null ? propertyPath.hashCode() : 0); - result = 31 * result + (elementType != null ? elementType.hashCode() : 0); - result = 31 * result + (constraintDescriptor != null ? constraintDescriptor.hashCode() : 0); - result = 31 * result + (returnValue != null ? returnValue.hashCode() : 0); - result = 31 * result + (parameters != null ? Arrays.hashCode(parameters) : 0); + private int computeHashCode() { + int result = Objects.hash(messageTemplate, message, rootBean, rootBeanClass, leafBean, value, propertyPath, + elementType, constraintDescriptor, returnValue); + result = 31 * result + (parameters == null ? 0 : Arrays.hashCode(parameters)); return result; } } http://git-wip-us.apache.org/repos/asf/bval/blob/a43c0b0c/bval-jsr/src/main/java/org/apache/bval/jsr/GraphContext.java ---------------------------------------------------------------------- diff --git a/bval-jsr/src/main/java/org/apache/bval/jsr/GraphContext.java b/bval-jsr/src/main/java/org/apache/bval/jsr/GraphContext.java new file mode 100644 index 0000000..020a950 --- /dev/null +++ b/bval-jsr/src/main/java/org/apache/bval/jsr/GraphContext.java @@ -0,0 +1,75 @@ +/* + * 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; + +import org.apache.bval.jsr.util.NodeImpl; +import org.apache.bval.jsr.util.PathImpl; +import org.apache.bval.util.Validate; + +public class GraphContext { + + private final ApacheFactoryContext validatorContext; + private final PathImpl path; + private final Object value; + private final GraphContext parent; + + public GraphContext(ApacheFactoryContext validatorContext, PathImpl path, Object value) { + this(validatorContext, path, value, null); + } + + private GraphContext(ApacheFactoryContext validatorContext, PathImpl path, Object value, GraphContext parent) { + super(); + this.validatorContext = Validate.notNull(validatorContext, "validatorContext"); + this.path = Validate.notNull(path, "path"); + this.value = value; + this.parent = parent; + } + + public ApacheFactoryContext getValidatorContext() { + return validatorContext; + } + + public PathImpl getPath() { + return PathImpl.copy(path); + } + + public Object getValue() { + return value; + } + + public GraphContext child(NodeImpl node, Object value) { + if (value == null || stackContains(value)) { + return null; + } + final PathImpl p = PathImpl.copy(path); + p.addNode(node); + return new GraphContext(validatorContext, p, value, this); + } + + private boolean stackContains(Object value) { + GraphContext c = this; + while (c != null) { + if (c.value == value) { + return true; + } + c = c.parent; + } + return false; + } +} http://git-wip-us.apache.org/repos/asf/bval/blob/a43c0b0c/bval-jsr/src/main/java/org/apache/bval/jsr/NodeBuilderCustomizableContextImpl.java ---------------------------------------------------------------------- diff --git a/bval-jsr/src/main/java/org/apache/bval/jsr/NodeBuilderCustomizableContextImpl.java b/bval-jsr/src/main/java/org/apache/bval/jsr/NodeBuilderCustomizableContextImpl.java new file mode 100644 index 0000000..8200bfe --- /dev/null +++ b/bval-jsr/src/main/java/org/apache/bval/jsr/NodeBuilderCustomizableContextImpl.java @@ -0,0 +1,89 @@ +/* + * 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; + +import org.apache.bval.jsr.util.LeafNodeBuilderCustomizableContextImpl; +import org.apache.bval.jsr.util.NodeImpl; +import org.apache.bval.jsr.util.PathImpl; + +import javax.validation.ConstraintValidatorContext; +import javax.validation.ConstraintValidatorContext.ConstraintViolationBuilder.ContainerElementNodeBuilderCustomizableContext; +import javax.validation.ConstraintValidatorContext.ConstraintViolationBuilder.NodeBuilderCustomizableContext; +import javax.validation.ElementKind; + +public class NodeBuilderCustomizableContextImpl + implements ConstraintValidatorContext.ConstraintViolationBuilder.NodeBuilderCustomizableContext { + private final PathImpl path; + private final ConstraintValidatorContextImpl context; + private final String template; + + public NodeBuilderCustomizableContextImpl(final ConstraintValidatorContextImpl parent, final String messageTemplate, + final PathImpl propertyPath) { + context = parent; + template = messageTemplate; + path = propertyPath; + } + + @Override + public ConstraintValidatorContext.ConstraintViolationBuilder.NodeContextBuilder inIterable() { + path.getLeafNode().setInIterable(true); + return new NodeContextBuilderImpl(context, template, path); + } + + @Override + public ConstraintValidatorContext.ConstraintViolationBuilder.NodeBuilderCustomizableContext addNode(String name) { + path.addNode(new NodeImpl(name)); + return this; + } + + @Override + public ConstraintValidatorContext.ConstraintViolationBuilder.NodeBuilderCustomizableContext addPropertyNode( + String name) { + final NodeImpl node = new NodeImpl.PropertyNodeImpl(name); + path.addNode(node); + return this; + } + + @Override + public ConstraintValidatorContext.ConstraintViolationBuilder.LeafNodeBuilderCustomizableContext addBeanNode() { + final NodeImpl node = new NodeImpl.BeanNodeImpl(); + path.addNode(node); + return null; +// return new LeafNodeBuilderCustomizableContextImpl(context, template, path); + } + + @Override + public ConstraintValidatorContext addConstraintViolation() { + context.addError(template, path); + return context; + } + + @Override + public NodeBuilderCustomizableContext inContainer(Class<?> containerClass, Integer typeArgumentIndex) { + // TODO Auto-generated method stub + return null; + } + + @Override + public ContainerElementNodeBuilderCustomizableContext addContainerElementNode(String name, Class<?> containerType, + Integer typeArgumentIndex) { + // TODO Auto-generated method stub + return null; + } +} http://git-wip-us.apache.org/repos/asf/bval/blob/a43c0b0c/bval-jsr/src/main/java/org/apache/bval/jsr/NodeContextBuilderImpl.java ---------------------------------------------------------------------- diff --git a/bval-jsr/src/main/java/org/apache/bval/jsr/NodeContextBuilderImpl.java b/bval-jsr/src/main/java/org/apache/bval/jsr/NodeContextBuilderImpl.java new file mode 100644 index 0000000..d1f191e --- /dev/null +++ b/bval-jsr/src/main/java/org/apache/bval/jsr/NodeContextBuilderImpl.java @@ -0,0 +1,88 @@ +/* + * 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; + +import org.apache.bval.jsr.util.LeafNodeBuilderCustomizableContextImpl; +import org.apache.bval.jsr.util.NodeBuilderDefinedContextImpl; +import org.apache.bval.jsr.util.NodeImpl; +import org.apache.bval.jsr.util.PathImpl; + +import javax.validation.ConstraintValidatorContext; +import javax.validation.ConstraintValidatorContext.ConstraintViolationBuilder.ContainerElementNodeBuilderCustomizableContext; +import javax.validation.ElementKind; + +public class NodeContextBuilderImpl + implements ConstraintValidatorContext.ConstraintViolationBuilder.NodeContextBuilder { + private final PathImpl path; + private final String template; + private final ConstraintValidatorContextImpl context; + + public NodeContextBuilderImpl(final ConstraintValidatorContextImpl context, final String template, + final PathImpl path) { + this.context = context; + this.template = template; + this.path = path; + } + + @Override + public ConstraintValidatorContext.ConstraintViolationBuilder.NodeBuilderDefinedContext atKey(Object key) { + path.getLeafNode().setKey(key); + return null; +// return new NodeBuilderDefinedContextImpl(context, template, path); + } + + @Override + public ConstraintValidatorContext.ConstraintViolationBuilder.NodeBuilderDefinedContext atIndex(Integer index) { + path.getLeafNode().setIndex(index); + return null; +// return new NodeBuilderDefinedContextImpl(context, template, path); + } + + @Override + public ConstraintValidatorContext.ConstraintViolationBuilder.NodeBuilderCustomizableContext addNode(String name) { + return new NodeBuilderCustomizableContextImpl(context, template, path).addNode(name); + } + + @Override + public ConstraintValidatorContext.ConstraintViolationBuilder.NodeBuilderCustomizableContext addPropertyNode( + String name) { + return new NodeBuilderCustomizableContextImpl(context, template, path).addPropertyNode(name); + } + + @Override + public ConstraintValidatorContext.ConstraintViolationBuilder.LeafNodeBuilderCustomizableContext addBeanNode() { + final NodeImpl node = new NodeImpl.BeanNodeImpl(); + path.addNode(node); + return null; +// return new LeafNodeBuilderCustomizableContextImpl(context, template, path); + } + + @Override + public ConstraintValidatorContext addConstraintViolation() { + context.addError(template, path); + return context; + } + + @Override + public ContainerElementNodeBuilderCustomizableContext addContainerElementNode(String name, Class<?> containerType, + Integer typeArgumentIndex) { + // TODO Auto-generated method stub + return null; + } +} http://git-wip-us.apache.org/repos/asf/bval/blob/a43c0b0c/bval-jsr/src/main/java/org/apache/bval/jsr/ParameterDescriptorImpl.java ---------------------------------------------------------------------- diff --git a/bval-jsr/src/main/java/org/apache/bval/jsr/ParameterDescriptorImpl.java b/bval-jsr/src/main/java/org/apache/bval/jsr/ParameterDescriptorImpl.java index 187fd7e..65f3ecc 100644 --- a/bval-jsr/src/main/java/org/apache/bval/jsr/ParameterDescriptorImpl.java +++ b/bval-jsr/src/main/java/org/apache/bval/jsr/ParameterDescriptorImpl.java @@ -21,6 +21,7 @@ import org.apache.bval.jsr.groups.GroupConversionDescriptorImpl; import org.apache.bval.model.MetaBean; import org.apache.bval.model.Validation; +import javax.validation.metadata.ContainerElementTypeDescriptor; import javax.validation.metadata.GroupConversionDescriptor; import javax.validation.metadata.ParameterDescriptor; import java.util.Set; @@ -86,4 +87,10 @@ public class ParameterDescriptorImpl extends ElementDescriptorImpl implements Pa groupConversions.add(new GroupConversionDescriptorImpl(from, to)); super.addGroupMapping(from, to); } + + @Override + public Set<ContainerElementTypeDescriptor> getConstrainedContainerElementTypes() { + // TODO Auto-generated method stub + return null; + } } http://git-wip-us.apache.org/repos/asf/bval/blob/a43c0b0c/bval-jsr/src/main/java/org/apache/bval/jsr/PropertyDescriptorImpl.java ---------------------------------------------------------------------- diff --git a/bval-jsr/src/main/java/org/apache/bval/jsr/PropertyDescriptorImpl.java b/bval-jsr/src/main/java/org/apache/bval/jsr/PropertyDescriptorImpl.java index 7f7c56d..03cf5de 100644 --- a/bval-jsr/src/main/java/org/apache/bval/jsr/PropertyDescriptorImpl.java +++ b/bval-jsr/src/main/java/org/apache/bval/jsr/PropertyDescriptorImpl.java @@ -21,6 +21,9 @@ package org.apache.bval.jsr; import org.apache.bval.model.Features; import org.apache.bval.model.MetaProperty; +import java.util.Set; + +import javax.validation.metadata.ContainerElementTypeDescriptor; import javax.validation.metadata.PropertyDescriptor; /** @@ -67,4 +70,10 @@ class PropertyDescriptorImpl extends ElementDescriptorImpl implements PropertyDe return "PropertyDescriptorImpl{" + "returnType=" + elementClass + ", propertyPath='" + propertyPath + '\'' + '}'; } + + @Override + public Set<ContainerElementTypeDescriptor> getConstrainedContainerElementTypes() { + // TODO Auto-generated method stub + return null; + } } http://git-wip-us.apache.org/repos/asf/bval/blob/a43c0b0c/bval-jsr/src/main/java/org/apache/bval/jsr/ReturnValueDescriptorImpl.java ---------------------------------------------------------------------- diff --git a/bval-jsr/src/main/java/org/apache/bval/jsr/ReturnValueDescriptorImpl.java b/bval-jsr/src/main/java/org/apache/bval/jsr/ReturnValueDescriptorImpl.java index b1fc72d..a6faa9b 100644 --- a/bval-jsr/src/main/java/org/apache/bval/jsr/ReturnValueDescriptorImpl.java +++ b/bval-jsr/src/main/java/org/apache/bval/jsr/ReturnValueDescriptorImpl.java @@ -18,8 +18,10 @@ package org.apache.bval.jsr; import org.apache.bval.model.MetaBean; +import javax.validation.metadata.ContainerElementTypeDescriptor; import javax.validation.metadata.ReturnValueDescriptor; import java.util.Collection; +import java.util.Set; public class ReturnValueDescriptorImpl extends ElementDescriptorImpl implements ReturnValueDescriptor { public ReturnValueDescriptorImpl(final MetaBean metaBean, Class<?> returnType, @@ -32,4 +34,10 @@ public class ReturnValueDescriptorImpl extends ElementDescriptorImpl implements public boolean hasConstraints() { return false; } + + @Override + public Set<ContainerElementTypeDescriptor> getConstrainedContainerElementTypes() { + // TODO Auto-generated method stub + return null; + } } http://git-wip-us.apache.org/repos/asf/bval/blob/a43c0b0c/bval-jsr/src/main/java/org/apache/bval/jsr/ValidatorImpl.java ---------------------------------------------------------------------- diff --git a/bval-jsr/src/main/java/org/apache/bval/jsr/ValidatorImpl.java b/bval-jsr/src/main/java/org/apache/bval/jsr/ValidatorImpl.java new file mode 100644 index 0000000..606e191 --- /dev/null +++ b/bval-jsr/src/main/java/org/apache/bval/jsr/ValidatorImpl.java @@ -0,0 +1,141 @@ +/* + * 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; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.util.Set; + +import javax.validation.ConstraintViolation; +import javax.validation.ValidationException; +import javax.validation.executable.ExecutableValidator; +import javax.validation.metadata.BeanDescriptor; + +import org.apache.bval.jsr.job.ValidationJobFactory; +import org.apache.bval.util.Validate; +import org.apache.bval.util.reflection.Reflection; + +public class ValidatorImpl implements CascadingPropertyValidator, ExecutableValidator { + + private final ApacheFactoryContext validatorContext; + private final ValidationJobFactory validationJobFactory; + + ValidatorImpl(ApacheFactoryContext validatorContext) { + super(); + this.validatorContext = Validate.notNull(validatorContext, "validatorContext"); + this.validationJobFactory = new ValidationJobFactory(validatorContext); + } + + @Override + public BeanDescriptor getConstraintsForClass(Class<?> clazz) { + return validatorContext.getDescriptorManager().getBeanDescriptor(clazz); + } + + @Override + public <T> Set<ConstraintViolation<T>> validate(T object, Class<?>... groups) { + return validationJobFactory.validateBean(object, groups).getResults(); + } + + @Override + public <T> Set<ConstraintViolation<T>> validateProperty(T object, String propertyName, boolean cascade, + Class<?>... groups) { + return validationJobFactory.validateProperty(object, propertyName, groups).cascade(cascade).getResults(); + } + + @Override + public <T> Set<ConstraintViolation<T>> validateValue(Class<T> beanType, String propertyName, Object value, + boolean cascade, Class<?>... groups) { + return validationJobFactory.validateValue(beanType, propertyName, value, groups).cascade(cascade).getResults(); + } + + @Override + public ExecutableValidator forExecutables() { + return this; + } + + @Override + public <T> Set<ConstraintViolation<T>> validateParameters(T object, Method method, Object[] parameterValues, + Class<?>... groups) { + return validationJobFactory.validateParameters(object, method, parameterValues, groups).getResults(); + } + + @Override + public <T> Set<ConstraintViolation<T>> validateReturnValue(T object, Method method, Object returnValue, + Class<?>... groups) { + return validationJobFactory.validateReturnValue(object, method, returnValue, groups).getResults(); + } + + @Override + public <T> Set<ConstraintViolation<T>> validateConstructorParameters(Constructor<? extends T> constructor, + Object[] parameterValues, Class<?>... groups) { + return validationJobFactory.<T> validateConstructorParameters(constructor, parameterValues, groups) + .getResults(); + } + + @Override + public <T> Set<ConstraintViolation<T>> validateConstructorReturnValue(Constructor<? extends T> constructor, + T createdObject, Class<?>... groups) { + return validationJobFactory.<T> validateConstructorReturnValue(constructor, createdObject, groups).getResults(); + } + + @Override + public <T> T unwrap(Class<T> type) { + // FIXME 2011-03-27 jw: + // This code is unsecure. + // It should allow only a fixed set of classes. + // Can't fix this because don't know which classes this method should support. + + if (type.isAssignableFrom(getClass())) { + @SuppressWarnings("unchecked") + final T result = (T) this; + return result; + } + if (!(type.isInterface() || Modifier.isAbstract(type.getModifiers()))) { + return newInstance(type); + } + try { + final Class<?> cls = Reflection.toClass(type.getName() + "Impl"); + if (type.isAssignableFrom(cls)) { + @SuppressWarnings("unchecked") + final Class<? extends T> implClass = (Class<? extends T>) cls; + return newInstance(implClass); + } + } catch (ClassNotFoundException e) { + } + throw new ValidationException("Type " + type + " not supported"); + } + + private <T> T newInstance(final Class<T> cls) { + final Constructor<T> cons = Reflection.getDeclaredConstructor(cls, ApacheFactoryContext.class); + if (cons == null) { + throw new ValidationException("Cannot instantiate " + cls); + } + final boolean mustUnset = Reflection.setAccessible(cons, true); + try { + return cons.newInstance(validatorContext); + } catch (final Exception ex) { + throw new ValidationException("Cannot instantiate " + cls, ex); + } finally { + if (mustUnset) { + Reflection.setAccessible(cons, false); + } + } + } +} http://git-wip-us.apache.org/repos/asf/bval/blob/a43c0b0c/bval-jsr/src/main/java/org/apache/bval/jsr/descriptor/BeanD.java ---------------------------------------------------------------------- diff --git a/bval-jsr/src/main/java/org/apache/bval/jsr/descriptor/BeanD.java b/bval-jsr/src/main/java/org/apache/bval/jsr/descriptor/BeanD.java new file mode 100644 index 0000000..570352b --- /dev/null +++ b/bval-jsr/src/main/java/org/apache/bval/jsr/descriptor/BeanD.java @@ -0,0 +1,112 @@ +/* + * 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.descriptor; + +import java.util.EnumSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.function.Function; + +import javax.validation.metadata.BeanDescriptor; +import javax.validation.metadata.ConstructorDescriptor; +import javax.validation.metadata.MethodDescriptor; +import javax.validation.metadata.MethodType; +import javax.validation.metadata.PropertyDescriptor; + +import org.apache.bval.jsr.metadata.Signature; +import org.apache.bval.jsr.util.ToUnmodifiable; +import org.apache.bval.util.Lazy; + +public class BeanD extends ElementD<Class<?>, MetadataReader.ForBean> implements BeanDescriptor { + + private static <K, V> Map<K, V> toMap(Set<V> set, Function<? super V, ? extends K> toKey) { + return set.stream().collect(ToUnmodifiable.map(toKey, Function.identity())); + } + + private final Class<?> beanClass; + + private final Lazy<List<Class<?>>> groupSequence; + private Lazy<Set<PropertyDescriptor>> properties; + private Lazy<Map<String, PropertyDescriptor>> propertiesMap; + private Lazy<Map<Signature, ConstructorD>> constructors; + private Lazy<Map<Signature, MethodD>> methods; + + BeanD(MetadataReader.ForBean reader) { + super(reader); + this.beanClass = reader.meta.getHost(); + + groupSequence = new Lazy<>(reader::getGroupSequence); + properties = new Lazy<>(() -> reader.getProperties(this)); + propertiesMap = new Lazy<>(() -> toMap(properties.get(), PropertyDescriptor::getPropertyName)); + constructors = new Lazy<>(() -> reader.getConstructors(this)); + methods = new Lazy<>(() -> reader.getMethods(this)); + } + + @Override + public Class<?> getElementClass() { + return beanClass; + } + + @Override + public boolean isBeanConstrained() { + return hasConstraints() || properties.get().stream().anyMatch(pd -> pd.isCascaded() || pd.hasConstraints()); + } + + @Override + public PropertyDescriptor getConstraintsForProperty(String propertyName) { + return propertiesMap.get().get(propertyName); + } + + @Override + public Set<PropertyDescriptor> getConstrainedProperties() { + return properties.get(); + } + + @Override + public MethodDescriptor getConstraintsForMethod(String methodName, Class<?>... parameterTypes) { + return methods.get().get(new Signature(methodName, parameterTypes)); + } + + @Override + public Set<MethodDescriptor> getConstrainedMethods(MethodType methodType, MethodType... methodTypes) { + return methods.get().values().stream().filter(EnumSet.of(methodType, methodTypes)::contains) + .collect(ToUnmodifiable.set()); + } + + @Override + public ConstructorDescriptor getConstraintsForConstructor(Class<?>... parameterTypes) { + return constructors.get().get(new Signature(beanClass.getSimpleName(), parameterTypes)); + } + + @Override + public Set<ConstructorDescriptor> getConstrainedConstructors() { + return constructors.get().values().stream().collect(ToUnmodifiable.set()); + } + + @Override + protected BeanD getBean() { + return this; + } + + @Override + List<Class<?>> getGroupSequence() { + return groupSequence.get(); + } +} http://git-wip-us.apache.org/repos/asf/bval/blob/a43c0b0c/bval-jsr/src/main/java/org/apache/bval/jsr/descriptor/CascadableContainerD.java ---------------------------------------------------------------------- diff --git a/bval-jsr/src/main/java/org/apache/bval/jsr/descriptor/CascadableContainerD.java b/bval-jsr/src/main/java/org/apache/bval/jsr/descriptor/CascadableContainerD.java new file mode 100644 index 0000000..163b6ca --- /dev/null +++ b/bval-jsr/src/main/java/org/apache/bval/jsr/descriptor/CascadableContainerD.java @@ -0,0 +1,92 @@ +/* + * 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.descriptor; + +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.util.Lazy; +import org.apache.bval.util.Validate; +import org.apache.bval.util.reflection.TypeUtils; + +public abstract class CascadableContainerD<P extends ElementD<?,?>, E extends AnnotatedElement> + extends ElementD.NonRoot<P, E, MetadataReader.ForContainer<E>> implements CascadableDescriptor, ContainerDescriptor { + + private final Class<?> type; + + private final boolean cascaded; + private final Set<GroupConversion> groupConversions; + private final Lazy<Set<ContainerElementTypeD>> containerElementTypes; + + protected CascadableContainerD(MetadataReader.ForContainer<E> reader, P parent) { + super(reader, parent); + + type = TypeUtils.getRawType(reader.meta.getType(), parent.getElementClass()); + + cascaded = reader.isCascaded(); + groupConversions = reader.getGroupConversions(); + containerElementTypes = new Lazy<>(() -> reader.getContainerElementTypes(this)); + } + + @Override + public Class<?> getElementClass() { + return type; + } + + @Override + public boolean isCascaded() { + return cascaded; + } + + @SuppressWarnings({ "unchecked", "rawtypes" }) + @Override + public Set<GroupConversionDescriptor> getGroupConversions() { + return (Set) groupConversions; + } + + @SuppressWarnings({ "unchecked", "rawtypes" }) + @Override + public Set<ContainerElementTypeDescriptor> getConstrainedContainerElementTypes() { + return (Set) containerElementTypes.get(); + } + + 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 new ValidationException(e); + } + } + + protected Stream<GraphContext> readImpl(GraphContext context) throws Exception { + throw new UnsupportedOperationException(); + } +} http://git-wip-us.apache.org/repos/asf/bval/blob/a43c0b0c/bval-jsr/src/main/java/org/apache/bval/jsr/descriptor/ComposedD.java ---------------------------------------------------------------------- diff --git a/bval-jsr/src/main/java/org/apache/bval/jsr/descriptor/ComposedD.java b/bval-jsr/src/main/java/org/apache/bval/jsr/descriptor/ComposedD.java new file mode 100644 index 0000000..14fb9a8 --- /dev/null +++ b/bval-jsr/src/main/java/org/apache/bval/jsr/descriptor/ComposedD.java @@ -0,0 +1,125 @@ +/* + * 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.descriptor; + +import java.util.Collection; +import java.util.List; +import java.util.Objects; +import java.util.Set; +import java.util.stream.Stream; + +import javax.validation.metadata.CascadableDescriptor; +import javax.validation.metadata.ConstraintDescriptor; +import javax.validation.metadata.ContainerDescriptor; +import javax.validation.metadata.ContainerElementTypeDescriptor; +import javax.validation.metadata.ElementDescriptor; +import javax.validation.metadata.GroupConversionDescriptor; +import javax.validation.metadata.PropertyDescriptor; + +import org.apache.bval.jsr.util.ToUnmodifiable; +import org.apache.bval.util.Validate; + +public abstract class ComposedD<D extends ElementD<?, ?>> implements ElementDescriptor { + + static abstract class ForCascadableContainer<D extends CascadableContainerD<?, ?>> extends ComposedD<D> + implements CascadableDescriptor, ContainerDescriptor { + + ForCascadableContainer(List<D> delegates) { + super(delegates); + } + + @Override + public Set<ContainerElementTypeDescriptor> getConstrainedContainerElementTypes() { + return delegates.stream().map(ContainerDescriptor::getConstrainedContainerElementTypes) + .flatMap(Collection::stream).collect(ToUnmodifiable.set()); + } + + @Override + public boolean isCascaded() { + return delegates.stream().anyMatch(CascadableDescriptor::isCascaded); + } + + @Override + public Set<GroupConversionDescriptor> getGroupConversions() { + return delegates.stream().map(CascadableDescriptor::getGroupConversions).flatMap(Collection::stream) + .collect(ToUnmodifiable.set()); + } + } + + static class ForProperty extends ComposedD.ForCascadableContainer<PropertyD<?>> implements PropertyDescriptor { + + ForProperty(List<PropertyD<?>> delegates) { + super(delegates); + } + + @Override + public String getPropertyName() { + return delegates.stream().map(PropertyDescriptor::getPropertyName).findFirst() + .orElseThrow(IllegalStateException::new); + } + } + + public static <T extends ElementD<?, ?>> Stream<T> unwrap(ElementDescriptor descriptor, Class<? super T> delegateType) { + final Stream<?> s; + + if (descriptor instanceof ComposedD<?>) { + s = ((ComposedD<?>) descriptor).delegates.stream() + // unwrap recursively: + .flatMap(d -> unwrap(d, delegateType)); + } else { + s = Stream.of(descriptor); + } + @SuppressWarnings("unchecked") + final Stream<T> result = (Stream<T>) s.map(delegateType::cast); + return result; + } + + protected final List<D> delegates; + + ComposedD(List<D> delegates) { + super(); + this.delegates = delegates; + + Validate.notNull(delegates, "delegates"); + Validate.isTrue(!delegates.isEmpty(), "At least one delegate is required"); + Validate.isTrue(delegates.stream().noneMatch(Objects::isNull), "null delegates not permitted"); + } + + @Override + public boolean hasConstraints() { + return delegates.stream().anyMatch(ElementDescriptor::hasConstraints); + } + + @Override + public Class<?> getElementClass() { + return delegates.stream().map(ElementDescriptor::getElementClass).findFirst() + .orElseThrow(IllegalStateException::new); + } + + @Override + public Set<ConstraintDescriptor<?>> getConstraintDescriptors() { + return delegates.stream().map(ElementDescriptor::getConstraintDescriptors).flatMap(Collection::stream) + .collect(ToUnmodifiable.set()); + } + + @Override + public ConstraintFinder findConstraints() { + return new Finder(this, delegates.stream().map(ElementD::getGroupSequence).findFirst().orElse(null)); + } +} http://git-wip-us.apache.org/repos/asf/bval/blob/a43c0b0c/bval-jsr/src/main/java/org/apache/bval/jsr/descriptor/ComputeConstraintValidatorClass.java ---------------------------------------------------------------------- diff --git a/bval-jsr/src/main/java/org/apache/bval/jsr/descriptor/ComputeConstraintValidatorClass.java b/bval-jsr/src/main/java/org/apache/bval/jsr/descriptor/ComputeConstraintValidatorClass.java new file mode 100644 index 0000000..4410726 --- /dev/null +++ b/bval-jsr/src/main/java/org/apache/bval/jsr/descriptor/ComputeConstraintValidatorClass.java @@ -0,0 +1,147 @@ +package org.apache.bval.jsr.descriptor; + +import java.lang.annotation.Annotation; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.lang.reflect.WildcardType; +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; +import java.util.Set; +import java.util.function.Function; +import java.util.function.Supplier; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import javax.validation.ConstraintDefinitionException; +import javax.validation.ConstraintValidator; +import javax.validation.UnexpectedTypeException; +import javax.validation.constraintvalidation.ValidationTarget; + +import org.apache.bval.jsr.ApacheValidatorFactory; +import org.apache.bval.jsr.ConstraintCached.ConstraintValidatorInfo; +import org.apache.bval.jsr.util.Exceptions; +import org.apache.bval.util.Validate; +import org.apache.bval.util.reflection.Reflection; +import org.apache.bval.util.reflection.Reflection.Interfaces; +import org.apache.bval.util.reflection.TypeUtils; +import org.apache.commons.weaver.privilizer.Privilizing; +import org.apache.commons.weaver.privilizer.Privilizing.CallTo; + +@Privilizing(@CallTo(Reflection.class)) +class ComputeConstraintValidatorClass<A extends Annotation> + implements Supplier<Class<? extends ConstraintValidator<A, ?>>> { + + private static final String CV = ConstraintValidator.class.getSimpleName(); + private static final WildcardType UNBOUNDED = TypeUtils.wildcardType().build(); + + private static Type getValidatedType(Class<? extends ConstraintValidator<?, ?>> validatorType) { + final Type result = TypeUtils.getTypeArguments(validatorType, ConstraintValidator.class) + .get(ConstraintValidator.class.getTypeParameters()[1]); + Exceptions.raiseUnless(isSupported(result), ConstraintDefinitionException::new, + "Validated type %s declared by %s %s is unsupported", result, CV, validatorType.getName()); + return result; + } + + private static boolean isSupported(Type validatedType) { + if (validatedType instanceof Class<?>) { + return true; + } + if (validatedType instanceof ParameterizedType) { + return Stream.of(((ParameterizedType) validatedType).getActualTypeArguments()) + .allMatch(arg -> TypeUtils.equals(arg, UNBOUNDED)); + } + return false; + } + + private final ApacheValidatorFactory validatorFactory; + private final Class<A> constraintType; + private final Class<?> validatedType; + private final ValidationTarget validationTarget; + + ComputeConstraintValidatorClass(ApacheValidatorFactory validatorFactory, ValidationTarget validationTarget, + Class<A> constraintType, Class<?> validatedType) { + super(); + this.validatorFactory = Validate.notNull(validatorFactory, "validatorFactory"); + this.validationTarget = Validate.notNull(validationTarget, "validationTarget"); + this.constraintType = Validate.notNull(constraintType, "constraintType"); + this.validatedType = Validate.notNull(validatedType, "validatedType"); + } + + @Override + public Class<? extends ConstraintValidator<A, ?>> get() { + final Optional<Class<? extends ConstraintValidator<A, ?>>> result = + validatorFactory.getConstraintsCache().getConstraintValidatorInfo(constraintType).map(this::findValidator); + + Exceptions.raiseUnless(result.isPresent(), UnexpectedTypeException::new, + "No %s found for %s constraint %s/type %s", CV, validationTarget, constraintType, validatedType); + + return result.get(); + } + + private Class<? extends ConstraintValidator<A, ?>> findValidator(Set<ConstraintValidatorInfo<A>> infos) { + switch (validationTarget) { + case PARAMETERS: + return findCrossParameterValidator(infos); + case ANNOTATED_ELEMENT: + return findAnnotatedElementValidator(infos); + default: + return null; + } + } + + private Class<? extends ConstraintValidator<A, ?>> findCrossParameterValidator( + Set<ConstraintValidatorInfo<A>> infos) { + + final Set<ConstraintValidatorInfo<A>> set = + infos.stream().filter(info -> info.getSupportedTargets().contains(ValidationTarget.PARAMETERS)) + .collect(Collectors.toSet()); + + Exceptions.raiseIf(set.isEmpty(), UnexpectedTypeException::new, + "No cross-parameter %s found for constraint type %s", CV, constraintType); + + Exceptions.raiseUnless(set.size() == 1, UnexpectedTypeException::new, + "%d cross-parameter %ss found for constraint type %s", set.size(), CV, constraintType); + + final Class<? extends ConstraintValidator<A, ?>> result = set.iterator().next().getType(); + Exceptions.raiseUnless(TypeUtils.isAssignable(Object[].class, getValidatedType(result)), + ConstraintDefinitionException::new, + "Cross-parameter %s %s does not support the validation of an object array", CV, result.getName()); + + return result; + } + + private Class<? extends ConstraintValidator<A, ?>> findAnnotatedElementValidator( + Set<ConstraintValidatorInfo<A>> infos) { + + final Class<?> effectiveValidatedType = Reflection.primitiveToWrapper(validatedType); + + final Map<Type, Class<? extends ConstraintValidator<?, ?>>> validators = + infos.stream().filter(info -> info.getSupportedTargets().contains(ValidationTarget.ANNOTATED_ELEMENT)) + .map(ConstraintValidatorInfo::getType) + .collect(Collectors.toMap(ComputeConstraintValidatorClass::getValidatedType, Function.identity())); + + final Map<Type, Class<? extends ConstraintValidator<?, ?>>> candidates = new HashMap<>(); + + for (Class<?> type : Reflection.hierarchy(effectiveValidatedType, Interfaces.INCLUDE)) { + if (validators.containsKey(type)) { + // if we already have a candidate whose validated type is a subtype of the current evaluated type, skip: + if (candidates.keySet().stream().anyMatch(k -> TypeUtils.isAssignable(k, type))) { + continue; + } + candidates.put(type, validators.get(type)); + } + } + + Exceptions.raiseIf(candidates.isEmpty(), UnexpectedTypeException::new, + "No compliant %s found for annotated element of type %s", CV, TypeUtils.toString(validatedType)); + + Exceptions.raiseIf(candidates.size() > 1, UnexpectedTypeException::new, + "> 1 maximally specific %s found for annotated element of type %s", CV, TypeUtils.toString(validatedType)); + + @SuppressWarnings("unchecked") + final Class<? extends ConstraintValidator<A, ?>> result = + (Class<? extends ConstraintValidator<A, ?>>) candidates.values().iterator().next(); + return result; + } +} http://git-wip-us.apache.org/repos/asf/bval/blob/a43c0b0c/bval-jsr/src/main/java/org/apache/bval/jsr/descriptor/ConstraintD.java ---------------------------------------------------------------------- diff --git a/bval-jsr/src/main/java/org/apache/bval/jsr/descriptor/ConstraintD.java b/bval-jsr/src/main/java/org/apache/bval/jsr/descriptor/ConstraintD.java new file mode 100644 index 0000000..d8d9bd7 --- /dev/null +++ b/bval-jsr/src/main/java/org/apache/bval/jsr/descriptor/ConstraintD.java @@ -0,0 +1,206 @@ +/* + * 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.descriptor; + +import java.lang.annotation.Annotation; +import java.lang.annotation.ElementType; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.Set; +import java.util.function.Supplier; +import java.util.stream.Stream; + +import javax.validation.ConstraintTarget; +import javax.validation.ConstraintValidator; +import javax.validation.Payload; +import javax.validation.ReportAsSingleViolation; +import javax.validation.UnexpectedTypeException; +import javax.validation.ValidationException; +import javax.validation.metadata.ConstraintDescriptor; +import javax.validation.metadata.Scope; +import javax.validation.metadata.ValidateUnwrappedValue; +import javax.validation.valueextraction.Unwrapping.Skip; +import javax.validation.valueextraction.Unwrapping.Unwrap; + +import org.apache.bval.jsr.ApacheValidatorFactory; +import org.apache.bval.jsr.ConstraintAnnotationAttributes; +import org.apache.bval.jsr.ConstraintAnnotationAttributes.Worker; +import org.apache.bval.jsr.metadata.Metas; +import org.apache.bval.jsr.util.AnnotationsManager; +import org.apache.bval.jsr.util.Exceptions; +import org.apache.bval.jsr.util.ToUnmodifiable; +import org.apache.bval.util.Lazy; +import org.apache.bval.util.Validate; +import org.apache.bval.util.reflection.TypeUtils; + +public class ConstraintD<A extends Annotation> implements ConstraintDescriptor<A> { + private static <T> Set<T> set(Supplier<T[]> array) { + return Stream.of(array.get()).collect(ToUnmodifiable.set()); + } + + private final A annotation; + private final Scope scope; + private final Metas<?> meta; + private final Class<?> validatedType; + + private final Lazy<Set<Class<?>>> groups = new Lazy<>(() -> set(() -> read(ConstraintAnnotationAttributes.GROUPS))); + + private final Lazy<Set<Class<? extends Payload>>> payload = + new Lazy<>(() -> set(() -> read(ConstraintAnnotationAttributes.PAYLOAD))); + + private final Lazy<Boolean> reportAsSingle = + new Lazy<>(() -> getAnnotation().annotationType().isAnnotationPresent(ReportAsSingleViolation.class)); + + private final Lazy<ValidateUnwrappedValue> valueUnwrapping = new Lazy<>(this::computeValidateUnwrappedValue); + + private final Lazy<Map<String, Object>> attributes; + private final Lazy<Set<ConstraintDescriptor<?>>> composingConstraints; + private final Lazy<List<Class<? extends ConstraintValidator<A, ?>>>> constraintValidatorClasses; + private final Lazy<Class<? extends ConstraintValidator<A, ?>>> constraintValidatorClass; + + public ConstraintD(A annotation, Scope scope, Metas<?> meta, ApacheValidatorFactory validatorFactory) { + this.annotation = Validate.notNull(annotation, "annotation"); + this.scope = Validate.notNull(scope, "scope"); + + this.meta = Validate.notNull(meta, "meta"); + validatedType = TypeUtils.getRawType(meta.getType(), null); + Exceptions.raiseIf(validatedType == null, UnexpectedTypeException::new, + "Could not calculate validated type from %s", meta.getType()); + + attributes = new Lazy<>(() -> AnnotationsManager.readAttributes(annotation)); + + // retain no references to the validatorFactory; only wrap it in lazy suppliers + Validate.notNull(validatorFactory, "validatorFactory"); + composingConstraints = new Lazy<>(computeComposingConstraints(validatorFactory)); + constraintValidatorClasses = new Lazy<>(computeConstraintValidatorClasses(validatorFactory)); + + @SuppressWarnings("unchecked") + final Supplier<Class<? extends ConstraintValidator<A, ?>>> computeConstraintValidatorClass = + new ComputeConstraintValidatorClass<>(validatorFactory, meta.getValidationTarget(), + (Class<A>) annotation.annotationType(), validatedType); + + constraintValidatorClass = new Lazy<>(computeConstraintValidatorClass); + } + + @Override + public A getAnnotation() { + return annotation; + } + + @Override + public Set<Class<?>> getGroups() { + return groups.get(); + } + + @Override + public Set<Class<? extends Payload>> getPayload() { + return payload.get(); + } + + @Override + public List<Class<? extends ConstraintValidator<A, ?>>> getConstraintValidatorClasses() { + return constraintValidatorClasses.get(); + } + + @Override + public Map<String, Object> getAttributes() { + return attributes.get(); + } + + @Override + public Set<ConstraintDescriptor<?>> getComposingConstraints() { + return composingConstraints.get(); + } + + @Override + public boolean isReportAsSingleViolation() { + return reportAsSingle.get().booleanValue(); + } + + @Override + public String getMessageTemplate() { + return read(ConstraintAnnotationAttributes.MESSAGE); + } + + @Override + public ConstraintTarget getValidationAppliesTo() { + return read(ConstraintAnnotationAttributes.VALIDATION_APPLIES_TO); + } + + @Override + public ValidateUnwrappedValue getValueUnwrapping() { + return valueUnwrapping.get(); + } + + @Override + public <U> U unwrap(Class<U> type) throws ValidationException { + try { + return type.cast(this); + } catch (ClassCastException e) { + throw new ValidationException(e); + } + } + + public Scope getScope() { + return scope; + } + + public ElementType getDeclaredOn() { + return meta.getElementType(); + } + + public Class<?> getValidatedType() { + return validatedType; + } + + public Class<? extends ConstraintValidator<A, ?>> getConstraintValidatorClass() { + return constraintValidatorClass.get(); + } + + private <T> T read(ConstraintAnnotationAttributes attr) { + return Optional.of(annotation.annotationType()).map(attr::analyze).filter(Worker::isValid) + .map(w -> w.<T> read(annotation)).orElse(null); + } + + private Supplier<Set<ConstraintDescriptor<?>>> computeComposingConstraints( + ApacheValidatorFactory validatorFactory) { + return () -> Stream.of(validatorFactory.getAnnotationsManager().getComposingConstraints(annotation)) + .map(c -> new ConstraintD<>(c, scope, meta, validatorFactory)).collect(ToUnmodifiable.set()); + } + + @SuppressWarnings("unchecked") + private Supplier<List<Class<? extends ConstraintValidator<A, ?>>>> computeConstraintValidatorClasses( + ApacheValidatorFactory validatorFactory) { + return () -> validatorFactory.getConstraintsCache() + .getConstraintValidatorClasses((Class<A>) annotation.annotationType()); + } + + private ValidateUnwrappedValue computeValidateUnwrappedValue() { + final Set<Class<? extends Payload>> p = getPayload(); + final boolean unwrap = p.contains(Unwrap.class); + final boolean skip = p.contains(Skip.class); + if (unwrap) { + Validate.validState(!skip, "Cannot specify both %s and %s", Unwrap.class.getSimpleName(), + Skip.class.getSimpleName()); + return ValidateUnwrappedValue.UNWRAP; + } + return skip ? ValidateUnwrappedValue.SKIP : ValidateUnwrappedValue.DEFAULT; + } +} http://git-wip-us.apache.org/repos/asf/bval/blob/a43c0b0c/bval-jsr/src/main/java/org/apache/bval/jsr/descriptor/ConstructorD.java ---------------------------------------------------------------------- diff --git a/bval-jsr/src/main/java/org/apache/bval/jsr/descriptor/ConstructorD.java b/bval-jsr/src/main/java/org/apache/bval/jsr/descriptor/ConstructorD.java new file mode 100644 index 0000000..9e457b5 --- /dev/null +++ b/bval-jsr/src/main/java/org/apache/bval/jsr/descriptor/ConstructorD.java @@ -0,0 +1,36 @@ +/* + * 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.descriptor; + +import java.lang.reflect.Constructor; + +import javax.validation.metadata.ConstructorDescriptor; + +public class ConstructorD extends ExecutableD<Constructor<?>, MetadataReader.ForConstructor, ConstructorD> + implements ConstructorDescriptor { + + ConstructorD(MetadataReader.ForConstructor reader, BeanD parent) { + super(reader, parent); + } + + @Override + protected String nameOf(Constructor<?> e) { + return e.getDeclaringClass().getSimpleName(); + } +} http://git-wip-us.apache.org/repos/asf/bval/blob/a43c0b0c/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 new file mode 100644 index 0000000..54b2c3e --- /dev/null +++ b/bval-jsr/src/main/java/org/apache/bval/jsr/descriptor/ContainerElementTypeD.java @@ -0,0 +1,119 @@ +/* + * 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.descriptor; + +import java.lang.reflect.AnnotatedType; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Stream; + +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.util.Exceptions; +import org.apache.bval.jsr.util.NodeImpl; +import org.apache.bval.util.Lazy; +import org.apache.bval.util.Validate; + +public class ContainerElementTypeD extends CascadableContainerD<CascadableContainerD<?, ?>, AnnotatedType> + implements ContainerElementTypeDescriptor { + + private static class Receiver implements ValueExtractor.ValueReceiver { + private final GraphContext context; + private Lazy<List<GraphContext>> result = new Lazy<>(ArrayList::new); + + Receiver(GraphContext context) { + super(); + this.context = context; + } + + @Override + public void value(String nodeName, Object object) { + addChild(new NodeImpl.PropertyNodeImpl(nodeName), object); + } + + @Override + public void iterableValue(String nodeName, Object object) { + final NodeImpl.PropertyNodeImpl node = new NodeImpl.PropertyNodeImpl(nodeName); + node.setInIterable(true); + addChild(node, object); + } + + @Override + public void indexedValue(String nodeName, int i, Object object) { + final NodeImpl.PropertyNodeImpl node = new NodeImpl.PropertyNodeImpl(nodeName); + node.setIndex(Integer.valueOf(i)); + addChild(node, object); + } + + @Override + public void keyedValue(String nodeName, Object key, Object object) { + final NodeImpl.PropertyNodeImpl node = new NodeImpl.PropertyNodeImpl(nodeName); + node.setKey(key); + addChild(node, object); + } + + private void addChild(NodeImpl node, Object value) { + result.get().add(context.child(node, value)); + } + } + + private final ContainerElementKey key; + + ContainerElementTypeD(ContainerElementKey key, MetadataReader.ForContainer<AnnotatedType> reader, + CascadableContainerD<?, ?> parent) { + super(reader, parent); + this.key = Validate.notNull(key, "key"); + } + + @Override + public Class<?> getContainerClass() { + return key.getContainerClass(); + } + + @Override + public Integer getTypeArgumentIndex() { + return Integer.valueOf(key.getTypeArgumentIndex()); + } + + ContainerElementKey getKey() { + return key; + } + + @SuppressWarnings({ "rawtypes", "unchecked" }) + @Override + protected Stream<GraphContext> readImpl(GraphContext context) throws Exception { + final ValueExtractor valueExtractor = context.getValidatorContext().getValueExtractors().find(key); + Exceptions.raiseIf(valueExtractor == null, ValidationException::new, "No %s found for %s", + ValueExtractor.class.getSimpleName(), key); + + final Receiver receiver = new Receiver(context); + try { + valueExtractor.extractValues(context.getValue(), receiver); + } catch (ValidationException e) { + throw e; + } catch (Exception e) { + throw new ValidationException(e); + } + return receiver.result.get().stream(); + } +} http://git-wip-us.apache.org/repos/asf/bval/blob/a43c0b0c/bval-jsr/src/main/java/org/apache/bval/jsr/descriptor/CrossParameterD.java ---------------------------------------------------------------------- diff --git a/bval-jsr/src/main/java/org/apache/bval/jsr/descriptor/CrossParameterD.java b/bval-jsr/src/main/java/org/apache/bval/jsr/descriptor/CrossParameterD.java new file mode 100644 index 0000000..0d51800 --- /dev/null +++ b/bval-jsr/src/main/java/org/apache/bval/jsr/descriptor/CrossParameterD.java @@ -0,0 +1,18 @@ +package org.apache.bval.jsr.descriptor; + +import java.lang.reflect.Executable; + +import javax.validation.metadata.CrossParameterDescriptor; + +public class CrossParameterD<P extends ExecutableD<?, ?, P>, E extends Executable> + extends ElementD.NonRoot<P, E, MetadataReader.ForElement<E, ?>> implements CrossParameterDescriptor { + + protected CrossParameterD(MetadataReader.ForElement<E, ?> reader, P parent) { + super(reader, parent); + } + + @Override + public Class<?> getElementClass() { + return Object[].class; + } +} http://git-wip-us.apache.org/repos/asf/bval/blob/a43c0b0c/bval-jsr/src/main/java/org/apache/bval/jsr/descriptor/DescriptorManager.java ---------------------------------------------------------------------- diff --git a/bval-jsr/src/main/java/org/apache/bval/jsr/descriptor/DescriptorManager.java b/bval-jsr/src/main/java/org/apache/bval/jsr/descriptor/DescriptorManager.java new file mode 100644 index 0000000..747e242 --- /dev/null +++ b/bval-jsr/src/main/java/org/apache/bval/jsr/descriptor/DescriptorManager.java @@ -0,0 +1,68 @@ +/* + * 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.descriptor; + +import java.util.List; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; + +import javax.validation.metadata.BeanDescriptor; + +import org.apache.bval.jsr.ApacheValidatorFactory; +import org.apache.bval.jsr.metadata.AnnotationBehaviorMergeStrategy; +import org.apache.bval.jsr.metadata.CompositeBuilder; +import org.apache.bval.jsr.metadata.HierarchyBuilder; +import org.apache.bval.jsr.metadata.MetadataBuilder; +import org.apache.bval.jsr.metadata.ParallelBuilder; +import org.apache.bval.jsr.metadata.ReflectionBuilder; +import org.apache.bval.util.Validate; + +public class DescriptorManager { + private final ApacheValidatorFactory validatorFactory; + private final ConcurrentMap<Class<?>, BeanD> beanDescriptors = new ConcurrentHashMap<>(); + private final ReflectionBuilder reflectionBuilder; + private final MetadataReader metadataReader; + + public DescriptorManager(ApacheValidatorFactory validatorFactory) { + super(); + this.validatorFactory = Validate.notNull(validatorFactory, "validatorFactory"); + this.reflectionBuilder = new ReflectionBuilder(validatorFactory); + this.metadataReader = new MetadataReader(validatorFactory); + } + + public BeanDescriptor getBeanDescriptor(Class<?> beanClass) { + Validate.notNull(beanClass, "beanClass"); + return beanDescriptors.computeIfAbsent(beanClass, k -> new BeanD(metadataReader.forBean(k, builder(k)))); + } + + private MetadataBuilder.ForBean builder(Class<?> beanClass) { + final MetadataBuilder.ForBean primaryBuilder = + new HierarchyBuilder(reflectionBuilder::forBean).forBean(beanClass); + + final MetadataBuilder.ForBean customBuilder = new HierarchyBuilder(this::customBuilder).forBean(beanClass); + + return customBuilder.isEmpty() ? primaryBuilder : ParallelBuilder.forBean(primaryBuilder, customBuilder); + } + + private MetadataBuilder.ForBean customBuilder(Class<?> beanClass) { + final List<MetadataBuilder.ForBean> customBuilders = + validatorFactory.getMetadataBuilders().getCustomBuilders(beanClass); + + return customBuilders.isEmpty() ? null : customBuilders.stream() + .collect(CompositeBuilder.with(AnnotationBehaviorMergeStrategy.consensus()).compose()); + } +} http://git-wip-us.apache.org/repos/asf/bval/blob/a43c0b0c/bval-jsr/src/main/java/org/apache/bval/jsr/descriptor/ElementD.java ---------------------------------------------------------------------- diff --git a/bval-jsr/src/main/java/org/apache/bval/jsr/descriptor/ElementD.java b/bval-jsr/src/main/java/org/apache/bval/jsr/descriptor/ElementD.java new file mode 100644 index 0000000..c64a19a --- /dev/null +++ b/bval-jsr/src/main/java/org/apache/bval/jsr/descriptor/ElementD.java @@ -0,0 +1,103 @@ +/* + * 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.descriptor; + +import java.lang.annotation.ElementType; +import java.lang.reflect.AnnotatedElement; +import java.util.List; +import java.util.Set; + +import javax.validation.metadata.ConstraintDescriptor; +import javax.validation.metadata.ElementDescriptor; + +import org.apache.bval.util.Validate; + +public abstract class ElementD<E extends AnnotatedElement, R extends MetadataReader.ForElement<E, ?>> + implements ElementDescriptor { + + public static abstract class NonRoot<P extends ElementD<?, ?>, E extends AnnotatedElement, R extends MetadataReader.ForElement<E, ?>> + extends ElementD<E, R> { + + protected final P parent; + + protected NonRoot(R reader, P parent) { + super(reader); + this.parent = Validate.notNull(parent, "parent"); + } + + public P getParent() { + return parent; + } + + @Override + final protected BeanD getBean() { + return parent.getBean(); + } + + @Override + final List<Class<?>> getGroupSequence() { + return getBean().getGroupSequence(); + } + } + + private final E target; + private final Set<ConstraintD<?>> constraints; + private final ElementType elementType; + + protected ElementD(R reader) { + super(); + Validate.notNull(reader, "reader"); + target = reader.meta.getHost(); + constraints = reader.getConstraints(); + elementType = reader.meta.getElementType(); + } + + @Override + public final boolean hasConstraints() { + return !constraints.isEmpty(); + } + + @SuppressWarnings({ "unchecked", "rawtypes" }) + @Override + public final Set<ConstraintDescriptor<?>> getConstraintDescriptors() { + return (Set) constraints; + } + + @Override + public final ConstraintFinder findConstraints() { + return new Finder(this, getGroupSequence()); + } + + public final ElementType getElementType() { + return elementType; + } + + public final E getTarget() { + return target; + } + + @Deprecated + final Set<ConstraintD<?>> getConstraints() { + return constraints; + } + + abstract List<Class<?>> getGroupSequence(); + + protected abstract BeanD getBean(); +} http://git-wip-us.apache.org/repos/asf/bval/blob/a43c0b0c/bval-jsr/src/main/java/org/apache/bval/jsr/descriptor/ExecutableD.java ---------------------------------------------------------------------- diff --git a/bval-jsr/src/main/java/org/apache/bval/jsr/descriptor/ExecutableD.java b/bval-jsr/src/main/java/org/apache/bval/jsr/descriptor/ExecutableD.java new file mode 100644 index 0000000..fe2a80e --- /dev/null +++ b/bval-jsr/src/main/java/org/apache/bval/jsr/descriptor/ExecutableD.java @@ -0,0 +1,89 @@ +/* + * 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.descriptor; + +import java.lang.reflect.Executable; +import java.util.List; + +import javax.validation.metadata.CrossParameterDescriptor; +import javax.validation.metadata.ExecutableDescriptor; +import javax.validation.metadata.ParameterDescriptor; +import javax.validation.metadata.ReturnValueDescriptor; + +public abstract class ExecutableD<E extends Executable, R extends MetadataReader.ForExecutable<E,R>, SELF extends ExecutableD<E, R, SELF>> + extends ElementD.NonRoot<BeanD, E, R> implements ExecutableDescriptor { + + private final String name; + private final ReturnValueD<SELF, E> returnValue; + private final List<ParameterD<SELF>> parameters; + private final CrossParameterD<SELF, E> crossParameter; + + @SuppressWarnings("unchecked") + protected ExecutableD(R reader, BeanD parent) { + super(reader, parent); + + name = reader.meta.getName(); + + returnValue = reader.getReturnValueDescriptor((SELF) this); + parameters = reader.getParameterDescriptors((SELF) this); + crossParameter = reader.getCrossParameterDescriptor((SELF) this); + } + + @Override + public final String getName() { + return name; + } + + @Override + public final Class<?> getElementClass() { + return returnValue.getElementClass(); + } + + @SuppressWarnings({ "unchecked", "rawtypes" }) + @Override + public final List<ParameterDescriptor> getParameterDescriptors() { + return (List) parameters; + } + + @Override + public final CrossParameterDescriptor getCrossParameterDescriptor() { + return crossParameter; + } + + @Override + public final ReturnValueDescriptor getReturnValueDescriptor() { + return returnValue; + } + + @Override + public final boolean hasConstrainedParameters() { + return parameters.stream().anyMatch(this::isConstrained); + } + + @Override + public final boolean hasConstrainedReturnValue() { + return isConstrained(returnValue); + } + + protected abstract String nameOf(E e); + + private boolean isConstrained(CascadableContainerD<?, ?> child) { + return child.isCascaded() || child.hasConstraints(); + } +}
