You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@bval.apache.org by rm...@apache.org on 2013/08/26 15:59:20 UTC
svn commit: r1517540 [6/15] - in /bval/branches/bval-11/bval-jsr: ./ src/
src/main/ src/main/appended-resources/
src/main/appended-resources/META-INF/ src/main/java/ src/main/java/org/
src/main/java/org/apache/ src/main/java/org/apache/bval/ src/main/j...
Added: bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintCached.java
URL: http://svn.apache.org/viewvc/bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintCached.java?rev=1517540&view=auto
==============================================================================
--- bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintCached.java (added)
+++ bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintCached.java Mon Aug 26 13:59:15 2013
@@ -0,0 +1,64 @@
+/*
+ * 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 javax.validation.ConstraintValidator;
+import java.lang.annotation.Annotation;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Description: hold the relationship annotation->validatedBy[] ConstraintValidator classes
+ * that are already parsed in a cache.<br/>
+ */
+public class ConstraintCached {
+ private final Map<Class<? extends Annotation>, Class<? extends ConstraintValidator<?, ?>>[]> classes =
+ new HashMap<Class<? extends Annotation>, Class<? extends ConstraintValidator<?,?>>[]>();
+
+ /**
+ * Record the set of validator classes for a given constraint annotation.
+ * @param annotationClass
+ * @param definitionClasses
+ */
+ public <A extends Annotation> void putConstraintValidator(Class<A> annotationClass,
+ Class<? extends ConstraintValidator<A, ?>>[] definitionClasses) {
+ classes.put(annotationClass, definitionClasses);
+ }
+
+ /**
+ * Learn whether we have cached the validator classes for the requested constraint annotation.
+ * @param annotationClass to look up
+ * @return boolean
+ */
+ public boolean containsConstraintValidator(Class<? extends Annotation> annotationClass) {
+ return classes.containsKey(annotationClass);
+ }
+
+ /**
+ * Get the cached validator classes for the requested constraint annotation.
+ * @param annotationClass to look up
+ * @return array of {@link ConstraintValidator} implementation types
+ */
+ @SuppressWarnings("unchecked")
+ public <A extends Annotation> Class<? extends ConstraintValidator<A, ?>>[] getConstraintValidators(
+ Class<A> annotationClass) {
+ return (Class<? extends ConstraintValidator<A, ?>>[]) classes.get(annotationClass);
+ }
+
+}
Added: bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintDefaults.java
URL: http://svn.apache.org/viewvc/bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintDefaults.java?rev=1517540&view=auto
==============================================================================
--- bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintDefaults.java (added)
+++ bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintDefaults.java Mon Aug 26 13:59:15 2013
@@ -0,0 +1,135 @@
+/*
+ * 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 javax.validation.ConstraintValidator;
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.annotation.Annotation;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.Map;
+import java.util.Properties;
+import java.util.StringTokenizer;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * Description: Provides access to the default constraints/validator implementation classes built into the framework.
+ * These are configured in DefaultConstraints.properties.<br/>
+ */
+public class ConstraintDefaults {
+ private static final Logger log = Logger.getLogger(ConstraintDefaults.class.getName());
+ private static final String DEFAULT_CONSTRAINTS =
+ "org/apache/bval/jsr/DefaultConstraints.properties";
+
+ /**
+ * The default constraint data stored herein.
+ */
+ protected Map<String, Class<? extends ConstraintValidator<?, ?>>[]> defaultConstraints;
+
+ /**
+ * Create a new ConstraintDefaults instance.
+ */
+ public ConstraintDefaults() {
+ defaultConstraints = loadDefaultConstraints(DEFAULT_CONSTRAINTS);
+ }
+
+ /**
+ * Get the default constraint data.
+ * @return String-keyed map
+ */
+ public Map<String, Class<? extends ConstraintValidator<?, ?>>[]> getDefaultConstraints() {
+ return defaultConstraints;
+ }
+
+ /**
+ * Get the default validator implementation types for the specified constraint annotation type.
+ * @param annotationType the annotation type
+ * @return array of {@link ConstraintValidator} implementation classes
+ */
+ @SuppressWarnings("unchecked")
+ public <A extends Annotation> Class<? extends ConstraintValidator<A, ?>>[] getValidatorClasses(
+ Class<A> annotationType) {
+ return (Class<? extends ConstraintValidator<A, ?>>[]) getDefaultConstraints().get(annotationType.getName());
+ }
+
+ @SuppressWarnings("unchecked")
+ private Map<String, Class<? extends ConstraintValidator<?, ?>>[]> loadDefaultConstraints(String resource) {
+ Properties constraintProperties = new Properties();
+ final ClassLoader classloader = getClassLoader();
+ InputStream stream = classloader.getResourceAsStream(resource);
+ if (stream != null) {
+ try {
+ constraintProperties.load(stream);
+ } catch (IOException e) {
+ log.log(Level.SEVERE, String.format("Cannot load %s", resource), e);
+ }
+ } else {
+ log.log(Level.WARNING, String.format("Cannot find %s", resource));
+ }
+
+ final Map<String, Class<? extends ConstraintValidator<?, ?>>[]> loadedConstraints = new HashMap<String, Class<? extends ConstraintValidator<?,?>>[]>();
+ for (final Map.Entry<Object, Object> entry : constraintProperties.entrySet()) {
+
+ final StringTokenizer tokens = new StringTokenizer((String) entry.getValue(), ", ");
+ final LinkedList<Class<?>> classes = new LinkedList<Class<?>>();
+ while (tokens.hasMoreTokens()) {
+ final String eachClassName = tokens.nextToken();
+
+ Class<?> constraintValidatorClass;
+ if (System.getSecurityManager() == null) {
+ try {
+ constraintValidatorClass = Class.forName(eachClassName, true, classloader);
+ } catch (final ClassNotFoundException e) {
+ log.log(Level.SEVERE, String.format("Cannot find class %s", eachClassName), e);
+ constraintValidatorClass = null;
+ }
+ } else {
+ constraintValidatorClass = AccessController.doPrivileged(new PrivilegedAction<Class<?>>() {
+ public Class<?> run() {
+ try {
+ return Class.forName(eachClassName, true, classloader);
+ } catch (final ClassNotFoundException e) {
+ log.log(Level.SEVERE, String.format("Cannot find class %s", eachClassName), e);
+ return null;
+ }
+ }
+ });
+ }
+
+ if (constraintValidatorClass != null) {
+ classes.add(constraintValidatorClass);
+ }
+
+ }
+
+ loadedConstraints.put((String) entry.getKey(), classes.toArray(new Class[classes.size()]));
+ }
+ return loadedConstraints;
+ }
+
+ private ClassLoader getClassLoader() {
+ ClassLoader classloader = Thread.currentThread().getContextClassLoader();
+ if (classloader == null) classloader = getClass().getClassLoader();
+ return classloader;
+ }
+}
Added: bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintDescriptorImpl.java
URL: http://svn.apache.org/viewvc/bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintDescriptorImpl.java?rev=1517540&view=auto
==============================================================================
--- bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintDescriptorImpl.java (added)
+++ bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintDescriptorImpl.java Mon Aug 26 13:59:15 2013
@@ -0,0 +1,187 @@
+/*
+ * 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 javax.validation.ConstraintTarget;
+import javax.validation.Payload;
+import javax.validation.metadata.ConstraintDescriptor;
+import java.io.Serializable;
+import java.lang.annotation.Annotation;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Description: immutable, serializable implementation of ConstraintDescriptor
+ * interface of JSR303<br>
+ * User: roman.stumm<br>
+ * Date: 22.04.2010<br>
+ * Time: 10:21:23<br>
+ */
+public class ConstraintDescriptorImpl<T extends Annotation> implements ConstraintDescriptor<T>, Serializable {
+ /** Serialization version */
+ private static final long serialVersionUID = 1L;
+
+ private final T annotation;
+ private final Set<Class<?>> groups;
+ private final Set<Class<? extends javax.validation.Payload>> payload;
+ private final List<java.lang.Class<? extends javax.validation.ConstraintValidator<T, ?>>> constraintValidatorClasses;
+ private final Map<String, Object> attributes;
+ private final Set<ConstraintDescriptor<?>> composingConstraints;
+ private final boolean reportAsSingleViolation;
+ private final ConstraintTarget validationAppliesTo;
+ private final String template;
+ private final int hashCode;
+
+ /**
+ * Create a new ConstraintDescriptorImpl instance.
+ *
+ * @param descriptor
+ */
+ public ConstraintDescriptorImpl(final ConstraintDescriptor<T> descriptor) {
+ this(descriptor.getAnnotation(), descriptor.getGroups(), descriptor.getPayload(), descriptor
+ .getConstraintValidatorClasses(), descriptor.getAttributes(), descriptor.getComposingConstraints(),
+ descriptor.isReportAsSingleViolation(), descriptor.getValidationAppliesTo(), descriptor.getMessageTemplate());
+ }
+
+ /**
+ * Create a new ConstraintDescriptorImpl instance.
+ *
+ * @param annotation
+ * @param groups
+ * @param payload
+ * @param constraintValidatorClasses
+ * @param attributes
+ * @param composingConstraints
+ * @param reportAsSingleViolation
+ */
+ public ConstraintDescriptorImpl(T annotation, Set<Class<?>> groups,
+ Set<Class<? extends javax.validation.Payload>> payload,
+ List<java.lang.Class<? extends javax.validation.ConstraintValidator<T, ?>>> constraintValidatorClasses,
+ Map<String, Object> attributes, Set<ConstraintDescriptor<?>> composingConstraints,
+ boolean reportAsSingleViolation, ConstraintTarget validationAppliesTo, String messageTemplate) {
+ this.annotation = annotation;
+ this.groups = groups;
+ this.payload = payload;
+ this.constraintValidatorClasses = constraintValidatorClasses;
+ this.attributes = attributes;
+ this.composingConstraints = composingConstraints;
+ this.reportAsSingleViolation = reportAsSingleViolation;
+ this.validationAppliesTo = validationAppliesTo;
+ this.template = messageTemplate;
+ this.hashCode = computeHashCode();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public T getAnnotation() {
+ return annotation;
+ }
+
+ public String getMessageTemplate() {
+ return template;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Set<Class<?>> getGroups() {
+ return groups;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Set<Class<? extends Payload>> getPayload() {
+ return payload;
+ }
+
+ public ConstraintTarget getValidationAppliesTo() {
+ return validationAppliesTo;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public List<java.lang.Class<? extends javax.validation.ConstraintValidator<T, ?>>> getConstraintValidatorClasses() {
+ return constraintValidatorClasses;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Map<String, Object> getAttributes() {
+ return attributes;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Set<ConstraintDescriptor<?>> getComposingConstraints() {
+ return composingConstraints;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isReportAsSingleViolation() {
+ return reportAsSingleViolation;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ final ConstraintDescriptorImpl that = (ConstraintDescriptorImpl) o;
+
+ if (reportAsSingleViolation != that.reportAsSingleViolation) return false;
+ if (!annotation.annotationType().equals(that.annotation.annotationType())) return false;
+ if (attributes != null ? !attributes.equals(that.attributes) : that.attributes != null) return false;
+ if (composingConstraints != null ? !composingConstraints.equals(that.composingConstraints) : that.composingConstraints != null)
+ return false;
+ if (constraintValidatorClasses != null ? !constraintValidatorClasses.equals(that.constraintValidatorClasses) : that.constraintValidatorClasses != null)
+ return false;
+ if (groups != null ? !groups.equals(that.groups) : that.groups != null) return false;
+ if (payload != null ? !payload.equals(that.payload) : that.payload != null) return false;
+ if (template != null ? !template.equals(that.template) : that.template != null) return false;
+ if (validationAppliesTo != that.validationAppliesTo) return false;
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ return hashCode;
+ }
+
+ public int computeHashCode() {
+ int result = annotation.annotationType().hashCode();
+ result = 31 * result + (groups != null ? groups.hashCode() : 0);
+ result = 31 * result + (payload != null ? payload.hashCode() : 0);
+ result = 31 * result + (constraintValidatorClasses != null ? constraintValidatorClasses.hashCode() : 0);
+ result = 31 * result + (attributes != null ? attributes.hashCode() : 0);
+ result = 31 * result + (composingConstraints != null ? composingConstraints.hashCode() : 0);
+ result = 31 * result + (reportAsSingleViolation ? 1 : 0);
+ result = 31 * result + (validationAppliesTo != null ? validationAppliesTo.hashCode() : 0);
+ result = 31 * result + (template != null ? template.hashCode() : 0);
+ return result;
+ }
+}
Added: bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintFinderImpl.java
URL: http://svn.apache.org/viewvc/bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintFinderImpl.java?rev=1517540&view=auto
==============================================================================
--- bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintFinderImpl.java (added)
+++ bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintFinderImpl.java Mon Aug 26 13:59:15 2013
@@ -0,0 +1,169 @@
+/*
+ * 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.groups.Group;
+import org.apache.bval.jsr.groups.Groups;
+import org.apache.bval.jsr.groups.GroupsComputer;
+import org.apache.bval.model.MetaBean;
+
+import javax.validation.metadata.ConstraintDescriptor;
+import javax.validation.metadata.ElementDescriptor;
+import javax.validation.metadata.ElementDescriptor.ConstraintFinder;
+import javax.validation.metadata.Scope;
+import java.lang.annotation.ElementType;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Description: Implementation of the fluent {@link ConstraintFinder} interface.<br/>
+ */
+final class ConstraintFinderImpl implements ElementDescriptor.ConstraintFinder {
+ private final MetaBean metaBean;
+ private final Set<Scope> findInScopes;
+ private Set<ConstraintValidation<?>> constraintDescriptors;
+
+ /**
+ * Create a new ConstraintFinderImpl instance.
+ *
+ * @param metaBean
+ * @param constraintDescriptors
+ */
+ ConstraintFinderImpl(MetaBean metaBean, Set<ConstraintValidation<?>> constraintDescriptors) {
+ this.metaBean = metaBean;
+ this.constraintDescriptors = constraintDescriptors;
+ this.findInScopes = new HashSet<Scope>(Arrays.asList(Scope.values()));
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public ElementDescriptor.ConstraintFinder unorderedAndMatchingGroups(Class<?>... groups) {
+ Set<ConstraintValidation<?>> matchingDescriptors =
+ new HashSet<ConstraintValidation<?>>(constraintDescriptors.size());
+ Groups groupChain = new GroupsComputer().computeGroups(groups);
+ for (Group group : groupChain.getGroups()) {
+ if (group.isDefault()) {
+ // If group is default, check if it gets redefined
+ List<Group> expandedDefaultGroup = metaBean.getFeature(JsrFeatures.Bean.GROUP_SEQUENCE);
+ for (Group defaultGroupMember : expandedDefaultGroup) {
+ for (ConstraintValidation<?> descriptor : constraintDescriptors) {
+ if (isInScope(descriptor) && isInGroup(descriptor, defaultGroupMember)) {
+ matchingDescriptors.add(descriptor);
+ }
+ }
+ }
+ } else {
+ for (ConstraintValidation<?> descriptor : constraintDescriptors) {
+ if (isInScope(descriptor) && isInGroup(descriptor, group)) {
+ matchingDescriptors.add(descriptor);
+ }
+ }
+ }
+ }
+ return thisWith(matchingDescriptors);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public ElementDescriptor.ConstraintFinder lookingAt(Scope scope) {
+ if (scope.equals(Scope.LOCAL_ELEMENT)) {
+ findInScopes.remove(Scope.HIERARCHY);
+ for (Iterator<ConstraintValidation<?>> it = constraintDescriptors.iterator(); it.hasNext();) {
+ ConstraintValidation<?> cv = it.next();
+ if (cv.getOwner() != metaBean.getBeanClass()) {
+ it.remove();
+ }
+ }
+ }
+ return this;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public ElementDescriptor.ConstraintFinder declaredOn(ElementType... elementTypes) {
+ Set<ConstraintValidation<?>> matchingDescriptors =
+ new HashSet<ConstraintValidation<?>>(constraintDescriptors.size());
+ for (ElementType each : elementTypes) {
+ for (ConstraintValidation<?> descriptor : constraintDescriptors) {
+ if (isInScope(descriptor) && isAtElement(descriptor, each)) {
+ matchingDescriptors.add(descriptor);
+ }
+ }
+ }
+ return thisWith(matchingDescriptors);
+ }
+
+ private boolean isAtElement(ConstraintValidation<?> descriptor, ElementType each) {
+ return descriptor.getAccess().getElementType() == each;
+ }
+
+ private boolean isInScope(ConstraintValidation<?> descriptor) {
+ if (findInScopes.size() == Scope.values().length)
+ return true; // all scopes
+ if (metaBean != null) {
+ Class<?> owner = descriptor.getOwner();
+ for (Scope scope : findInScopes) {
+ switch (scope) {
+ case LOCAL_ELEMENT:
+ if (owner.equals(metaBean.getBeanClass()))
+ return true;
+ break;
+ case HIERARCHY:
+ if (!owner.equals(metaBean.getBeanClass()))
+ return true;
+ break;
+ }
+ }
+ }
+ return false;
+ }
+
+ private boolean isInGroup(ConstraintValidation<?> descriptor, Group group) {
+ return descriptor.getGroups().contains(group.getGroup());
+ }
+
+ private ElementDescriptor.ConstraintFinder thisWith(Set<ConstraintValidation<?>> matchingDescriptors) {
+ constraintDescriptors = matchingDescriptors;
+ return this;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Set<ConstraintDescriptor<?>> getConstraintDescriptors() {
+ if (constraintDescriptors.isEmpty()) {
+ return Collections.emptySet();
+ }
+ return Collections.<ConstraintDescriptor<?>>unmodifiableSet(constraintDescriptors);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean hasConstraints() {
+ return !constraintDescriptors.isEmpty();
+ }
+}
Added: bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintValidation.java
URL: http://svn.apache.org/viewvc/bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintValidation.java?rev=1517540&view=auto
==============================================================================
--- bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintValidation.java (added)
+++ bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintValidation.java Mon Aug 26 13:59:15 2013
@@ -0,0 +1,585 @@
+/*
+ * 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.model.Validation;
+import org.apache.bval.model.ValidationContext;
+import org.apache.bval.model.ValidationListener;
+import org.apache.bval.util.AccessStrategy;
+import org.apache.commons.lang3.ArrayUtils;
+import org.apache.commons.lang3.ClassUtils;
+import org.apache.commons.lang3.reflect.TypeUtils;
+
+import javax.validation.ConstraintDefinitionException;
+import javax.validation.ConstraintTarget;
+import javax.validation.ConstraintValidator;
+import javax.validation.ConstraintValidatorFactory;
+import javax.validation.Payload;
+import javax.validation.UnexpectedTypeException;
+import javax.validation.ValidationException;
+import javax.validation.constraintvalidation.SupportedValidationTarget;
+import javax.validation.constraintvalidation.ValidationTarget;
+import javax.validation.metadata.ConstraintDescriptor;
+import java.io.Serializable;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Array;
+import java.lang.reflect.GenericArrayType;
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Description: Adapter between Constraint (JSR303) and Validation (Core)<br/>
+ * this instance is immutable!<br/>
+ */
+public class ConstraintValidation<T extends Annotation> implements Validation, ConstraintDescriptor<T> {
+ private final ConstraintValidatorFactory factory;
+ private final AccessStrategy access;
+ private final boolean reportFromComposite;
+ private final Map<String, Object> attributes;
+ private T annotation; // for metadata request API
+ private ConstraintValidator<T, ?> validator;
+
+ private Set<ConstraintValidation<?>> composedConstraints;
+
+ private boolean validated = false;
+
+ /**
+ * the owner is the type where the validation comes from. it is used to
+ * support implicit grouping.
+ */
+ private final Class<?> owner;
+ private Set<Class<?>> groups;
+ private Set<Class<? extends Payload>> payload;
+ private Class<? extends ConstraintValidator<T, ?>>[] validatorClasses;
+ private ConstraintTarget validationAppliesTo = null;
+
+ public ConstraintValidation(ConstraintValidatorFactory factory,
+ Class<? extends ConstraintValidator<T, ?>>[] validatorClasses,
+ T annotation, Class<?> owner, AccessStrategy access,
+ boolean reportFromComposite, ConstraintTarget target) {
+ this.factory = factory;
+ this.attributes = new HashMap<String, Object>();
+ this.validatorClasses = ArrayUtils.clone(validatorClasses);
+ this.annotation = annotation;
+ this.owner = owner;
+ this.access = access;
+ this.reportFromComposite = reportFromComposite;
+ this.validationAppliesTo = target;
+ }
+
+ /**
+ * Return a {@link Serializable} {@link ConstraintDescriptor} capturing a
+ * snapshot of current state.
+ *
+ * @return {@link ConstraintDescriptor}
+ */
+ public ConstraintDescriptor<T> asSerializableDescriptor() {
+ return new ConstraintDescriptorImpl<T>(this);
+ }
+
+ void setGroups(final Set<Class<?>> groups) {
+ this.groups = groups;
+ ConstraintAnnotationAttributes.GROUPS.put(attributes, groups.toArray(new Class<?>[groups.size()]));
+ }
+
+ void setGroups(final Class<?>[] groups) {
+ this.groups = new HashSet<Class<?>>();
+ Collections.addAll(this.groups, groups);
+ ConstraintAnnotationAttributes.GROUPS.put(attributes, groups);
+ }
+
+ void setPayload(Set<Class<? extends Payload>> payload) {
+ this.payload = payload;
+ ConstraintAnnotationAttributes.PAYLOAD.put(attributes, payload.toArray(new Class[payload.size()]));
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isReportAsSingleViolation() {
+ return reportFromComposite;
+ }
+
+ /**
+ * Add a composing constraint.
+ *
+ * @param aConstraintValidation to add
+ */
+ public void addComposed(ConstraintValidation<?> aConstraintValidation) {
+ if (composedConstraints == null) {
+ composedConstraints = new HashSet<ConstraintValidation<?>>();
+ }
+ composedConstraints.add(aConstraintValidation);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public <L extends ValidationListener> void validate(ValidationContext<L> context) {
+ validate((GroupValidationContext<?>) context);
+ }
+
+ /**
+ * Validate a {@link GroupValidationContext}.
+ *
+ * @param context root
+ */
+ public void validate(final GroupValidationContext<?> context) {
+ if (validator == null) {
+ synchronized (this) {
+ if (validator == null) {
+ try {
+ validator = getConstraintValidator(annotation, validatorClasses, owner, access);
+ if (validator != null) {
+ validator.initialize(annotation);
+ }
+ } catch (final RuntimeException re) {
+ if (ValidationException.class.isInstance(re)) {
+ throw re;
+ }
+ throw new ConstraintDefinitionException(re);
+ }
+ }
+ }
+ }
+
+ context.setConstraintValidation(this);
+ /**
+ * execute unless the given validation constraint has already been
+ * processed during this validation routine (as part of a previous group
+ * match)
+ */
+ if (!isMemberOf(context.getCurrentGroup().getGroup())) {
+ return; // do not validate in the current group
+ }
+ if (context.getCurrentOwner() != null && this.owner != context.getCurrentOwner()) {
+ return;
+ }
+ if (validator != null && !context.collectValidated(validator))
+ return; // already done
+
+ if (context.getMetaProperty() != null && !isReachable(context)) {
+ return;
+ }
+
+ // process composed constraints
+ if (isReportAsSingleViolation()) {
+ ConstraintValidationListener<?> listener = context.getListener();
+ listener.beginReportAsSingle();
+
+ boolean failed = listener.hasViolations();
+ try {
+ // stop validating when already failed and
+ // ReportAsSingleInvalidConstraint = true ?
+ for (Iterator<ConstraintValidation<?>> composed = getComposingValidations().iterator(); !failed && composed.hasNext(); ) {
+ composed.next().validate(context);
+ failed = listener.hasViolations();
+ }
+ } finally {
+ listener.endReportAsSingle();
+ // Restore current constraint validation
+ context.setConstraintValidation(this);
+ }
+
+ if (failed) {
+ // TODO RSt - how should the composed constraint error report look like?
+ ConstraintValidatorContextImpl jsrContext = new ConstraintValidatorContextImpl(context, this);
+ addErrors(context, jsrContext); // add defaultErrorMessage only
+ return;
+ }
+ } else {
+ for (ConstraintValidation<?> composed : getComposingValidations()) {
+ composed.validate(context);
+ }
+
+ // Restore current constraint validation
+ context.setConstraintValidation(this);
+ }
+
+ if (validator != null) {
+ ConstraintValidatorContextImpl jsrContext = new ConstraintValidatorContextImpl(context, this);
+ @SuppressWarnings("unchecked")
+ final ConstraintValidator<T, Object> objectValidator = (ConstraintValidator<T, Object>) validator;
+ if (!objectValidator.isValid(context.getValidatedValue(), jsrContext)) {
+ addErrors(context, jsrContext);
+ }
+ }
+ }
+
+ private <A extends Annotation, T> ConstraintValidator<A, ? super T> getConstraintValidator(A annotation,
+ Class<? extends ConstraintValidator<A, ?>>[] constraintClasses, Class<?> owner, AccessStrategy access) {
+ if (constraintClasses != null && constraintClasses.length > 0) {
+ Type type = determineTargetedType(owner, access);
+
+ /**
+ * spec says in chapter 3.5.3.: The ConstraintValidator chosen to
+ * validate a declared type T is the one where the type supported by
+ * the ConstraintValidator is a supertype of T and where there is no
+ * other ConstraintValidator whose supported type is a supertype of
+ * T and not a supertype of the chosen ConstraintValidator supported
+ * type.
+ */
+ final Map<Type, Collection<Class<? extends ConstraintValidator<A, ?>>>> validatorTypes = getValidatorsTypes(constraintClasses);
+ reduceTarget(validatorTypes, access);
+
+ final List<Type> assignableTypes = new ArrayList<Type>(constraintClasses.length);
+ fillAssignableTypes(type, validatorTypes.keySet(), assignableTypes);
+ reduceAssignableTypes(assignableTypes);
+ checkOneType(assignableTypes, type, owner, annotation, access);
+
+ if ((type == Object.class || type == Object[].class) && validatorTypes.containsKey(Object.class) && validatorTypes.containsKey(Object[].class)) {
+ throw new ConstraintDefinitionException("Only a validator for Object or Object[] should be provided for cross parameter validators");
+ }
+
+ final Collection<Class<? extends ConstraintValidator<A, ?>>> key = validatorTypes.get(assignableTypes.get(0));
+ if (key.size() > 1) {
+ final String message = "Factory returned " + key.size() + " validators";
+ if (ParametersAccess.class.isInstance(access)) { // cross parameter
+ throw new ConstraintDefinitionException(message);
+ }
+ throw new UnexpectedTypeException(message);
+ }
+
+ @SuppressWarnings("unchecked")
+ final ConstraintValidator<A, ? super T> validator = (ConstraintValidator<A, ? super T>) factory.getInstance(key.iterator().next());
+ if (validator == null) {
+ throw new ValidationException("Factory returned null validator for: " + key);
+
+ }
+ return validator;
+ // NOTE: validator initialization deferred until append phase
+ }
+ return null;
+ }
+
+ private <A extends Annotation> void reduceTarget(final Map<Type, Collection<Class<? extends ConstraintValidator<A, ?>>>> validator, final AccessStrategy access) {
+ for (final Map.Entry<Type, Collection<Class<? extends ConstraintValidator<A, ?>>>> entry : validator.entrySet()) {
+ final Collection<Class<? extends ConstraintValidator<A, ?>>> validators = entry.getValue();
+ final Iterator<Class<? extends ConstraintValidator<A, ?>>> it = validators.iterator();
+ while (it.hasNext()) {
+ final Type v = it.next();
+ if (!Class.class.isInstance(v)) {
+ continue; // TODO: handle this case
+ }
+
+ final Class<?> clazz = Class.class.cast(v);
+ final SupportedValidationTarget target = clazz.getAnnotation(SupportedValidationTarget.class);
+ if (target != null) {
+ final Collection<ValidationTarget> targets = Arrays.asList(target.value());
+ final boolean isParameter = ParameterAccess.class.isInstance(access) || ParametersAccess.class.isInstance(access);
+ if ((isParameter && !targets.contains(ValidationTarget.PARAMETERS))
+ || (!isParameter && !targets.contains(ValidationTarget.ANNOTATED_ELEMENT))) {
+ it.remove();
+ }
+ }
+ }
+ if (validators.isEmpty()) {
+ validator.remove(entry.getKey());
+ }
+ }
+ }
+
+ private static void checkOneType(List<Type> types, Type targetType, Class<?> owner, Annotation anno,
+ AccessStrategy access) {
+
+ if (types.isEmpty()) {
+ final String message = "No validator could be found for type " + stringForType(targetType)
+ + ". See: @" + anno.annotationType().getSimpleName() + " at " + stringForLocation(owner, access);
+ if (Object[].class.equals(targetType)) { // cross parameter
+ throw new ConstraintDefinitionException(message);
+ }
+ throw new UnexpectedTypeException(message);
+ } else if (types.size() > 1) {
+ StringBuilder buf = new StringBuilder();
+ buf.append("Ambiguous validators for type ");
+ buf.append(stringForType(targetType));
+ buf.append(". See: @").append(anno.annotationType().getSimpleName()).append(" at ").append(
+ stringForLocation(owner, access));
+ buf.append(". Validators are: ");
+ boolean comma = false;
+ for (Type each : types) {
+ if (comma)
+ buf.append(", ");
+ comma = true;
+ buf.append(each);
+ }
+ throw new UnexpectedTypeException(buf.toString());
+ }
+ }
+
+ private static String stringForType(Type clazz) {
+ if (clazz instanceof Class<?>) {
+ if (((Class<?>) clazz).isArray()) {
+ return ((Class<?>) clazz).getComponentType().getName() + "[]";
+ } else {
+ return ((Class<?>) clazz).getName();
+ }
+ } else {
+ return clazz.toString();
+ }
+ }
+
+ private static String stringForLocation(Class<?> owner, AccessStrategy access) {
+ if (access != null) {
+ return access.toString();
+ } else {
+ return owner.getName();
+ }
+ }
+
+ private static void fillAssignableTypes(Type type, Set<Type> validatorsTypes, List<Type> suitableTypes) {
+ for (final Type validatorType : validatorsTypes) {
+ if (org.apache.commons.lang3.reflect.TypeUtils.isAssignable(type, validatorType)
+ && !suitableTypes.contains(validatorType)) {
+ suitableTypes.add(validatorType);
+ }
+ }
+ }
+
+ /**
+ * Tries to reduce all assignable classes down to a single class.
+ *
+ * @param assignableTypes The set of all classes which are assignable to the class of
+ * the value to be validated and which are handled by at least
+ * one of the validators for the specified constraint.
+ */
+ private static void reduceAssignableTypes(List<Type> assignableTypes) {
+ if (assignableTypes.size() <= 1) {
+ return; // no need to reduce
+ }
+ boolean removed;
+ do {
+ removed = false;
+ final Type type = assignableTypes.get(0);
+ for (int i = 1; i < assignableTypes.size(); i++) {
+ Type nextType = assignableTypes.get(i);
+ if (TypeUtils.isAssignable(nextType, type)) {
+ assignableTypes.remove(0);
+ i--;
+ removed = true;
+ } else if (TypeUtils.isAssignable(type, nextType)) {
+ assignableTypes.remove(i--);
+ removed = true;
+ }
+ }
+ } while (removed && assignableTypes.size() > 1);
+
+ }
+
+ private static <A extends Annotation> Map<Type, Collection<Class<? extends ConstraintValidator<A, ?>>>> getValidatorsTypes(
+ Class<? extends ConstraintValidator<A, ?>>[] constraintValidatorClasses) {
+ final Map<Type, Collection<Class<? extends ConstraintValidator<A, ?>>>> validatorsTypes = new HashMap<Type, Collection<Class<? extends ConstraintValidator<A, ?>>>>();
+ for (Class<? extends ConstraintValidator<A, ?>> validatorType : constraintValidatorClasses) {
+ Type validatedType = TypeUtils.getTypeArguments(validatorType, ConstraintValidator.class).get(ConstraintValidator.class.getTypeParameters()[1]);
+ if (validatedType == null) {
+ throw new ValidationException(String.format("Could not detect validated type for %s", validatorType));
+ }
+ if (validatedType instanceof GenericArrayType) {
+ Type componentType = TypeUtils.getArrayComponentType(validatedType);
+ if (componentType instanceof Class<?>) {
+ validatedType = Array.newInstance((Class<?>) componentType, 0).getClass();
+ }
+ }
+ if (!validatorsTypes.containsKey(validatedType)) {
+ validatorsTypes.put(validatedType, new ArrayList<Class<? extends ConstraintValidator<A, ?>>>());
+ }
+ validatorsTypes.get(validatedType).add(validatorType);
+ }
+ return validatorsTypes;
+ }
+
+ /**
+ * implements spec chapter 3.5.3. ConstraintValidator resolution algorithm.
+ */
+ private static Type determineTargetedType(Class<?> owner, AccessStrategy access) {
+ // if the constraint declaration is hosted on a class or an interface,
+ // the targeted type is the class or the interface.
+ if (access == null)
+ return owner;
+ Type type = access.getJavaType();
+ if (type == null)
+ return Object.class;
+ if (type instanceof Class<?>)
+ type = ClassUtils.primitiveToWrapper((Class<?>) type);
+ return type;
+ }
+
+ /**
+ * Initialize the validator (if not <code>null</code>) with the stored
+ * annotation.
+ */
+ public void initialize() {
+ if (null != validator) {
+ try {
+ validator.initialize(annotation);
+ } catch (RuntimeException e) {
+ // Either a "legit" problem initializing the validator or a
+ // ClassCastException if the validator associated annotation is
+ // not a supertype of the validated annotation.
+ throw new ConstraintDefinitionException("Incorrect validator ["
+ + validator.getClass().getCanonicalName() + "] for annotation "
+ + annotation.annotationType().getCanonicalName(), e);
+ }
+ }
+ }
+
+ private boolean isReachable(GroupValidationContext<?> context) {
+ final PathImpl path = context.getPropertyPath();
+ final NodeImpl node = path.getLeafNode();
+ PathImpl beanPath = path.getPathWithoutLeafNode();
+ if (beanPath == null) {
+ beanPath = PathImpl.create();
+ }
+ try {
+ if (!context.getTraversableResolver().isReachable(context.getBean(), node,
+ context.getRootMetaBean().getBeanClass(), beanPath, access.getElementType()))
+ return false;
+ } catch (RuntimeException e) {
+ throw new ValidationException("Error in TraversableResolver.isReachable() for " + context.getBean(), e);
+ }
+
+ return true;
+ }
+
+ private void addErrors(GroupValidationContext<?> context, ConstraintValidatorContextImpl jsrContext) {
+ for (ValidationListener.Error each : jsrContext.getErrorMessages()) {
+ context.getListener().addError(each, context);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String toString() {
+ return "ConstraintValidation{" + validator + '}';
+ }
+
+ /**
+ * Get the message template used by this constraint.
+ *
+ * @return String
+ */
+ public String getMessageTemplate() {
+ return ConstraintAnnotationAttributes.MESSAGE.get(attributes);
+ }
+
+ public ConstraintValidator<T, ?> getValidator() {
+ return validator;
+ }
+
+ protected boolean isMemberOf(Class<?> reqGroup) {
+ return groups.contains(reqGroup);
+ }
+
+ public Class<?> getOwner() {
+ return owner;
+ }
+
+ public T getAnnotation() {
+ return annotation;
+ }
+
+ public AccessStrategy getAccess() {
+ return access;
+ }
+
+ public void setAnnotation(T annotation) {
+ this.annotation = annotation;
+ }
+
+ // ///////////////////////// ConstraintDescriptor implementation
+
+ /**
+ * {@inheritDoc}
+ */
+ public Map<String, Object> getAttributes() {
+ return attributes;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @SuppressWarnings("unchecked")
+ public Set<ConstraintDescriptor<?>> getComposingConstraints() {
+ return composedConstraints == null ? Collections.EMPTY_SET : composedConstraints;
+ }
+
+ /**
+ * Get the composing {@link ConstraintValidation} objects. This is
+ * effectively an implementation-specific analogue to
+ * {@link #getComposingConstraints()}.
+ *
+ * @return {@link Set} of {@link ConstraintValidation}
+ */
+ @SuppressWarnings("unchecked")
+ Set<ConstraintValidation<?>> getComposingValidations() {
+ return composedConstraints == null ? Collections.EMPTY_SET : composedConstraints;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Set<Class<?>> getGroups() {
+ return groups;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Set<Class<? extends Payload>> getPayload() {
+ return payload;
+ }
+
+ public ConstraintTarget getValidationAppliesTo() {
+ return validationAppliesTo;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public List<Class<? extends ConstraintValidator<T, ?>>> getConstraintValidatorClasses() {
+ if (validatorClasses == null) {
+ return Collections.emptyList();
+ }
+ return Arrays.asList(validatorClasses);
+ }
+
+ public void setValidationAppliesTo(final ConstraintTarget validationAppliesTo) {
+ this.validationAppliesTo = validationAppliesTo;
+ }
+
+ public boolean isValidated() {
+ return validated;
+ }
+
+ public void setValidated(final boolean validated) {
+ this.validated = validated;
+ }
+}
Added: bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintValidationListener.java
URL: http://svn.apache.org/viewvc/bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintValidationListener.java?rev=1517540&view=auto
==============================================================================
--- bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintValidationListener.java (added)
+++ bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintValidationListener.java Mon Aug 26 13:59:15 2013
@@ -0,0 +1,255 @@
+/*
+ * 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.PathImpl;
+import org.apache.bval.model.ValidationContext;
+import org.apache.bval.model.ValidationListener;
+
+import javax.validation.ConstraintViolation;
+import javax.validation.ElementKind;
+import javax.validation.MessageInterpolator;
+import javax.validation.Path;
+import javax.validation.metadata.ConstraintDescriptor;
+import java.lang.annotation.ElementType;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+/**
+ * Description: JSR-303 {@link ValidationListener} implementation; provides {@link ConstraintViolation}s.<br/>
+ *
+ * @version $Rev: 1503686 $ $Date: 2013-07-16 14:38:56 +0200 (mar., 16 juil. 2013) $
+ */
+public final class ConstraintValidationListener<T> implements ValidationListener {
+ private final Set<ConstraintViolation<T>> constraintViolations = new HashSet<ConstraintViolation<T>>();
+ private final T rootBean;
+ private final Class<T> rootBeanType;
+ // the validation process is single-threaded and it's unlikely to change in the near future (otherwise use AtomicInteger).
+ private int compositeDepth = 0;
+ private boolean hasCompositeError;
+
+ /**
+ * Create a new ConstraintValidationListener instance.
+ * @param aRootBean
+ * @param rootBeanType
+ */
+ public ConstraintValidationListener(T aRootBean, Class<T> rootBeanType) {
+ this.rootBean = aRootBean;
+ this.rootBeanType = rootBeanType;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public <VL extends ValidationListener> void addError(String reason, ValidationContext<VL> context) {
+ addError(reason, null, context);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public <VL extends ValidationListener> void addError(Error error, ValidationContext<VL> context) {
+ if (error.getOwner() instanceof Path) {
+ addError(error.getReason(), (Path) error.getOwner(), context);
+ } else {
+ addError(error.getReason(), null, context);
+ }
+ }
+
+ private void addError(String messageTemplate, Path propPath,
+ ValidationContext<?> context) {
+ if (compositeDepth > 0) {
+ hasCompositeError |= true;
+ return;
+ }
+ final Object value;
+
+ final ConstraintDescriptor<?> descriptor;
+ final String message;
+ if (context instanceof GroupValidationContext<?>) {
+ GroupValidationContext<?> gcontext = (GroupValidationContext<?>) context;
+ value = gcontext.getValidatedValue();
+ if (gcontext instanceof MessageInterpolator.Context) {
+ message = gcontext.getMessageResolver()
+ .interpolate(messageTemplate,
+ (MessageInterpolator.Context) gcontext);
+ } else {
+ message =
+ gcontext.getMessageResolver().interpolate(messageTemplate, null);
+ }
+ descriptor = gcontext.getConstraintValidation().asSerializableDescriptor();
+ if (propPath == null) propPath = gcontext.getPropertyPath();
+ } else {
+ if (context.getMetaProperty() == null) value = context.getBean();
+ else value = context.getPropertyValue();
+ message = messageTemplate;
+ if (propPath == null)
+ propPath = PathImpl.createPathFromString(context.getPropertyName());
+ descriptor = null;
+ }
+ ElementType elementType = (context.getAccess() != null) ? context.getAccess().getElementType() : null;
+
+ final Object[] parameters;
+ Object leaf;
+ Object returnValue;
+ T rootBean;
+ if (GroupValidationContext.class.isInstance(context)) { // TODO: clean up it but it would need to rework completely our context - get rid of it would be the best
+ final GroupValidationContext<T> ctx = GroupValidationContext.class.cast(context);
+ final ElementKind elementKind = ctx.getElementKind();
+ final Iterator<Path.Node> it = propPath.iterator();
+ final ElementKind kind = propPath.iterator().next().getKind();
+
+ returnValue = ctx.getReturnValue();
+
+ if (ElementKind.CONSTRUCTOR.equals(kind)) {
+ rootBean = null;
+ leaf = context.getBean();
+ returnValue = this.rootBean; // switch back return value and rootBean
+ } else if (ElementKind.METHOD.equals(kind)) {
+ if (ElementKind.RETURN_VALUE.equals(elementKind)) { // switch back return value and rootBean
+ rootBean = (T) returnValue;
+ if (kindOf(propPath, ElementKind.RETURN_VALUE)) {
+ leaf = returnValue;
+ returnValue = this.rootBean;
+ } else {
+ leaf = this.rootBean;
+ returnValue = this.rootBean;
+ }
+ } else {
+ rootBean = this.rootBean;
+ if (kindOf(propPath, ElementKind.PARAMETER, ElementKind.CROSS_PARAMETER)) {
+ leaf = rootBean;
+ } else {
+ leaf = context.getBean();
+ }
+ }
+ } else {
+ rootBean = this.rootBean;
+ leaf = context.getBean();
+ }
+
+ if (ElementKind.CONSTRUCTOR.equals(kind)
+ && (ElementKind.CROSS_PARAMETER.equals(elementKind)
+ || ElementKind.PARAMETER.equals(elementKind))
+ && (it.hasNext() && it.next() != null && it.hasNext() && it.next() != null && !it.hasNext())) { // means inherited validation use real value
+ leaf = null;
+ }
+
+ parameters = ctx.getParameters();
+ } else {
+ leaf = context.getBean();
+ returnValue = null;
+ parameters = null;
+ rootBean = this.rootBean;
+ }
+
+ constraintViolations.add(new ConstraintViolationImpl<T>(
+ messageTemplate, message,
+ rootBean, leaf,
+ propPath, value, descriptor,
+ rootBeanType,
+ elementType, returnValue, parameters));
+ }
+
+ private static boolean kindOf(final Path propPath, final ElementKind... kinds) {
+ final Iterator<Path.Node> node = propPath.iterator();
+ boolean isParam = false;
+ while (node.hasNext()) {
+ final ElementKind current = node.next().getKind();
+ isParam = false;
+ for (final ElementKind k : kinds) {
+ if (k.equals(current)) {
+ isParam = true;
+ break;
+ }
+ }
+ }
+ return isParam;
+ }
+
+ /**
+ * Get the {@link ConstraintViolation}s accumulated by this {@link ConstraintValidationListener}.
+ * @return {@link Set} of {@link ConstraintViolation}
+ */
+ public Set<ConstraintViolation<T>> getConstraintViolations() {
+ return constraintViolations;
+ }
+
+ /**
+ * Learn whether no violations were found.
+ * @return boolean
+ */
+ public boolean isEmpty() {
+ return constraintViolations.isEmpty();
+ }
+
+ /**
+ * Get the root bean.
+ * @return T
+ */
+ public T getRootBean() {
+ return rootBean;
+ }
+
+ /**
+ * Get the root bean type of this {@link ConstraintValidationListener}.
+ * @return Class<T>
+ */
+ public Class<T> getRootBeanType() {
+ return rootBeanType;
+ }
+
+ /**
+ * Get the count of encountered violations.
+ * @return int
+ */
+ public int violationsSize() {
+ return constraintViolations.size();
+ }
+
+ /**
+ * Learn whether there are violations available.
+ * If in report-as-single-violation mode, the result is scoped accordingly.
+ * Note that this means you must check before exiting report-as-single-violation mode
+ * @return boolean
+ */
+ public boolean hasViolations() {
+ return compositeDepth == 0 ? !constraintViolations.isEmpty() : hasCompositeError;
+ }
+
+ /**
+ * Signify the beginning of a report-as-single-violation composite validation.
+ * @return <code>true</code> as this call caused the listener to enter report-as-single-violation mode
+ */
+ public boolean beginReportAsSingle() {
+ return ++compositeDepth == 1;
+ }
+
+ /**
+ * Signify the end of a report-as-single-violation composite validation.
+ * @return <code>true</code> as this call caused the listener to exit report-as-single-violation mode
+ */
+ public boolean endReportAsSingle() {
+ boolean endOutMostReportAsSingle = (--compositeDepth == 0);
+ if( endOutMostReportAsSingle ) {
+ hasCompositeError = false;
+ }
+ return endOutMostReportAsSingle;
+ }
+}
Added: bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintValidatorContextImpl.java
URL: http://svn.apache.org/viewvc/bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintValidatorContextImpl.java?rev=1517540&view=auto
==============================================================================
--- bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintValidatorContextImpl.java (added)
+++ bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintValidatorContextImpl.java Mon Aug 26 13:59:15 2013
@@ -0,0 +1,208 @@
+/*
+ * 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 org.apache.bval.model.ValidationListener;
+
+import javax.validation.ConstraintValidator;
+import javax.validation.ConstraintValidatorContext;
+import javax.validation.ElementKind;
+import javax.validation.Path;
+import javax.validation.ValidationException;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.LinkedList;
+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 {
+ private final List<ValidationListener.Error> errorMessages =
+ new LinkedList<ValidationListener.Error>();
+
+ private final ConstraintValidation<?> constraintDescriptor;
+ private final GroupValidationContext<?> validationContext;
+
+ private boolean defaultDisabled;
+
+ /**
+ * Create a new ConstraintValidatorContextImpl instance.
+ * @param validationContext
+ * @param aConstraintValidation
+ */
+ public ConstraintValidatorContextImpl(GroupValidationContext<?> validationContext,
+ ConstraintValidation<?> aConstraintValidation) {
+ this.validationContext = validationContext;
+ this.constraintDescriptor = aConstraintValidation;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void disableDefaultConstraintViolation() {
+ defaultDisabled = true;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String getDefaultConstraintMessageTemplate() {
+ return constraintDescriptor.getMessageTemplate();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public ConstraintViolationBuilder buildConstraintViolationWithTemplate(
+ String messageTemplate) {
+ return new ConstraintViolationBuilderImpl(this, messageTemplate, validationContext.getPropertyPath());
+ }
+
+ public <T> T unwrap(Class<T> type) {
+ if (type.isInstance(this)) {
+ return type.cast(this);
+ }
+ throw new ValidationException("Type " + type + " not supported");
+ }
+
+ private static final class ConstraintViolationBuilderImpl
+ implements ConstraintValidatorContext.ConstraintViolationBuilder {
+ private final ConstraintValidatorContextImpl parent;
+ private final String messageTemplate;
+ private final PathImpl propertyPath;
+
+ /**
+ * Create a new ConstraintViolationBuilderImpl instance.
+ * @param contextImpl
+ * @param template
+ * @param path
+ */
+ ConstraintViolationBuilderImpl(ConstraintValidatorContextImpl contextImpl,
+ String template, PathImpl path) {
+ parent = contextImpl;
+ messageTemplate = template;
+ propertyPath = path;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public NodeBuilderDefinedContext addNode(String name) {
+ PathImpl path;
+ if (propertyPath.isRootPath()) {
+ path = PathImpl.create();
+ path.getLeafNode().setName(name);
+ } else {
+ path = PathImpl.copy(propertyPath);
+ path.addNode(new NodeImpl(name));
+ }
+ return new NodeBuilderDefinedContextImpl(parent, messageTemplate, path);
+ }
+
+ public NodeBuilderCustomizableContext addPropertyNode(String name) {
+ final NodeImpl node;
+ if (!propertyPath.isRootPath()) {
+ if (propertyPath.getLeafNode().getKind() != null) {
+ node = new NodeImpl.PropertyNodeImpl(name);
+ propertyPath.addNode(node);
+ } else {
+ node = propertyPath.getLeafNode();
+ }
+ } else {
+ node = new NodeImpl.PropertyNodeImpl(name);
+ propertyPath.addNode(node);
+ }
+ node.setName(name);
+ node.setKind(ElementKind.PROPERTY); // enforce it
+ return new NodeBuilderCustomizableContextImpl(parent, messageTemplate, propertyPath);
+ }
+
+ public LeafNodeBuilderCustomizableContext addBeanNode() {
+ final NodeImpl node = new NodeImpl.BeanNodeImpl();
+ node.setKind(ElementKind.BEAN);
+ propertyPath.addNode(node);
+ return new LeafNodeBuilderCustomizableContextImpl(parent, messageTemplate, propertyPath);
+ }
+
+ public NodeBuilderDefinedContext addParameterNode(int index) {
+ final Method method = parent.validationContext.getMethod();
+ final List<String> parameters = parent.validationContext.getParameterNameProvider().getParameterNames(method);
+ final NodeImpl node = new NodeImpl.ParameterNodeImpl(parameters.get(index), index);
+ node.setParameterIndex(index);
+ node.setKind(ElementKind.PARAMETER);
+ if (!propertyPath.isRootPath()) {
+ propertyPath.removeLeafNode();
+ }
+ propertyPath.addNode(node);
+ return new NodeBuilderDefinedContextImpl(parent, messageTemplate, propertyPath);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public ConstraintValidatorContext addConstraintViolation() {
+ parent.addError(messageTemplate, propertyPath);
+ return parent;
+ }
+ }
+
+ /**
+ * Get the queued error messages.
+ * @return List
+ */
+ public List<ValidationListener.Error> getErrorMessages() {
+ if (defaultDisabled && errorMessages.isEmpty()) {
+ throw new ValidationException(
+ "At least one custom message must be created if the default error message gets disabled.");
+ }
+
+ List<ValidationListener.Error> returnedErrorMessages =
+ new ArrayList<ValidationListener.Error>(errorMessages);
+ if (!defaultDisabled) {
+ returnedErrorMessages.add(new ValidationListener.Error(
+ getDefaultConstraintMessageTemplate(), validationContext.getPropertyPath(),
+ null));
+ }
+ return returnedErrorMessages;
+ }
+
+ /**
+ * Get this {@link ConstraintValidatorContext}'s {@link GroupValidationContext}.
+ * @return {@link GroupValidationContext}
+ */
+ public GroupValidationContext<?> getValidationContext() {
+ return validationContext;
+ }
+
+ /**
+ * Add an error message to this {@link ConstraintValidatorContext}.
+ * @param messageTemplate
+ * @param propertyPath
+ */
+ public void addError(String messageTemplate, Path propertyPath) {
+ errorMessages.add(new ValidationListener.Error(messageTemplate, propertyPath, null));
+ }
+}
Added: bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintValidatorIdentity.java
URL: http://svn.apache.org/viewvc/bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintValidatorIdentity.java?rev=1517540&view=auto
==============================================================================
--- bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintValidatorIdentity.java (added)
+++ bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintValidatorIdentity.java Mon Aug 26 13:59:15 2013
@@ -0,0 +1,134 @@
+/*
+ * 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 javax.validation.ConstraintValidator;
+import javax.validation.Path;
+
+/**
+ * Class that stores the needed properties to ensure that a validation is not
+ * checked more than once.
+ * <p>
+ * These properties are:
+ * <ul>
+ * <li>The ref of the bean to which the validation would be applied.</li>
+ * <li>The path of the property.</li>
+ * <li>The ref of the {@link ConstraintValidator}.</li>
+ * </ul>
+ *
+ * @author Carlos Vara
+ */
+final class ConstraintValidatorIdentity {
+
+ private final Object bean;
+ private final Path path;
+ private final ConstraintValidator<?, ?> constraintValidator;
+
+ /**
+ * Create a new ConstraintValidatorIdentity instance.
+ * @param bean
+ * @param path
+ * @param constraintValidator
+ */
+ public ConstraintValidatorIdentity(Object bean, Path path, ConstraintValidator<?, ?> constraintValidator) {
+ this.bean = bean;
+ this.path = path;
+ this.constraintValidator = constraintValidator;
+ }
+
+ /**
+ * Get the referenced bean.
+ * @return Object
+ */
+ public Object getBean() {
+ return bean;
+ }
+
+ /**
+ * Get the referenced property {@link Path}.
+ * @return Path
+ */
+ public Path getPath() {
+ return path;
+ }
+
+ /**
+ * Get the associated {@link ConstraintValidator}.
+ * @return {@link ConstraintValidator}
+ */
+ public ConstraintValidator<?, ?> getConstraintValidator() {
+ return constraintValidator;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean equals(Object obj) {
+
+ if (this == obj) {
+ return true;
+ }
+
+ if (obj == null) {
+ return false;
+ }
+
+ if (!(obj instanceof ConstraintValidatorIdentity)) {
+ return false;
+ }
+
+ ConstraintValidatorIdentity other = (ConstraintValidatorIdentity) obj;
+
+ // Bean ref must be the same
+ if (this.bean != other.bean) {
+ return false;
+ }
+
+ // ConstraintValidator ref must be the same
+ if (this.constraintValidator != other.constraintValidator) {
+ return false;
+ }
+
+ // Path must be equals
+ if (!this.path.equals(other.path)) {
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result
+ + ((this.bean == null) ? 0 : this.bean.hashCode());
+ result = prime * result
+ + ((this.path == null) ? 0 : this.path.hashCode());
+ result = prime * result
+ + ((this.constraintValidator == null) ? 0 : this.constraintValidator.hashCode());
+ return result;
+ }
+
+}
Added: bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintViolationImpl.java
URL: http://svn.apache.org/viewvc/bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintViolationImpl.java?rev=1517540&view=auto
==============================================================================
--- bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintViolationImpl.java (added)
+++ bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintViolationImpl.java Mon Aug 26 13:59:15 2013
@@ -0,0 +1,214 @@
+/*
+ * 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 javax.validation.ConstraintViolation;
+import javax.validation.Path;
+import javax.validation.ValidationException;
+import javax.validation.metadata.ConstraintDescriptor;
+import java.io.Serializable;
+import java.lang.annotation.ElementType;
+import java.util.Arrays;
+
+/**
+ * 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 {
+ /** Serialization version */
+ private static final long serialVersionUID = 1L;
+
+ private final String messageTemplate;
+ private final String message;
+ /** root bean validation was invoked on. */
+ private final T rootBean;
+ private final Class<T> rootBeanClass;
+ /** last bean validated. */
+ private final Object leafBean;
+ private final Object value;
+ private final Path propertyPath;
+ private final ElementType elementType;
+ private final ConstraintDescriptor<?> constraintDescriptor;
+ private final Object returnValue;
+ private final Object[] parameters;
+ private final int hashCode;
+
+ /**
+ * Create a new ConstraintViolationImpl instance.
+ * @param messageTemplate - message reason (raw message)
+ * @param message - interpolated message (locale specific)
+ * @param rootBean
+ * @param leafBean
+ * @param propertyPath
+ * @param value
+ * @param constraintDescriptor
+ * @param rootBeanClass
+ * @param elementType
+ * @param returnValue
+ * @param parameters
+ */
+ public ConstraintViolationImpl(String messageTemplate, String message, T rootBean, Object leafBean,
+ Path propertyPath, Object value,
+ ConstraintDescriptor<?> constraintDescriptor, Class<T> rootBeanClass,
+ ElementType elementType, Object returnValue, Object[] parameters) {
+ this.messageTemplate = messageTemplate;
+ this.message = message;
+ this.rootBean = rootBean;
+ this.rootBeanClass = rootBeanClass;
+ this.propertyPath = propertyPath;
+ this.leafBean = leafBean;
+ this.value = value;
+ this.constraintDescriptor = constraintDescriptor;
+ this.elementType = elementType;
+ this.returnValue = returnValue;
+ this.parameters = parameters;
+ this.hashCode = computeHashCode();
+ }
+
+ /**
+ * {@inheritDoc}
+ * former name getInterpolatedMessage()
+ * @return The interpolated error message for this constraint violation.
+ */
+ public String getMessage() {
+ return message;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String getMessageTemplate() {
+ return messageTemplate;
+ }
+
+ /**
+ * {@inheritDoc}
+ * @return Root bean being validated
+ */
+ public T getRootBean() {
+ return rootBean;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Class<T> getRootBeanClass() {
+ return rootBeanClass;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Object getLeafBean() {
+ return leafBean;
+ }
+
+ public Object[] getExecutableParameters() {
+ return parameters;
+ }
+
+ public Object getExecutableReturnValue() {
+ return returnValue;
+ }
+
+ /**
+ * {@inheritDoc}
+ * @return The value failing to pass the constraint
+ */
+ public Object getInvalidValue() {
+ return value;
+ }
+
+ /**
+ * {@inheritDoc}
+ * @return the property path to the value from <code>rootBean</code>
+ * Null if the value is the rootBean itself
+ */
+ public Path getPropertyPath() {
+ return propertyPath;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public ConstraintDescriptor<?> getConstraintDescriptor() {
+ return constraintDescriptor;
+ }
+
+ public <U> U unwrap(Class<U> type) {
+ if (type.isInstance(this)) {
+ return type.cast(this);
+ }
+ throw new ValidationException("Type " + type + " is not supported");
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String toString() {
+ return "ConstraintViolationImpl{" + "rootBean=" + rootBean + ", propertyPath='" +
+ propertyPath + '\'' + ", message='" + message + '\'' + ", leafBean=" +
+ leafBean + ", value=" + value + '}';
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != 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;
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ 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);
+ return result;
+ }
+}
Added: bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/ConstructorDescriptorImpl.java
URL: http://svn.apache.org/viewvc/bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/ConstructorDescriptorImpl.java?rev=1517540&view=auto
==============================================================================
--- bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/ConstructorDescriptorImpl.java (added)
+++ bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/ConstructorDescriptorImpl.java Mon Aug 26 13:59:15 2013
@@ -0,0 +1,61 @@
+/*
+ * 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.model.MetaBean;
+import org.apache.bval.model.MetaConstructor;
+import org.apache.bval.model.Validation;
+
+import javax.validation.metadata.ConstructorDescriptor;
+
+/**
+ * Description: {@link javax.validation.metadata.ConstructorDescriptor} implementation.<br/>
+ */
+public class ConstructorDescriptorImpl extends InvocableElementDescriptor
+ implements ConstructorDescriptor, ProcedureDescriptor {
+ /**
+ * Create a new ConstructorDescriptorImpl instance.
+ * @param metaBean
+ * @param validations
+ */
+ protected ConstructorDescriptorImpl(MetaBean metaBean, Validation[] validations) {
+ super(metaBean, metaBean.getBeanClass(), validations);
+ }
+
+ public ConstructorDescriptorImpl(final MetaBean metaBean, final MetaConstructor metaMethod) {
+ super(metaBean, metaBean.getBeanClass(), new Validation[0]);
+ setCascaded(false);
+ }
+
+ public String getName() {
+ return elementClass.getSimpleName();
+ }
+
+ @Override
+ public boolean hasConstraints() {
+ return false;
+ }
+
+ public boolean hasConstrainedParameters() {
+ return super.hasConstrainedParameters();
+ }
+
+ public boolean hasConstrainedReturnValue() {
+ return super.hasConstrainedReturnValue();
+ }
+}
Added: bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/CrossParameterDescriptorImpl.java
URL: http://svn.apache.org/viewvc/bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/CrossParameterDescriptorImpl.java?rev=1517540&view=auto
==============================================================================
--- bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/CrossParameterDescriptorImpl.java (added)
+++ bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/CrossParameterDescriptorImpl.java Mon Aug 26 13:59:15 2013
@@ -0,0 +1,34 @@
+/*
+ * 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.model.MetaBean;
+
+import javax.validation.metadata.CrossParameterDescriptor;
+import java.util.Collection;
+
+public class CrossParameterDescriptorImpl extends ElementDescriptorImpl implements CrossParameterDescriptor {
+ public CrossParameterDescriptorImpl(final MetaBean bean, final Collection<ConstraintValidation<?>> list) {
+ super(bean, Object[].class, list.toArray(new ConstraintValidation<?>[list.size()]));
+ }
+
+ public boolean hasConstraints() {
+ return !getConstraintDescriptors().isEmpty();
+ }
+}