You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@bval.apache.org by mb...@apache.org on 2018/02/21 21:02:06 UTC

[16/17] bval git commit: code updates

code updates


Project: http://git-wip-us.apache.org/repos/asf/bval/repo
Commit: http://git-wip-us.apache.org/repos/asf/bval/commit/f87be824
Tree: http://git-wip-us.apache.org/repos/asf/bval/tree/f87be824
Diff: http://git-wip-us.apache.org/repos/asf/bval/diff/f87be824

Branch: refs/heads/bv2
Commit: f87be824d77a26424e6856183391c8d3340b5241
Parents: b808381
Author: Matt Benson <mb...@apache.org>
Authored: Wed Feb 21 14:58:35 2018 -0600
Committer: Matt Benson <mb...@apache.org>
Committed: Wed Feb 21 14:59:59 2018 -0600

----------------------------------------------------------------------
 .../bval/routines/EMailValidationUtils.java     |   7 +-
 .../main/java/org/apache/bval/el/ELFacade.java  |  16 +--
 .../bval/jsr/AnnotationConstraintBuilder.java   |  38 ++---
 .../apache/bval/jsr/AnnotationProcessor.java    |  24 ++--
 .../jsr/ConstraintAnnotationAttributes.java     |  46 +++---
 .../org/apache/bval/jsr/ConstraintCached.java   | 143 +++++++++++++++++--
 .../org/apache/bval/jsr/ConstraintDefaults.java | 103 +++++--------
 .../bval/jsr/ConstraintDescriptorImpl.java      |  13 ++
 .../apache/bval/jsr/ConstraintValidation.java   |  33 ++++-
 .../jsr/ConstraintValidatorContextImpl.java     |  20 ++-
 .../bval/jsr/ConstraintValidatorIdentity.java   |   9 +-
 .../bval/jsr/ConstraintViolationImpl.java       |  94 +++++-------
 .../jsr/DefaultConstraintValidatorFactory.java  |  12 +-
 .../bval/jsr/DefaultMessageInterpolator.java    |  35 ++---
 .../jsr/DefaultValidationProviderResolver.java  |  50 +++----
 .../org/apache/bval/jsr/GraphBeanIdentity.java  |  28 +---
 .../bval/jsr/ParameterDescriptorImpl.java       |   7 +
 .../apache/bval/jsr/PropertyDescriptorImpl.java |   9 ++
 .../bval/jsr/ReturnValueDescriptorImpl.java     |   8 ++
 .../java/org/apache/bval/jsr/groups/Group.java  |  13 +-
 .../groups/GroupConversionDescriptorImpl.java   |   3 +-
 .../java/org/apache/bval/jsr/groups/Groups.java |  67 +++++----
 .../apache/bval/jsr/groups/GroupsComputer.java  | 111 +++++++-------
 .../parameter/DefaultParameterNameProvider.java |  25 ++--
 .../resolver/CachingTraversableResolver.java    |  26 ++--
 25 files changed, 506 insertions(+), 434 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/bval/blob/f87be824/bval-core/src/main/java/org/apache/bval/routines/EMailValidationUtils.java
----------------------------------------------------------------------
diff --git a/bval-core/src/main/java/org/apache/bval/routines/EMailValidationUtils.java b/bval-core/src/main/java/org/apache/bval/routines/EMailValidationUtils.java
index 1158c7f..0835bae 100644
--- a/bval-core/src/main/java/org/apache/bval/routines/EMailValidationUtils.java
+++ b/bval-core/src/main/java/org/apache/bval/routines/EMailValidationUtils.java
@@ -29,12 +29,11 @@ public class EMailValidationUtils {
     private static String ATOM = "[^\\x00-\\x1F\\(\\)\\<\\>\\@\\,\\;\\:\\\\\\\"\\.\\[\\]\\s]";
     private static String DOMAIN = "(" + ATOM + "+(\\." + ATOM + "+)*";
     private static String IP_DOMAIN = "\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\]";
-    public static final java.util.regex.Pattern DEFAULT_EMAIL_PATTERN;
+    public static final Pattern DEFAULT_EMAIL_PATTERN;
 
     static {
-        DEFAULT_EMAIL_PATTERN =
-            java.util.regex.Pattern.compile("^" + ATOM + "+(\\." + ATOM + "+)*@" + DOMAIN + "|" + IP_DOMAIN + ")$",
-                java.util.regex.Pattern.CASE_INSENSITIVE);
+        DEFAULT_EMAIL_PATTERN = Pattern.compile("^" + ATOM + "+(\\." + ATOM + "+)*@" + DOMAIN + "|" + IP_DOMAIN + ")$",
+            Pattern.CASE_INSENSITIVE);
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/bval/blob/f87be824/bval-jsr/src/main/java/org/apache/bval/el/ELFacade.java
----------------------------------------------------------------------
diff --git a/bval-jsr/src/main/java/org/apache/bval/el/ELFacade.java b/bval-jsr/src/main/java/org/apache/bval/el/ELFacade.java
index 49f236b..9798455 100644
--- a/bval-jsr/src/main/java/org/apache/bval/el/ELFacade.java
+++ b/bval-jsr/src/main/java/org/apache/bval/el/ELFacade.java
@@ -54,10 +54,9 @@ public final class ELFacade implements MessageEvaluator {
             if (EXPRESSION_FACTORY != null) {
                 final BValELContext context = new BValELContext();
                 final VariableMapper variables = context.getVariableMapper();
-                for (final Map.Entry<String, Object> var : annotationParameters.entrySet()) {
-                    variables.setVariable(var.getKey(),
-                        EXPRESSION_FACTORY.createValueExpression(var.getValue(), Object.class));
-                }
+                annotationParameters.forEach(
+                    (k, v) -> variables.setVariable(k, EXPRESSION_FACTORY.createValueExpression(v, Object.class)));
+
                 variables.setVariable("validatedValue",
                     EXPRESSION_FACTORY.createValueExpression(validatedValue, Object.class));
 
@@ -83,13 +82,8 @@ public final class ELFacade implements MessageEvaluator {
     }
 
     private static class BValELContext extends ELContext {
-        private final FunctionMapper functions;
-        private final VariableMapper variables;
-
-        public BValELContext() {
-            this.variables = new BValVariableMapper();
-            this.functions = new BValFunctionMapper();
-        }
+        private final FunctionMapper functions = new BValFunctionMapper();
+        private final VariableMapper variables = new BValVariableMapper();
 
         @Override
         public ELResolver getELResolver() {

http://git-wip-us.apache.org/repos/asf/bval/blob/f87be824/bval-jsr/src/main/java/org/apache/bval/jsr/AnnotationConstraintBuilder.java
----------------------------------------------------------------------
diff --git a/bval-jsr/src/main/java/org/apache/bval/jsr/AnnotationConstraintBuilder.java b/bval-jsr/src/main/java/org/apache/bval/jsr/AnnotationConstraintBuilder.java
index 017cabb..4b15ba7 100644
--- a/bval-jsr/src/main/java/org/apache/bval/jsr/AnnotationConstraintBuilder.java
+++ b/bval-jsr/src/main/java/org/apache/bval/jsr/AnnotationConstraintBuilder.java
@@ -72,7 +72,7 @@ final class AnnotationConstraintBuilder<A extends Annotation> {
         final boolean reportFromComposite =
             annotation != null && annotation.annotationType().isAnnotationPresent(ReportAsSingleViolation.class);
         constraintValidation =
-            new ConstraintValidation<A>(validatorClasses, annotation, owner, access, reportFromComposite, target);
+            new ConstraintValidation<>(validatorClasses, annotation, owner, access, reportFromComposite, target);
         buildFromAnnotation();
     }
 
@@ -139,7 +139,7 @@ final class AnnotationConstraintBuilder<A extends Annotation> {
         if (!foundGroups) {
             throw new ConstraintDefinitionException("Annotation " + annotationType.getName() + " has no groups method");
         }
-        if (validationAppliesTo != null && !ConstraintTarget.IMPLICIT.equals(validationAppliesTo.getDefaultValue())) {
+        if (validationAppliesTo != null && ConstraintTarget.IMPLICIT != validationAppliesTo.getDefaultValue()) {
             throw new ConstraintDefinitionException("validationAppliesTo default value should be IMPLICIT");
         }
 
@@ -257,9 +257,9 @@ final class AnnotationConstraintBuilder<A extends Annotation> {
 
         final Set<Class<? extends Payload>> payloadSet;
         if (payload_raw == null) {
-            payloadSet = Collections.<Class<? extends Payload>> emptySet();
+            payloadSet = Collections.emptySet();
         } else {
-            payloadSet = new HashSet<Class<? extends Payload>>(payload_raw.length);
+            payloadSet = new HashSet<>(payload_raw.length);
             Collections.addAll(payloadSet, payload_raw);
         }
         constraintValidation.setPayload(payloadSet);
@@ -323,18 +323,13 @@ final class AnnotationConstraintBuilder<A extends Annotation> {
      * @return An integer index always >= 0
      */
     private int computeIndex(ConstraintValidation<?> composite) {
-        int idx = 0;
-        for (ConstraintValidation<?> each : constraintValidation.getComposingValidations()) {
-            if (each.getAnnotation().annotationType() == composite.getAnnotation().annotationType()) {
-                idx++;
-            }
-        }
-        return idx;
+        return (int) constraintValidation.getComposingValidations().stream()
+            .filter(v -> v.getAnnotation().annotationType().equals(composite.getAnnotation().annotationType())).count();
     }
 
     /** read overridesAttributes from constraintValidation.annotation */
     private void buildOverridesAttributes() {
-        overrides = new LinkedList<ConstraintOverrides>();
+        overrides = new LinkedList<>();
         for (Method method : constraintValidation.getAnnotation().annotationType().getDeclaredMethods()) {
             final OverridesAttribute.List overridesAttributeList = method.getAnnotation(OverridesAttribute.List.class);
             if (overridesAttributeList != null) {
@@ -359,12 +354,9 @@ final class AnnotationConstraintBuilder<A extends Annotation> {
     }
 
     private ConstraintOverrides findOverride(Class<? extends Annotation> constraint, int constraintIndex) {
-        for (ConstraintOverrides each : overrides) {
-            if (each.constraintType == constraint && each.constraintIndex == constraintIndex) {
-                return each;
-            }
-        }
-        return null;
+        return overrides.stream()
+            .filter(ov -> ov.constraintType.equals(constraint) && ov.constraintIndex == constraintIndex).findFirst()
+            .orElse(null);
     }
 
     /**
@@ -381,7 +373,7 @@ final class AnnotationConstraintBuilder<A extends Annotation> {
         private ConstraintOverrides(Class<? extends Annotation> constraintType, int constraintIndex) {
             this.constraintType = constraintType;
             this.constraintIndex = constraintIndex;
-            values = new HashMap<String, Object>();
+            values = new HashMap<>();
         }
 
         @SuppressWarnings("unchecked")
@@ -392,11 +384,9 @@ final class AnnotationConstraintBuilder<A extends Annotation> {
             // And the annotation
             final Annotation originalAnnot = composite.getAnnotation();
             final AnnotationProxyBuilder<Annotation> apb = new AnnotationProxyBuilder<Annotation>(originalAnnot);
-            for (String key : values.keySet()) {
-                apb.putValue(key, values.get(key));
-            }
-            final Annotation newAnnot = apb.createAnnotation();
-            ((ConstraintValidation<Annotation>) composite).setAnnotation(newAnnot);
+            values.forEach(apb::putValue);
+
+            ((ConstraintValidation<Annotation>) composite).setAnnotation(apb.createAnnotation());
         }
     }
 

http://git-wip-us.apache.org/repos/asf/bval/blob/f87be824/bval-jsr/src/main/java/org/apache/bval/jsr/AnnotationProcessor.java
----------------------------------------------------------------------
diff --git a/bval-jsr/src/main/java/org/apache/bval/jsr/AnnotationProcessor.java b/bval-jsr/src/main/java/org/apache/bval/jsr/AnnotationProcessor.java
index 4bdb331..3c4b046 100644
--- a/bval-jsr/src/main/java/org/apache/bval/jsr/AnnotationProcessor.java
+++ b/bval-jsr/src/main/java/org/apache/bval/jsr/AnnotationProcessor.java
@@ -38,7 +38,9 @@ import java.lang.annotation.Annotation;
 import java.lang.reflect.AnnotatedElement;
 import java.lang.reflect.InvocationTargetException;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collection;
+import java.util.List;
 import java.util.Set;
 
 /**
@@ -121,7 +123,7 @@ public final class AnnotationProcessor {
             if (!reflection) {
                 Collection<Annotation> annotations = prop.getFeature(JsrFeatures.Property.ANNOTATIONS_TO_PROCESS);
                 if (annotations == null) {
-                    annotations = new ArrayList<Annotation>();
+                    annotations = new ArrayList<>();
                     prop.putFeature(JsrFeatures.Property.ANNOTATIONS_TO_PROCESS, annotations);
                 }
                 annotations.add(annotation);
@@ -129,18 +131,19 @@ public final class AnnotationProcessor {
             return true;
         }
 
-        /**
+        /*
          * An annotation is considered a constraint definition if its retention
          * policy contains RUNTIME and if the annotation itself is annotated
          * with javax.validation.Constraint.
          */
         final Constraint vcAnno = annotation.annotationType().getAnnotation(Constraint.class);
         if (vcAnno != null) {
-            Class<? extends ConstraintValidator<A, ?>>[] validatorClasses;
-            validatorClasses = findConstraintValidatorClasses(annotation, vcAnno);
+            Class<? extends ConstraintValidator<A, ?>>[] validatorClasses =
+                findConstraintValidatorClasses(annotation, vcAnno);
             return applyConstraint(annotation, validatorClasses, prop, owner, access, appender);
         }
-        /**
+
+        /*
          * Multi-valued constraints: To support this requirement, the bean
          * validation provider treats regular annotations (annotations not
          * annotated by @Constraint) whose value element has a return type of an
@@ -202,15 +205,14 @@ public final class AnnotationProcessor {
             vcAnno = annotation.annotationType().getAnnotation(Constraint.class);
         }
         final Class<A> annotationType = (Class<A>) annotation.annotationType();
-        Class<? extends ConstraintValidator<A, ?>>[] validatorClasses =
-            factory.getConstraintsCache().getConstraintValidators(annotationType);
+        List<Class<? extends ConstraintValidator<A, ?>>> validatorClasses =
+            factory.getConstraintsCache().getConstraintValidatorClasses(annotationType);
         if (validatorClasses == null) {
-            validatorClasses = (Class<? extends ConstraintValidator<A, ?>>[]) vcAnno.validatedBy();
-            if (validatorClasses.length == 0) {
-                validatorClasses = factory.getDefaultConstraints().getValidatorClasses(annotationType);
+            validatorClasses = Arrays.asList((Class<? extends ConstraintValidator<A, ?>>[]) vcAnno.validatedBy());
+            if (validatorClasses.isEmpty()) {
             }
         }
-        return validatorClasses;
+        return validatorClasses.toArray(new Class[validatorClasses.size()]);
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/bval/blob/f87be824/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintAnnotationAttributes.java
----------------------------------------------------------------------
diff --git a/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintAnnotationAttributes.java b/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintAnnotationAttributes.java
index 24b38ea..df99bf9 100644
--- a/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintAnnotationAttributes.java
+++ b/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintAnnotationAttributes.java
@@ -16,6 +16,7 @@
  */
 package org.apache.bval.jsr;
 
+import org.apache.bval.util.Exceptions;
 import org.apache.bval.util.reflection.Reflection;
 import org.apache.bval.util.reflection.TypeUtils;
 import org.apache.commons.weaver.privilizer.Privilizing;
@@ -125,29 +126,24 @@ public enum ConstraintAnnotationAttributes {
     public <V> V get(Map<? super String, ? super V> map) {
         @SuppressWarnings("unchecked")
         final V result = (V) map.get(getAttributeName());
-        if (TypeUtils.isInstance(result, getType())) {
-            return result;
-        }
-        throw new IllegalStateException(String.format("Invalid '%s' value: %s", getAttributeName(), result));
+        Exceptions.raiseUnless(TypeUtils.isInstance(result, getType()), IllegalStateException::new,
+            "Invalid '%s' value: %s", getAttributeName(), result);
+        return result;
     }
 
     public <C extends Annotation> Worker<C> analyze(final Class<C> clazz) {
         if (clazz.getName().startsWith("javax.validation.constraint.")) { // cache only APIs classes to avoid memory leaks
             @SuppressWarnings("unchecked")
-            Worker<C> w = Worker.class.cast(WORKER_CACHE.get(clazz));
-            if (w == null) {
-                w = new Worker<C>(clazz);
-                WORKER_CACHE.putIfAbsent(clazz, w);
-                return w;
-            }
+            final Worker<C> w = (Worker<C>) WORKER_CACHE.computeIfAbsent(clazz, Worker::new);
+            return w;
         }
         return new Worker<C>(clazz);
     }
 
     // this is static but related to Worker
-    private static final ConcurrentMap<Class<?>, Worker<?>> WORKER_CACHE = new ConcurrentHashMap<Class<?>, Worker<?>>();
+    private static final ConcurrentMap<Class<?>, Worker<?>> WORKER_CACHE = new ConcurrentHashMap<>();
     private static final ConcurrentMap<Class<?>, ConcurrentMap<String, Method>> METHOD_BY_NAME_AND_CLASS =
-        new ConcurrentHashMap<Class<?>, ConcurrentMap<String, Method>>();
+        new ConcurrentHashMap<>();
     private static final Method NULL_METHOD;
     static {
         try {
@@ -171,14 +167,8 @@ public enum ConstraintAnnotationAttributes {
         }
 
         private Method findMethod(final Class<C> constraintType, final String attributeName) {
-            ConcurrentMap<String, Method> cache = METHOD_BY_NAME_AND_CLASS.get(constraintType);
-            if (cache == null) {
-                cache = new ConcurrentHashMap<String, Method>();
-                final ConcurrentMap<String, Method> old = METHOD_BY_NAME_AND_CLASS.putIfAbsent(constraintType, cache);
-                if (old != null) {
-                    cache = old;
-                }
-            }
+            ConcurrentMap<String, Method> cache =
+                METHOD_BY_NAME_AND_CLASS.computeIfAbsent(constraintType, t -> new ConcurrentHashMap<>());
 
             final Method found = cache.get(attributeName);
             if (found != null) {
@@ -189,15 +179,19 @@ public enum ConstraintAnnotationAttributes {
                 cache.putIfAbsent(attributeName, NULL_METHOD);
                 return null;
             }
-            final Method oldMtd = cache.putIfAbsent(attributeName, m);
-            if (oldMtd != null) {
-                return oldMtd;
-            }
-            return m;
+            return cache.computeIfAbsent(attributeName, s -> m);
         }
 
         public boolean isValid() {
-            return method != null && method != NULL_METHOD;
+            return method != null && method != NULL_METHOD && TypeUtils.isAssignable(method.getReturnType(), type);
+        }
+
+        /**
+         * @since 2.0
+         * @return {@link Type}
+         */
+        public Type getSpecificType() {
+            return isValid() ? method.getGenericReturnType() : type;
         }
 
         public <T> T read(final Annotation constraint) {

http://git-wip-us.apache.org/repos/asf/bval/blob/f87be824/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintCached.java
----------------------------------------------------------------------
diff --git a/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintCached.java b/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintCached.java
index 1bb012f..a1f3924 100644
--- a/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintCached.java
+++ b/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintCached.java
@@ -18,18 +18,92 @@
  */
 package org.apache.bval.jsr;
 
-import javax.validation.ConstraintValidator;
 import java.lang.annotation.Annotation;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.EnumSet;
 import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
 import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import javax.validation.ConstraintValidator;
+import javax.validation.constraintvalidation.SupportedValidationTarget;
+import javax.validation.constraintvalidation.ValidationTarget;
+
+import org.apache.bval.jsr.metadata.AnnotationDeclaredValidatorMappingProvider;
+import org.apache.bval.jsr.metadata.CompositeValidatorMappingProvider;
+import org.apache.bval.jsr.metadata.DualValidationMappingProvider;
+import org.apache.bval.jsr.metadata.ValidatorMappingProvider;
+import org.apache.bval.jsr.util.ToUnmodifiable;
+import org.apache.bval.util.Lazy;
+import org.apache.bval.util.ObjectUtils;
+import org.apache.bval.util.Validate;
 
 /**
- * Description: hold the relationship annotation->validatedBy[] ConstraintValidator classes that are already parsed in a
- * cache.<br/>
+ * 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<?, ?>>[]>();
+
+    /**
+     * Describes a {@link ConstraintValidator} implementation type.
+     * 
+     * @since 2.0
+     */
+    public static final class ConstraintValidatorInfo<T extends Annotation> {
+        private static final Set<ValidationTarget> DEFAULT_VALIDATION_TARGETS =
+            Collections.singleton(ValidationTarget.ANNOTATED_ELEMENT);
+
+        private final Class<? extends ConstraintValidator<T, ?>> type;
+        private Set<ValidationTarget> supportedTargets;
+
+        ConstraintValidatorInfo(Class<? extends ConstraintValidator<T, ?>> type) {
+            super();
+            this.type = Validate.notNull(type);
+            final SupportedValidationTarget svt = type.getAnnotation(SupportedValidationTarget.class);
+
+            supportedTargets = svt == null ? DEFAULT_VALIDATION_TARGETS
+                : Collections.unmodifiableSet(EnumSet.copyOf(Arrays.asList(svt.value())));
+        }
+
+        public Class<? extends ConstraintValidator<T, ?>> getType() {
+            return type;
+        }
+
+        public Set<ValidationTarget> getSupportedTargets() {
+            return supportedTargets;
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            return obj == this
+                || obj instanceof ConstraintValidatorInfo<?> && ((ConstraintValidatorInfo<?>) obj).type.equals(type);
+        }
+
+        @Override
+        public int hashCode() {
+            return Objects.hash(type);
+        }
+    }
+
+    private final Map<Class<? extends Annotation>, Set<ConstraintValidatorInfo<?>>> constraintValidatorInfo =
+        new HashMap<>();
+
+    private final List<ValidatorMappingProvider> customValidatorMappingProviders = new ArrayList<>();
+    private final Lazy<ValidatorMappingProvider> validatorMappingProvider =
+        new Lazy<>(this::createValidatorMappingProvider);
+
+    public void add(ValidatorMappingProvider validatorMappingProvider) {
+        if (customValidatorMappingProviders.add(validatorMappingProvider)) {
+            this.validatorMappingProvider.reset(this::createValidatorMappingProvider);
+        }
+    }
 
     /**
      * Record the set of validator classes for a given constraint annotation.
@@ -37,33 +111,80 @@ public class ConstraintCached {
      * @param annotationClass
      * @param definitionClasses
      */
+    @Deprecated
     public <A extends Annotation> void putConstraintValidator(Class<A> annotationClass,
         Class<? extends ConstraintValidator<A, ?>>[] definitionClasses) {
-        classes.put(annotationClass, definitionClasses);
+        if (ObjectUtils.isEmpty(definitionClasses)) {
+            return;
+        }
+        Validate.notNull(annotationClass, "annotationClass");
+        Stream.of(definitionClasses).map(t -> new ConstraintValidatorInfo<>(t))
+            .forEach(constraintValidatorInfo.computeIfAbsent(annotationClass, k -> new HashSet<>())::add);
     }
 
     /**
-     * Learn whether we have cached the validator classes for the requested constraint annotation.
+     * Learn whether we have cached the validator classes for the requested
+     * constraint annotation.
      * 
      * @param annotationClass
      *            to look up
      * @return boolean
      */
+    @Deprecated
     public boolean containsConstraintValidator(Class<? extends Annotation> annotationClass) {
-        return classes.containsKey(annotationClass);
+        return constraintValidatorInfo.containsKey(annotationClass);
     }
 
     /**
      * Get the cached validator classes for the requested constraint annotation.
      * 
-     * @param annotationClass
+     * @param constraintType
      *            to look up
      * @return array of {@link ConstraintValidator} implementation types
      */
     @SuppressWarnings("unchecked")
+    @Deprecated
     public <A extends Annotation> Class<? extends ConstraintValidator<A, ?>>[] getConstraintValidators(
-        Class<A> annotationClass) {
-        return (Class<? extends ConstraintValidator<A, ?>>[]) classes.get(annotationClass);
+        Class<A> constraintType) {
+        final Set<ConstraintValidatorInfo<A>> infos = infos(constraintType);
+        return infos == null ? new Class[0]
+            : infos.stream().map(ConstraintValidatorInfo::getType).toArray(Class[]::new);
     }
 
+    public <A extends Annotation> List<Class<? extends ConstraintValidator<A, ?>>> getConstraintValidatorClasses(
+        Class<A> constraintType) {
+        final Set<ConstraintValidatorInfo<A>> infos = infos(constraintType);
+        return infos == null ? Collections.emptyList()
+            : infos.stream().map(ConstraintValidatorInfo::getType).collect(ToUnmodifiable.list());
+    }
+
+    public <A extends Annotation> Set<ConstraintValidatorInfo<A>> getConstraintValidatorInfo(Class<A> constraintType) {
+        return Collections.unmodifiableSet(infos(constraintType));
+    }
+
+    @SuppressWarnings({ "unchecked", "rawtypes" })
+    private <A extends Annotation> Set<ConstraintValidatorInfo<A>> infos(Class<A> constraintType) {
+        return (Set) constraintValidatorInfo.computeIfAbsent(constraintType,
+            c -> validatorMappingProvider.get().getValidatorMapping(c).getValidatorTypes().stream()
+                .map(ConstraintValidatorInfo::new).collect(Collectors.toSet()));
+    }
+
+    private ValidatorMappingProvider createValidatorMappingProvider() {
+        final ValidatorMappingProvider configured;
+        if (customValidatorMappingProviders.isEmpty()) {
+            configured = AnnotationDeclaredValidatorMappingProvider.INSTANCE;
+        } else {
+            final ValidatorMappingProvider custom;
+            if (customValidatorMappingProviders.size() == 1) {
+                custom = customValidatorMappingProviders.get(0);
+            } else {
+                custom = new CompositeValidatorMappingProvider(customValidatorMappingProviders);
+            }
+            configured = new DualValidationMappingProvider(AnnotationDeclaredValidatorMappingProvider.INSTANCE, custom);
+        }
+        // interpret spec as saying that default constraint validators are
+        // always present even when annotation-based validators
+        // have been excluded by custom (i.e. XML) config:
+        return new DualValidationMappingProvider(configured, ConstraintDefaults.INSTANCE);
+    }
 }

http://git-wip-us.apache.org/repos/asf/bval/blob/f87be824/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..9ea93e7 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
@@ -21,101 +21,70 @@ package org.apache.bval.jsr;
 import java.io.IOException;
 import java.io.InputStream;
 import java.lang.annotation.Annotation;
-import java.util.HashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
 import java.util.Properties;
 import java.util.logging.Level;
 import java.util.logging.Logger;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
 
 import javax.validation.ConstraintValidator;
 
+import org.apache.bval.jsr.metadata.ClassLoadingValidatorMappingProvider;
+import org.apache.bval.jsr.metadata.ValidatorMapping;
 import org.apache.bval.util.StringUtils;
 import org.apache.bval.util.reflection.Reflection;
 import org.apache.commons.weaver.privilizer.Privilizing;
 import org.apache.commons.weaver.privilizer.Privilizing.CallTo;
 
 /**
- * Description: Provides access to the default constraints/validator implementation classes built into the framework.
- * These are configured in DefaultConstraints.properties.<br/>
+ * Description: Provides access to the default constraints/validator
+ * implementation classes built into the framework. These are configured in
+ * DefaultConstraints.properties.<br/>
  */
 @Privilizing(@CallTo(Reflection.class))
-public class ConstraintDefaults {
+public class ConstraintDefaults extends ClassLoadingValidatorMappingProvider {
+    public static final ConstraintDefaults INSTANCE = new 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.
-     */
-    private Map<String, Class<? extends ConstraintValidator<?, ?>>[]> defaultConstraints;
+    private final Properties properties;
 
     /**
      * 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());
+    private ConstraintDefaults() {
+        this.properties = loadProperties(DEFAULT_CONSTRAINTS);
     }
 
-    @SuppressWarnings("unchecked")
-    private Map<String, Class<? extends ConstraintValidator<?, ?>>[]> loadDefaultConstraints(String resource) {
-        final Properties constraintProperties = new Properties();
+    private Properties loadProperties(String resource) {
+        final Properties result = 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 {
-                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
-                }
+        try (final InputStream stream = classloader.getResourceAsStream(resource)) {
+            if (stream == null) {
+                log.log(Level.WARNING, String.format("Cannot find %s", resource));
+            } else {
+                result.load(stream);
             }
+        } catch (IOException e) {
+            log.log(Level.SEVERE, String.format("Cannot load %s", resource), e);
         }
+        return result;
+    }
 
-        final Map<String, Class<? extends ConstraintValidator<?, ?>>[]> loadedConstraints =
-            new HashMap<String, Class<? extends ConstraintValidator<?, ?>>[]>();
+    @SuppressWarnings({ "unchecked", "rawtypes" })
+    @Override
+    public <A extends Annotation> ValidatorMapping<A> doGetValidatorMapping(Class<A> constraintType) {
 
-        for (final Map.Entry<Object, Object> entry : constraintProperties.entrySet()) {
-            final List<Class<?>> classes = new LinkedList<Class<?>>();
-            for (String className : StringUtils.split((String) entry.getValue(), ',')) {
-                try {
-                    classes.add(Reflection.toClass(className.trim(), classloader));
-                } catch (Exception e) {
-                    log.log(Level.SEVERE, String.format("Cannot find class %s", className), e);
-                }
-            }
-            loadedConstraints.put((String) entry.getKey(), classes.toArray(new Class[classes.size()]));
-        }
-        return loadedConstraints;
-    }
+        final String validators = properties.getProperty(constraintType.getName());
 
-    private ClassLoader getClassLoader() {
-        final ClassLoader classloader = Thread.currentThread().getContextClassLoader();
-        return classloader == null ? getClass().getClassLoader() : classloader;
+        if (StringUtils.isBlank(validators)) {
+            return null;
+        }
+        return new ValidatorMapping<>("built-in",
+            load(Stream.of(StringUtils.split(validators, ',')).map(String::trim),
+                (Class<ConstraintValidator<A, ?>>) (Class) ConstraintValidator.class,
+                e -> log.log(Level.SEVERE, "exception loading default constraint validators", e))
+                    .collect(Collectors.toList()));
     }
 }

http://git-wip-us.apache.org/repos/asf/bval/blob/f87be824/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/f87be824/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/f87be824/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/f87be824/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintValidatorIdentity.java
----------------------------------------------------------------------
diff --git a/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintValidatorIdentity.java b/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintValidatorIdentity.java
index 1092323..572c39a 100644
--- a/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintValidatorIdentity.java
+++ b/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintValidatorIdentity.java
@@ -19,6 +19,8 @@
 
 package org.apache.bval.jsr;
 
+import java.util.Objects;
+
 import javax.validation.ConstraintValidator;
 import javax.validation.Path;
 
@@ -120,12 +122,7 @@ final class ConstraintValidatorIdentity {
      */
     @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;
+        return Objects.hash(bean, path, constraintValidator);
     }
 
 }

http://git-wip-us.apache.org/repos/asf/bval/blob/f87be824/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..91ae20d 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,20 @@ import javax.validation.ConstraintViolation;
 import javax.validation.Path;
 import javax.validation.ValidationException;
 import javax.validation.metadata.ConstraintDescriptor;
+
+import org.apache.bval.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
+ * 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;
 
@@ -49,8 +54,11 @@ class ConstraintViolationImpl<T> implements ConstraintViolation<T>, Serializable
 
     /**
      * Create a new ConstraintViolationImpl instance.
-     * @param messageTemplate - message reason (raw message)
-     * @param message - interpolated message (locale specific)
+     * 
+     * @param messageTemplate
+     *            - message reason (raw message)
+     * @param message
+     *            - interpolated message (locale specific)
      * @param rootBean
      * @param leafBean
      * @param propertyPath
@@ -79,8 +87,8 @@ class ConstraintViolationImpl<T> implements ConstraintViolation<T>, Serializable
     }
 
     /**
-     * {@inheritDoc}
-     * former name getInterpolatedMessage()
+     * {@inheritDoc} former name getInterpolatedMessage()
+     * 
      * @return The interpolated error message for this constraint violation.
      */
     @Override
@@ -98,6 +106,7 @@ class ConstraintViolationImpl<T> implements ConstraintViolation<T>, Serializable
 
     /**
      * {@inheritDoc}
+     * 
      * @return Root bean being validated
      */
     @Override
@@ -133,6 +142,7 @@ class ConstraintViolationImpl<T> implements ConstraintViolation<T>, Serializable
 
     /**
      * {@inheritDoc}
+     * 
      * @return The value failing to pass the constraint
      */
     @Override
@@ -142,8 +152,9 @@ class ConstraintViolationImpl<T> implements ConstraintViolation<T>, Serializable
 
     /**
      * {@inheritDoc}
-     * @return the property path to the value from <code>rootBean</code>
-     *         Null if the value is the rootBean itself
+     * 
+     * @return the property path to the value from <code>rootBean</code> Null if
+     *         the value is the rootBean itself
      */
     @Override
     public Path getPropertyPath() {
@@ -160,10 +171,8 @@ class ConstraintViolationImpl<T> implements ConstraintViolation<T>, Serializable
 
     @Override
     public <U> U unwrap(Class<U> type) {
-        if (type.isInstance(this)) {
-            return type.cast(this);
-        }
-        throw new ValidationException("Type " + type + " is not supported");
+        Exceptions.raiseUnless(type.isInstance(this), ValidationException::new, "Type %s is not supported", type);
+        return type.cast(this);
     }
 
     /**
@@ -171,45 +180,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 +209,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/f87be824/bval-jsr/src/main/java/org/apache/bval/jsr/DefaultConstraintValidatorFactory.java
----------------------------------------------------------------------
diff --git a/bval-jsr/src/main/java/org/apache/bval/jsr/DefaultConstraintValidatorFactory.java b/bval-jsr/src/main/java/org/apache/bval/jsr/DefaultConstraintValidatorFactory.java
index 4aca48a..9474705 100644
--- a/bval-jsr/src/main/java/org/apache/bval/jsr/DefaultConstraintValidatorFactory.java
+++ b/bval-jsr/src/main/java/org/apache/bval/jsr/DefaultConstraintValidatorFactory.java
@@ -32,8 +32,7 @@ import java.util.concurrent.CopyOnWriteArrayList;
  * Description: create constraint instances with the default / no-arg constructor <br/>
  */
 public class DefaultConstraintValidatorFactory implements ConstraintValidatorFactory, Closeable {
-    private final Collection<BValExtension.Releasable<?>> releasables =
-        new CopyOnWriteArrayList<BValExtension.Releasable<?>>();
+    private final Collection<BValExtension.Releasable<?>> releasables = new CopyOnWriteArrayList<>();
     private volatile Boolean useCdi = null; // store it to avoid NoClassDefFoundError when cdi is not present (it is slow) + lazily (to wait cdi is started)
 
     /**
@@ -49,9 +48,7 @@ public class DefaultConstraintValidatorFactory implements ConstraintValidatorFac
                 if (useCdi == null) {
                     try {
                         useCdi = BValExtension.getBeanManager() != null;
-                    } catch (final NoClassDefFoundError error) {
-                        useCdi = Boolean.FALSE;
-                    } catch (final Exception e) {
+                    } catch (NoClassDefFoundError | Exception error) {
                         useCdi = Boolean.FALSE;
                     }
                 }
@@ -69,10 +66,7 @@ public class DefaultConstraintValidatorFactory implements ConstraintValidatorFac
                         return instance.getInstance();
                     }
                     throw new IllegalStateException("Can't create " + constraintClass.getName());
-                } catch (final Exception e) {
-                    return constraintClass.newInstance();
-                } catch (final NoClassDefFoundError error) {
-                    return constraintClass.newInstance();
+                } catch (Exception | NoClassDefFoundError e) {
                 }
             }
             return constraintClass.newInstance();

http://git-wip-us.apache.org/repos/asf/bval/blob/f87be824/bval-jsr/src/main/java/org/apache/bval/jsr/DefaultMessageInterpolator.java
----------------------------------------------------------------------
diff --git a/bval-jsr/src/main/java/org/apache/bval/jsr/DefaultMessageInterpolator.java b/bval-jsr/src/main/java/org/apache/bval/jsr/DefaultMessageInterpolator.java
index 8c77162..6a85a2a 100644
--- a/bval-jsr/src/main/java/org/apache/bval/jsr/DefaultMessageInterpolator.java
+++ b/bval-jsr/src/main/java/org/apache/bval/jsr/DefaultMessageInterpolator.java
@@ -54,10 +54,10 @@ public class DefaultMessageInterpolator implements MessageInterpolator {
     private Locale defaultLocale;
 
     /** User specified resource bundles hashed against their locale. */
-    private final Map<Locale, ResourceBundle> userBundlesMap = new ConcurrentHashMap<Locale, ResourceBundle>();
+    private final Map<Locale, ResourceBundle> userBundlesMap = new ConcurrentHashMap<>();
 
     /** Builtin resource bundles hashed against their locale. */
-    private final Map<Locale, ResourceBundle> defaultBundlesMap = new ConcurrentHashMap<Locale, ResourceBundle>();
+    private final Map<Locale, ResourceBundle> defaultBundlesMap = new ConcurrentHashMap<>();
 
     private final MessageEvaluator evaluator;
 
@@ -83,12 +83,12 @@ public class DefaultMessageInterpolator implements MessageInterpolator {
             userBundlesMap.put(defaultLocale, resourceBundle);
         }
 
-        MessageEvaluator ev = null;
+        MessageEvaluator ev;
         try {
             ev = MessageEvaluator.class
                 .cast(getClass().getClassLoader().loadClass("org.apache.bval.el.ELFacade").newInstance());
         } catch (final Throwable e) { // can be exception or error
-            // no-op
+            ev = null;
         }
         evaluator = ev;
     }
@@ -170,47 +170,42 @@ public class DefaultMessageInterpolator implements MessageInterpolator {
      * @return the resource bundle or <code>null</code> if none is found.
      */
     private ResourceBundle getFileBasedResourceBundle(Locale locale) {
-        ResourceBundle rb = null;
+        ResourceBundle rb;
         final ClassLoader classLoader = Reflection.getClassLoader(DefaultMessageInterpolator.class);
         if (classLoader != null) {
             rb = loadBundle(classLoader, locale, USER_VALIDATION_MESSAGES + " not found by thread local classloader");
-        }
-
+        } else {
         // 2011-03-27 jw: No privileged action required.
         // A class can always access the classloader of itself and of subclasses.
-        if (rb == null) {
             rb = loadBundle(getClass().getClassLoader(), locale,
                 USER_VALIDATION_MESSAGES + " not found by validator classloader");
         }
         if (LOG_FINEST) {
-            if (rb != null) {
-                log.log(Level.FINEST, String.format("%s found", USER_VALIDATION_MESSAGES));
-            } else {
+            if (rb == null) {
                 log.log(Level.FINEST, String.format("%s not found. Delegating to %s", USER_VALIDATION_MESSAGES,
                     DEFAULT_VALIDATION_MESSAGES));
+            } else {
+                log.log(Level.FINEST, String.format("%s found", USER_VALIDATION_MESSAGES));
             }
         }
         return rb;
     }
 
     private ResourceBundle loadBundle(ClassLoader classLoader, Locale locale, String message) {
-        ResourceBundle rb = null;
         try {
-            rb = ResourceBundle.getBundle(USER_VALIDATION_MESSAGES, locale, classLoader);
+            return ResourceBundle.getBundle(USER_VALIDATION_MESSAGES, locale, classLoader);
         } catch (final MissingResourceException e) {
             log.fine(message);
         }
-        return rb;
+        return null;
     }
 
     private String replaceVariables(String message, ResourceBundle bundle, Locale locale, boolean recurse) {
         final Matcher matcher = messageParameterPattern.matcher(message);
         final StringBuffer sb = new StringBuffer(64);
-        String resolvedParameterValue;
         while (matcher.find()) {
             final String parameter = matcher.group(1);
-            resolvedParameterValue = resolveParameter(parameter, bundle, locale, recurse);
-
+            String resolvedParameterValue = resolveParameter(parameter, bundle, locale, recurse);
             matcher.appendReplacement(sb, sanitizeForAppendReplacement(resolvedParameterValue));
         }
         matcher.appendTail(sb);
@@ -242,13 +237,13 @@ public class DefaultMessageInterpolator implements MessageInterpolator {
     private String resolveParameter(String parameterName, ResourceBundle bundle, Locale locale, boolean recurse) {
         String parameterValue;
         try {
-            if (bundle != null) {
+            if (bundle == null) {
+                parameterValue = parameterName;
+            } else {
                 parameterValue = bundle.getString(removeCurlyBrace(parameterName));
                 if (recurse) {
                     parameterValue = replaceVariables(parameterValue, bundle, locale, recurse);
                 }
-            } else {
-                parameterValue = parameterName;
             }
         } catch (final MissingResourceException e) {
             // return parameter itself

http://git-wip-us.apache.org/repos/asf/bval/blob/f87be824/bval-jsr/src/main/java/org/apache/bval/jsr/DefaultValidationProviderResolver.java
----------------------------------------------------------------------
diff --git a/bval-jsr/src/main/java/org/apache/bval/jsr/DefaultValidationProviderResolver.java b/bval-jsr/src/main/java/org/apache/bval/jsr/DefaultValidationProviderResolver.java
index 671b0d9..e63bdf4 100644
--- a/bval-jsr/src/main/java/org/apache/bval/jsr/DefaultValidationProviderResolver.java
+++ b/bval-jsr/src/main/java/org/apache/bval/jsr/DefaultValidationProviderResolver.java
@@ -38,6 +38,11 @@ public class DefaultValidationProviderResolver implements ValidationProviderReso
     //TODO - Spec recommends caching per classloader
     private static final String SPI_CFG = "META-INF/services/javax.validation.spi.ValidationProvider";
 
+    private static ClassLoader getCurrentClassLoader() {
+        ClassLoader cl = Thread.currentThread().getContextClassLoader();
+        return cl == null ? DefaultValidationProviderResolver.class.getClassLoader() : cl;
+    }
+
     /**
      * {@inheritDoc}
      */
@@ -46,43 +51,28 @@ public class DefaultValidationProviderResolver implements ValidationProviderReso
         List<ValidationProvider<?>> providers = new ArrayList<ValidationProvider<?>>();
         try {
             // get our classloader
-            ClassLoader cl = Thread.currentThread().getContextClassLoader();
-            if (cl == null)
-                cl = DefaultValidationProviderResolver.class.getClassLoader();
+            ClassLoader cl = getCurrentClassLoader();
             // find all service provider cfgs
             Enumeration<URL> cfgs = cl.getResources(SPI_CFG);
             while (cfgs.hasMoreElements()) {
                 final URL url = cfgs.nextElement();
-                BufferedReader br = null;
-                try {
-                    br = new BufferedReader(new InputStreamReader(url.openStream()), 256);
-                    String line = br.readLine();
-                    // cfgs may contain multiple providers and/or comments
-                    while (line != null) {
-                        line = line.trim();
-                        if (!line.startsWith("#")) {
-                            try {
-                                // try loading the specified class
-                                @SuppressWarnings("rawtypes")
-                                final Class<? extends ValidationProvider> providerType =
-                                    cl.loadClass(line).asSubclass(ValidationProvider.class);
-                                // create an instance to return
-                                providers
-                                    .add(Reflection.newInstance(providerType.asSubclass(ValidationProvider.class)));
-
-                            } catch (ClassNotFoundException e) {
-                                throw new ValidationException(
-                                    "Failed to load provider " + line + " configured in file " + url, e);
-                            }
+                try (BufferedReader br = new BufferedReader(new InputStreamReader(url.openStream()), 256)) {
+                    br.lines().filter(s -> s.charAt(0) != '#').map(String::trim).forEach(line -> {
+                        // cfgs may contain multiple providers and/or comments
+                        try {
+                            // try loading the specified class
+                            @SuppressWarnings("rawtypes")
+                            final Class<? extends ValidationProvider> providerType =
+                                cl.loadClass(line).asSubclass(ValidationProvider.class);
+                            // create an instance to return
+                            providers.add(Reflection.newInstance(providerType));
+                        } catch (ClassNotFoundException e) {
+                            throw new ValidationException(
+                                "Failed to load provider " + line + " configured in file " + url, e);
                         }
-                        line = br.readLine();
-                    }
+                    });
                 } catch (IOException e) {
                     throw new ValidationException("Error trying to read " + url, e);
-                } finally {
-                    if (br != null) {
-                        br.close();
-                    }
                 }
             }
         } catch (IOException e) {

http://git-wip-us.apache.org/repos/asf/bval/blob/f87be824/bval-jsr/src/main/java/org/apache/bval/jsr/GraphBeanIdentity.java
----------------------------------------------------------------------
diff --git a/bval-jsr/src/main/java/org/apache/bval/jsr/GraphBeanIdentity.java b/bval-jsr/src/main/java/org/apache/bval/jsr/GraphBeanIdentity.java
index 3ec666e..26391e6 100644
--- a/bval-jsr/src/main/java/org/apache/bval/jsr/GraphBeanIdentity.java
+++ b/bval-jsr/src/main/java/org/apache/bval/jsr/GraphBeanIdentity.java
@@ -18,6 +18,8 @@
  */
 package org.apache.bval.jsr;
 
+import java.util.Objects;
+
 /**
  * Class that stores the needed properties to avoid circular paths when
  * validating an object graph.
@@ -80,32 +82,16 @@ public class GraphBeanIdentity {
      */
     @Override
     public boolean equals(Object obj) {
-
         if (this == obj) {
             return true;
         }
-
-        if (obj == null) {
-            return false;
-        }
-
         if (!(obj instanceof GraphBeanIdentity)) {
             return false;
         }
-
         GraphBeanIdentity other = (GraphBeanIdentity) obj;
 
-        // Bean ref must be the same
-        if (this.bean != other.bean) {
-            return false;
-        }
-
-        // Group ref must be the same
-        if (this.group != other.group) {
-            return false;
-        }
-
-        return true;
+        // Bean ref must be the same; Group ref must be the same
+        return bean == other.bean && group == other.group;
     }
 
     /**
@@ -113,11 +99,7 @@ public class GraphBeanIdentity {
      */
     @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.group == null) ? 0 : this.group.hashCode());
-        return result;
+        return Objects.hash(bean, group);
     }
 
 }

http://git-wip-us.apache.org/repos/asf/bval/blob/f87be824/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/f87be824/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/f87be824/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/f87be824/bval-jsr/src/main/java/org/apache/bval/jsr/groups/Group.java
----------------------------------------------------------------------
diff --git a/bval-jsr/src/main/java/org/apache/bval/jsr/groups/Group.java b/bval-jsr/src/main/java/org/apache/bval/jsr/groups/Group.java
index 4f9d10a..6a211ed 100644
--- a/bval-jsr/src/main/java/org/apache/bval/jsr/groups/Group.java
+++ b/bval-jsr/src/main/java/org/apache/bval/jsr/groups/Group.java
@@ -18,6 +18,8 @@
  */
 package org.apache.bval.jsr.groups;
 
+import java.util.Objects;
+
 import javax.validation.groups.Default;
 
 /**
@@ -52,7 +54,7 @@ public final class Group {
      */
     @Override
     public String toString() {
-        return "Group{" + "group=" + group + '}';
+        return String.format("%s{group=%s}", Group.class.getSimpleName(), group);
     }
 
     /**
@@ -71,13 +73,10 @@ public final class Group {
         if (this == o) {
             return true;
         }
-        if (o == null || getClass() != o.getClass()) {
+        if (o == null || !getClass().equals(o.getClass())) {
             return false;
         }
-
-        Group group1 = (Group) o;
-
-        return group != null ? group.equals(group1.group) : group1.group == null;
+        return Objects.equals(group, ((Group) o).group);
     }
 
     /**
@@ -85,6 +84,6 @@ public final class Group {
      */
     @Override
     public int hashCode() {
-        return (group != null ? group.hashCode() : 0);
+        return Objects.hashCode(group);
     }
 }

http://git-wip-us.apache.org/repos/asf/bval/blob/f87be824/bval-jsr/src/main/java/org/apache/bval/jsr/groups/GroupConversionDescriptorImpl.java
----------------------------------------------------------------------
diff --git a/bval-jsr/src/main/java/org/apache/bval/jsr/groups/GroupConversionDescriptorImpl.java b/bval-jsr/src/main/java/org/apache/bval/jsr/groups/GroupConversionDescriptorImpl.java
index ba3a617..6d45ced 100644
--- a/bval-jsr/src/main/java/org/apache/bval/jsr/groups/GroupConversionDescriptorImpl.java
+++ b/bval-jsr/src/main/java/org/apache/bval/jsr/groups/GroupConversionDescriptorImpl.java
@@ -26,10 +26,9 @@ public class GroupConversionDescriptorImpl implements GroupConversionDescriptor
 
     public GroupConversionDescriptorImpl(final Group from, final Group to) {
         this.from = from.getGroup();
-        if (this.from.getAnnotation(GroupSequence.class) != null) {
+        if (this.from.isAnnotationPresent(GroupSequence.class)) {
             throw new ConstraintDeclarationException("from() can't get a group sequence");
         }
-
         this.to = to.getGroup();
     }
 

http://git-wip-us.apache.org/repos/asf/bval/blob/f87be824/bval-jsr/src/main/java/org/apache/bval/jsr/groups/Groups.java
----------------------------------------------------------------------
diff --git a/bval-jsr/src/main/java/org/apache/bval/jsr/groups/Groups.java b/bval-jsr/src/main/java/org/apache/bval/jsr/groups/Groups.java
index 162bb66..3e7f008 100644
--- a/bval-jsr/src/main/java/org/apache/bval/jsr/groups/Groups.java
+++ b/bval-jsr/src/main/java/org/apache/bval/jsr/groups/Groups.java
@@ -18,25 +18,29 @@
  */
 package org.apache.bval.jsr.groups;
 
-import javax.validation.GroupDefinitionException;
-import java.util.LinkedList;
+import java.util.ArrayList;
 import java.util.List;
 
+import javax.validation.GroupDefinitionException;
+
+import org.apache.bval.util.Exceptions;
+
 /**
- * Defines the order to validate groups during validation.
- * with some inspiration from reference implementation
+ * Defines the order to validate groups during validation. with some inspiration
+ * from reference implementation
  *
  * @author Roman Stumm
  */
 public class Groups {
-    /** The list of single groups. */
-    final List<Group> groups = new LinkedList<Group>();
-
     /** The list of sequences. */
-    final List<List<Group>> sequences = new LinkedList<List<Group>>();
+    private final List<List<Group>> sequences = new ArrayList<>();
+
+    /** The list of single groups. */
+    final List<Group> groups = new ArrayList<>();
 
     /**
      * Get the Groups.
+     * 
      * @return {@link List} of {@link Group}.
      */
     public List<Group> getGroups() {
@@ -45,6 +49,7 @@ public class Groups {
 
     /**
      * Get the Group sequences.
+     * 
      * @return {@link List} of {@link List} of {@link Group}
      */
     public List<List<Group>> getSequences() {
@@ -53,7 +58,9 @@ public class Groups {
 
     /**
      * Insert a {@link Group}.
-     * @param group to insert
+     * 
+     * @param group
+     *            to insert
      */
     void insertGroup(Group group) {
         if (!groups.contains(group)) {
@@ -63,52 +70,52 @@ public class Groups {
 
     /**
      * Insert a sequence.
-     * @param groups {@link List} of {@link Group} to insert
+     * 
+     * @param groups
+     *            {@link List} of {@link Group} to insert
      */
     void insertSequence(List<Group> groups) {
-        if (groups == null || groups.isEmpty()) {
-            return;
-        }
-
-        if (!sequences.contains(groups)) {
+        if (!(groups == null || groups.isEmpty() || sequences.contains(groups))) {
             sequences.add(groups);
         }
     }
 
     /**
-     * Assert that the default group can be expanded to <code>defaultGroups</code>.
+     * Assert that the default group can be expanded to
+     * <code>defaultGroups</code>.
+     * 
      * @param defaultGroups
      */
     public void assertDefaultGroupSequenceIsExpandable(List<Group> defaultGroups) {
         for (List<Group> groupList : sequences) {
-            int idx = groupList.indexOf(Group.DEFAULT);
-            if (idx != -1) {
+            final int idx = groupList.indexOf(Group.DEFAULT);
+            if (idx >= 0) {
                 ensureExpandable(groupList, defaultGroups, idx);
             }
         }
     }
 
     private void ensureExpandable(List<Group> groupList, List<Group> defaultGroupList, int defaultGroupIndex) {
-        for (int i = 0; i < defaultGroupList.size(); i++) {
-            Group group = defaultGroupList.get(i);
+        for (int i = 0, sz = defaultGroupList.size(); i < sz; i++) {
+            final Group group = defaultGroupList.get(i);
             if (group.isDefault()) {
                 continue; // the default group is the one we want to replace
             }
-            int index = groupList.indexOf(group); // sequence contains group of default group sequence
-            if (index == -1) {
-                continue; // if group is not in the sequence
+            // sequence contains group of default group sequence
+            final int index = groupList.indexOf(group);
+            if (index < 0) {
+                // group is not in the sequence
+                continue;
             }
-
             if ((i == 0 && index == defaultGroupIndex - 1)
                 || (i == defaultGroupList.size() - 1 && index == defaultGroupIndex + 1)) {
-                // if we are at the beginning or end of he defaultGroupSequence and the
-                // matches are either directly before or after we can continue,
-                // since we basically have two groups
+                // if we are at the beginning or end of he defaultGroupSequence
+                // and the matches are either directly before or after we can
+                // continue, since we basically have two groups
                 continue;
             }
-            throw new GroupDefinitionException(
-                "Unable to expand default group list" + defaultGroupList + " into sequence " + groupList);
+            Exceptions.raise(GroupDefinitionException::new, "Unable to expand default group list %s into sequence %s",
+                defaultGroupList, groupList);
         }
     }
-
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/bval/blob/f87be824/bval-jsr/src/main/java/org/apache/bval/jsr/groups/GroupsComputer.java
----------------------------------------------------------------------
diff --git a/bval-jsr/src/main/java/org/apache/bval/jsr/groups/GroupsComputer.java b/bval-jsr/src/main/java/org/apache/bval/jsr/groups/GroupsComputer.java
index 398d6c3..ae6f629 100644
--- a/bval-jsr/src/main/java/org/apache/bval/jsr/groups/GroupsComputer.java
+++ b/bval-jsr/src/main/java/org/apache/bval/jsr/groups/GroupsComputer.java
@@ -18,126 +18,115 @@
  */
 package org.apache.bval.jsr.groups;
 
-import javax.validation.GroupDefinitionException;
-import javax.validation.GroupSequence;
-import javax.validation.ValidationException;
-import javax.validation.groups.Default;
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.HashSet;
-import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
+import java.util.Objects;
 import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
 
+import javax.validation.GroupDefinitionException;
+import javax.validation.GroupSequence;
+import javax.validation.ValidationException;
+import javax.validation.groups.Default;
+
+import org.apache.bval.util.Exceptions;
+import org.apache.bval.util.Validate;
+
 /**
  * Description: compute group order, based on the RI behavior as to guarantee
  * compatibility with interpretations of the spec.<br/>
  * Implementation is thread-safe.
  */
 public class GroupsComputer {
-    public static final Class<?>[] DEFAULT_GROUP = new Class<?>[] { Default.class };
+    public static final Class<?>[] DEFAULT_GROUP = { Default.class };
 
-    /** The default group array used in case any of the validate methods is called without a group. */
+    /**
+     * The default group array used in case any of the validate methods is
+     * called without a group.
+     */
     private static final Groups DEFAULT_GROUPS;
     static {
-        DEFAULT_GROUPS = new GroupsComputer().computeGroups(Arrays.asList(DEFAULT_GROUP));
+        DEFAULT_GROUPS = new Groups();
+        for (Class<?> g : DEFAULT_GROUP) {
+            DEFAULT_GROUPS.insertGroup(new Group(g));
+        }
     }
 
     /** caching resolved groups in a thread-safe map. */
-    private final Map<Class<?>, List<Group>> resolvedSequences = new ConcurrentHashMap<Class<?>, List<Group>>();
+    private final Map<Class<?>, List<Group>> resolvedSequences = new ConcurrentHashMap<>();
 
     /**
      * Compute groups from an array of group classes.
+     * 
      * @param groups
      * @return {@link Groups}
      */
-    public Groups computeGroups(Class<?>[] groups) {
-        if (groups == null) {
-            throw new IllegalArgumentException("null passed as group");
-        }
-
-        // if no groups is specified use the default
-        if (groups.length == 0) {
-            return DEFAULT_GROUPS;
-        }
-
+    @SafeVarargs
+    public final Groups computeGroups(Class<?>... groups) {
+        Exceptions.raiseIf(groups == null, IllegalArgumentException::new, "null validation groups specified");
         return computeGroups(Arrays.asList(groups));
     }
 
     /**
      * Main compute implementation.
+     * 
      * @param groups
      * @return {@link Groups}
      */
     protected Groups computeGroups(Collection<Class<?>> groups) {
-        if (groups == null || groups.size() == 0) {
-            throw new IllegalArgumentException("At least one group has to be specified.");
+        Validate.notNull(groups, "groups");
+
+        if (groups.isEmpty() || Arrays.asList(DEFAULT_GROUP).equals(new ArrayList<>(groups))) {
+            return DEFAULT_GROUPS;
         }
+        Exceptions.raiseIf(groups.stream().anyMatch(Objects::isNull), IllegalArgumentException::new,
+            "Null group specified");
 
         for (final Class<?> clazz : groups) {
-            if (clazz == null) {
-                throw new IllegalArgumentException("At least one group has to be specified.");
-            }
-
-            if (!clazz.isInterface()) {
-                throw new ValidationException("A group has to be an interface. " + clazz.getName() + " is not.");
-            }
+            Exceptions.raiseUnless(clazz.isInterface(), ValidationException::new,
+                "A group must be an interface. %s is not.", clazz);
         }
-
-        Groups chain = new Groups();
+        final Groups chain = new Groups();
         for (Class<?> clazz : groups) {
-            GroupSequence anno = clazz.getAnnotation(GroupSequence.class);
+            final GroupSequence anno = clazz.getAnnotation(GroupSequence.class);
             if (anno == null) {
-                Group group = new Group(clazz);
-                chain.insertGroup(group);
+                chain.insertGroup(new Group(clazz));
                 insertInheritedGroups(clazz, chain);
-            } else {
-                insertSequence(clazz, anno, chain);
+                continue;
             }
+            chain.insertSequence(
+                resolvedSequences.computeIfAbsent(clazz, g -> resolveSequence(g, anno, new HashSet<>())));
         }
-
         return chain;
     }
 
     private void insertInheritedGroups(Class<?> clazz, Groups chain) {
         for (Class<?> extendedInterface : clazz.getInterfaces()) {
-            Group group = new Group(extendedInterface);
-            chain.insertGroup(group);
+            chain.insertGroup(new Group(extendedInterface));
             insertInheritedGroups(extendedInterface, chain);
         }
     }
 
-    private void insertSequence(Class<?> clazz, GroupSequence anno, Groups chain) {
-        List<Group> sequence;
-        if (resolvedSequences.containsKey(clazz)) {
-            sequence = resolvedSequences.get(clazz);
-        } else {
-            sequence = resolveSequence(clazz, anno, new HashSet<Class<?>>());
-        }
-        chain.insertSequence(sequence);
-    }
-
     private List<Group> resolveSequence(Class<?> group, GroupSequence sequenceAnnotation,
         Set<Class<?>> processedSequences) {
-        if (processedSequences.contains(group)) {
-            throw new GroupDefinitionException("Cyclic dependency in groups definition");
-        } else {
-            processedSequences.add(group);
-        }
-        List<Group> resolvedGroupSequence = new LinkedList<Group>();
-        Class<?>[] sequenceArray = sequenceAnnotation.value();
-        for (Class<?> clazz : sequenceArray) {
-            GroupSequence anno = clazz.getAnnotation(GroupSequence.class);
+        Exceptions.raiseUnless(processedSequences.add(group), GroupDefinitionException::new,
+            "Cyclic dependency in groups definition");
+
+        final List<Group> resolvedGroupSequence = new ArrayList<>();
+        for (Class<?> clazz : sequenceAnnotation.value()) {
+            final GroupSequence anno = clazz.getAnnotation(GroupSequence.class);
             if (anno == null) {
-                resolvedGroupSequence.add(new Group(clazz)); // group part of sequence
+                // group part of sequence
+                resolvedGroupSequence.add(new Group(clazz));
             } else {
-                List<Group> tmpSequence = resolveSequence(clazz, anno, processedSequences); // recursion!
-                resolvedGroupSequence.addAll(tmpSequence);
+                // recursion!
+                resolvedGroupSequence.addAll(resolveSequence(clazz, anno, processedSequences));
             }
         }
-        resolvedSequences.put(group, resolvedGroupSequence);
         return resolvedGroupSequence;
     }
 }

http://git-wip-us.apache.org/repos/asf/bval/blob/f87be824/bval-jsr/src/main/java/org/apache/bval/jsr/parameter/DefaultParameterNameProvider.java
----------------------------------------------------------------------
diff --git a/bval-jsr/src/main/java/org/apache/bval/jsr/parameter/DefaultParameterNameProvider.java b/bval-jsr/src/main/java/org/apache/bval/jsr/parameter/DefaultParameterNameProvider.java
index 2b43bcd..dec9ae8 100644
--- a/bval-jsr/src/main/java/org/apache/bval/jsr/parameter/DefaultParameterNameProvider.java
+++ b/bval-jsr/src/main/java/org/apache/bval/jsr/parameter/DefaultParameterNameProvider.java
@@ -18,30 +18,29 @@
  */
 package org.apache.bval.jsr.parameter;
 
-import javax.validation.ParameterNameProvider;
 import java.lang.reflect.Constructor;
+import java.lang.reflect.Executable;
 import java.lang.reflect.Method;
-import java.util.ArrayList;
+import java.lang.reflect.Parameter;
 import java.util.List;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import javax.validation.ParameterNameProvider;
 
 public class DefaultParameterNameProvider implements ParameterNameProvider {
-    private static final String ARG = "arg";
+
+    private static List<String> parameterNames(Executable exe) {
+        return Stream.of(exe.getParameters()).map(Parameter::getName).collect(Collectors.toList());
+    }
 
     @Override
     public List<String> getParameterNames(Constructor<?> constructor) {
-        return names(constructor.getParameterTypes().length);
+        return parameterNames(constructor);
     }
 
     @Override
     public List<String> getParameterNames(Method method) {
-        return names(method.getParameterTypes().length);
-    }
-
-    private static List<String> names(final int length) {
-        final List<String> list = new ArrayList<String>();
-        for (int i = 0; i < length; i++) {
-            list.add(ARG + i);
-        }
-        return list;
+        return parameterNames(method);
     }
 }