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/03/01 18:13:57 UTC

bval git commit: extract ValidateExecutable to properly handle method/ctor path nodes in parameter/return value validation jobs, which urged greater depth of generics throughout the descriptor package and underlying structures

Repository: bval
Updated Branches:
  refs/heads/bv2 f28324ea4 -> 8689861e0


extract ValidateExecutable to properly handle method/ctor path nodes in parameter/return value validation jobs, which urged greater depth of generics throughout the descriptor package and underlying structures


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

Branch: refs/heads/bv2
Commit: 8689861e0af8fecb6af6bd2c71539e186e9e21fd
Parents: f28324e
Author: Matt Benson <mb...@apache.org>
Authored: Thu Mar 1 12:13:49 2018 -0600
Committer: Matt Benson <mb...@apache.org>
Committed: Thu Mar 1 12:13:49 2018 -0600

----------------------------------------------------------------------
 .../org/apache/bval/jsr/descriptor/BeanD.java   | 10 +--
 .../bval/jsr/descriptor/ConstructorD.java       |  6 +-
 .../bval/jsr/descriptor/DescriptorManager.java  | 21 +++---
 .../apache/bval/jsr/descriptor/ElementD.java    |  4 +-
 .../apache/bval/jsr/descriptor/ExecutableD.java |  4 +-
 .../bval/jsr/descriptor/MetadataReader.java     | 33 +++++----
 .../org/apache/bval/jsr/descriptor/MethodD.java |  2 +-
 .../apache/bval/jsr/descriptor/PropertyD.java   |  8 +-
 .../org/apache/bval/jsr/job/ValidateBean.java   |  4 +-
 .../apache/bval/jsr/job/ValidateExecutable.java | 71 ++++++++++++++++++
 .../apache/bval/jsr/job/ValidateParameters.java | 33 ++-------
 .../apache/bval/jsr/job/ValidateProperty.java   | 28 ++++---
 .../bval/jsr/job/ValidateReturnValue.java       | 10 +--
 .../org/apache/bval/jsr/job/ValidationJob.java  |  9 ++-
 .../bval/jsr/metadata/CompositeBuilder.java     | 28 +++----
 .../apache/bval/jsr/metadata/DualBuilder.java   | 34 ++++-----
 .../apache/bval/jsr/metadata/EmptyBuilder.java  | 22 +++---
 .../bval/jsr/metadata/HierarchyBuilder.java     | 78 +++++++++++++-------
 .../java/org/apache/bval/jsr/metadata/Meta.java | 15 ++--
 .../bval/jsr/metadata/MetadataBuilder.java      | 16 ++--
 .../bval/jsr/metadata/MetadataBuilders.java     |  9 ++-
 .../bval/jsr/metadata/ReflectionBuilder.java    | 32 ++++----
 .../apache/bval/jsr/metadata/XmlBuilder.java    | 24 +++---
 .../bval/jsr/xml/ValidationMappingParser.java   |  5 +-
 .../apache/bval/util/reflection/Reflection.java |  5 +-
 .../bval/jsr/groups/GroupSequenceTest.java      |  8 +-
 26 files changed, 307 insertions(+), 212 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/bval/blob/8689861e/bval-jsr/src/main/java/org/apache/bval/jsr/descriptor/BeanD.java
----------------------------------------------------------------------
diff --git a/bval-jsr/src/main/java/org/apache/bval/jsr/descriptor/BeanD.java b/bval-jsr/src/main/java/org/apache/bval/jsr/descriptor/BeanD.java
index 0fa44f1..caf567b 100644
--- a/bval-jsr/src/main/java/org/apache/bval/jsr/descriptor/BeanD.java
+++ b/bval-jsr/src/main/java/org/apache/bval/jsr/descriptor/BeanD.java
@@ -36,16 +36,16 @@ import org.apache.bval.jsr.util.ToUnmodifiable;
 import org.apache.bval.util.Exceptions;
 import org.apache.bval.util.StringUtils;
 
-public class BeanD extends ElementD<Class<?>, MetadataReader.ForBean> implements BeanDescriptor {
+public class BeanD<T> extends ElementD<Class<T>, MetadataReader.ForBean<T>> implements BeanDescriptor {
 
-    private final Class<?> beanClass;
+    private final Class<T> beanClass;
     private final List<Class<?>> groupSequence;
     private final Map<String, PropertyDescriptor> propertiesMap;
     private final Set<PropertyDescriptor> properties;
-    private final Map<Signature, ConstructorD> constructors;
+    private final Map<Signature, ConstructorD<T>> constructors;
     private final Map<Signature, MethodD> methods;
 
-    BeanD(MetadataReader.ForBean reader) {
+    BeanD(MetadataReader.ForBean<T> reader) {
         super(reader);
         this.beanClass = reader.meta.getHost();
 
@@ -107,7 +107,7 @@ public class BeanD extends ElementD<Class<?>, MetadataReader.ForBean> implements
     }
 
     @Override
-    protected BeanD getBean() {
+    protected BeanD<T> getBean() {
         return this;
     }
 

http://git-wip-us.apache.org/repos/asf/bval/blob/8689861e/bval-jsr/src/main/java/org/apache/bval/jsr/descriptor/ConstructorD.java
----------------------------------------------------------------------
diff --git a/bval-jsr/src/main/java/org/apache/bval/jsr/descriptor/ConstructorD.java b/bval-jsr/src/main/java/org/apache/bval/jsr/descriptor/ConstructorD.java
index b89d29c..2385384 100644
--- a/bval-jsr/src/main/java/org/apache/bval/jsr/descriptor/ConstructorD.java
+++ b/bval-jsr/src/main/java/org/apache/bval/jsr/descriptor/ConstructorD.java
@@ -22,10 +22,10 @@ import java.lang.reflect.Constructor;
 
 import javax.validation.metadata.ConstructorDescriptor;
 
-public class ConstructorD extends ExecutableD<Constructor<?>, MetadataReader.ForConstructor, ConstructorD>
+public class ConstructorD<T> extends ExecutableD<Constructor<? extends T>, MetadataReader.ForConstructor<T>, ConstructorD<T>>
     implements ConstructorDescriptor {
 
-    ConstructorD(MetadataReader.ForConstructor reader, BeanD parent) {
+    ConstructorD(MetadataReader.ForConstructor<T> reader, BeanD<T> parent) {
         super(reader, parent);
     }
 
@@ -35,7 +35,7 @@ public class ConstructorD extends ExecutableD<Constructor<?>, MetadataReader.For
     }
 
     @Override
-    protected String nameOf(Constructor<?> e) {
+    protected String nameOf(Constructor<? extends T> e) {
         return e.getDeclaringClass().getSimpleName();
     }
 }

http://git-wip-us.apache.org/repos/asf/bval/blob/8689861e/bval-jsr/src/main/java/org/apache/bval/jsr/descriptor/DescriptorManager.java
----------------------------------------------------------------------
diff --git a/bval-jsr/src/main/java/org/apache/bval/jsr/descriptor/DescriptorManager.java b/bval-jsr/src/main/java/org/apache/bval/jsr/descriptor/DescriptorManager.java
index 279560d..0f1a13a 100644
--- a/bval-jsr/src/main/java/org/apache/bval/jsr/descriptor/DescriptorManager.java
+++ b/bval-jsr/src/main/java/org/apache/bval/jsr/descriptor/DescriptorManager.java
@@ -40,7 +40,7 @@ public class DescriptorManager {
     }
 
     private final ApacheValidatorFactory validatorFactory;
-    private final ConcurrentMap<Class<?>, BeanD> beanDescriptors = new ConcurrentHashMap<>();
+    private final ConcurrentMap<Class<?>, BeanD<?>> beanDescriptors = new ConcurrentHashMap<>();
     private final ReflectionBuilder reflectionBuilder;
     private final MetadataReader metadataReader;
 
@@ -51,33 +51,36 @@ public class DescriptorManager {
         this.metadataReader = new MetadataReader(validatorFactory);
     }
 
-    public BeanDescriptor getBeanDescriptor(Class<?> beanClass) {
+    public <T> BeanDescriptor getBeanDescriptor(Class<T> beanClass) {
         Validate.notNull(beanClass, IllegalArgumentException::new, "beanClass");
 
         // cannot use computeIfAbsent due to recursion being the usual case:
         if (beanDescriptors.containsKey(beanClass)) {
             return beanDescriptors.get(beanClass);
         }
-        final BeanD beanD = new BeanD(metadataReader.forBean(beanClass, builder(beanClass)));
-        return Optional.ofNullable(beanDescriptors.putIfAbsent(beanClass, beanD)).orElse(beanD);
+        final BeanD<T> beanD = new BeanD<>(metadataReader.forBean(beanClass, builder(beanClass)));
+        @SuppressWarnings("unchecked")
+        final BeanD<T> result =
+            Optional.ofNullable((BeanD<T>) beanDescriptors.putIfAbsent(beanClass, beanD)).orElse(beanD);
+        return result;
     }
 
     public void clear() {
         beanDescriptors.clear();
     }
 
-    private MetadataBuilder.ForBean builder(Class<?> beanClass) {
-        final MetadataBuilder.ForBean primaryBuilder =
+    private <T> MetadataBuilder.ForBean<T> builder(Class<T> beanClass) {
+        final MetadataBuilder.ForBean<T> primaryBuilder =
             new HierarchyBuilder(validatorFactory, reflectionBuilder::forBean).forBean(beanClass);
 
-        final MetadataBuilder.ForBean customBuilder =
+        final MetadataBuilder.ForBean<T> customBuilder =
             new HierarchyBuilder(validatorFactory, this::customBuilder).forBean(beanClass);
 
         return customBuilder.isEmpty() ? primaryBuilder : DualBuilder.forBean(primaryBuilder, customBuilder);
     }
 
-    private MetadataBuilder.ForBean customBuilder(Class<?> beanClass) {
-        final List<MetadataBuilder.ForBean> customBuilders =
+    private <T> MetadataBuilder.ForBean<T> customBuilder(Class<T> beanClass) {
+        final List<MetadataBuilder.ForBean<T>> customBuilders =
             validatorFactory.getMetadataBuilders().getCustomBuilders(beanClass);
 
         if (customBuilders.isEmpty()) {

http://git-wip-us.apache.org/repos/asf/bval/blob/8689861e/bval-jsr/src/main/java/org/apache/bval/jsr/descriptor/ElementD.java
----------------------------------------------------------------------
diff --git a/bval-jsr/src/main/java/org/apache/bval/jsr/descriptor/ElementD.java b/bval-jsr/src/main/java/org/apache/bval/jsr/descriptor/ElementD.java
index c139773..249b555 100644
--- a/bval-jsr/src/main/java/org/apache/bval/jsr/descriptor/ElementD.java
+++ b/bval-jsr/src/main/java/org/apache/bval/jsr/descriptor/ElementD.java
@@ -60,7 +60,7 @@ public abstract class ElementD<E extends AnnotatedElement, R extends MetadataRea
         }
 
         @Override
-        final protected BeanD getBean() {
+        final protected BeanD<?> getBean() {
             return parent.getBean();
         }
 
@@ -113,7 +113,7 @@ public abstract class ElementD<E extends AnnotatedElement, R extends MetadataRea
 
     public abstract List<Class<?>> getGroupSequence();
 
-    protected abstract BeanD getBean();
+    protected abstract BeanD<?> getBean();
 
     @Override
     public String toString() {

http://git-wip-us.apache.org/repos/asf/bval/blob/8689861e/bval-jsr/src/main/java/org/apache/bval/jsr/descriptor/ExecutableD.java
----------------------------------------------------------------------
diff --git a/bval-jsr/src/main/java/org/apache/bval/jsr/descriptor/ExecutableD.java b/bval-jsr/src/main/java/org/apache/bval/jsr/descriptor/ExecutableD.java
index db3df6c..4cbb22f 100644
--- a/bval-jsr/src/main/java/org/apache/bval/jsr/descriptor/ExecutableD.java
+++ b/bval-jsr/src/main/java/org/apache/bval/jsr/descriptor/ExecutableD.java
@@ -27,7 +27,7 @@ import javax.validation.metadata.ParameterDescriptor;
 import javax.validation.metadata.ReturnValueDescriptor;
 
 public abstract class ExecutableD<E extends Executable, R extends MetadataReader.ForExecutable<E, R>, SELF extends ExecutableD<E, R, SELF>>
-    extends ElementD.NonRoot<BeanD, E, R> implements ExecutableDescriptor {
+    extends ElementD.NonRoot<BeanD<?>, E, R> implements ExecutableDescriptor {
 
     private final String name;
     private final ReturnValueD<SELF, E> returnValue;
@@ -35,7 +35,7 @@ public abstract class ExecutableD<E extends Executable, R extends MetadataReader
     private final CrossParameterD<SELF, E> crossParameter;
 
     @SuppressWarnings("unchecked")
-    protected ExecutableD(R reader, BeanD parent) {
+    protected ExecutableD(R reader, BeanD<?> parent) {
         super(reader, parent);
 
         name = reader.meta.getName();

http://git-wip-us.apache.org/repos/asf/bval/blob/8689861e/bval-jsr/src/main/java/org/apache/bval/jsr/descriptor/MetadataReader.java
----------------------------------------------------------------------
diff --git a/bval-jsr/src/main/java/org/apache/bval/jsr/descriptor/MetadataReader.java b/bval-jsr/src/main/java/org/apache/bval/jsr/descriptor/MetadataReader.java
index 2e9a31f..177b5c0 100644
--- a/bval-jsr/src/main/java/org/apache/bval/jsr/descriptor/MetadataReader.java
+++ b/bval-jsr/src/main/java/org/apache/bval/jsr/descriptor/MetadataReader.java
@@ -53,8 +53,8 @@ import org.apache.bval.jsr.ApacheValidatorFactory;
 import org.apache.bval.jsr.groups.GroupConversion;
 import org.apache.bval.jsr.metadata.ContainerElementKey;
 import org.apache.bval.jsr.metadata.EmptyBuilder;
-import org.apache.bval.jsr.metadata.MetadataBuilder;
 import org.apache.bval.jsr.metadata.Meta;
+import org.apache.bval.jsr.metadata.MetadataBuilder;
 import org.apache.bval.jsr.metadata.Signature;
 import org.apache.bval.jsr.util.Methods;
 import org.apache.bval.jsr.util.ToUnmodifiable;
@@ -84,15 +84,15 @@ class MetadataReader {
         }
     }
 
-    class ForBean extends MetadataReader.ForElement<Class<?>, MetadataBuilder.ForClass> {
-        private final MetadataBuilder.ForBean beanBuilder;
+    class ForBean<T> extends MetadataReader.ForElement<Class<T>, MetadataBuilder.ForClass<T>> {
+        private final MetadataBuilder.ForBean<T> beanBuilder;
 
-        ForBean(Meta<Class<?>> meta, MetadataBuilder.ForBean builder) {
+        ForBean(Meta<Class<T>> meta, MetadataBuilder.ForBean<T> builder) {
             super(meta, Validate.notNull(builder, "builder").getClass(meta));
             this.beanBuilder = builder;
         }
 
-        Map<String, PropertyDescriptor> getProperties(BeanD parent) {
+        Map<String, PropertyDescriptor> getProperties(BeanD<T> parent) {
             final Map<String, List<PropertyD<?>>> properties = new LinkedHashMap<>();
             final Function<? super String, ? extends List<PropertyD<?>>> descriptorList = k -> new ArrayList<>();
 
@@ -129,7 +129,7 @@ class MetadataReader {
             }));
         }
 
-        Map<Signature, MethodD> getMethods(BeanD parent) {
+        Map<Signature, MethodD> getMethods(BeanD<T> parent) {
             final Map<Signature, MetadataBuilder.ForExecutable<Method>> methodBuilders = beanBuilder.getMethods(meta);
             if (methodBuilders.isEmpty()) {
                 return Collections.emptyMap();
@@ -145,19 +145,20 @@ class MetadataReader {
             return Collections.unmodifiableMap(result);
         }
 
-        Map<Signature, ConstructorD> getConstructors(BeanD parent) {
-            final Map<Signature, MetadataBuilder.ForExecutable<Constructor<?>>> ctorBuilders =
+        Map<Signature, ConstructorD<T>> getConstructors(BeanD<T> parent) {
+            final Map<Signature, MetadataBuilder.ForExecutable<Constructor<? extends T>>> ctorBuilders =
                 beanBuilder.getConstructors(meta);
 
             if (ctorBuilders.isEmpty()) {
                 return Collections.emptyMap();
             }
-            final Map<Signature, ConstructorD> result = new LinkedHashMap<>();
+            final Map<Signature, ConstructorD<T>> result = new LinkedHashMap<>();
 
             ctorBuilders.forEach((sig, builder) -> {
                 final Constructor<?> c = Reflection.getDeclaredConstructor(meta.getHost(), sig.getParameterTypes());
-                result.put(sig,
-                    new ConstructorD(new MetadataReader.ForConstructor(new Meta.ForConstructor(c), builder), parent));
+                @SuppressWarnings({ "unchecked", "rawtypes" })
+                final Meta.ForConstructor<T> metaCtor = (Meta.ForConstructor) new Meta.ForConstructor<>(c);
+                result.put(sig, new ConstructorD<>(new MetadataReader.ForConstructor<T>(metaCtor, builder), parent));
             });
             return Collections.unmodifiableMap(result);
         }
@@ -283,14 +284,14 @@ class MetadataReader {
         }
     }
 
-    class ForConstructor extends ForExecutable<Constructor<?>, ForConstructor> {
+    class ForConstructor<T> extends ForExecutable<Constructor<? extends T>, ForConstructor<T>> {
 
-        ForConstructor(Meta<Constructor<?>> meta, MetadataBuilder.ForExecutable<Constructor<?>> builder) {
+        ForConstructor(Meta<Constructor<? extends T>> meta, MetadataBuilder.ForExecutable<Constructor<? extends T>> builder) {
             super(meta, builder);
         }
 
         @Override
-        List<String> getParameterNames(ParameterNameProvider parameterNameProvider, Constructor<?> host) {
+        List<String> getParameterNames(ParameterNameProvider parameterNameProvider, Constructor<? extends T> host) {
             return parameterNameProvider.getParameterNames(host);
         }
     }
@@ -302,7 +303,7 @@ class MetadataReader {
         this.validatorFactory = Validate.notNull(validatorFactory, "validatorFactory");
     }
 
-    MetadataReader.ForBean forBean(Class<?> beanClass, MetadataBuilder.ForBean builder) {
-        return new MetadataReader.ForBean(new Meta.ForClass(beanClass), builder);
+    <T> MetadataReader.ForBean<T> forBean(Class<T> beanClass, MetadataBuilder.ForBean<T> builder) {
+        return new MetadataReader.ForBean<>(new Meta.ForClass<>(beanClass), builder);
     }
 }

http://git-wip-us.apache.org/repos/asf/bval/blob/8689861e/bval-jsr/src/main/java/org/apache/bval/jsr/descriptor/MethodD.java
----------------------------------------------------------------------
diff --git a/bval-jsr/src/main/java/org/apache/bval/jsr/descriptor/MethodD.java b/bval-jsr/src/main/java/org/apache/bval/jsr/descriptor/MethodD.java
index 647569d..73585b5 100644
--- a/bval-jsr/src/main/java/org/apache/bval/jsr/descriptor/MethodD.java
+++ b/bval-jsr/src/main/java/org/apache/bval/jsr/descriptor/MethodD.java
@@ -28,7 +28,7 @@ import org.apache.bval.jsr.util.Methods;
 class MethodD extends ExecutableD<Method, MetadataReader.ForMethod, MethodD> implements MethodDescriptor {
     private final MethodType methodType;
 
-    MethodD(MetadataReader.ForMethod reader, BeanD parent) {
+    MethodD(MetadataReader.ForMethod reader, BeanD<?> parent) {
         super(reader, parent);
         methodType = Methods.isGetter(reader.meta.getHost()) ? MethodType.GETTER : MethodType.NON_GETTER;
     }

http://git-wip-us.apache.org/repos/asf/bval/blob/8689861e/bval-jsr/src/main/java/org/apache/bval/jsr/descriptor/PropertyD.java
----------------------------------------------------------------------
diff --git a/bval-jsr/src/main/java/org/apache/bval/jsr/descriptor/PropertyD.java b/bval-jsr/src/main/java/org/apache/bval/jsr/descriptor/PropertyD.java
index 818e7e0..c7c2eff 100644
--- a/bval-jsr/src/main/java/org/apache/bval/jsr/descriptor/PropertyD.java
+++ b/bval-jsr/src/main/java/org/apache/bval/jsr/descriptor/PropertyD.java
@@ -33,12 +33,12 @@ import org.apache.commons.weaver.privilizer.Privilizing;
 import org.apache.commons.weaver.privilizer.Privilizing.CallTo;
 
 @Privilizing(@CallTo(Reflection.class))
-public abstract class PropertyD<E extends AnnotatedElement> extends CascadableContainerD<BeanD, E>
+public abstract class PropertyD<E extends AnnotatedElement> extends CascadableContainerD<BeanD<?>, E>
     implements PropertyDescriptor {
 
     static class ForField extends PropertyD<Field> {
 
-        ForField(MetadataReader.ForContainer<Field> reader, BeanD parent) {
+        ForField(MetadataReader.ForContainer<Field> reader, BeanD<?> parent) {
             super(reader, parent);
         }
 
@@ -64,7 +64,7 @@ public abstract class PropertyD<E extends AnnotatedElement> extends CascadableCo
 
     static class ForMethod extends PropertyD<Method> {
 
-        ForMethod(MetadataReader.ForContainer<Method> reader, BeanD parent) {
+        ForMethod(MetadataReader.ForContainer<Method> reader, BeanD<?> parent) {
             super(reader, parent);
         }
 
@@ -90,7 +90,7 @@ public abstract class PropertyD<E extends AnnotatedElement> extends CascadableCo
 
     protected final E host;
 
-    protected PropertyD(MetadataReader.ForContainer<E> reader, BeanD parent) {
+    protected PropertyD(MetadataReader.ForContainer<E> reader, BeanD<?> parent) {
         super(reader, parent);
         this.host = reader.meta.getHost();
     }

http://git-wip-us.apache.org/repos/asf/bval/blob/8689861e/bval-jsr/src/main/java/org/apache/bval/jsr/job/ValidateBean.java
----------------------------------------------------------------------
diff --git a/bval-jsr/src/main/java/org/apache/bval/jsr/job/ValidateBean.java b/bval-jsr/src/main/java/org/apache/bval/jsr/job/ValidateBean.java
index 3331c17..f533314 100644
--- a/bval-jsr/src/main/java/org/apache/bval/jsr/job/ValidateBean.java
+++ b/bval-jsr/src/main/java/org/apache/bval/jsr/job/ValidateBean.java
@@ -38,8 +38,8 @@ public final class ValidateBean<T> extends ValidationJob<T> {
     }
 
     @Override
-    protected Frame<BeanD> computeBaseFrame() {
-        return new BeanFrame(new GraphContext(validatorContext, PathImpl.create(), bean));
+    protected Frame<BeanD<T>> computeBaseFrame() {
+        return new BeanFrame<T>(new GraphContext(validatorContext, PathImpl.create(), bean));
     }
 
     @SuppressWarnings("unchecked")

http://git-wip-us.apache.org/repos/asf/bval/blob/8689861e/bval-jsr/src/main/java/org/apache/bval/jsr/job/ValidateExecutable.java
----------------------------------------------------------------------
diff --git a/bval-jsr/src/main/java/org/apache/bval/jsr/job/ValidateExecutable.java b/bval-jsr/src/main/java/org/apache/bval/jsr/job/ValidateExecutable.java
new file mode 100644
index 0000000..8d835e0
--- /dev/null
+++ b/bval-jsr/src/main/java/org/apache/bval/jsr/job/ValidateExecutable.java
@@ -0,0 +1,71 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.bval.jsr.job;
+
+import java.lang.annotation.ElementType;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Executable;
+import java.lang.reflect.Method;
+import java.util.Arrays;
+import java.util.function.Function;
+
+import javax.validation.Path;
+import javax.validation.Path.Node;
+
+import org.apache.bval.jsr.ApacheFactoryContext;
+import org.apache.bval.jsr.metadata.Meta;
+import org.apache.bval.jsr.util.NodeImpl;
+import org.apache.bval.jsr.util.PathImpl;
+import org.apache.bval.util.Exceptions;
+import org.apache.bval.util.Validate;
+
+public abstract class ValidateExecutable<E extends Executable, T> extends ValidationJob<T> {
+    private static final Function<Method, Path.Node> METHOD_NODE =
+        m -> new NodeImpl.MethodNodeImpl(m.getName(), Arrays.asList(m.getParameterTypes()));
+
+    private static final Function<Constructor<?>, Path.Node> CONSTRUCTOR_NODE =
+        c -> new NodeImpl.ConstructorNodeImpl(c.getDeclaringClass().getSimpleName(),
+            Arrays.asList(c.getParameterTypes()));
+
+    protected final E executable;
+
+    private final Function<E, Path.Node> executableNode;
+
+    @SuppressWarnings("unchecked")
+    public ValidateExecutable(ApacheFactoryContext validatorContext, Class<?>[] groups, Meta<E> meta) {
+        super(validatorContext, groups);
+        this.executable = Validate.notNull(meta, IllegalArgumentException::new, "meta").getHost();
+
+        switch (meta.getElementType()) {
+        case CONSTRUCTOR:
+            executableNode = (Function<E, Node>) CONSTRUCTOR_NODE;
+            break;
+        case METHOD:
+            executableNode = (Function<E, Node>) METHOD_NODE;
+            break;
+        default:
+            throw Exceptions.create(IllegalArgumentException::new, "Unsupported %s: %s",
+                ElementType.class.getSimpleName(), meta);
+        }
+    }
+
+    protected PathImpl createBasePath() {
+        final PathImpl path = PathImpl.create();
+        path.addNode(executableNode.apply(executable));
+        return path;
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/bval/blob/8689861e/bval-jsr/src/main/java/org/apache/bval/jsr/job/ValidateParameters.java
----------------------------------------------------------------------
diff --git a/bval-jsr/src/main/java/org/apache/bval/jsr/job/ValidateParameters.java b/bval-jsr/src/main/java/org/apache/bval/jsr/job/ValidateParameters.java
index dab98b0..ce93eaf 100644
--- a/bval-jsr/src/main/java/org/apache/bval/jsr/job/ValidateParameters.java
+++ b/bval-jsr/src/main/java/org/apache/bval/jsr/job/ValidateParameters.java
@@ -22,7 +22,6 @@ import java.lang.reflect.Constructor;
 import java.lang.reflect.Executable;
 import java.lang.reflect.Method;
 import java.lang.reflect.Type;
-import java.util.Arrays;
 import java.util.List;
 import java.util.function.Consumer;
 import java.util.stream.IntStream;
@@ -30,7 +29,6 @@ import java.util.stream.IntStream;
 import javax.validation.ConstraintViolation;
 import javax.validation.ParameterNameProvider;
 import javax.validation.Path;
-import javax.validation.Path.Node;
 import javax.validation.metadata.ExecutableDescriptor;
 
 import org.apache.bval.jsr.ApacheFactoryContext;
@@ -39,6 +37,7 @@ import org.apache.bval.jsr.GraphContext;
 import org.apache.bval.jsr.descriptor.ConstraintD;
 import org.apache.bval.jsr.descriptor.CrossParameterD;
 import org.apache.bval.jsr.descriptor.ParameterD;
+import org.apache.bval.jsr.metadata.Meta;
 import org.apache.bval.jsr.util.NodeImpl;
 import org.apache.bval.jsr.util.PathImpl;
 import org.apache.bval.util.Exceptions;
@@ -46,7 +45,7 @@ import org.apache.bval.util.Lazy;
 import org.apache.bval.util.Validate;
 import org.apache.bval.util.reflection.TypeUtils;
 
-public abstract class ValidateParameters<E extends Executable, T> extends ValidationJob<T> {
+public abstract class ValidateParameters<E extends Executable, T> extends ValidateExecutable<E, T> {
 
     public static class ForMethod<T> extends ValidateParameters<Method, T> {
 
@@ -54,7 +53,7 @@ public abstract class ValidateParameters<E extends Executable, T> extends Valida
 
         ForMethod(ApacheFactoryContext validatorContext, T object, Method executable, Object[] parameterValues,
             Class<?>[] groups) {
-            super(validatorContext, object, executable, parameterValues, groups);
+            super(validatorContext, object, executable, parameterValues, groups, new Meta.ForMethod(executable));
             this.object = Validate.notNull(object, IllegalArgumentException::new, "object");
         }
 
@@ -79,18 +78,13 @@ public abstract class ValidateParameters<E extends Executable, T> extends Valida
         protected T getRootBean() {
             return object;
         }
-
-        @Override
-        protected Node executableNode() {
-            return new NodeImpl.MethodNodeImpl(executable.getName(), Arrays.asList(executable.getParameterTypes()));
-        }
     }
 
     public static class ForConstructor<T> extends ValidateParameters<Constructor<? extends T>, T> {
 
         ForConstructor(ApacheFactoryContext validatorContext, Constructor<? extends T> executable,
             Object[] parameterValues, Class<?>[] groups) {
-            super(validatorContext, null, executable, parameterValues, groups);
+            super(validatorContext, null, executable, parameterValues, groups, new Meta.ForConstructor<>(executable));
         }
 
         @Override
@@ -114,12 +108,6 @@ public abstract class ValidateParameters<E extends Executable, T> extends Valida
         protected T getRootBean() {
             return null;
         }
-
-        @Override
-        protected Node executableNode() {
-            return new NodeImpl.ConstructorNodeImpl(executable.getDeclaringClass().getSimpleName(),
-                Arrays.asList(executable.getParameterTypes()));
-        }
     }
 
     class ParametersFrame extends Frame<CrossParameterD<?, ?>> {
@@ -147,17 +135,15 @@ public abstract class ValidateParameters<E extends Executable, T> extends Valida
     private static final String PARAMETERS_DO_NOT_MATCH = "Parameters do not match";
 
     protected final T object;
-    protected final E executable;
     protected final Lazy<List<String>> parameterNames =
         new Lazy<>(() -> getParameterNames(validatorContext.getParameterNameProvider()));
 
     private final Object[] parameterValues;
 
     ValidateParameters(ApacheFactoryContext validatorContext, T object, E executable, Object[] parameterValues,
-        Class<?>[] groups) {
-        super(validatorContext, groups);
+        Class<?>[] groups, Meta<E> meta) {
+        super(validatorContext, groups, meta);
         this.object = object;
-        this.executable = Validate.notNull(executable, IllegalArgumentException::new, "executable");
         this.parameterValues =
             Validate.notNull(parameterValues, IllegalArgumentException::new, "parameterValues").clone();
 
@@ -171,16 +157,13 @@ public abstract class ValidateParameters<E extends Executable, T> extends Valida
 
     @Override
     protected Frame<?> computeBaseFrame() {
-        final PathImpl cp = PathImpl.create();
-        cp.addNode(executableNode());
+        final PathImpl cp = createBasePath();
         cp.addNode(new NodeImpl.CrossParameterNodeImpl());
         return new ParametersFrame(describe(), new GraphContext(validatorContext, cp, parameterValues));
     }
 
     protected abstract ExecutableDescriptor describe();
 
-    protected abstract Path.Node executableNode();
-
     protected abstract List<String> getParameterNames(ParameterNameProvider parameterNameProvider);
 
     protected abstract T getRootBean();
@@ -194,7 +177,7 @@ public abstract class ValidateParameters<E extends Executable, T> extends Valida
     }
 
     private GraphContext parameter(int i) {
-        final PathImpl path = PathImpl.create();
+        final PathImpl path = createBasePath();
         path.addNode(new NodeImpl.ParameterNodeImpl(parameterNames.get().get(i), i));
         return new GraphContext(validatorContext, path, parameterValues[i]);
     }

http://git-wip-us.apache.org/repos/asf/bval/blob/8689861e/bval-jsr/src/main/java/org/apache/bval/jsr/job/ValidateProperty.java
----------------------------------------------------------------------
diff --git a/bval-jsr/src/main/java/org/apache/bval/jsr/job/ValidateProperty.java b/bval-jsr/src/main/java/org/apache/bval/jsr/job/ValidateProperty.java
index 59bd636..e3ec306 100644
--- a/bval-jsr/src/main/java/org/apache/bval/jsr/job/ValidateProperty.java
+++ b/bval-jsr/src/main/java/org/apache/bval/jsr/job/ValidateProperty.java
@@ -107,9 +107,9 @@ public final class ValidateProperty<T> extends ValidationJob<T> {
         @Override
         public ValidateProperty<T>.Frame<?> frame(ValidateProperty<T> job, PathImpl path) {
             if (job.descriptor instanceof BeanDescriptor) {
-                return job.new LeafFrame(leafContext.get());
+                return job.new LeafFrame<>(leafContext.get());
             }
-            return job.new PropertyFrame<PropertyD<?>>(job.new BeanFrame(leafContext.get()),
+            return job.new PropertyFrame<PropertyD<?>>(job.new BeanFrame<>(leafContext.get()),
                 (PropertyD<?>) job.descriptor, leafContext.get().child(path, value.get()));
         }
     }
@@ -126,7 +126,7 @@ public final class ValidateProperty<T> extends ValidationJob<T> {
         public ValidateProperty<T>.Frame<?> frame(ValidateProperty<T> job, PathImpl path) {
             final GraphContext context = new GraphContext(job.validatorContext, path, value);
             if (job.descriptor instanceof BeanDescriptor) {
-                return job.new LeafFrame(context);
+                return job.new LeafFrame<>(context);
             }
             return job.new PropertyFrame<PropertyD<?>>(null, (PropertyD<?>) job.descriptor, context);
         }
@@ -176,7 +176,7 @@ public final class ValidateProperty<T> extends ValidationJob<T> {
         public ElementD<?, ?> element() {
             final Class<?> beanClass = TypeUtils.getRawType(type, null);
             return beanClass == null ? null
-                : (BeanD) validatorContext.getDescriptorManager().getBeanDescriptor(beanClass);
+                : (BeanD<?>) validatorContext.getDescriptorManager().getBeanDescriptor(beanClass);
         }
     }
 
@@ -192,11 +192,11 @@ public final class ValidateProperty<T> extends ValidationJob<T> {
         @Override
         public void handleProperty(String name) {
             final ElementDescriptor element = current.element();
-            final BeanD bean;
-            if (element instanceof BeanD) {
-                bean = (BeanD) element;
+            final BeanD<?> bean;
+            if (element instanceof BeanD<?>) {
+                bean = (BeanD<?>) element;
             } else {
-                bean = (BeanD) validatorContext.getDescriptorManager().getBeanDescriptor(element.getElementClass());
+                bean = (BeanD<?>) validatorContext.getDescriptorManager().getBeanDescriptor(element.getElementClass());
             }
             final PropertyDescriptor property = bean.getProperty(name);
             Exceptions.raiseIf(property == null, IllegalArgumentException::new, "Unknown property %s of %s", name,
@@ -410,7 +410,7 @@ public final class ValidateProperty<T> extends ValidationJob<T> {
         }
     }
 
-    class LeafFrame extends BeanFrame {
+    class LeafFrame<L> extends BeanFrame<L> {
 
         LeafFrame(GraphContext context) {
             super(context);
@@ -468,8 +468,14 @@ public final class ValidateProperty<T> extends ValidationJob<T> {
         this(new ForPropertyValue<>(value), validatorContext, rootBeanClass, property, groups);
         if (descriptor == null) {
             // should only occur when the root class is raw
-            descriptor = (ElementD<?, ?>) validatorContext.getDescriptorManager()
-                .getBeanDescriptor(value == null ? Object.class : value.getClass());
+
+            final Class<?> t;
+            if (value == null) {
+                t = Object.class;
+            } else {
+                t = value.getClass();
+            }
+            descriptor = (ElementD<?, ?>) validatorContext.getDescriptorManager().getBeanDescriptor(t);
         } else {
             final Class<?> propertyType = descriptor.getElementClass();
             Exceptions.raiseUnless(TypeUtils.isInstance(value, propertyType), IllegalArgumentException::new,

http://git-wip-us.apache.org/repos/asf/bval/blob/8689861e/bval-jsr/src/main/java/org/apache/bval/jsr/job/ValidateReturnValue.java
----------------------------------------------------------------------
diff --git a/bval-jsr/src/main/java/org/apache/bval/jsr/job/ValidateReturnValue.java b/bval-jsr/src/main/java/org/apache/bval/jsr/job/ValidateReturnValue.java
index 52f64da..21126a6 100644
--- a/bval-jsr/src/main/java/org/apache/bval/jsr/job/ValidateReturnValue.java
+++ b/bval-jsr/src/main/java/org/apache/bval/jsr/job/ValidateReturnValue.java
@@ -36,7 +36,7 @@ import org.apache.bval.util.Exceptions;
 import org.apache.bval.util.Validate;
 import org.apache.bval.util.reflection.TypeUtils;
 
-public abstract class ValidateReturnValue<E extends Executable, T> extends ValidationJob<T> {
+public abstract class ValidateReturnValue<E extends Executable, T> extends ValidateExecutable<E, T> {
     public static class ForMethod<T> extends ValidateReturnValue<Method, T> {
         private final T object;
 
@@ -73,7 +73,7 @@ public abstract class ValidateReturnValue<E extends Executable, T> extends Valid
         ForConstructor(ApacheFactoryContext validatorContext, Constructor<? extends T> ctor, Object returnValue,
             Class<?>[] groups) {
             super(validatorContext,
-                new Meta.ForConstructor(Validate.notNull(ctor, IllegalArgumentException::new, "ctor")), returnValue,
+                new Meta.ForConstructor<>(Validate.notNull(ctor, IllegalArgumentException::new, "ctor")), returnValue,
                 groups);
         }
 
@@ -97,17 +97,15 @@ public abstract class ValidateReturnValue<E extends Executable, T> extends Valid
         }
     }
 
-    protected final E executable;
     private final Object returnValue;
 
     ValidateReturnValue(ApacheFactoryContext validatorContext, Meta<E> meta, Object returnValue, Class<?>[] groups) {
-        super(validatorContext, groups);
+        super(validatorContext, groups, meta);
 
-        final Type type = Validate.notNull(meta, "meta").getType();
+        final Type type = Validate.notNull(meta, IllegalArgumentException::new, "meta").getType();
         Exceptions.raiseUnless(TypeUtils.isInstance(returnValue, type), IllegalArgumentException::new,
             "%s is not an instance of %s", returnValue, type);
 
-        this.executable = meta.getHost();
         this.returnValue = returnValue;
     }
 

http://git-wip-us.apache.org/repos/asf/bval/blob/8689861e/bval-jsr/src/main/java/org/apache/bval/jsr/job/ValidationJob.java
----------------------------------------------------------------------
diff --git a/bval-jsr/src/main/java/org/apache/bval/jsr/job/ValidationJob.java b/bval-jsr/src/main/java/org/apache/bval/jsr/job/ValidationJob.java
index dbcdc1c..88fd40c 100644
--- a/bval-jsr/src/main/java/org/apache/bval/jsr/job/ValidationJob.java
+++ b/bval-jsr/src/main/java/org/apache/bval/jsr/job/ValidationJob.java
@@ -203,7 +203,7 @@ public abstract class ValidationJob<T> {
         }
     }
 
-    public class BeanFrame extends Frame<BeanD> {
+    public class BeanFrame<B> extends Frame<BeanD<B>> {
 
         BeanFrame(GraphContext context) {
             this(null, context);
@@ -283,7 +283,7 @@ public abstract class ValidationJob<T> {
                     return;
                 }
             }
-            multiplex().filter(context -> context.getValue() != null).map(context -> new BeanFrame(this, context))
+            multiplex().filter(context -> context.getValue() != null).map(context -> new BeanFrame<>(this, context))
                 .forEach(b -> b.process(group, sink));
         }
 
@@ -402,9 +402,10 @@ public abstract class ValidationJob<T> {
         return true;
     }
 
-    private BeanD getBeanDescriptor(Object bean) {
+    @SuppressWarnings("unchecked")
+    private <O> BeanD<O> getBeanDescriptor(Object bean) {
         final Class<? extends Object> t = Proxies.classFor(Validate.notNull(bean, "bean").getClass());
-        return (BeanD) validatorContext.getDescriptorManager().getBeanDescriptor(t);
+        return (BeanD<O>) validatorContext.getDescriptorManager().getBeanDescriptor(t);
     }
 
     final ConstraintViolationImpl<T> createViolation(String messageTemplate, ConstraintValidatorContextImpl<T> context,

http://git-wip-us.apache.org/repos/asf/bval/blob/8689861e/bval-jsr/src/main/java/org/apache/bval/jsr/metadata/CompositeBuilder.java
----------------------------------------------------------------------
diff --git a/bval-jsr/src/main/java/org/apache/bval/jsr/metadata/CompositeBuilder.java b/bval-jsr/src/main/java/org/apache/bval/jsr/metadata/CompositeBuilder.java
index f96b37b..d8ac834 100644
--- a/bval-jsr/src/main/java/org/apache/bval/jsr/metadata/CompositeBuilder.java
+++ b/bval-jsr/src/main/java/org/apache/bval/jsr/metadata/CompositeBuilder.java
@@ -83,21 +83,21 @@ public class CompositeBuilder {
         }
     }
 
-    private class ForBean extends CompositeBuilder.Delegator<MetadataBuilder.ForBean>
-        implements MetadataBuilder.ForBean {
+    private class ForBean<T> extends CompositeBuilder.Delegator<MetadataBuilder.ForBean<T>>
+        implements MetadataBuilder.ForBean<T> {
 
-        ForBean(List<MetadataBuilder.ForBean> delegates) {
+        ForBean(List<MetadataBuilder.ForBean<T>> delegates) {
             super(delegates);
         }
 
         @Override
-        public MetadataBuilder.ForClass getClass(Meta<Class<?>> meta) {
-            return new CompositeBuilder.ForClass(
+        public MetadataBuilder.ForClass<T> getClass(Meta<Class<T>> meta) {
+            return new CompositeBuilder.ForClass<>(
                 delegates.stream().map(d -> d.getClass(meta)).collect(Collectors.toList()));
         }
 
         @Override
-        public Map<String, MetadataBuilder.ForContainer<Field>> getFields(Meta<Class<?>> meta) {
+        public Map<String, MetadataBuilder.ForContainer<Field>> getFields(Meta<Class<T>> meta) {
             return merge(b -> b.getFields(meta), (f, l) -> {
                 final Field fld = Reflection.find(meta.getHost(), t -> Reflection.getDeclaredField(t, f));
                 Exceptions.raiseIf(fld == null, IllegalStateException::new, "Could not find field %s of %s", f,
@@ -107,7 +107,7 @@ public class CompositeBuilder {
         }
 
         @Override
-        public Map<String, MetadataBuilder.ForContainer<Method>> getGetters(Meta<Class<?>> meta) {
+        public Map<String, MetadataBuilder.ForContainer<Method>> getGetters(Meta<Class<T>> meta) {
             return merge(b -> b.getGetters(meta), (g, l) -> {
                 final Method getter = Methods.getter(meta.getHost(), g);
                 Exceptions.raiseIf(getter == null, IllegalStateException::new,
@@ -117,13 +117,13 @@ public class CompositeBuilder {
         }
 
         @Override
-        public Map<Signature, MetadataBuilder.ForExecutable<Constructor<?>>> getConstructors(Meta<Class<?>> meta) {
+        public Map<Signature, MetadataBuilder.ForExecutable<Constructor<? extends T>>> getConstructors(Meta<Class<T>> meta) {
             return merge(b -> b.getConstructors(meta),
                 d -> new CompositeBuilder.ForExecutable<>(d, ParameterNameProvider::getParameterNames));
         }
 
         @Override
-        public Map<Signature, MetadataBuilder.ForExecutable<Method>> getMethods(Meta<Class<?>> meta) {
+        public Map<Signature, MetadataBuilder.ForExecutable<Method>> getMethods(Meta<Class<T>> meta) {
             return merge(b -> b.getMethods(meta),
                 d -> new CompositeBuilder.ForExecutable<>(d, ParameterNameProvider::getParameterNames));
         }
@@ -148,14 +148,14 @@ public class CompositeBuilder {
         }
     }
 
-    class ForClass extends ForElement<MetadataBuilder.ForClass, Class<?>> implements MetadataBuilder.ForClass {
+    class ForClass<T> extends ForElement<MetadataBuilder.ForClass<T>, Class<T>> implements MetadataBuilder.ForClass<T> {
 
-        ForClass(List<MetadataBuilder.ForClass> delegates) {
+        ForClass(List<MetadataBuilder.ForClass<T>> delegates) {
             super(delegates);
         }
 
         @Override
-        public List<Class<?>> getGroupSequence(Meta<Class<?>> meta) {
+        public List<Class<?>> getGroupSequence(Meta<Class<T>> meta) {
             return CompositeBuilder.this.getGroupSequence(this, meta);
         }
     }
@@ -242,7 +242,7 @@ public class CompositeBuilder {
         this.validatorFactory = Validate.notNull(validatorFactory, "validatorFactory");
     }
 
-    public Collector<MetadataBuilder.ForBean, ?, MetadataBuilder.ForBean> compose() {
+    public <T> Collector<MetadataBuilder.ForBean<T>, ?, MetadataBuilder.ForBean<T>> compose() {
         return Collectors.collectingAndThen(Collectors.toList(), CompositeBuilder.ForBean::new);
     }
 
@@ -264,7 +264,7 @@ public class CompositeBuilder {
         return Collections.singletonMap(Scope.LOCAL_ELEMENT, composite.getDeclaredConstraints(meta));
     }
 
-    protected List<Class<?>> getGroupSequence(CompositeBuilder.ForClass composite, Meta<Class<?>> meta) {
+    protected <T> List<Class<?>> getGroupSequence(CompositeBuilder.ForClass<T> composite, Meta<Class<T>> meta) {
         final List<List<Class<?>>> groupSequence =
             composite.delegates.stream().map(d -> d.getGroupSequence(meta)).collect(Collectors.toList());
         Validate.validState(groupSequence.size() <= 1,

http://git-wip-us.apache.org/repos/asf/bval/blob/8689861e/bval-jsr/src/main/java/org/apache/bval/jsr/metadata/DualBuilder.java
----------------------------------------------------------------------
diff --git a/bval-jsr/src/main/java/org/apache/bval/jsr/metadata/DualBuilder.java b/bval-jsr/src/main/java/org/apache/bval/jsr/metadata/DualBuilder.java
index 831bc38..3c6b07b 100644
--- a/bval-jsr/src/main/java/org/apache/bval/jsr/metadata/DualBuilder.java
+++ b/bval-jsr/src/main/java/org/apache/bval/jsr/metadata/DualBuilder.java
@@ -106,38 +106,38 @@ public class DualBuilder {
         }
     }
 
-    private static class ForBean extends DualBuilder.Delegator<MetadataBuilder.ForBean>
-        implements MetadataBuilder.ForBean {
+    private static class ForBean<T> extends DualBuilder.Delegator<MetadataBuilder.ForBean<T>>
+        implements MetadataBuilder.ForBean<T> {
 
-        ForBean(MetadataBuilder.ForBean primaryDelegate, MetadataBuilder.ForBean customDelegate) {
+        ForBean(MetadataBuilder.ForBean<T> primaryDelegate, MetadataBuilder.ForBean<T> customDelegate) {
             super(null, primaryDelegate, customDelegate);
         }
 
         @Override
-        public MetadataBuilder.ForClass getClass(Meta<Class<?>> meta) {
-            return new DualBuilder.ForClass(this, primaryDelegate.getClass(meta), customDelegate.getClass(meta));
+        public MetadataBuilder.ForClass<T> getClass(Meta<Class<T>> meta) {
+            return new DualBuilder.ForClass<>(this, primaryDelegate.getClass(meta), customDelegate.getClass(meta));
         }
 
         @Override
-        public Map<String, MetadataBuilder.ForContainer<Field>> getFields(Meta<Class<?>> meta) {
+        public Map<String, MetadataBuilder.ForContainer<Field>> getFields(Meta<Class<T>> meta) {
             return merge(b -> b.getFields(meta), (t, u) -> new DualBuilder.ForContainer<>(this, t, u),
                 EmptyBuilder.instance()::forContainer);
         }
 
         @Override
-        public Map<String, MetadataBuilder.ForContainer<Method>> getGetters(Meta<Class<?>> meta) {
+        public Map<String, MetadataBuilder.ForContainer<Method>> getGetters(Meta<Class<T>> meta) {
             return merge(b -> b.getGetters(meta), (t, u) -> new DualBuilder.ForContainer<>(this, t, u),
                 EmptyBuilder.instance()::forContainer);
         }
 
         @Override
-        public Map<Signature, MetadataBuilder.ForExecutable<Constructor<?>>> getConstructors(Meta<Class<?>> meta) {
+        public Map<Signature, MetadataBuilder.ForExecutable<Constructor<? extends T>>> getConstructors(Meta<Class<T>> meta) {
             return merge(b -> b.getConstructors(meta), (t, u) -> new DualBuilder.ForExecutable<>(this, t, u),
                 EmptyBuilder.instance()::forExecutable);
         }
 
         @Override
-        public Map<Signature, MetadataBuilder.ForExecutable<Method>> getMethods(Meta<Class<?>> meta) {
+        public Map<Signature, MetadataBuilder.ForExecutable<Method>> getMethods(Meta<Class<T>> meta) {
             return merge(b -> b.getMethods(meta), (t, u) -> new DualBuilder.ForExecutable<>(this, t, u),
                 EmptyBuilder.instance()::forExecutable);
         }
@@ -157,16 +157,16 @@ public class DualBuilder {
         }
     }
 
-    private static class ForClass extends ForElement<MetadataBuilder.ForClass, Class<?>>
-        implements MetadataBuilder.ForClass {
+    private static class ForClass<T> extends ForElement<MetadataBuilder.ForClass<T>, Class<T>>
+        implements MetadataBuilder.ForClass<T> {
 
-        ForClass(Delegator<?> parent, MetadataBuilder.ForClass primaryDelegate,
-            MetadataBuilder.ForClass customDelegate) {
+        ForClass(Delegator<?> parent, MetadataBuilder.ForClass<T> primaryDelegate,
+            MetadataBuilder.ForClass<T> customDelegate) {
             super(parent, primaryDelegate, customDelegate);
         }
 
         @Override
-        public List<Class<?>> getGroupSequence(Meta<Class<?>> meta) {
+        public List<Class<?>> getGroupSequence(Meta<Class<T>> meta) {
             final List<Class<?>> customGroupSequence = customDelegate.getGroupSequence(meta);
             if (customGroupSequence != null) {
                 return customGroupSequence;
@@ -236,8 +236,8 @@ public class DualBuilder {
         }
     }
 
-    public static MetadataBuilder.ForBean forBean(MetadataBuilder.ForBean primaryDelegate,
-        MetadataBuilder.ForBean customDelegate) {
-        return new DualBuilder.ForBean(primaryDelegate, customDelegate);
+    public static <T> MetadataBuilder.ForBean<T> forBean(MetadataBuilder.ForBean<T> primaryDelegate,
+        MetadataBuilder.ForBean<T> customDelegate) {
+        return new DualBuilder.ForBean<>(primaryDelegate, customDelegate);
     }
 }

http://git-wip-us.apache.org/repos/asf/bval/blob/8689861e/bval-jsr/src/main/java/org/apache/bval/jsr/metadata/EmptyBuilder.java
----------------------------------------------------------------------
diff --git a/bval-jsr/src/main/java/org/apache/bval/jsr/metadata/EmptyBuilder.java b/bval-jsr/src/main/java/org/apache/bval/jsr/metadata/EmptyBuilder.java
index 759176b..461e491 100644
--- a/bval-jsr/src/main/java/org/apache/bval/jsr/metadata/EmptyBuilder.java
+++ b/bval-jsr/src/main/java/org/apache/bval/jsr/metadata/EmptyBuilder.java
@@ -54,31 +54,33 @@ public class EmptyBuilder {
         }
     }
 
-    private class ForBean extends Level implements MetadataBuilder.ForBean {
+    private class ForBean<T> extends Level implements MetadataBuilder.ForBean<T> {
+        @SuppressWarnings("rawtypes")
         private final Lazy<EmptyBuilder.ForClass> forClass = new Lazy<>(EmptyBuilder.ForClass::new);
 
+        @SuppressWarnings("unchecked")
         @Override
-        public MetadataBuilder.ForClass getClass(Meta<Class<?>> meta) {
+        public MetadataBuilder.ForClass<T> getClass(Meta<Class<T>> meta) {
             return forClass.get();
         }
 
         @Override
-        public Map<String, MetadataBuilder.ForContainer<Field>> getFields(Meta<Class<?>> meta) {
+        public Map<String, MetadataBuilder.ForContainer<Field>> getFields(Meta<Class<T>> meta) {
             return Collections.emptyMap();
         }
 
         @Override
-        public Map<String, MetadataBuilder.ForContainer<Method>> getGetters(Meta<Class<?>> meta) {
+        public Map<String, MetadataBuilder.ForContainer<Method>> getGetters(Meta<Class<T>> meta) {
             return Collections.emptyMap();
         }
 
         @Override
-        public Map<Signature, MetadataBuilder.ForExecutable<Constructor<?>>> getConstructors(Meta<Class<?>> meta) {
+        public Map<Signature, MetadataBuilder.ForExecutable<Constructor<? extends T>>> getConstructors(Meta<Class<T>> meta) {
             return Collections.emptyMap();
         }
 
         @Override
-        public Map<Signature, MetadataBuilder.ForExecutable<Method>> getMethods(Meta<Class<?>> meta) {
+        public Map<Signature, MetadataBuilder.ForExecutable<Method>> getMethods(Meta<Class<T>> meta) {
             return Collections.emptyMap();
         }
 
@@ -96,10 +98,10 @@ public class EmptyBuilder {
         }
     }
 
-    private class ForClass extends ForElement<Class<?>> implements MetadataBuilder.ForClass {
+    private class ForClass<T> extends ForElement<Class<T>> implements MetadataBuilder.ForClass<T> {
 
         @Override
-        public List<Class<?>> getGroupSequence(Meta<Class<?>> meta) {
+        public List<Class<?>> getGroupSequence(Meta<Class<T>> meta) {
             return null;
         }
     }
@@ -145,6 +147,7 @@ public class EmptyBuilder {
     }
 
     private final AnnotationBehavior annotationBehavior;
+    @SuppressWarnings("rawtypes")
     private final Lazy<EmptyBuilder.ForBean> forBean;
     @SuppressWarnings("rawtypes")
     private final Lazy<EmptyBuilder.ForContainer> forContainer;
@@ -162,7 +165,8 @@ public class EmptyBuilder {
         forElement = new Lazy<>(EmptyBuilder.ForElement::new);
     }
 
-    public MetadataBuilder.ForBean forBean() {
+    @SuppressWarnings("unchecked")
+    public <T> MetadataBuilder.ForBean<T> forBean() {
         return forBean.get();
     }
 

http://git-wip-us.apache.org/repos/asf/bval/blob/8689861e/bval-jsr/src/main/java/org/apache/bval/jsr/metadata/HierarchyBuilder.java
----------------------------------------------------------------------
diff --git a/bval-jsr/src/main/java/org/apache/bval/jsr/metadata/HierarchyBuilder.java b/bval-jsr/src/main/java/org/apache/bval/jsr/metadata/HierarchyBuilder.java
index ea3f7cb..a028b59 100644
--- a/bval-jsr/src/main/java/org/apache/bval/jsr/metadata/HierarchyBuilder.java
+++ b/bval-jsr/src/main/java/org/apache/bval/jsr/metadata/HierarchyBuilder.java
@@ -71,47 +71,48 @@ public class HierarchyBuilder extends CompositeBuilder {
     }
 
     static abstract class ElementDelegate<E extends AnnotatedElement, T extends MetadataBuilder.ForElement<E>>
-        extends HierarchyDelegate<E, T> implements MetadataBuilder.ForElement<E> {
+        extends HierarchyDelegate<E, T> {
 
         ElementDelegate(T delegate, Meta<E> hierarchyElement) {
             super(delegate, hierarchyElement);
         }
-        
+
         Annotation[] getDeclaredConstraints() {
             return delegate.getDeclaredConstraints(hierarchyElement);
         }
-
-        @Override
-        public final Annotation[] getDeclaredConstraints(Meta<E> meta) {
-            return getDeclaredConstraints();
-        }
     }
 
-    private class BeanDelegate extends HierarchyDelegate<Class<?>, MetadataBuilder.ForBean>
-        implements MetadataBuilder.ForBean {
+    private class BeanDelegate<H, T extends H> extends HierarchyDelegate<Class<H>, MetadataBuilder.ForBean<H>>
+        implements MetadataBuilder.ForBean<T> {
 
-        BeanDelegate(MetadataBuilder.ForBean delegate, Class<?> hierarchyType) {
-            super(delegate, new Meta.ForClass(hierarchyType));
+        BeanDelegate(MetadataBuilder.ForBean<H> delegate, Class<H> hierarchyType) {
+            super(delegate, new Meta.ForClass<H>(hierarchyType));
         }
 
         @Override
-        public MetadataBuilder.ForClass getClass(Meta<Class<?>> meta) {
-            return new ClassDelegate(delegate.getClass(hierarchyElement), hierarchyElement);
+        public MetadataBuilder.ForClass<T> getClass(Meta<Class<T>> meta) {
+            return new ClassDelegate<>(delegate.getClass(hierarchyElement), hierarchyElement);
         }
 
         @Override
-        public Map<String, MetadataBuilder.ForContainer<Field>> getFields(Meta<Class<?>> meta) {
+        public Map<String, MetadataBuilder.ForContainer<Field>> getFields(Meta<Class<T>> meta) {
             return delegate.getFields(hierarchyElement);
         }
 
         @Override
-        public Map<Signature, MetadataBuilder.ForExecutable<Constructor<?>>> getConstructors(Meta<Class<?>> meta) {
+        public Map<Signature, MetadataBuilder.ForExecutable<Constructor<? extends T>>> getConstructors(Meta<Class<T>> meta) {
+            if (hierarchyElement.equals(meta)) {
+                @SuppressWarnings("unchecked")
+                final Map<Signature, MetadataBuilder.ForExecutable<Constructor<? extends T>>> result =
+                    ((MetadataBuilder.ForBean<T>) delegate).getConstructors(meta);
+                return result;
+            }
             // ignore hierarchical ctors:
-            return hierarchyElement.equals(meta) ? delegate.getConstructors(hierarchyElement) : Collections.emptyMap();
+            return Collections.emptyMap();
         }
 
         @Override
-        public Map<String, MetadataBuilder.ForContainer<Method>> getGetters(Meta<Class<?>> meta) {
+        public Map<String, MetadataBuilder.ForContainer<Method>> getGetters(Meta<Class<T>> meta) {
             final Map<String, MetadataBuilder.ForContainer<Method>> getters = delegate.getGetters(hierarchyElement);
             final Map<String, MetadataBuilder.ForContainer<Method>> result = new LinkedHashMap<>();
 
@@ -127,7 +128,7 @@ public class HierarchyBuilder extends CompositeBuilder {
         }
 
         @Override
-        public Map<Signature, MetadataBuilder.ForExecutable<Method>> getMethods(Meta<Class<?>> meta) {
+        public Map<Signature, MetadataBuilder.ForExecutable<Method>> getMethods(Meta<Class<T>> meta) {
             final Map<Signature, MetadataBuilder.ForExecutable<Method>> methods = delegate.getMethods(hierarchyElement);
             if (methods.isEmpty()) {
                 return methods;
@@ -142,17 +143,22 @@ public class HierarchyBuilder extends CompositeBuilder {
         }
     }
 
-    private class ClassDelegate extends ElementDelegate<Class<?>, MetadataBuilder.ForClass>
-        implements MetadataBuilder.ForClass {
+    private class ClassDelegate<H, T extends H> extends ElementDelegate<Class<H>, MetadataBuilder.ForClass<H>>
+        implements MetadataBuilder.ForClass<T> {
 
-        ClassDelegate(MetadataBuilder.ForClass delegate, Meta<Class<?>> hierarchyType) {
+        ClassDelegate(MetadataBuilder.ForClass<H> delegate, Meta<Class<H>> hierarchyType) {
             super(delegate, hierarchyType);
         }
 
         @Override
-        public List<Class<?>> getGroupSequence(Meta<Class<?>> meta) {
+        public List<Class<?>> getGroupSequence(Meta<Class<T>> meta) {
             return delegate.getGroupSequence(hierarchyElement);
         }
+
+        @Override
+        public Annotation[] getDeclaredConstraints(Meta<Class<T>> meta) {
+            return getDeclaredConstraints();
+        }
     }
 
     class ContainerDelegate<E extends AnnotatedElement> extends ElementDelegate<E, MetadataBuilder.ForContainer<E>>
@@ -193,6 +199,11 @@ public class HierarchyBuilder extends CompositeBuilder {
             });
             return result;
         }
+
+        @Override
+        public Annotation[] getDeclaredConstraints(Meta<E> meta) {
+            return getDeclaredConstraints();
+        }
     }
 
     private class ExecutableDelegate<E extends Executable>
@@ -241,6 +252,11 @@ public class HierarchyBuilder extends CompositeBuilder {
         CrossParameterDelegate(MetadataBuilder.ForElement<E> delegate, Meta<E> hierarchyElement) {
             super(delegate, hierarchyElement);
         }
+
+        @Override
+        public Annotation[] getDeclaredConstraints(Meta<E> meta) {
+            return getDeclaredConstraints();
+        }
     }
 
     private class ForCrossParameter<E extends Executable>
@@ -261,16 +277,17 @@ public class HierarchyBuilder extends CompositeBuilder {
         }
     }
 
-    private final Function<Class<?>, MetadataBuilder.ForBean> getBeanBuilder;
+    private final Function<Class<?>, MetadataBuilder.ForBean<?>> getBeanBuilder;
 
     public HierarchyBuilder(ApacheValidatorFactory validatorFactory,
-        Function<Class<?>, MetadataBuilder.ForBean> getBeanBuilder) {
+        Function<Class<?>, MetadataBuilder.ForBean<?>> getBeanBuilder) {
         super(validatorFactory, AnnotationBehaviorMergeStrategy.first());
         this.getBeanBuilder = Validate.notNull(getBeanBuilder, "getBeanBuilder function was null");
     }
 
-    public MetadataBuilder.ForBean forBean(Class<?> beanClass) {
-        final List<MetadataBuilder.ForBean> delegates = new ArrayList<>();
+    @SuppressWarnings({ "unchecked", "rawtypes" })
+    public <T> MetadataBuilder.ForBean<T> forBean(Class<T> beanClass) {
+        final List<MetadataBuilder.ForBean<?>> delegates = new ArrayList<>();
 
         /*
          * First add the delegate for the requested bean class, forcing to empty if absent. This is important for the
@@ -287,7 +304,12 @@ public class HierarchyBuilder extends CompositeBuilder {
         hierarchy.forEachRemaining(t -> Optional.of(t).filter(this::canValidate).map(getBeanBuilder)
             .filter(b -> !b.isEmpty()).map(b -> new BeanDelegate(b, t)).ifPresent(delegates::add));
 
-        return delegates.size() == 1 ? delegates.get(0) : delegates.stream().collect(compose());
+        if (delegates.size() == 1) {
+            return (MetadataBuilder.ForBean<T>) delegates.get(0);
+        }
+        // pretend:
+        return delegates.stream().<MetadataBuilder.ForBean<T>> map(MetadataBuilder.ForBean.class::cast)
+            .collect(compose());
     }
 
     @Override
@@ -308,7 +330,7 @@ public class HierarchyBuilder extends CompositeBuilder {
     }
 
     @Override
-    protected List<Class<?>> getGroupSequence(CompositeBuilder.ForClass composite, Meta<Class<?>> meta) {
+    protected <T> List<Class<?>> getGroupSequence(CompositeBuilder.ForClass<T> composite, Meta<Class<T>> meta) {
         return composite.delegates.get(0).getGroupSequence(meta);
     }
 

http://git-wip-us.apache.org/repos/asf/bval/blob/8689861e/bval-jsr/src/main/java/org/apache/bval/jsr/metadata/Meta.java
----------------------------------------------------------------------
diff --git a/bval-jsr/src/main/java/org/apache/bval/jsr/metadata/Meta.java b/bval-jsr/src/main/java/org/apache/bval/jsr/metadata/Meta.java
index 17b75a9..2ec80d2 100644
--- a/bval-jsr/src/main/java/org/apache/bval/jsr/metadata/Meta.java
+++ b/bval-jsr/src/main/java/org/apache/bval/jsr/metadata/Meta.java
@@ -43,14 +43,14 @@ import org.apache.bval.util.Validate;
  */
 public abstract class Meta<E extends AnnotatedElement> {
 
-    public static class ForClass extends Meta<Class<?>> {
+    public static class ForClass<T> extends Meta<Class<T>> {
 
-        public ForClass(Class<?> host) {
+        public ForClass(Class<T> host) {
             super(host, ElementType.TYPE);
         }
 
         @Override
-        public final Class<?> getDeclaringClass() {
+        public final Class<T> getDeclaringClass() {
             return getHost();
         }
 
@@ -74,7 +74,7 @@ public abstract class Meta<E extends AnnotatedElement> {
                 }
 
                 @Override
-                public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
+                public <A extends Annotation> A getAnnotation(Class<A> annotationClass) {
                     return getHost().getAnnotation(annotationClass);
                 }
 
@@ -97,6 +97,7 @@ public abstract class Meta<E extends AnnotatedElement> {
     }
 
     public static abstract class ForMember<M extends Member & AnnotatedElement> extends Meta<M> {
+        @SuppressWarnings({ "rawtypes", "unchecked" })
         private final Lazy<Meta<Class<?>>> parent = new Lazy<>(() -> new Meta.ForClass(getDeclaringClass()));
 
         protected ForMember(M host, ElementType elementType) {
@@ -148,9 +149,9 @@ public abstract class Meta<E extends AnnotatedElement> {
         }
     }
 
-    public static class ForConstructor extends ForExecutable<Constructor<?>> {
+    public static class ForConstructor<T> extends ForExecutable<Constructor<? extends T>> {
 
-        public ForConstructor(Constructor<?> host) {
+        public ForConstructor(Constructor<? extends T> host) {
             super(host, ElementType.CONSTRUCTOR);
         }
 
@@ -269,7 +270,7 @@ public abstract class Meta<E extends AnnotatedElement> {
         private Meta<? extends Executable> computeParent() {
             final Executable exe = getHost().getDeclaringExecutable();
             return exe instanceof Method ? new Meta.ForMethod((Method) exe)
-                : new Meta.ForConstructor((Constructor<?>) exe);
+                : new Meta.ForConstructor<>((Constructor<?>) exe);
         }
     }
 

http://git-wip-us.apache.org/repos/asf/bval/blob/8689861e/bval-jsr/src/main/java/org/apache/bval/jsr/metadata/MetadataBuilder.java
----------------------------------------------------------------------
diff --git a/bval-jsr/src/main/java/org/apache/bval/jsr/metadata/MetadataBuilder.java b/bval-jsr/src/main/java/org/apache/bval/jsr/metadata/MetadataBuilder.java
index 512daca..ff60df0 100644
--- a/bval-jsr/src/main/java/org/apache/bval/jsr/metadata/MetadataBuilder.java
+++ b/bval-jsr/src/main/java/org/apache/bval/jsr/metadata/MetadataBuilder.java
@@ -39,10 +39,10 @@ import org.apache.bval.jsr.groups.GroupConversion;
  */
 public final class MetadataBuilder {
 
-    public interface ForBean extends HasAnnotationBehavior {
-        MetadataBuilder.ForClass getClass(Meta<Class<?>> meta);
+    public interface ForBean<T> extends HasAnnotationBehavior {
+        MetadataBuilder.ForClass<T> getClass(Meta<Class<T>> meta);
 
-        Map<String, ForContainer<Field>> getFields(Meta<Class<?>> meta);
+        Map<String, ForContainer<Field>> getFields(Meta<Class<T>> meta);
 
         /**
          * Returned keys are property names per XML mapping spec.
@@ -50,11 +50,11 @@ public final class MetadataBuilder {
          * @param meta
          * @return {@link Map}
          */
-        Map<String, ForContainer<Method>> getGetters(Meta<Class<?>> meta);
+        Map<String, ForContainer<Method>> getGetters(Meta<Class<T>> meta);
 
-        Map<Signature, ForExecutable<Constructor<?>>> getConstructors(Meta<Class<?>> meta);
+        Map<Signature, ForExecutable<Constructor<? extends T>>> getConstructors(Meta<Class<T>> meta);
 
-        Map<Signature, ForExecutable<Method>> getMethods(Meta<Class<?>> meta);
+        Map<Signature, ForExecutable<Method>> getMethods(Meta<Class<T>> meta);
 
         default boolean isEmpty() {
             return false;
@@ -70,9 +70,9 @@ public final class MetadataBuilder {
         }
     }
 
-    public interface ForClass extends ForElement<Class<?>> {
+    public interface ForClass<T> extends ForElement<Class<T>> {
 
-        List<Class<?>> getGroupSequence(Meta<Class<?>> meta);
+        List<Class<?>> getGroupSequence(Meta<Class<T>> meta);
     }
 
     public interface ForContainer<E extends AnnotatedElement> extends MetadataBuilder.ForElement<E> {

http://git-wip-us.apache.org/repos/asf/bval/blob/8689861e/bval-jsr/src/main/java/org/apache/bval/jsr/metadata/MetadataBuilders.java
----------------------------------------------------------------------
diff --git a/bval-jsr/src/main/java/org/apache/bval/jsr/metadata/MetadataBuilders.java b/bval-jsr/src/main/java/org/apache/bval/jsr/metadata/MetadataBuilders.java
index aa301a4..7b6d495 100644
--- a/bval-jsr/src/main/java/org/apache/bval/jsr/metadata/MetadataBuilders.java
+++ b/bval-jsr/src/main/java/org/apache/bval/jsr/metadata/MetadataBuilders.java
@@ -26,16 +26,17 @@ import org.apache.bval.util.Validate;
 
 public class MetadataBuilders {
 
-    private final Map<Class<?>, List<MetadataBuilder.ForBean>> beanBuilders = new ConcurrentHashMap<>();
+    private final Map<Class<?>, List<MetadataBuilder.ForBean<?>>> beanBuilders = new ConcurrentHashMap<>();
 
-    public <T> void registerCustomBuilder(Class<?> bean, MetadataBuilder.ForBean builder) {
+    public <T> void registerCustomBuilder(Class<T> bean, MetadataBuilder.ForBean<T> builder) {
         Validate.notNull(bean, "bean");
         Validate.notNull(builder, "builder");
         beanBuilders.computeIfAbsent(bean, c -> new ArrayList<>()).add(builder);
     }
 
-    public List<MetadataBuilder.ForBean> getCustomBuilders(Class<?> bean) {
-        final List<MetadataBuilder.ForBean> list = beanBuilders.get(bean);
+    public <T> List<MetadataBuilder.ForBean<T>> getCustomBuilders(Class<T> bean) {
+        @SuppressWarnings({ "unchecked", "rawtypes" })
+        final List<MetadataBuilder.ForBean<T>> list = (List) beanBuilders.get(bean);
         return list == null ? Collections.emptyList() : Collections.unmodifiableList(list);
     }
 }

http://git-wip-us.apache.org/repos/asf/bval/blob/8689861e/bval-jsr/src/main/java/org/apache/bval/jsr/metadata/ReflectionBuilder.java
----------------------------------------------------------------------
diff --git a/bval-jsr/src/main/java/org/apache/bval/jsr/metadata/ReflectionBuilder.java b/bval-jsr/src/main/java/org/apache/bval/jsr/metadata/ReflectionBuilder.java
index a8a6984..ea396a0 100644
--- a/bval-jsr/src/main/java/org/apache/bval/jsr/metadata/ReflectionBuilder.java
+++ b/bval-jsr/src/main/java/org/apache/bval/jsr/metadata/ReflectionBuilder.java
@@ -62,21 +62,21 @@ import org.apache.commons.weaver.privilizer.Privilizing.CallTo;
 @Privilizing(@CallTo(Reflection.class))
 public class ReflectionBuilder {
 
-    private class ForBean implements MetadataBuilder.ForBean {
-        private final Meta<Class<?>> meta;
+    private class ForBean<T> implements MetadataBuilder.ForBean<T> {
+        private final Meta<Class<T>> meta;
 
-        ForBean(Meta<Class<?>> meta) {
+        ForBean(Meta<Class<T>> meta) {
             super();
             this.meta = Validate.notNull(meta, "meta");
         }
 
         @Override
-        public MetadataBuilder.ForClass getClass(Meta<Class<?>> ignored) {
-            return new ReflectionBuilder.ForClass(meta);
+        public MetadataBuilder.ForClass<T> getClass(Meta<Class<T>> ignored) {
+            return new ReflectionBuilder.ForClass<>(meta);
         }
 
         @Override
-        public Map<String, MetadataBuilder.ForContainer<Field>> getFields(Meta<Class<?>> ignored) {
+        public Map<String, MetadataBuilder.ForContainer<Field>> getFields(Meta<Class<T>> ignored) {
             final Field[] declaredFields = Reflection.getDeclaredFields(meta.getHost());
             if (declaredFields.length == 0) {
                 return Collections.emptyMap();
@@ -86,25 +86,25 @@ public class ReflectionBuilder {
         }
 
         @Override
-        public Map<String, MetadataBuilder.ForContainer<Method>> getGetters(Meta<Class<?>> ignored) {
+        public Map<String, MetadataBuilder.ForContainer<Method>> getGetters(Meta<Class<T>> ignored) {
             return Stream.of(Reflection.getDeclaredMethods(meta.getHost())).filter(Methods::isGetter)
                 .collect(ToUnmodifiable.map(Methods::propertyName,
                     g -> new ReflectionBuilder.ForContainer<>(new Meta.ForMethod(g))));
         }
 
         @Override
-        public Map<Signature, MetadataBuilder.ForExecutable<Constructor<?>>> getConstructors(Meta<Class<?>> ignored) {
-            final Constructor<?>[] declaredConstructors = Reflection.getDeclaredConstructors(meta.getHost());
+        public Map<Signature, MetadataBuilder.ForExecutable<Constructor<? extends T>>> getConstructors(Meta<Class<T>> ignored) {
+            final Constructor<? extends T>[] declaredConstructors = Reflection.getDeclaredConstructors(meta.getHost());
             if (declaredConstructors.length == 0) {
                 return Collections.emptyMap();
             }
             return Stream.of(declaredConstructors).collect(
-                Collectors.toMap(Signature::of, c -> new ReflectionBuilder.ForExecutable<>(new Meta.ForConstructor(c),
+                Collectors.toMap(Signature::of, c -> new ReflectionBuilder.ForExecutable<>(new Meta.ForConstructor<>(c),
                     validatorFactory.getParameterNameProvider()::getParameterNames)));
         }
 
         @Override
-        public Map<Signature, MetadataBuilder.ForExecutable<Method>> getMethods(Meta<Class<?>> ignored) {
+        public Map<Signature, MetadataBuilder.ForExecutable<Method>> getMethods(Meta<Class<T>> ignored) {
             final Method[] declaredMethods = Reflection.getDeclaredMethods(meta.getHost());
             if (declaredMethods.length == 0) {
                 return Collections.emptyMap();
@@ -130,14 +130,14 @@ public class ReflectionBuilder {
         }
     }
 
-    private class ForClass extends ForElement<Class<?>> implements MetadataBuilder.ForClass {
+    private class ForClass<T> extends ForElement<Class<T>> implements MetadataBuilder.ForClass<T> {
 
-        ForClass(Meta<Class<?>> meta) {
+        ForClass(Meta<Class<T>> meta) {
             super(meta);
         }
 
         @Override
-        public List<Class<?>> getGroupSequence(Meta<Class<?>> ignored) {
+        public List<Class<?>> getGroupSequence(Meta<Class<T>> ignored) {
             final GroupSequence groupSequence = meta.getHost().getAnnotation(GroupSequence.class);
             return groupSequence == null ? null : Collections.unmodifiableList(Arrays.asList(groupSequence.value()));
         }
@@ -298,7 +298,7 @@ public class ReflectionBuilder {
         this.validatorFactory = Validate.notNull(validatorFactory, "validatorFactory");
     }
 
-    public <T> MetadataBuilder.ForBean forBean(Class<?> beanClass) {
-        return new ReflectionBuilder.ForBean(new Meta.ForClass(beanClass));
+    public <T> MetadataBuilder.ForBean<T> forBean(Class<T> beanClass) {
+        return new ReflectionBuilder.ForBean<>(new Meta.ForClass<T>(beanClass));
     }
 }

http://git-wip-us.apache.org/repos/asf/bval/blob/8689861e/bval-jsr/src/main/java/org/apache/bval/jsr/metadata/XmlBuilder.java
----------------------------------------------------------------------
diff --git a/bval-jsr/src/main/java/org/apache/bval/jsr/metadata/XmlBuilder.java b/bval-jsr/src/main/java/org/apache/bval/jsr/metadata/XmlBuilder.java
index 382bab7..404954c 100644
--- a/bval-jsr/src/main/java/org/apache/bval/jsr/metadata/XmlBuilder.java
+++ b/bval-jsr/src/main/java/org/apache/bval/jsr/metadata/XmlBuilder.java
@@ -98,7 +98,7 @@ public class XmlBuilder {
     }
     //@formatter:on
 
-    private class ForBean implements MetadataBuilder.ForBean {
+    private class ForBean<T> implements MetadataBuilder.ForBean<T> {
 
         private final BeanType descriptor;
 
@@ -112,26 +112,26 @@ public class XmlBuilder {
         }
 
         @Override
-        public MetadataBuilder.ForClass getClass(Meta<Class<?>> meta) {
+        public MetadataBuilder.ForClass<T> getClass(Meta<Class<T>> meta) {
             final ClassType classType = descriptor.getClassType();
-            return classType == null ? EmptyBuilder.instance().forBean().getClass(meta)
-                : new XmlBuilder.ForClass(classType);
+            return classType == null ? EmptyBuilder.instance().<T> forBean().getClass(meta)
+                : new XmlBuilder.ForClass<T>(classType);
         }
 
         @Override
-        public Map<String, MetadataBuilder.ForContainer<Field>> getFields(Meta<Class<?>> meta) {
+        public Map<String, MetadataBuilder.ForContainer<Field>> getFields(Meta<Class<T>> meta) {
             return descriptor.getField().stream()
                 .collect(ToUnmodifiable.map(FieldType::getName, XmlBuilder.ForField::new));
         }
 
         @Override
-        public Map<String, MetadataBuilder.ForContainer<Method>> getGetters(Meta<Class<?>> meta) {
+        public Map<String, MetadataBuilder.ForContainer<Method>> getGetters(Meta<Class<T>> meta) {
             return descriptor.getGetter().stream()
                 .collect(ToUnmodifiable.map(GetterType::getName, XmlBuilder.ForGetter::new));
         }
 
         @Override
-        public Map<Signature, MetadataBuilder.ForExecutable<Constructor<?>>> getConstructors(Meta<Class<?>> meta) {
+        public Map<Signature, MetadataBuilder.ForExecutable<Constructor<? extends T>>> getConstructors(Meta<Class<T>> meta) {
             if (!atLeast(Version.v11)) {
                 return Collections.emptyMap();
             }
@@ -146,7 +146,7 @@ public class XmlBuilder {
         }
 
         @Override
-        public Map<Signature, MetadataBuilder.ForExecutable<Method>> getMethods(Meta<Class<?>> meta) {
+        public Map<Signature, MetadataBuilder.ForExecutable<Method>> getMethods(Meta<Class<T>> meta) {
             if (!atLeast(Version.v11)) {
                 return Collections.emptyMap();
             }
@@ -214,7 +214,7 @@ public class XmlBuilder {
         }
     }
 
-    private class ForClass extends ForElement<ForClass, Class<?>, ClassType> implements MetadataBuilder.ForClass {
+    private class ForClass<T> extends ForElement<ForClass<T>, Class<T>, ClassType> implements MetadataBuilder.ForClass<T> {
 
         ForClass(ClassType descriptor) {
             super(descriptor);
@@ -222,7 +222,7 @@ public class XmlBuilder {
         }
 
         @Override
-        public List<Class<?>> getGroupSequence(Meta<Class<?>> meta) {
+        public List<Class<?>> getGroupSequence(Meta<Class<T>> meta) {
             final GroupSequenceType groupSequence = descriptor.getGroupSequence();
             return groupSequence == null ? null
                 : groupSequence.getValue().stream().map(XmlBuilder.this::resolveClass).collect(ToUnmodifiable.list());
@@ -392,7 +392,7 @@ public class XmlBuilder {
         }
     }
 
-    private class ForConstructor extends ForExecutable<ForConstructor, Constructor<?>, ConstructorType> {
+    private class ForConstructor<T> extends ForExecutable<ForConstructor<T>, Constructor<? extends T>, ConstructorType> {
 
         ForConstructor(ConstructorType descriptor) {
             super(descriptor);
@@ -473,7 +473,7 @@ public class XmlBuilder {
         this.version = v;
     }
 
-    public Map<Class<?>, MetadataBuilder.ForBean> forBeans() {
+    public Map<Class<?>, MetadataBuilder.ForBean<?>> forBeans() {
         return constraintMappings.getBean().stream().map(XmlBuilder.ForBean::new)
             .collect(ToUnmodifiable.map(XmlBuilder.ForBean::getBeanClass, Function.identity()));
     }

http://git-wip-us.apache.org/repos/asf/bval/blob/8689861e/bval-jsr/src/main/java/org/apache/bval/jsr/xml/ValidationMappingParser.java
----------------------------------------------------------------------
diff --git a/bval-jsr/src/main/java/org/apache/bval/jsr/xml/ValidationMappingParser.java b/bval-jsr/src/main/java/org/apache/bval/jsr/xml/ValidationMappingParser.java
index 3a86142..766871f 100644
--- a/bval-jsr/src/main/java/org/apache/bval/jsr/xml/ValidationMappingParser.java
+++ b/bval-jsr/src/main/java/org/apache/bval/jsr/xml/ValidationMappingParser.java
@@ -27,6 +27,7 @@ import java.util.Set;
 import javax.validation.ValidationException;
 
 import org.apache.bval.jsr.ApacheValidatorFactory;
+import org.apache.bval.jsr.metadata.MetadataBuilder;
 import org.apache.bval.jsr.metadata.XmlBuilder;
 import org.apache.bval.jsr.metadata.XmlValidationMappingProvider;
 import org.apache.bval.util.Exceptions;
@@ -63,11 +64,13 @@ public class ValidationMappingParser {
      * @param xmlStreams
      *            - one or more contraints.xml file streams to parse
      */
+    @SuppressWarnings({ "unchecked", "rawtypes" })
     public void processMappingConfig(Set<InputStream> xmlStreams) throws ValidationException {
         for (final InputStream xmlStream : xmlStreams) {
             final ConstraintMappingsType mapping = parseXmlMappings(xmlStream);
             processConstraintDefinitions(mapping.getConstraintDefinition(), mapping.getDefaultPackage());
-            new XmlBuilder(mapping).forBeans().forEach(factory.getMetadataBuilders()::registerCustomBuilder);
+            new XmlBuilder(mapping).forBeans().forEach(
+                (k, v) -> factory.getMetadataBuilders().registerCustomBuilder((Class) k, (MetadataBuilder.ForBean) v));
         }
     }
 

http://git-wip-us.apache.org/repos/asf/bval/blob/8689861e/bval-jsr/src/main/java/org/apache/bval/util/reflection/Reflection.java
----------------------------------------------------------------------
diff --git a/bval-jsr/src/main/java/org/apache/bval/util/reflection/Reflection.java b/bval-jsr/src/main/java/org/apache/bval/util/reflection/Reflection.java
index 2c8b7b6..97cafda 100644
--- a/bval-jsr/src/main/java/org/apache/bval/util/reflection/Reflection.java
+++ b/bval-jsr/src/main/java/org/apache/bval/util/reflection/Reflection.java
@@ -290,8 +290,9 @@ public class Reflection {
      * @param clazz
      * @return {@link Constructor} array
      */
-    public static Constructor<?>[] getDeclaredConstructors(final Class<?> clazz) {
-        return clazz.getDeclaredConstructors();
+    @SuppressWarnings("unchecked")
+    public static <T> Constructor<? extends T>[] getDeclaredConstructors(final Class<T> clazz) {
+        return (Constructor<? extends T>[]) clazz.getDeclaredConstructors();
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/bval/blob/8689861e/bval-jsr/src/test/java/org/apache/bval/jsr/groups/GroupSequenceTest.java
----------------------------------------------------------------------
diff --git a/bval-jsr/src/test/java/org/apache/bval/jsr/groups/GroupSequenceTest.java b/bval-jsr/src/test/java/org/apache/bval/jsr/groups/GroupSequenceTest.java
index d6651b3..85e969a 100644
--- a/bval-jsr/src/test/java/org/apache/bval/jsr/groups/GroupSequenceTest.java
+++ b/bval-jsr/src/test/java/org/apache/bval/jsr/groups/GroupSequenceTest.java
@@ -48,7 +48,7 @@ public class GroupSequenceTest extends ValidationTestBase {
 
     @Test
     public void testGroupSequence1() {
-        BeanD bean = (BeanD) ApacheValidatorFactory.getDefault().usingContext().getValidator()
+        BeanD<?> bean = (BeanD<?>) ApacheValidatorFactory.getDefault().usingContext().getValidator()
             .getConstraintsForClass(GInterface1.class);
 
         assertEquals(Collections.singletonList(GInterface1.class), bean.getGroupSequence());
@@ -56,7 +56,7 @@ public class GroupSequenceTest extends ValidationTestBase {
 
     @Test
     public void testGroupSequence2() {
-        BeanD bean = (BeanD) ApacheValidatorFactory.getDefault().usingContext().getValidator()
+        BeanD<?> bean = (BeanD<?>) ApacheValidatorFactory.getDefault().usingContext().getValidator()
             .getConstraintsForClass(GClass1.class);
 
         assertNull(bean.getGroupSequence());
@@ -64,7 +64,7 @@ public class GroupSequenceTest extends ValidationTestBase {
 
     @Test
     public void testGroupSequence3() {
-        BeanD bean = (BeanD) ApacheValidatorFactory.getDefault().usingContext().getValidator()
+        BeanD<?> bean = (BeanD<?>) ApacheValidatorFactory.getDefault().usingContext().getValidator()
                 .getConstraintsForClass(GClass2.class);
 
         assertEquals(Arrays.asList(GClass1.class, GClass2.class), bean.getGroupSequence());
@@ -72,7 +72,7 @@ public class GroupSequenceTest extends ValidationTestBase {
 
     @Test
     public void testGroupSequence4() {
-        BeanD bean = (BeanD) ApacheValidatorFactory.getDefault().usingContext().getValidator()
+        BeanD<?> bean = (BeanD<?>) ApacheValidatorFactory.getDefault().usingContext().getValidator()
                 .getConstraintsForClass(GClass3.class);
 
         assertEquals(Arrays.asList(GClass3.class, GClass1.class), bean.getGroupSequence());