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 20:25:05 UTC

[09/11] bval git commit: implement BV 2.0 against existing BVal unit tests

http://git-wip-us.apache.org/repos/asf/bval/blob/3f287a7a/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/3f287a7a/bval-jsr/src/main/java/org/apache/bval/jsr/AbstractConstraintDescriptor.java
----------------------------------------------------------------------
diff --git a/bval-jsr/src/main/java/org/apache/bval/jsr/AbstractConstraintDescriptor.java b/bval-jsr/src/main/java/org/apache/bval/jsr/AbstractConstraintDescriptor.java
new file mode 100644
index 0000000..4c303ae
--- /dev/null
+++ b/bval-jsr/src/main/java/org/apache/bval/jsr/AbstractConstraintDescriptor.java
@@ -0,0 +1,32 @@
+package org.apache.bval.jsr;
+
+import java.lang.annotation.Annotation;
+import java.util.Set;
+
+import javax.validation.Payload;
+import javax.validation.metadata.ConstraintDescriptor;
+import javax.validation.metadata.ValidateUnwrappedValue;
+import javax.validation.valueextraction.Unwrapping;
+
+abstract class AbstractConstraintDescriptor<T extends Annotation> implements ConstraintDescriptor<T> {
+
+    @Override
+    public ValidateUnwrappedValue getValueUnwrapping() {
+        final Set<Class<? extends Payload>> payload = getPayload();
+        if (payload != null) {
+            if (payload.contains(Unwrapping.Unwrap.class)) {
+                return ValidateUnwrappedValue.UNWRAP;
+            }
+            if (payload.contains(Unwrapping.Skip.class)) {
+                return ValidateUnwrappedValue.SKIP;
+            }
+        }
+        // TODO handle UnwrapByDefault extractors
+        return ValidateUnwrappedValue.DEFAULT;
+    }
+
+    @Override
+    public <U> U unwrap(Class<U> type) {
+        throw new UnsupportedOperationException();
+    }
+}

http://git-wip-us.apache.org/repos/asf/bval/blob/3f287a7a/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/3f287a7a/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/3f287a7a/bval-jsr/src/main/java/org/apache/bval/jsr/ApacheFactoryContext.java
----------------------------------------------------------------------
diff --git a/bval-jsr/src/main/java/org/apache/bval/jsr/ApacheFactoryContext.java b/bval-jsr/src/main/java/org/apache/bval/jsr/ApacheFactoryContext.java
index 8f68b9e..1e4b263 100644
--- a/bval-jsr/src/main/java/org/apache/bval/jsr/ApacheFactoryContext.java
+++ b/bval-jsr/src/main/java/org/apache/bval/jsr/ApacheFactoryContext.java
@@ -18,46 +18,56 @@
  */
 package org.apache.bval.jsr;
 
-import org.apache.bval.MetaBeanFinder;
-import org.apache.bval.util.reflection.Reflection;
-import org.apache.commons.weaver.privilizer.Privilizing;
-import org.apache.commons.weaver.privilizer.Privilizing.CallTo;
-
+import javax.validation.ClockProvider;
 import javax.validation.ConstraintValidatorFactory;
 import javax.validation.MessageInterpolator;
 import javax.validation.ParameterNameProvider;
 import javax.validation.TraversableResolver;
 import javax.validation.Validator;
 import javax.validation.ValidatorContext;
+import javax.validation.valueextraction.ValueExtractor;
+
+import org.apache.bval.MetaBeanFinder;
+import org.apache.bval.jsr.descriptor.DescriptorManager;
+import org.apache.bval.jsr.groups.GroupsComputer;
+import org.apache.bval.jsr.valueextraction.ValueExtractors;
+import org.apache.bval.util.Lazy;
+import org.apache.bval.util.reflection.Reflection;
+import org.apache.commons.weaver.privilizer.Privilizing;
+import org.apache.commons.weaver.privilizer.Privilizing.CallTo;
 
 /**
- * Description: Represents the context that is used to create
- * {@link ClassValidator} instances.
+ * Description: Represents the context that is used to create {@link ClassValidator} instances.
  */
 @Privilizing(@CallTo(Reflection.class))
 public class ApacheFactoryContext implements ValidatorContext {
+    private final Lazy<GroupsComputer> groupsComputer = new Lazy<>(GroupsComputer::new);
     private final ApacheValidatorFactory factory;
+    private final ValueExtractors valueExtractors;
     private volatile MetaBeanFinder metaBeanFinder;
 
     private MessageInterpolator messageInterpolator;
     private TraversableResolver traversableResolver;
     private ParameterNameProvider parameterNameProvider;
     private ConstraintValidatorFactory constraintValidatorFactory;
+    private ClockProvider clockProvider;
 
     /**
      * Create a new ApacheFactoryContext instance.
      * 
-     * @param factory validator factory
-     * @param metaBeanFinder meta finder
+     * @param factory
+     *            validator factory
+     * @param metaBeanFinder
+     *            meta finder
      */
     public ApacheFactoryContext(ApacheValidatorFactory factory, MetaBeanFinder metaBeanFinder) {
         this.factory = factory;
         this.metaBeanFinder = metaBeanFinder;
+        valueExtractors = factory.getValueExtractors().createChild();
     }
 
     /**
-     * Get the {@link ApacheValidatorFactory} used by this
-     * {@link ApacheFactoryContext}.
+     * Get the {@link ApacheValidatorFactory} used by this {@link ApacheFactoryContext}.
      * 
      * @return {@link ApacheValidatorFactory}
      */
@@ -75,13 +85,13 @@ public class ApacheFactoryContext implements ValidatorContext {
     }
 
     /**
-     * Discard cached metadata. Calling this method unnecessarily has the effect of severly
-     * limiting performance, therefore only do so when changes have been made that affect
-     * validation metadata, i.e. particularly NOT in response to:
+     * Discard cached metadata. Calling this method unnecessarily has the effect of severly limiting performance,
+     * therefore only do so when changes have been made that affect validation metadata, i.e. particularly NOT in
+     * response to:
      * <ul>
-     *   <li>{@link #messageInterpolator(MessageInterpolator)}</li>
-     *   <li>{@link #traversableResolver(TraversableResolver)}</li>
-     *   <li>{@link #constraintValidatorFactory(ConstraintValidatorFactory)</li>
+     * <li>{@link #messageInterpolator(MessageInterpolator)}</li>
+     * <li>{@link #traversableResolver(TraversableResolver)}</li>
+     * <li>{@link #constraintValidatorFactory(ConstraintValidatorFactory)</li>
      * </ul>
      */
     private synchronized void resetMeta() {
@@ -92,7 +102,7 @@ public class ApacheFactoryContext implements ValidatorContext {
      * {@inheritDoc}
      */
     @Override
-    public ValidatorContext messageInterpolator(MessageInterpolator messageInterpolator) {
+    public ApacheFactoryContext messageInterpolator(MessageInterpolator messageInterpolator) {
         this.messageInterpolator = messageInterpolator;
         return this;
     }
@@ -101,7 +111,7 @@ public class ApacheFactoryContext implements ValidatorContext {
      * {@inheritDoc}
      */
     @Override
-    public ValidatorContext traversableResolver(TraversableResolver traversableResolver) {
+    public ApacheFactoryContext traversableResolver(TraversableResolver traversableResolver) {
         this.traversableResolver = traversableResolver;
         return this;
     }
@@ -110,18 +120,30 @@ public class ApacheFactoryContext implements ValidatorContext {
      * {@inheritDoc}
      */
     @Override
-    public ValidatorContext constraintValidatorFactory(ConstraintValidatorFactory constraintValidatorFactory) {
+    public ApacheFactoryContext constraintValidatorFactory(ConstraintValidatorFactory constraintValidatorFactory) {
         this.constraintValidatorFactory = constraintValidatorFactory;
         return this;
     }
 
     @Override
-    public ValidatorContext parameterNameProvider(ParameterNameProvider parameterNameProvider) {
+    public ApacheFactoryContext parameterNameProvider(ParameterNameProvider parameterNameProvider) {
         this.parameterNameProvider = parameterNameProvider;
         resetMeta(); // needed since parameter names are a component of validation metadata
         return this;
     }
 
+    @Override
+    public ApacheFactoryContext clockProvider(ClockProvider clockProvider) {
+        this.clockProvider = clockProvider;
+        return this;
+    }
+
+    @Override
+    public ApacheFactoryContext addValueExtractor(ValueExtractor<?> extractor) {
+        valueExtractors.add(extractor);
+        return this;
+    }
+
     /**
      * Get the {@link ConstraintValidatorFactory}.
      * 
@@ -137,7 +159,7 @@ public class ApacheFactoryContext implements ValidatorContext {
      */
     @Override
     public Validator getValidator() {
-        return new ClassValidator(this);
+        return new ValidatorImpl(this);
     }
 
     /**
@@ -162,6 +184,23 @@ public class ApacheFactoryContext implements ValidatorContext {
         return parameterNameProvider == null ? factory.getParameterNameProvider() : parameterNameProvider;
     }
 
+    public ClockProvider getClockProvider() {
+        return clockProvider == null ? factory.getClockProvider() : clockProvider;
+    }
+
+    public ValueExtractors getValueExtractors() {
+        return valueExtractors;
+    }
+
+    public DescriptorManager getDescriptorManager() {
+        // TODO handle context customizations
+        return factory.getDescriptorManager();
+    }
+
+    public GroupsComputer getGroupsComputer() {
+        return groupsComputer.get();
+    }
+
     boolean isTreatMapsLikeBeans() {
         return Boolean
             .parseBoolean(factory.getProperties().get(ApacheValidatorConfiguration.Properties.TREAT_MAPS_LIKE_BEANS));

http://git-wip-us.apache.org/repos/asf/bval/blob/3f287a7a/bval-jsr/src/main/java/org/apache/bval/jsr/ApacheValidatorConfiguration.java
----------------------------------------------------------------------
diff --git a/bval-jsr/src/main/java/org/apache/bval/jsr/ApacheValidatorConfiguration.java b/bval-jsr/src/main/java/org/apache/bval/jsr/ApacheValidatorConfiguration.java
index fb64d4e..81187f3 100644
--- a/bval-jsr/src/main/java/org/apache/bval/jsr/ApacheValidatorConfiguration.java
+++ b/bval-jsr/src/main/java/org/apache/bval/jsr/ApacheValidatorConfiguration.java
@@ -32,7 +32,7 @@ public interface ApacheValidatorConfiguration extends Configuration<ApacheValida
     /**
      * Proprietary property keys for {@link ConfigurationImpl}  
      */
-    public interface Properties {
+    interface Properties {
         /**
          * the location where to look for the validation.xml file.
          * default: "META-INF/validation.xml"
@@ -91,5 +91,10 @@ public interface ApacheValidatorConfiguration extends Configuration<ApacheValida
          * </ol>
          */
         String METABEAN_FACTORY_CLASSNAMES = "apache.bval.metabean-factory-classnames";
+
+        /**
+         * Size to use for caching of constraint-related information. Default is {@code 50}.
+         */
+        String CONSTRAINTS_CACHE_SIZE = "apache.bval.constraints-cache-size";
     }
 }

http://git-wip-us.apache.org/repos/asf/bval/blob/3f287a7a/bval-jsr/src/main/java/org/apache/bval/jsr/ApacheValidatorFactory.java
----------------------------------------------------------------------
diff --git a/bval-jsr/src/main/java/org/apache/bval/jsr/ApacheValidatorFactory.java b/bval-jsr/src/main/java/org/apache/bval/jsr/ApacheValidatorFactory.java
index 5e6a611..b516a73 100644
--- a/bval-jsr/src/main/java/org/apache/bval/jsr/ApacheValidatorFactory.java
+++ b/bval-jsr/src/main/java/org/apache/bval/jsr/ApacheValidatorFactory.java
@@ -18,11 +18,39 @@
  */
 package org.apache.bval.jsr;
 
+import java.io.Closeable;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Modifier;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+import javax.validation.ClockProvider;
+import javax.validation.ConstraintValidatorFactory;
+import javax.validation.MessageInterpolator;
+import javax.validation.ParameterNameProvider;
+import javax.validation.TraversableResolver;
+import javax.validation.Validation;
+import javax.validation.ValidationException;
+import javax.validation.Validator;
+import javax.validation.ValidatorFactory;
+import javax.validation.spi.ConfigurationState;
+
 import org.apache.bval.IntrospectorMetaBeanFactory;
 import org.apache.bval.MetaBeanBuilder;
 import org.apache.bval.MetaBeanFactory;
 import org.apache.bval.MetaBeanFinder;
 import org.apache.bval.MetaBeanManager;
+import org.apache.bval.jsr.descriptor.DescriptorManager;
+import org.apache.bval.jsr.metadata.MetadataBuilders;
+import org.apache.bval.jsr.util.AnnotationsManager;
+import org.apache.bval.jsr.valueextraction.ValueExtractors;
 import org.apache.bval.jsr.xml.AnnotationIgnores;
 import org.apache.bval.jsr.xml.MetaConstraint;
 import org.apache.bval.jsr.xml.ValidationMappingParser;
@@ -37,28 +65,6 @@ import org.apache.commons.weaver.privilizer.Privileged;
 import org.apache.commons.weaver.privilizer.Privilizing;
 import org.apache.commons.weaver.privilizer.Privilizing.CallTo;
 
-import javax.validation.ConstraintValidatorFactory;
-import javax.validation.MessageInterpolator;
-import javax.validation.ParameterNameProvider;
-import javax.validation.TraversableResolver;
-import javax.validation.Validation;
-import javax.validation.ValidationException;
-import javax.validation.Validator;
-import javax.validation.ValidatorFactory;
-import javax.validation.spi.ConfigurationState;
-import java.io.Closeable;
-import java.lang.annotation.Annotation;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.Modifier;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
-
 /**
  * Description: a factory is a complete configurated object that can create
  * validators.<br/>
@@ -68,13 +74,17 @@ import java.util.concurrent.ConcurrentMap;
 public class ApacheValidatorFactory implements ValidatorFactory, Cloneable {
 
     private static volatile ApacheValidatorFactory DEFAULT_FACTORY;
-    private static final ConstraintDefaults DEFAULT_CONSTRAINTS = new ConstraintDefaults();
 
     private MessageInterpolator messageResolver;
     private TraversableResolver traversableResolver;
     private ConstraintValidatorFactory constraintValidatorFactory;
     private ParameterNameProvider parameterNameProvider;
+    private ClockProvider clockProvider;
     private final Map<String, String> properties;
+    private final AnnotationsManager annotationsManager;
+    private final DescriptorManager descriptorManager = new DescriptorManager(this);
+    private final MetadataBuilders metadataBuilders = new MetadataBuilders();
+    private final ValueExtractors valueExtractors = new ValueExtractors();
 
     /**
      * information from xml parsing
@@ -89,7 +99,7 @@ public class ApacheValidatorFactory implements ValidatorFactory, Cloneable {
     private final ConcurrentMap<Class<?>, List<AccessStrategy>> validAccesses;
     private final ConcurrentMap<Class<?>, List<MetaConstraint<?, ? extends Annotation>>> constraintMap;
 
-    private final Collection<Closeable> toClose = new ArrayList<Closeable>();
+    private final Collection<Closeable> toClose = new ArrayList<>();
     private final MetaBeanFinder defaultMetaBeanFinder;
 
     /**
@@ -112,7 +122,7 @@ public class ApacheValidatorFactory implements ValidatorFactory, Cloneable {
      * @return a new instance of MetaBeanManager with adequate MetaBeanFactories
      */
     protected MetaBeanFinder buildMetaBeanFinder() {
-        final List<MetaBeanFactory> builders = new ArrayList<MetaBeanFactory>();
+        final List<MetaBeanFactory> builders = new ArrayList<>();
         if (Boolean.parseBoolean(getProperties().get(ApacheValidatorConfiguration.Properties.ENABLE_INTROSPECTOR))) {
             builders.add(new IntrospectorMetaBeanFactory());
         }
@@ -121,9 +131,8 @@ public class ApacheValidatorFactory implements ValidatorFactory, Cloneable {
         if (factoryClassNames != null) {
             for (String clsName : factoryClassNames) {
                 // cast, relying on #createMetaBeanFactory to throw the exception if incompatible:
-                @SuppressWarnings("unchecked")
                 final Class<? extends MetaBeanFactory> factoryClass =
-                    (Class<? extends MetaBeanFactory>) loadClass(clsName);
+                    loadClass(clsName).asSubclass(MetaBeanFactory.class);
                 builders.add(createMetaBeanFactory(factoryClass));
             }
         }
@@ -173,24 +182,27 @@ public class ApacheValidatorFactory implements ValidatorFactory, Cloneable {
      * Create a new ApacheValidatorFactory instance.
      */
     public ApacheValidatorFactory(ConfigurationState configuration) {
-        properties = new HashMap<String, String>(configuration.getProperties());
-        defaultSequences = new HashMap<Class<?>, Class<?>[]>();
-        validAccesses = new ConcurrentHashMap<Class<?>, List<AccessStrategy>>();
-        constraintMap = new ConcurrentHashMap<Class<?>, List<MetaConstraint<?, ? extends Annotation>>>();
+        properties = new HashMap<>(configuration.getProperties());
+        defaultSequences = new HashMap<>();
+        validAccesses = new ConcurrentHashMap<>();
+        constraintMap = new ConcurrentHashMap<>();
 
         parameterNameProvider = configuration.getParameterNameProvider();
         messageResolver = configuration.getMessageInterpolator();
         traversableResolver = configuration.getTraversableResolver();
         constraintValidatorFactory = configuration.getConstraintValidatorFactory();
+        clockProvider = configuration.getClockProvider();
 
         if (ConfigurationImpl.class.isInstance(configuration)) {
-            final ConfigurationImpl impl = ConfigurationImpl.class.cast(configuration);
-            toClose.add(impl.getClosable());
+            toClose.add(ConfigurationImpl.class.cast(configuration).getClosable());
         }
 
         new ValidationMappingParser(this).processMappingConfig(configuration.getMappingStreams());
 
         defaultMetaBeanFinder = buildMetaBeanFinder();
+
+        configuration.getValueExtractors().forEach(valueExtractors::add);
+        annotationsManager = new AnnotationsManager(this);
     }
 
     /**
@@ -203,8 +215,7 @@ public class ApacheValidatorFactory implements ValidatorFactory, Cloneable {
     }
 
     /**
-     * Shortcut method to create a new Validator instance with factory's
-     * settings
+     * Shortcut method to create a new Validator instance with factory's settings
      *
      * @return the new validator instance
      */
@@ -271,6 +282,12 @@ public class ApacheValidatorFactory implements ValidatorFactory, Cloneable {
         }
     }
 
+    public void setClockProvider(final ClockProvider clockProvider) {
+        if (clockProvider != null) {
+            this.clockProvider = clockProvider;
+        }
+    }
+
     /**
      * {@inheritDoc}
      */
@@ -307,6 +324,11 @@ public class ApacheValidatorFactory implements ValidatorFactory, Cloneable {
     }
 
     @Override
+    public ClockProvider getClockProvider() {
+        return clockProvider;
+    }
+
+    @Override
     public void close() {
         try {
             for (final Closeable c : toClose) {
@@ -319,13 +341,14 @@ public class ApacheValidatorFactory implements ValidatorFactory, Cloneable {
     }
 
     /**
-     * Return an object of the specified type to allow access to the
-     * provider-specific API. If the Bean Validation provider implementation
-     * does not support the specified class, the ValidationException is thrown.
+     * Return an object of the specified type to allow access to the provider-specific API. If the Bean Validation
+     * provider implementation does not support the specified class, the ValidationException is thrown.
      *
-     * @param type the class of the object to be returned.
+     * @param type
+     *            the class of the object to be returned.
      * @return an instance of the specified class
-     * @throws ValidationException if the provider does not support the call.
+     * @throws ValidationException
+     *             if the provider does not support the call.
      */
     @Override
     public <T> T unwrap(final Class<T> type) {
@@ -365,15 +388,6 @@ public class ApacheValidatorFactory implements ValidatorFactory, Cloneable {
     }
 
     /**
-     * Get the detected {@link ConstraintDefaults}.
-     *
-     * @return ConstraintDefaults
-     */
-    public ConstraintDefaults getDefaultConstraints() {
-        return DEFAULT_CONSTRAINTS;
-    }
-
-    /**
      * Get the detected {@link AnnotationIgnores}.
      *
      * @return AnnotationIgnores
@@ -392,8 +406,34 @@ public class ApacheValidatorFactory implements ValidatorFactory, Cloneable {
     }
 
     /**
-     * Add a meta-constraint to this {@link ApacheValidatorFactory}'s runtime
-     * customizations.
+     * Get the {@link AnnotationsManager}.
+     * 
+     * @return {@link AnnotationsManager}
+     */
+    public AnnotationsManager getAnnotationsManager() {
+        return annotationsManager;
+    }
+
+    /**
+     * Get the {@link DescriptorManager}.
+     * 
+     * @return {@link DescriptorManager}
+     */
+    public DescriptorManager getDescriptorManager() {
+        return descriptorManager;
+    }
+
+    /**
+     * Get the {@link ValueExtractors}.
+     * 
+     * @return {@link ValueExtractors}
+     */
+    public ValueExtractors getValueExtractors() {
+        return valueExtractors;
+    }
+
+    /**
+     * Add a meta-constraint to this {@link ApacheValidatorFactory}'s runtime customizations.
      *
      * @param beanClass
      * @param metaConstraint
@@ -401,7 +441,7 @@ public class ApacheValidatorFactory implements ValidatorFactory, Cloneable {
     public void addMetaConstraint(final Class<?> beanClass, final MetaConstraint<?, ?> metaConstraint) {
         List<MetaConstraint<?, ? extends Annotation>> slot = constraintMap.get(beanClass);
         if (slot == null) {
-            slot = new ArrayList<MetaConstraint<?, ? extends Annotation>>();
+            slot = new ArrayList<>();
             final List<MetaConstraint<?, ? extends Annotation>> old = constraintMap.putIfAbsent(beanClass, slot);
             if (old != null) {
                 slot = old;
@@ -420,7 +460,7 @@ public class ApacheValidatorFactory implements ValidatorFactory, Cloneable {
     public void addValid(Class<?> beanClass, AccessStrategy accessStrategy) {
         List<AccessStrategy> slot = validAccesses.get(beanClass);
         if (slot == null) {
-            slot = new ArrayList<AccessStrategy>();
+            slot = new ArrayList<>();
             final List<AccessStrategy> old = validAccesses.putIfAbsent(beanClass, slot);
             if (old != null) {
                 slot = old;
@@ -444,8 +484,7 @@ public class ApacheValidatorFactory implements ValidatorFactory, Cloneable {
      *
      * @param <T>
      * @param beanClass
-     * @return List of {@link MetaConstraint}s applicable to
-     *         <code>beanClass</code>
+     * @return List of {@link MetaConstraint}s applicable to <code>beanClass</code>
      */
     public <T> List<MetaConstraint<T, ? extends Annotation>> getMetaConstraints(Class<T> beanClass) {
         final List<MetaConstraint<?, ? extends Annotation>> slot = constraintMap.get(beanClass);
@@ -459,16 +498,15 @@ public class ApacheValidatorFactory implements ValidatorFactory, Cloneable {
     }
 
     /**
-     * Get the {@link AccessStrategy} {@link List} indicating nested bean
-     * validations that must be triggered in the course of validating a
-     * <code>beanClass</code> graph.
+     * Get the {@link AccessStrategy} {@link List} indicating nested bean validations that must be triggered in the
+     * course of validating a <code>beanClass</code> graph.
      *
      * @param beanClass
      * @return {@link List} of {@link AccessStrategy}
      */
     public List<AccessStrategy> getValidAccesses(Class<?> beanClass) {
         final List<AccessStrategy> slot = validAccesses.get(beanClass);
-        return slot == null ? Collections.<AccessStrategy> emptyList() : Collections.unmodifiableList(slot);
+        return slot == null ? Collections.emptyList() : Collections.unmodifiableList(slot);
     }
 
     /**
@@ -481,6 +519,10 @@ public class ApacheValidatorFactory implements ValidatorFactory, Cloneable {
         return safeArray(defaultSequences.get(beanClass));
     }
 
+    public MetadataBuilders getMetadataBuilders() {
+        return metadataBuilders;
+    }
+
     private static Class<?>[] safeArray(Class<?>... array) {
         return array == null || array.length == 0 ? ObjectUtils.EMPTY_CLASS_ARRAY : array.clone();
     }
@@ -519,9 +561,8 @@ public class ApacheValidatorFactory implements ValidatorFactory, Cloneable {
     }
 
     /**
-     * separate class to prevent the classloader to immediately load optional
-     * classes: XMLMetaBeanManager, XMLMetaBeanFactory, XMLMetaBeanBuilder that
-     * might not be available in the classpath
+     * separate class to prevent the classloader to immediately load optional classes: XMLMetaBeanManager,
+     * XMLMetaBeanFactory, XMLMetaBeanBuilder that might not be available in the classpath
      */
     private static class XMLMetaBeanManagerCreator {
 
@@ -530,10 +571,10 @@ public class ApacheValidatorFactory implements ValidatorFactory, Cloneable {
         }
 
         /**
-         * Create the {@link MetaBeanManager} to process JSR303 XML. Requires
-         * bval-xstream at RT.
+         * Create the {@link MetaBeanManager} to process JSR303 XML. Requires bval-xstream at RT.
          *
-         * @param builders meta bean builders
+         * @param builders
+         *            meta bean builders
          * @return {@link MetaBeanManager}
          */
         // NOTE - We return MetaBeanManager instead of XMLMetaBeanManager to

http://git-wip-us.apache.org/repos/asf/bval/blob/3f287a7a/bval-jsr/src/main/java/org/apache/bval/jsr/BootstrapConfigurationImpl.java
----------------------------------------------------------------------
diff --git a/bval-jsr/src/main/java/org/apache/bval/jsr/BootstrapConfigurationImpl.java b/bval-jsr/src/main/java/org/apache/bval/jsr/BootstrapConfigurationImpl.java
index 3a3abf1..d85ab51 100644
--- a/bval-jsr/src/main/java/org/apache/bval/jsr/BootstrapConfigurationImpl.java
+++ b/bval-jsr/src/main/java/org/apache/bval/jsr/BootstrapConfigurationImpl.java
@@ -34,12 +34,15 @@ public class BootstrapConfigurationImpl implements BootstrapConfiguration {
     private String messageInterpolatorClassName;
     private String constraintValidatorFactoryClassName;
     private String defaultProviderClassName;
+    private String clockProviderClassName;
+    private Set<String> valueExtractorClassNames;
 
     public BootstrapConfigurationImpl(final String defaultProviderClassName,
         final String constraintValidatorFactoryClassName, final String messageInterpolatorClassName,
         final String traversableResolverClassName, final String parameterNameProviderClassName,
         final Set<String> constraintMappingResourcePaths, final boolean executableValidationEnabled,
-        final Set<ExecutableType> defaultValidatedExecutableTypes, final Map<String, String> properties) {
+        final Set<ExecutableType> defaultValidatedExecutableTypes, final Map<String, String> properties,
+        final String clockProviderClassName, final Set<String> valueExtractorClassNames) {
         this.properties = Collections.unmodifiableMap(properties);
         this.defaultValidatedExecutableTypes = Collections.unmodifiableSet(defaultValidatedExecutableTypes);
         this.executableValidationEnabled = executableValidationEnabled;
@@ -49,6 +52,8 @@ public class BootstrapConfigurationImpl implements BootstrapConfiguration {
         this.messageInterpolatorClassName = messageInterpolatorClassName;
         this.constraintValidatorFactoryClassName = constraintValidatorFactoryClassName;
         this.defaultProviderClassName = defaultProviderClassName;
+        this.clockProviderClassName = clockProviderClassName;
+        this.valueExtractorClassNames = valueExtractorClassNames;
     }
 
     @Override
@@ -78,7 +83,7 @@ public class BootstrapConfigurationImpl implements BootstrapConfiguration {
 
     @Override
     public Set<String> getConstraintMappingResourcePaths() {
-        return constraintMappingResourcePaths;
+        return Collections.unmodifiableSet(constraintMappingResourcePaths);
     }
 
     @Override
@@ -88,11 +93,27 @@ public class BootstrapConfigurationImpl implements BootstrapConfiguration {
 
     @Override
     public Set<ExecutableType> getDefaultValidatedExecutableTypes() {
-        return defaultValidatedExecutableTypes;
+        return Collections.unmodifiableSet(defaultValidatedExecutableTypes);
     }
 
     @Override
     public Map<String, String> getProperties() {
-        return properties;
+        return Collections.unmodifiableMap(properties);
+    }
+
+    /**
+     * @since 2.0
+     */
+    @Override
+    public String getClockProviderClassName() {
+        return clockProviderClassName;
+    }
+
+    /**
+     * @since 2.0
+     */
+    @Override
+    public Set<String> getValueExtractorClassNames() {
+        return Collections.unmodifiableSet(valueExtractorClassNames);
     }
 }

http://git-wip-us.apache.org/repos/asf/bval/blob/3f287a7a/bval-jsr/src/main/java/org/apache/bval/jsr/CascadingPropertyValidator.java
----------------------------------------------------------------------
diff --git a/bval-jsr/src/main/java/org/apache/bval/jsr/CascadingPropertyValidator.java b/bval-jsr/src/main/java/org/apache/bval/jsr/CascadingPropertyValidator.java
index ff2e273..f183c12 100644
--- a/bval-jsr/src/main/java/org/apache/bval/jsr/CascadingPropertyValidator.java
+++ b/bval-jsr/src/main/java/org/apache/bval/jsr/CascadingPropertyValidator.java
@@ -18,7 +18,9 @@ package org.apache.bval.jsr;
 
 import javax.validation.ConstraintViolation;
 import javax.validation.Valid;
+import javax.validation.ValidationException;
 import javax.validation.Validator;
+
 import java.util.Set;
 
 /**
@@ -30,38 +32,90 @@ import java.util.Set;
  * It should be noted that {@link Validator#validateProperty(Object, String, Class...)}
  * and {@link Validator#validateValue(Class, String, Object, Class...)} are assumed
  * semantically equivalent to calling the {@link CascadingPropertyValidator}-defined
- * methods with <code>cascade == false</code>.
+ * methods with {@code cascade == false}.
  * 
  * @version $Rev: 993539 $ $Date: 2010-09-07 16:27:50 -0500 (Tue, 07 Sep 2010) $
  */
 public interface CascadingPropertyValidator extends Validator {
 
     /**
-     * Validates all constraints placed on <code>object</code>'s
-     * <code>propertyName</code> property, with optional validation cascading.
-     * 
-     * @param <T>
-     * @param object
-     * @param propertyName
-     * @param cascade
-     * @param groups
-     * @return the resulting {@link Set} of {@link ConstraintViolation}s.
+     * {@inheritDoc} Validates all constraints placed on the property of {@code object} named {@code propertyName}.
+     *
+     * @param object       object to validate
+     * @param propertyName property to validate (i.e. field and getter constraints). Nested
+     *                     properties may be referenced (e.g. prop[2].subpropA.subpropB)
+     * @param groups       group or list of groups targeted for validation (default to
+     *                     {@link javax.validation.groups.Default})
+     * @return constraint violations or an empty {@link Set} if none
+     * @throws IllegalArgumentException if {@code object} is {@code null}, if {@code propertyName null},
+     *                                  empty or not a valid object property or if {@code null} is
+     *                                  passed to the varargs {@code groups}
+     * @throws ValidationException      if a non recoverable error happens during the validation process
+     */
+    @Override
+    default <T> Set<ConstraintViolation<T>> validateProperty(T object, String propertyName, Class<?>... groups) {
+        return validateProperty(object, propertyName, false, groups);
+    }
+
+    /**
+     * Validates all constraints placed on the property of {@code object} named {@code propertyName}.
+     *
+     * @param object       object to validate
+     * @param propertyName property to validate (i.e. field and getter constraints). Nested
+     *                     properties may be referenced (e.g. prop[2].subpropA.subpropB)
+     * @param cascade      whether to cascade along {@link Valid} properties
+     * @param groups       group or list of groups targeted for validation (default to
+     *                     {@link javax.validation.groups.Default})
+     * @return constraint violations or an empty {@link Set} if none
+     * @throws IllegalArgumentException if {@code object} is {@code null}, if {@code propertyName null},
+     *                                  empty or not a valid object property or if {@code null} is
+     *                                  passed to the varargs {@code groups}
+     * @throws ValidationException      if a non recoverable error happens during the validation process
      */
     <T> Set<javax.validation.ConstraintViolation<T>> validateProperty(T object, String propertyName, boolean cascade,
         Class<?>... groups);
 
     /**
-     * Validates all constraints placed on <code>object</code>'s
-     * <code>propertyName</code> property, with optional validation cascading,
-     * given a hypothetical property <code>value</code>.
-     * 
-     * @param <T>
-     * @param beanType
-     * @param propertyName
-     * @param value
-     * @param cascade
-     * @param groups
-     * @return the resulting {@link Set} of {@link ConstraintViolation}s.
+     * {@inheritDoc} Validates all constraints placed on the property named {@code propertyName} of the class
+     * {@code beanType} would the property value be {@code value}.
+     * <p/>
+     * {@link ConstraintViolation} objects return {@code null} for {@link ConstraintViolation#getRootBean()} and
+     * {@link ConstraintViolation#getLeafBean()}.
+     *
+     * @param beanType     the bean type
+     * @param propertyName property to validate
+     * @param value        property value to validate
+     * @param groups       group or list of groups targeted for validation (default to
+     *                     {@link javax.validation.groups.Default})
+     * @return constraint violations or an empty {@link Set} if none
+     * @throws IllegalArgumentException if {@code beanType} is {@code null}, if
+     *                                  {@code propertyName null}, empty or not a valid object
+     *                                  property or if {@code null} is passed to the varargs {@code groups}
+     * @throws ValidationException      if a non recoverable error happens during the validation process
+     */
+    @Override
+    default <T> Set<ConstraintViolation<T>> validateValue(Class<T> beanType, String propertyName, Object value,
+        Class<?>... groups) {
+        return validateValue(beanType, propertyName, value, false, groups);
+    }
+
+    /**
+     * {@inheritDoc} Validates all constraints placed on the property named {@code propertyName} of the class
+     * {@code beanType} would the property value be {@code value}.
+     * <p/>
+     * {@link ConstraintViolation} objects return {@code null} for {@link ConstraintViolation#getRootBean()} and
+     * {@link ConstraintViolation#getLeafBean()}.
+     *
+     * @param beanType     the bean type
+     * @param propertyName property to validate
+     * @param value        property value to validate
+     * @param groups       group or list of groups targeted for validation (default to
+     *                     {@link javax.validation.groups.Default})
+     * @return constraint violations or an empty {@link Set} if none
+     * @throws IllegalArgumentException if {@code beanType} is {@code null}, if
+     *                                  {@code propertyName null}, empty or not a valid object
+     *                                  property or if {@code null} is passed to the varargs {@code groups}
+     * @throws ValidationException      if a non recoverable error happens during the validation process
      */
     <T> Set<javax.validation.ConstraintViolation<T>> validateValue(Class<T> beanType, String propertyName, Object value,
         boolean cascade, Class<?>... groups);

http://git-wip-us.apache.org/repos/asf/bval/blob/3f287a7a/bval-jsr/src/main/java/org/apache/bval/jsr/ConfigurationImpl.java
----------------------------------------------------------------------
diff --git a/bval-jsr/src/main/java/org/apache/bval/jsr/ConfigurationImpl.java b/bval-jsr/src/main/java/org/apache/bval/jsr/ConfigurationImpl.java
index 7c4780f..046d6d2 100644
--- a/bval-jsr/src/main/java/org/apache/bval/jsr/ConfigurationImpl.java
+++ b/bval-jsr/src/main/java/org/apache/bval/jsr/ConfigurationImpl.java
@@ -19,9 +19,10 @@
 package org.apache.bval.jsr;
 
 import java.io.Closeable;
-import java.io.IOException;
 import java.io.InputStream;
+import java.time.Clock;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Map;
@@ -29,6 +30,7 @@ import java.util.Set;
 import java.util.concurrent.CopyOnWriteArrayList;
 
 import javax.validation.BootstrapConfiguration;
+import javax.validation.ClockProvider;
 import javax.validation.ConstraintValidatorFactory;
 import javax.validation.MessageInterpolator;
 import javax.validation.ParameterNameProvider;
@@ -40,6 +42,7 @@ import javax.validation.executable.ExecutableType;
 import javax.validation.spi.BootstrapState;
 import javax.validation.spi.ConfigurationState;
 import javax.validation.spi.ValidationProvider;
+import javax.validation.valueextraction.ValueExtractor;
 
 import org.apache.bval.cdi.BValExtension;
 import org.apache.bval.jsr.parameter.DefaultParameterNameProvider;
@@ -76,29 +79,33 @@ public class ConfigurationImpl implements ApacheValidatorConfiguration, Configur
      */
     protected MessageInterpolator defaultMessageInterpolator = new DefaultMessageInterpolator();
     protected volatile MessageInterpolator messageInterpolator = defaultMessageInterpolator;
-    protected Class<? extends MessageInterpolator> messageInterpolatorClass = null;
+    protected Class<? extends MessageInterpolator> messageInterpolatorClass;
 
     /**
      * Configured {@link ConstraintValidatorFactory}
      */
     protected ConstraintValidatorFactory defaultConstraintValidatorFactory = new DefaultConstraintValidatorFactory();
     protected volatile ConstraintValidatorFactory constraintValidatorFactory = defaultConstraintValidatorFactory;
-    protected Class<? extends ConstraintValidatorFactory> constraintValidatorFactoryClass = null;
+    protected Class<? extends ConstraintValidatorFactory> constraintValidatorFactoryClass;
 
     protected TraversableResolver defaultTraversableResolver = new DefaultTraversableResolver();
     protected volatile TraversableResolver traversableResolver = defaultTraversableResolver;
-    protected Class<? extends TraversableResolver> traversableResolverClass = null;
+    protected Class<? extends TraversableResolver> traversableResolverClass;
 
     protected ParameterNameProvider defaultParameterNameProvider = new DefaultParameterNameProvider();
     protected volatile ParameterNameProvider parameterNameProvider = defaultParameterNameProvider;
-    protected Class<? extends ParameterNameProvider> parameterNameProviderClass = null;
+    protected Class<? extends ParameterNameProvider> parameterNameProviderClass;
 
     protected BootstrapConfiguration bootstrapConfiguration;
 
     protected Collection<ExecutableType> executableValidation;
 
-    private Collection<BValExtension.Releasable<?>> releasables =
-        new CopyOnWriteArrayList<BValExtension.Releasable<?>>();
+    private Collection<BValExtension.Releasable<?>> releasables = new CopyOnWriteArrayList<>();
+    protected ClockProvider defaultClockProvider = Clock::systemDefaultZone;
+    protected volatile ClockProvider clockProvider = defaultClockProvider;
+    protected Class<? extends ClockProvider> clockProviderClass;
+
+    protected Set<ValueExtractor<?>> valueExtractors = new HashSet<>();
 
     private boolean beforeCdi = false;
 
@@ -109,8 +116,8 @@ public class ConfigurationImpl implements ApacheValidatorConfiguration, Configur
     private boolean prepared = false;
     // END DEFAULTS
 
-    private Set<InputStream> mappingStreams = new HashSet<InputStream>();
-    private Map<String, String> properties = new HashMap<String, String>();
+    private Set<InputStream> mappingStreams = new HashSet<>();
+    private Map<String, String> properties = new HashMap<>();
     private boolean ignoreXmlConfiguration = false;
 
     private volatile ValidationParser parser;
@@ -134,6 +141,7 @@ public class ConfigurationImpl implements ApacheValidatorConfiguration, Configur
         } else {
             throw new ValidationException("either provider or state are required");
         }
+        initializePropertyDefaults();
     }
 
     /**
@@ -141,13 +149,11 @@ public class ConfigurationImpl implements ApacheValidatorConfiguration, Configur
      */
     @Override
     public ApacheValidatorConfiguration traversableResolver(TraversableResolver resolver) {
-        if (resolver == null) {
-            return this;
+        if (resolver != null) {
+            this.traversableResolverClass = null;
+            this.traversableResolver = resolver;
+            this.prepared = false;
         }
-
-        this.traversableResolverClass = null;
-        this.traversableResolver = resolver;
-        this.prepared = false;
         return this;
     }
 
@@ -169,13 +175,11 @@ public class ConfigurationImpl implements ApacheValidatorConfiguration, Configur
      */
     @Override
     public ConfigurationImpl messageInterpolator(MessageInterpolator resolver) {
-        if (resolver == null) {
-            return this;
+        if (resolver != null) {
+            this.messageInterpolatorClass = null;
+            this.messageInterpolator = resolver;
+            this.prepared = false;
         }
-
-        this.messageInterpolatorClass = null;
-        this.messageInterpolator = resolver;
-        this.prepared = false;
         return this;
     }
 
@@ -184,23 +188,20 @@ public class ConfigurationImpl implements ApacheValidatorConfiguration, Configur
      */
     @Override
     public ConfigurationImpl constraintValidatorFactory(ConstraintValidatorFactory constraintFactory) {
-        if (constraintFactory == null) {
-            return this;
+        if (constraintFactory != null) {
+            this.constraintValidatorFactoryClass = null;
+            this.constraintValidatorFactory = constraintFactory;
+            this.prepared = false;
         }
-
-        this.constraintValidatorFactoryClass = null;
-        this.constraintValidatorFactory = constraintFactory;
-        this.prepared = false;
         return this;
     }
 
     @Override
     public ApacheValidatorConfiguration parameterNameProvider(ParameterNameProvider parameterNameProvider) {
-        if (parameterNameProvider == null) {
-            return this;
+        if (parameterNameProvider != null) {
+            this.parameterNameProviderClass = null;
+            this.parameterNameProvider = parameterNameProvider;
         }
-        this.parameterNameProviderClass = null;
-        this.parameterNameProvider = parameterNameProvider;
         return this;
     }
 
@@ -213,10 +214,9 @@ public class ConfigurationImpl implements ApacheValidatorConfiguration, Configur
      */
     @Override
     public ApacheValidatorConfiguration addMapping(InputStream stream) {
-        if (stream == null) {
-            return this;
+        if (stream != null) {
+            mappingStreams.add(IOs.convertToMarkableInputStream(stream));
         }
-        mappingStreams.add(IOs.convertToMarkableInputStream(stream));
         return this;
     }
 
@@ -297,7 +297,6 @@ public class ConfigurationImpl implements ApacheValidatorConfiguration, Configur
         if (beforeCdi) {
             return defaultMessageInterpolator;
         }
-
         if (messageInterpolator == defaultMessageInterpolator && messageInterpolatorClass != null) {
             synchronized (this) {
                 if (messageInterpolator == defaultMessageInterpolator && messageInterpolatorClass != null) {
@@ -336,7 +335,6 @@ public class ConfigurationImpl implements ApacheValidatorConfiguration, Configur
         if (prepared) {
             return this;
         }
-
         createBootstrapConfiguration();
         parser.applyConfigWithInstantiation(this); // instantiate the config if needed
 
@@ -367,7 +365,6 @@ public class ConfigurationImpl implements ApacheValidatorConfiguration, Configur
         if (beforeCdi) {
             return constraintValidatorFactory;
         }
-
         if (constraintValidatorFactory == defaultConstraintValidatorFactory
             && constraintValidatorFactoryClass != null) {
             synchronized (this) {
@@ -388,7 +385,6 @@ public class ConfigurationImpl implements ApacheValidatorConfiguration, Configur
         if (beforeCdi) {
             return defaultTraversableResolver;
         }
-
         if (traversableResolver == defaultTraversableResolver && traversableResolverClass != null) {
             synchronized (this) {
                 if (traversableResolver == defaultTraversableResolver && traversableResolverClass != null) {
@@ -404,7 +400,6 @@ public class ConfigurationImpl implements ApacheValidatorConfiguration, Configur
         if (beforeCdi) {
             return defaultParameterNameProvider;
         }
-
         if (parameterNameProvider == defaultParameterNameProvider && parameterNameProviderClass != null) {
             synchronized (this) {
                 if (parameterNameProvider == defaultParameterNameProvider && parameterNameProviderClass != null) {
@@ -452,14 +447,11 @@ public class ConfigurationImpl implements ApacheValidatorConfiguration, Configur
     }
 
     public Closeable getClosable() {
-        return new Closeable() {
-            @Override
-            public void close() throws IOException {
-                for (final BValExtension.Releasable<?> releasable : releasables) {
-                    releasable.release();
-                }
-                releasables.clear();
+        return () -> {
+            for (final BValExtension.Releasable<?> releasable : releasables) {
+                releasable.release();
             }
+            releasables.clear();
         };
     }
 
@@ -469,8 +461,7 @@ public class ConfigurationImpl implements ApacheValidatorConfiguration, Configur
             final BValExtension.Releasable<T> releasable = BValExtension.inject(cls);
             releasables.add(releasable);
             return releasable.getInstance();
-        } catch (final Exception e) {
-        } catch (final NoClassDefFoundError error) {
+        } catch (Exception | NoClassDefFoundError e) {
         }
         try {
             return cls.newInstance();
@@ -494,4 +485,45 @@ public class ConfigurationImpl implements ApacheValidatorConfiguration, Configur
     public void parameterNameProviderClass(final Class<? extends ParameterNameProvider> clazz) {
         parameterNameProviderClass = clazz;
     }
+
+    @Override
+    public ApacheValidatorConfiguration clockProvider(ClockProvider clockProvider) {
+        this.clockProvider = clockProvider;
+        return this;
+    }
+
+    @Override
+    public ApacheValidatorConfiguration addValueExtractor(ValueExtractor<?> extractor) {
+        valueExtractors.add(extractor);
+        return this;
+    }
+
+    @Override
+    public ClockProvider getDefaultClockProvider() {
+        return defaultClockProvider;
+    }
+
+    @Override
+    public Set<ValueExtractor<?>> getValueExtractors() {
+        return Collections.unmodifiableSet(valueExtractors);
+    }
+
+    @Override
+    public ClockProvider getClockProvider() {
+        if (beforeCdi) {
+            return defaultClockProvider;
+        }
+        if (clockProvider == defaultClockProvider && clockProviderClass != null) {
+            synchronized (this) {
+                if (clockProvider == defaultClockProvider && clockProviderClass != null) {
+                    clockProvider = newInstance(clockProviderClass);
+                }
+            }
+        }
+        return clockProvider;
+    }
+
+    protected void initializePropertyDefaults() {
+        properties.put(Properties.CONSTRAINTS_CACHE_SIZE, Integer.toString(50));
+    }
 }

http://git-wip-us.apache.org/repos/asf/bval/blob/3f287a7a/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/3f287a7a/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/3f287a7a/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/3f287a7a/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/3f287a7a/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/3f287a7a/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/3f287a7a/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);
     }
 
 }