http://git-wip-us.apache.org/repos/asf/bval/blob/ed299e4f/bval-jsr/src/main/java/org/apache/bval/util/reflection/TypeUtils.java
----------------------------------------------------------------------
diff --git 
a/bval-jsr/src/main/java/org/apache/bval/util/reflection/TypeUtils.java 
b/bval-jsr/src/main/java/org/apache/bval/util/reflection/TypeUtils.java
new file mode 100644
index 0000000..a75e1ad
--- /dev/null
+++ b/bval-jsr/src/main/java/org/apache/bval/util/reflection/TypeUtils.java
@@ -0,0 +1,1557 @@
+/*
+ * 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.util.reflection;
+
+import java.lang.reflect.Array;
+import java.lang.reflect.GenericArrayType;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.lang.reflect.TypeVariable;
+import java.lang.reflect.WildcardType;
+import java.util.Arrays;
+import java.util.Collections;
+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.Stream;
+
+import org.apache.bval.util.ObjectUtils;
+import org.apache.bval.util.Validate;
+
+/**
+ * Taken from commons-lang3.
+ *
+ * <p> Utility methods focusing on type inspection, particularly with regard to
+ * generics. </p>
+ *
+ * @since 1.1.2
+ */
+public class TypeUtils {
+
+    /**
+     * {@link WildcardType} builder.
+     */
+    public static class WildcardTypeBuilder {
+        /**
+         * Constructor
+         */
+        private WildcardTypeBuilder() {
+        }
+        
+        private Type[] upperBounds;
+        private Type[] lowerBounds;
+
+        /**
+         * Specify upper bounds of the wildcard type to build.
+         * @param bounds to set
+         * @return {@code this}
+         */
+        public WildcardTypeBuilder withUpperBounds(final Type... bounds) {
+            this.upperBounds = bounds;
+            return this;
+        }
+
+        /**
+         * Specify lower bounds of the wildcard type to build.
+         * @param bounds to set
+         * @return {@code this}
+         */
+        public WildcardTypeBuilder withLowerBounds(final Type... bounds) {
+            this.lowerBounds = bounds;
+            return this;
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        public WildcardType build() {
+            return new WildcardTypeImpl(upperBounds, lowerBounds);
+        }
+    }
+
+    /**
+     * ParameterizedType implementation class.
+     */
+    private static final class ParameterizedTypeImpl implements 
ParameterizedType {
+        private final Class<?> raw;
+        private final Type useOwner;
+        private final Type[] typeArguments;
+
+        /**
+         * Constructor
+         * @param raw type
+         * @param useOwner owner type to use, if any
+         * @param typeArguments formal type arguments
+         */
+        private ParameterizedTypeImpl(final Class<?> raw, final Type useOwner, 
final Type[] typeArguments) {
+            this.raw = raw;
+            this.useOwner = useOwner;
+            this.typeArguments = typeArguments.clone();
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        @Override
+        public Type getRawType() {
+            return raw;
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        @Override
+        public Type getOwnerType() {
+            return useOwner;
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        @Override
+        public Type[] getActualTypeArguments() {
+            return typeArguments.clone();
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        @Override
+        public String toString() {
+            return TypeUtils.toString(this);
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        @Override
+        public boolean equals(final Object obj) {
+            return obj == this || obj instanceof ParameterizedType && 
TypeUtils.equals(this, ((ParameterizedType) obj));
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        @Override
+        public int hashCode() {
+            return Objects.hash(raw, useOwner, typeArguments);
+        }
+    }
+
+    /**
+     * WildcardType implementation class.
+     */
+    private static final class WildcardTypeImpl implements WildcardType {
+        private static final Type[] EMPTY_UPPER_BOUNDS = { Object.class };
+        private static final Type[] EMPTY_LOWER_BOUNDS = new Type[0];
+
+        private final Type[] upperBounds;
+        private final Type[] lowerBounds;
+
+        /**
+         * Constructor
+         * @param upperBounds of this type
+         * @param lowerBounds of this type
+         */
+        private WildcardTypeImpl(final Type[] upperBounds, final Type[] 
lowerBounds) {
+            this.upperBounds = ObjectUtils.isEmpty(upperBounds) ? 
EMPTY_UPPER_BOUNDS : upperBounds;
+            this.lowerBounds = lowerBounds == null ? EMPTY_LOWER_BOUNDS : 
lowerBounds;
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        @Override
+        public Type[] getUpperBounds() {
+            return upperBounds.clone();
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        @Override
+        public Type[] getLowerBounds() {
+            return lowerBounds.clone();
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        @Override
+        public String toString() {
+            return TypeUtils.toString(this);
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        @Override
+        public boolean equals(final Object obj) {
+            return obj == this || obj instanceof WildcardType && 
TypeUtils.equals(this, (WildcardType) obj);
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        @Override
+        public int hashCode() {
+            return Objects.hash(upperBounds, lowerBounds);
+        }
+    }
+
+    /**
+     * <p>{@code TypeUtils} instances should NOT be constructed in standard
+     * programming. Instead, the class should be used as
+     * {@code TypeUtils.isAssignable(cls, toClass)}.</p> <p>This
+     * constructor is public to permit tools that require a JavaBean instance 
to
+     * operate.</p>
+     */
+    private TypeUtils() {
+    }
+
+    /**
+     * <p>Checks if the subject type may be implicitly cast to the target type
+     * following the Java generics rules. If both types are {@link Class}
+     * objects, the method returns the result of
+     * {@link Class#isAssignableFrom(Class)}.</p>
+     *
+     * @param type the subject type to be assigned to the target type
+     * @param toType the target type
+     * @return {@code true} if {@code type} is assignable to {@code toType}.
+     */
+    public static boolean isAssignable(final Type type, final Type toType) {
+        return isAssignable(type, toType, null);
+    }
+
+    /**
+     * <p>Checks if the subject type may be implicitly cast to the target type
+     * following the Java generics rules.</p>
+     *
+     * @param type the subject type to be assigned to the target type
+     * @param toType the target type
+     * @param typeVarAssigns optional map of type variable assignments
+     * @return {@code true} if {@code type} is assignable to {@code toType}.
+     */
+    private static boolean isAssignable(final Type type, final Type toType,
+            final Map<TypeVariable<?>, Type> typeVarAssigns) {
+        if (toType == null || toType instanceof Class<?>) {
+            return isAssignable(type, (Class<?>) toType);
+        }
+
+        if (toType instanceof ParameterizedType) {
+            return isAssignable(type, (ParameterizedType) toType, 
typeVarAssigns);
+        }
+
+        if (toType instanceof GenericArrayType) {
+            return isAssignable(type, (GenericArrayType) toType, 
typeVarAssigns);
+        }
+
+        if (toType instanceof WildcardType) {
+            return isAssignable(type, (WildcardType) toType, typeVarAssigns);
+        }
+
+        if (toType instanceof TypeVariable<?>) {
+            return isAssignable(type, (TypeVariable<?>) toType, 
typeVarAssigns);
+        }
+
+        throw new IllegalStateException("found an unhandled type: " + toType);
+    }
+
+    /**
+     * <p>Checks if the subject type may be implicitly cast to the target class
+     * following the Java generics rules.</p>
+     *
+     * @param type the subject type to be assigned to the target type
+     * @param toClass the target class
+     * @return {@code true} if {@code type} is assignable to {@code toClass}.
+     */
+    private static boolean isAssignable(final Type type, final Class<?> 
toClass) {
+        if (type == null) {
+            // consistency with ClassUtils.isAssignable() behavior
+            return toClass == null || !toClass.isPrimitive();
+        }
+
+        // only a null type can be assigned to null type which
+        // would have cause the previous to return true
+        if (toClass == null) {
+            return false;
+        }
+
+        // all types are assignable to themselves
+        if (toClass.equals(type)) {
+            return true;
+        }
+
+        if (type instanceof Class<?>) {
+            // just comparing two classes
+            // also take primitives into account!
+            return isAssignable((Class<?>) type, toClass);
+        }
+
+        if (type instanceof ParameterizedType) {
+            // only have to compare the raw type to the class
+            return isAssignable(getRawType((ParameterizedType) type), toClass);
+        }
+
+        // *
+        if (type instanceof TypeVariable<?>) {
+            // if any of the bounds are assignable to the class, then the
+            // type is assignable to the class.
+            return Stream.of(((TypeVariable<?>) 
type).getBounds()).anyMatch(bound -> isAssignable(bound, toClass));
+        }
+
+        // the only classes to which a generic array type can be assigned
+        // are class Object and array classes
+        if (type instanceof GenericArrayType) {
+            return Object.class.equals(toClass)
+                    || toClass.isArray()
+                    && isAssignable(((GenericArrayType) 
type).getGenericComponentType(), toClass
+                            .getComponentType());
+        }
+
+        // wildcard types are not assignable to a class (though one would think
+        // "? super Object" would be assignable to Object)
+        if (type instanceof WildcardType) {
+            return false;
+        }
+
+        throw new IllegalStateException("found an unhandled type: " + type);
+    }
+
+    private static boolean isAssignable(Class<?> cls, final Class<?> toClass) {
+        if (toClass == null) {
+            return false;
+        }
+        // have to check for null, as isAssignableFrom doesn't
+        if (cls == null) {
+            return !toClass.isPrimitive();
+        }
+
+        if (cls.isPrimitive() && !toClass.isPrimitive()) {
+            cls = Reflection.primitiveToWrapper(cls);
+            if (cls == null) {
+                return false;
+            }
+        }
+        if (toClass.isPrimitive() && !cls.isPrimitive()) {
+            cls = Reflection.wrapperToPrimitive(cls);
+            if (cls == null) {
+                return false;
+            }
+        }
+        if (cls.equals(toClass)) {
+            return true;
+        }
+        if (cls.isPrimitive()) {
+            if (toClass.isPrimitive() == false) {
+                return false;
+            }
+            if (Integer.TYPE.equals(cls)) {
+                return Long.TYPE.equals(toClass)
+                        || Float.TYPE.equals(toClass)
+                        || Double.TYPE.equals(toClass);
+            }
+            if (Long.TYPE.equals(cls)) {
+                return Float.TYPE.equals(toClass)
+                        || Double.TYPE.equals(toClass);
+            }
+            if (Boolean.TYPE.equals(cls)) {
+                return false;
+            }
+            if (Double.TYPE.equals(cls)) {
+                return false;
+            }
+            if (Float.TYPE.equals(cls)) {
+                return Double.TYPE.equals(toClass);
+            }
+            if (Character.TYPE.equals(cls)) {
+                return Integer.TYPE.equals(toClass)
+                        || Long.TYPE.equals(toClass)
+                        || Float.TYPE.equals(toClass)
+                        || Double.TYPE.equals(toClass);
+            }
+            if (Short.TYPE.equals(cls)) {
+                return Integer.TYPE.equals(toClass)
+                        || Long.TYPE.equals(toClass)
+                        || Float.TYPE.equals(toClass)
+                        || Double.TYPE.equals(toClass);
+            }
+            if (Byte.TYPE.equals(cls)) {
+                return Short.TYPE.equals(toClass)
+                        || Integer.TYPE.equals(toClass)
+                        || Long.TYPE.equals(toClass)
+                        || Float.TYPE.equals(toClass)
+                        || Double.TYPE.equals(toClass);
+            }
+            // should never get here
+            return false;
+        }
+        return toClass.isAssignableFrom(cls);
+
+    }
+
+    /**
+     * <p>Checks if the subject type may be implicitly cast to the target
+     * parameterized type following the Java generics rules.</p>
+     *
+     * @param type the subject type to be assigned to the target type
+     * @param toParameterizedType the target parameterized type
+     * @param typeVarAssigns a map with type variables
+     * @return {@code true} if {@code type} is assignable to {@code toType}.
+     */
+    private static boolean isAssignable(final Type type, final 
ParameterizedType toParameterizedType,
+            final Map<TypeVariable<?>, Type> typeVarAssigns) {
+        if (type == null) {
+            return true;
+        }
+
+        // only a null type can be assigned to null type which
+        // would have cause the previous to return true
+        if (toParameterizedType == null) {
+            return false;
+        }
+
+        // all types are assignable to themselves
+        if (toParameterizedType.equals(type)) {
+            return true;
+        }
+
+        // get the target type's raw type
+        final Class<?> toClass = getRawType(toParameterizedType);
+        // get the subject type's type arguments including owner type arguments
+        // and supertype arguments up to and including the target class.
+        final Map<TypeVariable<?>, Type> fromTypeVarAssigns = 
getTypeArguments(type, toClass, null);
+
+        // null means the two types are not compatible
+        if (fromTypeVarAssigns == null) {
+            return false;
+        }
+
+        // compatible types, but there's no type arguments. this is equivalent
+        // to comparing Map< ?, ? > to Map, and raw types are always assignable
+        // to parameterized types.
+        if (fromTypeVarAssigns.isEmpty()) {
+            return true;
+        }
+
+        // get the target type's type arguments including owner type arguments
+        final Map<TypeVariable<?>, Type> toTypeVarAssigns = 
getTypeArguments(toParameterizedType,
+                toClass, typeVarAssigns);
+
+        // now to check each type argument
+        for (final TypeVariable<?> var : toTypeVarAssigns.keySet()) {
+            final Type toTypeArg = unrollVariableAssignments(var, 
toTypeVarAssigns);
+            final Type fromTypeArg = unrollVariableAssignments(var, 
fromTypeVarAssigns);
+
+            if (toTypeArg == null && fromTypeArg instanceof Class) {
+                continue;
+            }
+
+            // parameters must either be absent from the subject type, within
+            // the bounds of the wildcard type, or be an exact match to the
+            // parameters of the target type.
+            if (fromTypeArg != null
+                    && !toTypeArg.equals(fromTypeArg)
+                    && !(toTypeArg instanceof WildcardType && 
isAssignable(fromTypeArg, toTypeArg,
+                            typeVarAssigns))) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    /**
+     * Look up {@code var} in {@code typeVarAssigns} <em>transitively</em>,
+     * i.e. keep looking until the value found is <em>not</em> a type variable.
+     * @param var the type variable to look up
+     * @param typeVarAssigns the map used for the look up
+     * @return Type or {@code null} if some variable was not in the map
+     */
+    private static Type unrollVariableAssignments(TypeVariable<?> var, final 
Map<TypeVariable<?>, Type> typeVarAssigns) {
+        Type result;
+        do {
+            result = typeVarAssigns.get(var);
+            if (result instanceof TypeVariable<?> && !result.equals(var)) {
+                var = (TypeVariable<?>) result;
+                continue;
+            }
+            break;
+        } while (true);
+        return result;
+    }
+
+    /**
+     * <p>Checks if the subject type may be implicitly cast to the target
+     * generic array type following the Java generics rules.</p>
+     *
+     * @param type the subject type to be assigned to the target type
+     * @param toGenericArrayType the target generic array type
+     * @param typeVarAssigns a map with type variables
+     * @return {@code true} if {@code type} is assignable to
+     * {@code toGenericArrayType}.
+     */
+    private static boolean isAssignable(final Type type, final 
GenericArrayType toGenericArrayType,
+            final Map<TypeVariable<?>, Type> typeVarAssigns) {
+        if (type == null) {
+            return true;
+        }
+
+        // only a null type can be assigned to null type which
+        // would have cause the previous to return true
+        if (toGenericArrayType == null) {
+            return false;
+        }
+
+        // all types are assignable to themselves
+        if (toGenericArrayType.equals(type)) {
+            return true;
+        }
+
+        final Type toComponentType = 
toGenericArrayType.getGenericComponentType();
+
+        if (type instanceof Class<?>) {
+            final Class<?> cls = (Class<?>) type;
+
+            // compare the component types
+            return cls.isArray()
+                    && isAssignable(cls.getComponentType(), toComponentType, 
typeVarAssigns);
+        }
+
+        if (type instanceof GenericArrayType) {
+            // compare the component types
+            return isAssignable(((GenericArrayType) 
type).getGenericComponentType(),
+                    toComponentType, typeVarAssigns);
+        }
+
+        if (type instanceof WildcardType) {
+            // so long as one of the upper bounds is assignable, it's good
+            return Stream.of(getImplicitUpperBounds((WildcardType) type))
+                .anyMatch(bound -> isAssignable(bound, toGenericArrayType));
+        }
+
+        if (type instanceof TypeVariable<?>) {
+            // probably should remove the following logic and just return 
false.
+            // type variables cannot specify arrays as bounds.
+            return Stream.of(getImplicitBounds((TypeVariable<?>) type))
+                .anyMatch(bound -> isAssignable(bound, toGenericArrayType));
+        }
+
+        if (type instanceof ParameterizedType) {
+            // the raw type of a parameterized type is never an array or
+            // generic array, otherwise the declaration would look like this:
+            // Collection[]< ? extends String > collection;
+            return false;
+        }
+
+        throw new IllegalStateException("found an unhandled type: " + type);
+    }
+
+    /**
+     * <p>Checks if the subject type may be implicitly cast to the target
+     * wildcard type following the Java generics rules.</p>
+     *
+     * @param type the subject type to be assigned to the target type
+     * @param toWildcardType the target wildcard type
+     * @param typeVarAssigns a map with type variables
+     * @return {@code true} if {@code type} is assignable to
+     * {@code toWildcardType}.
+     */
+    private static boolean isAssignable(final Type type, final WildcardType 
toWildcardType,
+            final Map<TypeVariable<?>, Type> typeVarAssigns) {
+        if (type == null) {
+            return true;
+        }
+
+        // only a null type can be assigned to null type which
+        // would have cause the previous to return true
+        if (toWildcardType == null) {
+            return false;
+        }
+
+        // all types are assignable to themselves
+        if (toWildcardType.equals(type)) {
+            return true;
+        }
+
+        final Type[] toUpperBounds = getImplicitUpperBounds(toWildcardType);
+        final Type[] toLowerBounds = getImplicitLowerBounds(toWildcardType);
+
+        if (type instanceof WildcardType) {
+            final WildcardType wildcardType = (WildcardType) type;
+            final Type[] upperBounds = getImplicitUpperBounds(wildcardType);
+            final Type[] lowerBounds = getImplicitLowerBounds(wildcardType);
+
+            for (Type toBound : toUpperBounds) {
+                // if there are assignments for unresolved type variables,
+                // now's the time to substitute them.
+                toBound = substituteTypeVariables(toBound, typeVarAssigns);
+
+                // each upper bound of the subject type has to be assignable to
+                // each
+                // upper bound of the target type
+                for (final Type bound : upperBounds) {
+                    if (!isAssignable(bound, toBound, typeVarAssigns)) {
+                        return false;
+                    }
+                }
+            }
+
+            for (Type toBound : toLowerBounds) {
+                // if there are assignments for unresolved type variables,
+                // now's the time to substitute them.
+                toBound = substituteTypeVariables(toBound, typeVarAssigns);
+
+                // each lower bound of the target type has to be assignable to
+                // each
+                // lower bound of the subject type
+                for (final Type bound : lowerBounds) {
+                    if (!isAssignable(toBound, bound, typeVarAssigns)) {
+                        return false;
+                    }
+                }
+            }
+            return true;
+        }
+
+        for (final Type toBound : toUpperBounds) {
+            // if there are assignments for unresolved type variables,
+            // now's the time to substitute them.
+            if (!isAssignable(type, substituteTypeVariables(toBound, 
typeVarAssigns),
+                    typeVarAssigns)) {
+                return false;
+            }
+        }
+
+        for (final Type toBound : toLowerBounds) {
+            // if there are assignments for unresolved type variables,
+            // now's the time to substitute them.
+            if (!isAssignable(substituteTypeVariables(toBound, 
typeVarAssigns), type,
+                    typeVarAssigns)) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    /**
+     * <p>Checks if the subject type may be implicitly cast to the target type
+     * variable following the Java generics rules.</p>
+     *
+     * @param type the subject type to be assigned to the target type
+     * @param toTypeVariable the target type variable
+     * @param typeVarAssigns a map with type variables
+     * @return {@code true} if {@code type} is assignable to
+     * {@code toTypeVariable}.
+     */
+    private static boolean isAssignable(final Type type, final TypeVariable<?> 
toTypeVariable,
+            final Map<TypeVariable<?>, Type> typeVarAssigns) {
+        if (type == null) {
+            return true;
+        }
+
+        // only a null type can be assigned to null type which
+        // would have cause the previous to return true
+        if (toTypeVariable == null) {
+            return false;
+        }
+
+        // all types are assignable to themselves
+        if (toTypeVariable.equals(type)) {
+            return true;
+        }
+
+        if (type instanceof TypeVariable<?>) {
+            // a type variable is assignable to another type variable, if
+            // and only if the former is the latter, extends the latter, or
+            // is otherwise a descendant of the latter.
+            final Type[] bounds = getImplicitBounds((TypeVariable<?>) type);
+
+            for (final Type bound : bounds) {
+                if (isAssignable(bound, toTypeVariable, typeVarAssigns)) {
+                    return true;
+                }
+            }
+        }
+
+        if (type instanceof Class<?> || type instanceof ParameterizedType
+                || type instanceof GenericArrayType || type instanceof 
WildcardType) {
+            return false;
+        }
+
+        throw new IllegalStateException("found an unhandled type: " + type);
+    }
+
+    /**
+     * <p>Find the mapping for {@code type} in {@code typeVarAssigns}.</p>
+     *
+     * @param type the type to be replaced
+     * @param typeVarAssigns the map with type variables
+     * @return the replaced type
+     * @throws IllegalArgumentException if the type cannot be substituted
+     */
+    private static Type substituteTypeVariables(final Type type, final 
Map<TypeVariable<?>, Type> typeVarAssigns) {
+        if (type instanceof TypeVariable<?> && typeVarAssigns != null) {
+            final Type replacementType = typeVarAssigns.get(type);
+
+            if (replacementType == null) {
+                throw new IllegalArgumentException("missing assignment type 
for type variable "
+                        + type);
+            }
+            return replacementType;
+        }
+        return type;
+    }
+
+    /**
+     * <p>Retrieves all the type arguments for this parameterized type
+     * including owner hierarchy arguments such as
+     * {@code Outer<K,V>.Inner<T>.DeepInner<E>} .
+     * The arguments are returned in a
+     * {@link Map} specifying the argument type for each {@link TypeVariable}.
+     * </p>
+     *
+     * @param type specifies the subject parameterized type from which to
+     *             harvest the parameters.
+     * @return a {@code Map} of the type arguments to their respective type
+     * variables.
+     */
+    public static Map<TypeVariable<?>, Type> getTypeArguments(final 
ParameterizedType type) {
+        return getTypeArguments(type, getRawType(type), null);
+    }
+
+    /**
+     * <p>Gets the type arguments of a class/interface based on a subtype. For
+     * instance, this method will determine that both of the parameters for the
+     * interface {@link Map} are {@link Object} for the subtype
+     * {@link java.util.Properties Properties} even though the subtype does not
+     * directly implement the {@code Map} interface.</p>
+     * <p>This method returns {@code null} if {@code type} is not assignable to
+     * {@code toClass}. It returns an empty map if none of the classes or
+     * interfaces in its inheritance hierarchy specify any type arguments.</p>
+     * <p>A side effect of this method is that it also retrieves the type
+     * arguments for the classes and interfaces that are part of the hierarchy
+     * between {@code type} and {@code toClass}. So with the above
+     * example, this method will also determine that the type arguments for
+     * {@link java.util.Hashtable Hashtable} are also both {@code Object}.
+     * In cases where the interface specified by {@code toClass} is
+     * (indirectly) implemented more than once (e.g. where {@code toClass}
+     * specifies the interface {@link Iterable Iterable} and
+     * {@code type} specifies a parameterized type that implements both
+     * {@link Set Set} and {@link java.util.Collection Collection}),
+     * this method will look at the inheritance hierarchy of only one of the
+     * implementations/subclasses; the first interface encountered that isn't a
+     * subinterface to one of the others in the {@code type} to
+     * {@code toClass} hierarchy.</p>
+     *
+     * @param type the type from which to determine the type parameters of
+     * {@code toClass}
+     * @param toClass the class whose type parameters are to be determined 
based
+     * on the subtype {@code type}
+     * @return a {@code Map} of the type assignments for the type variables in
+     * each type in the inheritance hierarchy from {@code type} to
+     * {@code toClass} inclusive.
+     */
+    public static Map<TypeVariable<?>, Type> getTypeArguments(final Type type, 
final Class<?> toClass) {
+        return getTypeArguments(type, toClass, null);
+    }
+
+    /**
+     * <p>Return a map of the type arguments of @{code type} in the context of 
{@code toClass}.</p>
+     *
+     * @param type the type in question
+     * @param toClass the class
+     * @param subtypeVarAssigns a map with type variables
+     * @return the {@code Map} with type arguments
+     */
+    private static Map<TypeVariable<?>, Type> getTypeArguments(final Type 
type, final Class<?> toClass,
+            final Map<TypeVariable<?>, Type> subtypeVarAssigns) {
+        if (type instanceof Class<?>) {
+            return getTypeArguments((Class<?>) type, toClass, 
subtypeVarAssigns);
+        }
+
+        if (type instanceof ParameterizedType) {
+            return getTypeArguments((ParameterizedType) type, toClass, 
subtypeVarAssigns);
+        }
+
+        if (type instanceof GenericArrayType) {
+            return getTypeArguments(((GenericArrayType) 
type).getGenericComponentType(), toClass
+                    .isArray() ? toClass.getComponentType() : toClass, 
subtypeVarAssigns);
+        }
+
+        // since wildcard types are not assignable to classes, should this just
+        // return null?
+        if (type instanceof WildcardType) {
+            for (final Type bound : getImplicitUpperBounds((WildcardType) 
type)) {
+                // find the first bound that is assignable to the target class
+                if (isAssignable(bound, toClass)) {
+                    return getTypeArguments(bound, toClass, subtypeVarAssigns);
+                }
+            }
+
+            return null;
+        }
+
+        if (type instanceof TypeVariable<?>) {
+            for (final Type bound : getImplicitBounds((TypeVariable<?>) type)) 
{
+                // find the first bound that is assignable to the target class
+                if (isAssignable(bound, toClass)) {
+                    return getTypeArguments(bound, toClass, subtypeVarAssigns);
+                }
+            }
+
+            return null;
+        }
+        throw new IllegalStateException("found an unhandled type: " + type);
+    }
+
+    /**
+     * <p>Return a map of the type arguments of a parameterized type in the 
context of {@code toClass}.</p>
+     *
+     * @param parameterizedType the parameterized type
+     * @param toClass the class
+     * @param subtypeVarAssigns a map with type variables
+     * @return the {@code Map} with type arguments
+     */
+    private static Map<TypeVariable<?>, Type> getTypeArguments(
+            final ParameterizedType parameterizedType, final Class<?> toClass,
+            final Map<TypeVariable<?>, Type> subtypeVarAssigns) {
+        final Class<?> cls = getRawType(parameterizedType);
+
+        // make sure they're assignable
+        if (!isAssignable(cls, toClass)) {
+            return null;
+        }
+
+        final Type ownerType = parameterizedType.getOwnerType();
+        Map<TypeVariable<?>, Type> typeVarAssigns;
+
+        if (ownerType instanceof ParameterizedType) {
+            // get the owner type arguments first
+            final ParameterizedType parameterizedOwnerType = 
(ParameterizedType) ownerType;
+            typeVarAssigns = getTypeArguments(parameterizedOwnerType,
+                    getRawType(parameterizedOwnerType), subtypeVarAssigns);
+        } else {
+            // no owner, prep the type variable assignments map
+            typeVarAssigns = subtypeVarAssigns == null ? new HashMap<>() : new 
HashMap<>(subtypeVarAssigns);
+        }
+
+        // get the subject parameterized type's arguments
+        final Type[] typeArgs = parameterizedType.getActualTypeArguments();
+        // and get the corresponding type variables from the raw class
+        final TypeVariable<?>[] typeParams = cls.getTypeParameters();
+
+        // map the arguments to their respective type variables
+        for (int i = 0; i < typeParams.length; i++) {
+            final Type typeArg = typeArgs[i];
+            typeVarAssigns.put(typeParams[i], 
typeVarAssigns.containsKey(typeArg) ? typeVarAssigns
+                    .get(typeArg) : typeArg);
+        }
+
+        if (toClass.equals(cls)) {
+            // target class has been reached. Done.
+            return typeVarAssigns;
+        }
+
+        // walk the inheritance hierarchy until the target class is reached
+        return getTypeArguments(getClosestParentType(cls, toClass), toClass, 
typeVarAssigns);
+    }
+
+    /**
+     * <p>Return a map of the type arguments of a class in the context of 
@{code toClass}.</p>
+     *
+     * @param cls the class in question
+     * @param toClass the context class
+     * @param subtypeVarAssigns a map with type variables
+     * @return the {@code Map} with type arguments
+     */
+    private static Map<TypeVariable<?>, Type> getTypeArguments(Class<?> cls, 
final Class<?> toClass,
+            final Map<TypeVariable<?>, Type> subtypeVarAssigns) {
+        // make sure they're assignable
+        if (!isAssignable(cls, toClass)) {
+            return null;
+        }
+
+        // can't work with primitives
+        if (cls.isPrimitive()) {
+            // both classes are primitives?
+            if (toClass.isPrimitive()) {
+                // dealing with widening here. No type arguments to be
+                // harvested with these two types.
+                return new HashMap<>();
+            }
+
+            // work with wrapper the wrapper class instead of the primitive
+            cls = Reflection.primitiveToWrapper(cls);
+        }
+
+        // create a copy of the incoming map, or an empty one if it's null
+        final Map<TypeVariable<?>, Type> typeVarAssigns =
+            subtypeVarAssigns == null ? new HashMap<>() : new 
HashMap<>(subtypeVarAssigns);
+
+        // has target class been reached?
+        if (toClass.equals(cls)) {
+            return typeVarAssigns;
+        }
+
+        // walk the inheritance hierarchy until the target class is reached
+        return getTypeArguments(getClosestParentType(cls, toClass), toClass, 
typeVarAssigns);
+    }
+
+    /**
+     * <p>Get the closest parent type to the
+     * super class specified by {@code superClass}.</p>
+     *
+     * @param cls the class in question
+     * @param superClass the super class
+     * @return the closes parent type
+     */
+    private static Type getClosestParentType(final Class<?> cls, final 
Class<?> superClass) {
+        // only look at the interfaces if the super class is also an interface
+        if (superClass.isInterface()) {
+            // get the generic interfaces of the subject class
+            final Type[] interfaceTypes = cls.getGenericInterfaces();
+            // will hold the best generic interface match found
+            Type genericInterface = null;
+
+            // find the interface closest to the super class
+            for (final Type midType : interfaceTypes) {
+                Class<?> midClass = null;
+
+                if (midType instanceof ParameterizedType) {
+                    midClass = getRawType((ParameterizedType) midType);
+                } else if (midType instanceof Class<?>) {
+                    midClass = (Class<?>) midType;
+                } else {
+                    throw new IllegalStateException("Unexpected generic"
+                            + " interface type found: " + midType);
+                }
+
+                // check if this interface is further up the inheritance chain
+                // than the previously found match
+                if (isAssignable(midClass, superClass)
+                        && isAssignable(genericInterface, (Type) midClass)) {
+                    genericInterface = midType;
+                }
+            }
+
+            // found a match?
+            if (genericInterface != null) {
+                return genericInterface;
+            }
+        }
+
+        // none of the interfaces were descendants of the target class, so the
+        // super class has to be one, instead
+        return cls.getGenericSuperclass();
+    }
+
+    /**
+     * <p>Checks if the given value can be assigned to the target type
+     * following the Java generics rules.</p>
+     *
+     * @param value the value to be checked
+     * @param type the target type
+     * @return {@code true} if {@code value} is an instance of {@code type}.
+     */
+    public static boolean isInstance(final Object value, final Type type) {
+        if (type == null) {
+            return false;
+        }
+
+        return value == null ? !(type instanceof Class<?>) || type == 
void.class || !((Class<?>) type).isPrimitive()
+                : isAssignable(value.getClass(), type, null);
+    }
+
+    /**
+     * <p>This method strips out the redundant upper bound types in type
+     * variable types and wildcard types (or it would with wildcard types if
+     * multiple upper bounds were allowed).</p> <p>Example, with the variable
+     * type declaration:
+     *
+     * <pre>&lt;K extends java.util.Collection&lt;String&gt; &amp;
+     * java.util.List&lt;String&gt;&gt;</pre>
+     *
+     * <p>
+     * since {@code List} is a subinterface of {@code Collection},
+     * this method will return the bounds as if the declaration had been:
+     * </p>
+     *
+     * <pre>&lt;K extends java.util.List&lt;String&gt;&gt;</pre>
+     *
+     * @param bounds an array of types representing the upper bounds of either
+     * {@link WildcardType} or {@link TypeVariable}, not {@code null}.
+     * @return an array containing the values from {@code bounds} minus the
+     * redundant types.
+     */
+    public static Type[] normalizeUpperBounds(final Type[] bounds) {
+        Validate.notNull(bounds, "null value specified for bounds array");
+        // don't bother if there's only one (or none) type
+        if (bounds.length < 2) {
+            return bounds;
+        }
+
+        final Set<Type> types = new HashSet<>(bounds.length);
+
+        for (final Type type1 : bounds) {
+            boolean subtypeFound = false;
+
+            for (final Type type2 : bounds) {
+                if (type1 != type2 && isAssignable(type2, type1, null)) {
+                    subtypeFound = true;
+                    break;
+                }
+            }
+
+            if (!subtypeFound) {
+                types.add(type1);
+            }
+        }
+
+        return types.toArray(new Type[types.size()]);
+    }
+
+    /**
+     * <p>Returns an array containing the sole type of {@link Object} if
+     * {@link TypeVariable#getBounds()} returns an empty array. Otherwise, it
+     * returns the result of {@link TypeVariable#getBounds()} passed into
+     * {@link #normalizeUpperBounds}.</p>
+     *
+     * @param typeVariable the subject type variable, not {@code null}
+     * @return a non-empty array containing the bounds of the type variable.
+     */
+    public static Type[] getImplicitBounds(final TypeVariable<?> typeVariable) 
{
+        Validate.notNull(typeVariable, "typeVariable is null");
+        final Type[] bounds = typeVariable.getBounds();
+
+        return bounds.length == 0 ? new Type[] { Object.class } : 
normalizeUpperBounds(bounds);
+    }
+
+    /**
+     * <p>Returns an array containing the sole value of {@link Object} if
+     * {@link WildcardType#getUpperBounds()} returns an empty array. Otherwise,
+     * it returns the result of {@link WildcardType#getUpperBounds()}
+     * passed into {@link #normalizeUpperBounds}.</p>
+     *
+     * @param wildcardType the subject wildcard type, not {@code null}
+     * @return a non-empty array containing the upper bounds of the wildcard
+     * type.
+     */
+    public static Type[] getImplicitUpperBounds(final WildcardType 
wildcardType) {
+        Validate.notNull(wildcardType, "wildcardType is null");
+        final Type[] bounds = wildcardType.getUpperBounds();
+
+        return bounds.length == 0 ? new Type[] { Object.class } : 
normalizeUpperBounds(bounds);
+    }
+
+    /**
+     * <p>Returns an array containing a single value of {@code null} if
+     * {@link WildcardType#getLowerBounds()} returns an empty array. Otherwise,
+     * it returns the result of {@link WildcardType#getLowerBounds()}.</p>
+     *
+     * @param wildcardType the subject wildcard type, not {@code null}
+     * @return a non-empty array containing the lower bounds of the wildcard
+     * type.
+     */
+    public static Type[] getImplicitLowerBounds(final WildcardType 
wildcardType) {
+        Validate.notNull(wildcardType, "wildcardType is null");
+        final Type[] bounds = wildcardType.getLowerBounds();
+
+        return bounds.length == 0 ? new Type[] { null } : bounds;
+    }
+
+    /**
+     * <p>Transforms the passed in type to a {@link Class} object. 
Type-checking method of convenience.</p>
+     *
+     * @param parameterizedType the type to be converted
+     * @return the corresponding {@code Class} object
+     * @throws IllegalStateException if the conversion fails
+     */
+    private static Class<?> getRawType(final ParameterizedType 
parameterizedType) {
+        final Type rawType = parameterizedType.getRawType();
+
+        // check if raw type is a Class object
+        // not currently necessary, but since the return type is Type instead 
of
+        // Class, there's enough reason to believe that future versions of Java
+        // may return other Type implementations. And type-safety checking is
+        // rarely a bad idea.
+        if (!(rawType instanceof Class<?>)) {
+            throw new IllegalStateException("Wait... What!? Type of rawType: " 
+ rawType);
+        }
+
+        return (Class<?>) rawType;
+    }
+
+    /**
+     * <p>Get the raw type of a Java type, given its context. Primarily for use
+     * with {@link TypeVariable}s and {@link GenericArrayType}s, or when you do
+     * not know the runtime type of {@code type}: if you know you have a
+     * {@link Class} instance, it is already raw; if you know you have a
+     * {@link ParameterizedType}, its raw type is only a method call away.</p>
+     *
+     * @param type to resolve
+     * @param assigningType type to be resolved against
+     * @return the resolved {@link Class} object or {@code null} if
+     * the type could not be resolved
+     */
+    public static Class<?> getRawType(final Type type, final Type 
assigningType) {
+        if (type instanceof Class<?>) {
+            // it is raw, no problem
+            return (Class<?>) type;
+        }
+
+        if (type instanceof ParameterizedType) {
+            // simple enough to get the raw type of a ParameterizedType
+            return getRawType((ParameterizedType) type);
+        }
+
+        if (type instanceof TypeVariable<?>) {
+            if (assigningType == null) {
+                return null;
+            }
+
+            // get the entity declaring this type variable
+            final Object genericDeclaration = ((TypeVariable<?>) 
type).getGenericDeclaration();
+
+            // can't get the raw type of a method- or constructor-declared type
+            // variable
+            if (!(genericDeclaration instanceof Class<?>)) {
+                return null;
+            }
+
+            // get the type arguments for the declaring class/interface based
+            // on the enclosing type
+            final Map<TypeVariable<?>, Type> typeVarAssigns = 
getTypeArguments(assigningType,
+                    (Class<?>) genericDeclaration);
+
+            // enclosingType has to be a subclass (or subinterface) of the
+            // declaring type
+            if (typeVarAssigns == null) {
+                return null;
+            }
+
+            // get the argument assigned to this type variable
+            final Type typeArgument = typeVarAssigns.get(type);
+
+            if (typeArgument == null) {
+                return null;
+            }
+
+            // get the argument for this type variable
+            return getRawType(typeArgument, assigningType);
+        }
+
+        if (type instanceof GenericArrayType) {
+            // get raw component type
+            final Class<?> rawComponentType = getRawType(((GenericArrayType) 
type)
+                    .getGenericComponentType(), assigningType);
+
+            // create array type from raw component type and return its class
+            return Array.newInstance(rawComponentType, 0).getClass();
+        }
+
+        // (hand-waving) this is not the method you're looking for
+        if (type instanceof WildcardType) {
+            return null;
+        }
+
+        throw new IllegalArgumentException("unknown type: " + type);
+    }
+
+    /**
+     * Learn whether the specified type denotes an array type.
+     * @param type the type to be checked
+     * @return {@code true} if {@code type} is an array class or a {@link 
GenericArrayType}.
+     */
+    public static boolean isArrayType(final Type type) {
+        return type instanceof GenericArrayType || type instanceof Class<?> && 
((Class<?>) type).isArray();
+    }
+
+    /**
+     * Get the array component type of {@code type}.
+     * @param type the type to be checked
+     * @return component type or null if type is not an array type
+     */
+    public static Type getArrayComponentType(final Type type) {
+        if (type instanceof Class<?>) {
+            final Class<?> clazz = (Class<?>) type;
+            return clazz.isArray() ? clazz.getComponentType() : null;
+        }
+        if (type instanceof GenericArrayType) {
+            return ((GenericArrayType) type).getGenericComponentType();
+        }
+        return null;
+    }
+
+    /**
+     * Get a type representing {@code type} with variable assignments 
"unrolled."
+     *
+     * @param typeArguments as from {@link TypeUtils#getTypeArguments(Type, 
Class)}
+     * @param type the type to unroll variable assignments for
+     * @return Type
+     */
+    public static Type unrollVariables(Map<TypeVariable<?>, Type> 
typeArguments, final Type type) {
+        if (typeArguments == null) {
+            typeArguments = Collections.<TypeVariable<?>, Type> emptyMap();
+        }
+        if (containsTypeVariables(type)) {
+            if (type instanceof TypeVariable<?>) {
+                return unrollVariables(typeArguments, typeArguments.get(type));
+            }
+            if (type instanceof ParameterizedType) {
+                final ParameterizedType p = (ParameterizedType) type;
+                final Map<TypeVariable<?>, Type> parameterizedTypeArguments;
+                if (p.getOwnerType() == null) {
+                    parameterizedTypeArguments = typeArguments;
+                } else {
+                    parameterizedTypeArguments = new HashMap<>(typeArguments);
+                    
parameterizedTypeArguments.putAll(TypeUtils.getTypeArguments(p));
+                }
+                final Type[] args = p.getActualTypeArguments();
+                for (int i = 0; i < args.length; i++) {
+                    final Type unrolled = 
unrollVariables(parameterizedTypeArguments, args[i]);
+                    if (unrolled != null) {
+                        args[i] = unrolled;
+                    }
+                }
+                return parameterizeWithOwner(p.getOwnerType(), (Class<?>) 
p.getRawType(), args);
+            }
+            if (type instanceof WildcardType) {
+                final WildcardType wild = (WildcardType) type;
+                return 
wildcardType().withUpperBounds(unrollBounds(typeArguments, 
wild.getUpperBounds()))
+                    .withLowerBounds(unrollBounds(typeArguments, 
wild.getLowerBounds())).build();
+            }
+        }
+        return type;
+    }
+
+    /**
+     * Local helper method to unroll variables in a type bounds array.
+     * 
+     * @param typeArguments assignments {@link Map}
+     * @param bounds in which to expand variables
+     * @return {@code bounds} with any variables reassigned
+     */
+    private static Type[] unrollBounds(final Map<TypeVariable<?>, Type> 
typeArguments, final Type[] bounds) {
+        Type[] result = bounds;
+        int i = 0;
+        for (; i < result.length; i++) {
+            final Type unrolled = unrollVariables(typeArguments, result[i]);
+            if (unrolled == null) {
+                List<Type> types = Arrays.asList(result);
+                types.remove(i--);
+                result = types.toArray(new Type[types.size()]);
+            } else {
+                result[i] = unrolled;
+            }
+        }
+        return result;
+    }
+
+    /**
+     * Learn, recursively, whether any of the type parameters associated with 
{@code type} are bound to variables.
+     *
+     * @param type the type to check for type variables
+     * @return boolean
+     */
+    public static boolean containsTypeVariables(final Type type) {
+        if (type instanceof TypeVariable<?>) {
+            return true;
+        }
+        if (type instanceof Class<?>) {
+            return ((Class<?>) type).getTypeParameters().length > 0;
+        }
+        if (type instanceof ParameterizedType) {
+            for (final Type arg : ((ParameterizedType) 
type).getActualTypeArguments()) {
+                if (containsTypeVariables(arg)) {
+                    return true;
+                }
+            }
+            return false;
+        }
+        if (type instanceof WildcardType) {
+            final WildcardType wild = (WildcardType) type;
+            return 
containsTypeVariables(TypeUtils.getImplicitLowerBounds(wild)[0])
+                || 
containsTypeVariables(TypeUtils.getImplicitUpperBounds(wild)[0]);
+        }
+        return false;
+    }
+
+
+    /**
+     * Create a parameterized type instance.
+     *
+     * @param owner the owning type
+     * @param raw the raw class to create a parameterized type instance for
+     * @param typeArguments the types used for parameterization
+     *
+     * @return {@link ParameterizedType}
+     */
+    public static final ParameterizedType parameterizeWithOwner(final Type 
owner, final Class<?> raw,
+        final Type... typeArguments) {
+        Validate.notNull(raw, "raw class is null");
+        final Type useOwner;
+        if (raw.getEnclosingClass() == null) {
+            Validate.isTrue(owner == null, "no owner allowed for top-level 
%s", raw);
+            useOwner = null;
+        } else if (owner == null) {
+            useOwner = raw.getEnclosingClass();
+        } else {
+            Validate.isTrue(TypeUtils.isAssignable(owner, 
raw.getEnclosingClass()),
+                "%s is invalid owner type for parameterized %s", owner, raw);
+            useOwner = owner;
+        }
+        Validate.isTrue(raw.getTypeParameters().length == typeArguments.length,
+            "invalid number of type parameters specified: expected %d, got 
%d", raw.getTypeParameters().length,
+            typeArguments.length);
+
+        return new ParameterizedTypeImpl(raw, useOwner, typeArguments);
+    }
+
+    /**
+     * Get a {@link WildcardTypeBuilder}.
+     * @return {@link WildcardTypeBuilder}
+     */
+    public static WildcardTypeBuilder wildcardType() {
+        return new WildcardTypeBuilder();
+    }
+
+    /**
+     * Check equality of types.
+     *
+     * @param t1 the first type
+     * @param t2 the second type
+     * @return boolean
+     */
+    public static boolean equals(final Type t1, final Type t2) {
+        if (t1 == t2) {
+            return true;
+        }
+        if (t1 == null || t2 == null) {
+            return false;
+        }
+
+        if (t1.equals(t2)) {
+            return true;
+        }
+        if (t1 instanceof ParameterizedType) {
+            return equals((ParameterizedType) t1, t2);
+        }
+        if (t1 instanceof GenericArrayType) {
+            return equals((GenericArrayType) t1, t2);
+        }
+        if (t1 instanceof WildcardType) {
+            return equals((WildcardType) t1, t2);
+        }
+        return false;
+    }
+
+    /**
+     * Learn whether {@code t} equals {@code p}.
+     * @param p LHS
+     * @param t RHS
+     * @return boolean
+     */
+    private static boolean equals(final ParameterizedType p, final Type t) {
+        if (t instanceof ParameterizedType) {
+            final ParameterizedType other = (ParameterizedType) t;
+            if (equals(p.getRawType(), other.getRawType()) && 
equals(p.getOwnerType(), other.getOwnerType())) {
+                return equals(p.getActualTypeArguments(), 
other.getActualTypeArguments());
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Learn whether {@code t} equals {@code a}.
+     * @param a LHS
+     * @param t RHS
+     * @return boolean
+     */
+    private static boolean equals(final GenericArrayType a, final Type t) {
+        return t instanceof GenericArrayType
+            && equals(a.getGenericComponentType(), ((GenericArrayType) 
t).getGenericComponentType());
+    }
+
+    /**
+     * Learn whether {@code t} equals {@code w}.
+     * @param w LHS
+     * @param t RHS
+     * @return boolean
+     */
+    private static boolean equals(final WildcardType w, final Type t) {
+        if (t instanceof WildcardType) {
+            final WildcardType other = (WildcardType) t;
+            return equals(getImplicitLowerBounds(w), 
getImplicitLowerBounds(other))
+                && equals(getImplicitUpperBounds(w), 
getImplicitUpperBounds(other));
+        }
+        return false;
+    }
+
+    /**
+     * Learn whether {@code t1} equals {@code t2}.
+     * @param t1 LHS
+     * @param t2 RHS
+     * @return boolean
+     */
+    private static boolean equals(final Type[] t1, final Type[] t2) {
+        if (t1.length == t2.length) {
+            for (int i = 0; i < t1.length; i++) {
+                if (!equals(t1[i], t2[i])) {
+                    return false;
+                }
+            }
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * Present a given type as a Java-esque String.
+     *
+     * @param type the type to create a String representation for, not {@code 
null}
+     * @return String
+     */
+    public static String toString(final Type type) {
+        Validate.notNull(type);
+        if (type instanceof Class<?>) {
+            return classToString((Class<?>) type);
+        }
+        if (type instanceof ParameterizedType) {
+            return parameterizedTypeToString((ParameterizedType) type);
+        }
+        if (type instanceof WildcardType) {
+            return wildcardTypeToString((WildcardType) type);
+        }
+        if (type instanceof TypeVariable<?>) {
+            return typeVariableToString((TypeVariable<?>) type);
+        }
+        if (type instanceof GenericArrayType) {
+            return genericArrayTypeToString((GenericArrayType) type);
+        }
+        throw new IllegalArgumentException(type.toString());
+    }
+
+
+    /**
+     * Format a {@link Class} as a {@link String}.
+     * @param c {@code Class} to format
+     * @return String
+     */
+    private static String classToString(final Class<?> c) {
+        final StringBuilder buf = new StringBuilder();
+
+        if (c.getEnclosingClass() != null) {
+            
buf.append(classToString(c.getEnclosingClass())).append('.').append(c.getSimpleName());
+        } else {
+            buf.append(c.getName());
+        }
+        if (c.getTypeParameters().length > 0) {
+            buf.append('<');
+            appendAllTo(buf, ", ", c.getTypeParameters());
+            buf.append('>');
+        }
+        return buf.toString();
+    }
+
+    /**
+     * Format a {@link TypeVariable} as a {@link String}.
+     * @param v {@code TypeVariable} to format
+     * @return String
+     */
+    private static String typeVariableToString(final TypeVariable<?> v) {
+        final StringBuilder buf = new StringBuilder(v.getName());
+        final Type[] bounds = v.getBounds();
+        if (bounds.length > 0 && !(bounds.length == 1 && 
Object.class.equals(bounds[0]))) {
+            buf.append(" extends ");
+            appendAllTo(buf, " & ", v.getBounds());
+        }
+        return buf.toString();
+    }
+
+    /**
+     * Format a {@link ParameterizedType} as a {@link String}.
+     * @param p {@code ParameterizedType} to format
+     * @return String
+     */
+    private static String parameterizedTypeToString(final ParameterizedType p) 
{
+        final StringBuilder buf = new StringBuilder();
+
+        final Type useOwner = p.getOwnerType();
+        final Class<?> raw = (Class<?>) p.getRawType();
+        final Type[] typeArguments = p.getActualTypeArguments();
+        if (useOwner == null) {
+            buf.append(raw.getName());
+        } else {
+            if (useOwner instanceof Class<?>) {
+                buf.append(((Class<?>) useOwner).getName());
+            } else {
+                buf.append(useOwner.toString());
+            }
+            buf.append('.').append(raw.getSimpleName());
+        }
+
+        appendAllTo(buf.append('<'), ", ", typeArguments).append('>');
+        return buf.toString();
+    }
+
+    /**
+     * Format a {@link WildcardType} as a {@link String}.
+     * @param w {@code WildcardType} to format
+     * @return String
+     */
+    private static String wildcardTypeToString(final WildcardType w) {
+        final StringBuilder buf = new StringBuilder().append('?');
+        final Type[] lowerBounds = w.getLowerBounds();
+        final Type[] upperBounds = w.getUpperBounds();
+        if (lowerBounds.length > 1 || lowerBounds.length == 1 && 
lowerBounds[0] != null) {
+            appendAllTo(buf.append(" super "), " & ", lowerBounds);
+        } else if (upperBounds.length > 1 || upperBounds.length == 1 && 
!Object.class.equals(upperBounds[0])) {
+            appendAllTo(buf.append(" extends "), " & ", upperBounds);
+        }
+        return buf.toString();
+    }
+
+    /**
+     * Format a {@link GenericArrayType} as a {@link String}.
+     * @param g {@code GenericArrayType} to format
+     * @return String
+     */
+    private static String genericArrayTypeToString(final GenericArrayType g) {
+        return String.format("%s[]", toString(g.getGenericComponentType()));
+    }
+
+    /**
+     * Append {@code types} to @{code buf} with separator {@code sep}.
+     * @param buf destination
+     * @param sep separator
+     * @param types to append
+     * @return {@code buf}
+     */
+    private static StringBuilder appendAllTo(final StringBuilder buf, final 
String sep, final Type... types) {
+        if (types.length > 0) {
+            buf.append(toString(types[0]));
+            for (int i = 1; i < types.length; i++) {
+                buf.append(sep).append(toString(types[i]));
+            }
+        }
+        return buf;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/bval/blob/ed299e4f/bval-jsr/src/test/java/org/apache/bval/jsr/TckReproducerTest.java
----------------------------------------------------------------------
diff --git a/bval-jsr/src/test/java/org/apache/bval/jsr/TckReproducerTest.java 
b/bval-jsr/src/test/java/org/apache/bval/jsr/TckReproducerTest.java
index ab65286..0fed395 100644
--- a/bval-jsr/src/test/java/org/apache/bval/jsr/TckReproducerTest.java
+++ b/bval-jsr/src/test/java/org/apache/bval/jsr/TckReproducerTest.java
@@ -26,7 +26,6 @@ import java.util.Set;
 import javax.validation.ConstraintViolation;
 import javax.validation.constraints.Pattern;
 
-import org.apache.bval.util.PropertyAccess;
 import org.junit.Test;
 
 /**
@@ -44,18 +43,18 @@ public class TckReproducerTest extends ValidationTestBase {
             expectedViolations, violations.size());
     }
 
-    @Test
-    public void testPropertyAccessOnNonPublicClass() throws Exception {
-        Car car = new Car("USd-298");
-        assertEquals(car.getLicensePlateNumber(), 
PropertyAccess.getProperty(car, "licensePlateNumber"));
-
-        assertCorrectNumberOfViolations(validator.validateProperty(car, 
"licensePlateNumber", First.class,
-            org.apache.bval.jsr.example.Second.class), 1);
-
-        car.setLicensePlateNumber("USD-298");
-        assertCorrectNumberOfViolations(validator.validateProperty(car, 
"licensePlateNumber", First.class,
-            org.apache.bval.jsr.example.Second.class), 0);
-    }
+//    @Test
+//    public void testPropertyAccessOnNonPublicClass() throws Exception {
+//        Car car = new Car("USd-298");
+//        assertEquals(car.getLicensePlateNumber(), 
PropertyAccess.getProperty(car, "licensePlateNumber"));
+//
+//        assertCorrectNumberOfViolations(validator.validateProperty(car, 
"licensePlateNumber", First.class,
+//            org.apache.bval.jsr.example.Second.class), 1);
+//
+//        car.setLicensePlateNumber("USD-298");
+//        assertCorrectNumberOfViolations(validator.validateProperty(car, 
"licensePlateNumber", First.class,
+//            org.apache.bval.jsr.example.Second.class), 0);
+//    }
 
     static class Car {
         @Pattern(regexp = "[A-Z][A-Z][A-Z]-[0-9][0-9][0-9]", groups = { 
First.class, Second.class })

http://git-wip-us.apache.org/repos/asf/bval/blob/ed299e4f/bval-xstream/findbugs-exclude-filter.xml
----------------------------------------------------------------------
diff --git a/bval-xstream/findbugs-exclude-filter.xml 
b/bval-xstream/findbugs-exclude-filter.xml
deleted file mode 100644
index eaf41b1..0000000
--- a/bval-xstream/findbugs-exclude-filter.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0"?>
-<!--
-   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.
--->
-
-<!--
-  This file contains some false positive bugs detected by findbugs. Their
-  false positive nature has been analyzed individually and they have been
-  put here to instruct findbugs it must ignore them.
--->
-<FindBugsFilter>
-  <!-- not a problem -->
-  <Match>
-    <Class name="org.apache.bval.xml.XMLMetaBeanManager" />
-    <Method name="computeRelatedMetaBean" 
params="org.apache.bval.model.MetaProperty,java.lang.String" returns="void" />
-    <Bug pattern="NP_LOAD_OF_KNOWN_NULL_VALUE" />
-  </Match>
-</FindBugsFilter>

http://git-wip-us.apache.org/repos/asf/bval/blob/ed299e4f/bval-xstream/pom.xml
----------------------------------------------------------------------
diff --git a/bval-xstream/pom.xml b/bval-xstream/pom.xml
deleted file mode 100644
index bf90180..0000000
--- a/bval-xstream/pom.xml
+++ /dev/null
@@ -1,102 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- 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.
--->
-<!--
-       Maven release plugin requires the project tag to be on a single line.
--->
-<project xmlns="http://maven.apache.org/POM/4.0.0"; 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"; 
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/maven-v4_0_0.xsd";>
-
-    <modelVersion>4.0.0</modelVersion>
-
-    <parent>
-        <groupId>org.apache.bval</groupId>
-        <artifactId>bval-parent</artifactId>
-        <version>2.0.0-SNAPSHOT</version>
-    </parent>
-
-    <artifactId>bval-xstream</artifactId>
-    <name>Apache BVal :: bval-xstream (optional)</name>
-    <packaging>jar</packaging>
-
-    <description>BVal XML Metadata with XStream</description>
-
-    <dependencies>
-        <dependency>
-            <groupId>org.apache.bval</groupId>
-            <artifactId>bval-core</artifactId>
-            <version>${project.version}</version>
-        </dependency>
-        <dependency>
-            <groupId>com.thoughtworks.xstream</groupId>
-            <artifactId>xstream</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.commons</groupId>
-            <artifactId>commons-weaver-privilizer-api</artifactId>
-        </dependency>
-        <!-- Test dependencies -->
-        <dependency>
-            <groupId>junit</groupId>
-            <artifactId>junit</artifactId>
-            <scope>test</scope>
-        </dependency>
-    </dependencies>
-
-    <build>
-        <plugins>
-            <!-- create mainClass attribute -->
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-jar-plugin</artifactId>
-                <executions>
-                    <execution>
-                        <id>default-jar</id>
-                        <goals>
-                            <goal>jar</goal>
-                        </goals>
-                        <configuration>
-                            <archive>
-                                <manifest>
-                                    
<mainClass>org.apache.bval.util.BValVersion</mainClass>
-                                </manifest>
-                            </archive>
-                        </configuration>
-                    </execution>
-                    <execution>
-                        <id>attach-tests</id>
-                        <goals>
-                            <goal>test-jar</goal>
-                        </goals>
-                    </execution>
-                </executions>
-            </plugin>
-            <plugin>
-                <groupId>org.codehaus.mojo</groupId>
-                <artifactId>findbugs-maven-plugin</artifactId>
-                <configuration>
-                    
<excludeFilterFile>findbugs-exclude-filter.xml</excludeFilterFile>
-                </configuration>
-            </plugin>
-            <plugin>
-                <groupId>org.apache.commons</groupId>
-                <artifactId>commons-weaver-maven-plugin</artifactId>
-            </plugin>
-        </plugins>
-    </build>
-</project>

http://git-wip-us.apache.org/repos/asf/bval/blob/ed299e4f/bval-xstream/src/main/java/org/apache/bval/routines/EMailValidation.java
----------------------------------------------------------------------
diff --git 
a/bval-xstream/src/main/java/org/apache/bval/routines/EMailValidation.java 
b/bval-xstream/src/main/java/org/apache/bval/routines/EMailValidation.java
deleted file mode 100644
index 925b9c2..0000000
--- a/bval-xstream/src/main/java/org/apache/bval/routines/EMailValidation.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- *  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.routines;
-
-import org.apache.bval.model.Validation;
-import org.apache.bval.model.ValidationContext;
-import org.apache.bval.model.ValidationListener;
-
-import java.util.regex.Pattern;
-
-/**
- * Description: example validation for email addresses using a regular 
expression<br/>
- */
-public class EMailValidation implements Validation {
-
-    private java.util.regex.Pattern pattern = 
EMailValidationUtils.DEFAULT_EMAIL_PATTERN;
-
-    @Override
-    public <T extends ValidationListener> void validate(ValidationContext<T> 
context) {
-        if (context.getPropertyValue() == null)
-            return;
-        if (!EMailValidationUtils.isValid(context.getPropertyValue(), 
getPattern())) {
-            context.getListener().addError(Reasons.EMAIL_ADDRESS, context);
-        }
-    }
-
-    public Pattern getPattern() {
-        return pattern;
-    }
-
-    public void setPattern(Pattern pattern) {
-        this.pattern = pattern;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/bval/blob/ed299e4f/bval-xstream/src/main/java/org/apache/bval/routines/NOPValidation.java
----------------------------------------------------------------------
diff --git 
a/bval-xstream/src/main/java/org/apache/bval/routines/NOPValidation.java 
b/bval-xstream/src/main/java/org/apache/bval/routines/NOPValidation.java
deleted file mode 100644
index f6b4cce..0000000
--- a/bval-xstream/src/main/java/org/apache/bval/routines/NOPValidation.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- *  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.routines;
-
-import org.apache.bval.model.Validation;
-import org.apache.bval.model.ValidationContext;
-import org.apache.bval.model.ValidationListener;
-
-/**
- * Description: DO NOTHING VALIDATION (can be used to turn off standard 
validation)<br/>
- */
-public class NOPValidation implements Validation {
-
-    @Override
-    public <T extends ValidationListener> void validate(ValidationContext<T> 
context) {
-        // do nothing
-    }
-}

http://git-wip-us.apache.org/repos/asf/bval/blob/ed299e4f/bval-xstream/src/main/java/org/apache/bval/routines/Reasons.java
----------------------------------------------------------------------
diff --git a/bval-xstream/src/main/java/org/apache/bval/routines/Reasons.java 
b/bval-xstream/src/main/java/org/apache/bval/routines/Reasons.java
deleted file mode 100644
index 397081f..0000000
--- a/bval-xstream/src/main/java/org/apache/bval/routines/Reasons.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- *  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.routines;
-
-import org.apache.bval.model.Features;
-
-/**
- * Description: StandardReasons for validation errors found in
- * {@link org.apache.bval.ValidationResults}<br/>
- */
-public interface Reasons extends Features.Property {
-    // The reasons inherited from Features are VALIDATION features only.
-    // INFO features are not meant to be validated.
-
-    // Add more reasons here.
-    String EMAIL_ADDRESS = "emailAddress";
-}

http://git-wip-us.apache.org/repos/asf/bval/blob/ed299e4f/bval-xstream/src/main/java/org/apache/bval/routines/StandardValidation.java
----------------------------------------------------------------------
diff --git 
a/bval-xstream/src/main/java/org/apache/bval/routines/StandardValidation.java 
b/bval-xstream/src/main/java/org/apache/bval/routines/StandardValidation.java
deleted file mode 100644
index 5d8b84a..0000000
--- 
a/bval-xstream/src/main/java/org/apache/bval/routines/StandardValidation.java
+++ /dev/null
@@ -1,192 +0,0 @@
-/*
- *  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.routines;
-
-import org.apache.bval.model.Features;
-import org.apache.bval.model.MetaProperty;
-import org.apache.bval.model.Validation;
-import org.apache.bval.model.ValidationContext;
-import org.apache.bval.model.ValidationListener;
-import org.apache.bval.xml.XMLMetaValue;
-
-import java.util.Collection;
-import java.util.Date;
-import java.util.regex.Pattern;
-import java.util.regex.PatternSyntaxException;
-
-import static org.apache.bval.model.Features.Property.MANDATORY;
-import static org.apache.bval.model.Features.Property.MAX_LENGTH;
-import static org.apache.bval.model.Features.Property.MAX_VALUE;
-import static org.apache.bval.model.Features.Property.MIN_LENGTH;
-import static org.apache.bval.model.Features.Property.MIN_VALUE;
-import static org.apache.bval.model.Features.Property.REG_EXP;
-import static org.apache.bval.model.Features.Property.TIME_LAG;
-
-/**
- * Description: This class implements the standard validations for properties!
- * You can subclass this class and replace the implementation
- * in the beanInfo-xml by providing it a validation "standard"<br/>
- */
-public class StandardValidation implements Validation {
-
-    /** key for this validation in the validation list of the beanInfos */
-    public String getValidationId() {
-        return "standard";
-    }
-
-    @Override
-    public <T extends ValidationListener> void validate(ValidationContext<T> 
context) {
-        validateMandatory(context);
-        validateMaxLength(context);
-        validateMinLength(context);
-        validateMaxValue(context);
-        validateMinValue(context);
-        validateRegExp(context);
-        validateTimeLag(context);
-    }
-
-    protected <T extends ValidationListener> void 
validateTimeLag(ValidationContext<T> context) {
-        String lag = (String) context.getMetaProperty().getFeature(TIME_LAG);
-        if (lag == null)
-            return;
-        if (context.getPropertyValue() == null)
-            return;
-        long date = ((Date) context.getPropertyValue()).getTime();
-        long now = System.currentTimeMillis();
-        if (XMLMetaValue.TIMELAG_Future.equals(lag)) {
-            if (date < now) {
-                context.getListener().addError(TIME_LAG, context);
-            }
-        } else if (XMLMetaValue.TIMELAG_Past.equals(lag)) {
-            if (date > now) {
-                context.getListener().addError(TIME_LAG, context);
-            }
-        } else {
-            throw new IllegalArgumentException("unknown timelag " + lag + " at 
" + context);
-        }
-    }
-
-    private static final String REG_EXP_PATTERN = "cachedRegExpPattern";
-
-    protected <T extends ValidationListener> void 
validateRegExp(ValidationContext<T> context) {
-        final MetaProperty meta = context.getMetaProperty();
-        final String regExp = (String) meta.getFeature(REG_EXP);
-        if (regExp == null)
-            return;
-        if (context.getPropertyValue() == null)
-            return;
-
-        final String value = String.valueOf(context.getPropertyValue());
-        try {
-            Pattern pattern = (Pattern) meta.getFeature(REG_EXP_PATTERN);
-            if (pattern == null) {
-                pattern = Pattern.compile(regExp);
-                meta.putFeature(REG_EXP_PATTERN, pattern);
-            }
-            if (!pattern.matcher(value).matches()) {
-                context.getListener().addError(REG_EXP, context);
-            }
-        } catch (PatternSyntaxException e) {
-            throw new IllegalArgumentException("regular expression malformed. 
regexp " + regExp + " at " + context, e);
-        }
-    }
-
-    protected <T extends ValidationListener> void 
validateMinValue(ValidationContext<T> context) {
-        @SuppressWarnings("unchecked")
-        Comparable<Object> minValue = (Comparable<Object>) 
context.getMetaProperty().getFeature(MIN_VALUE);
-        if (minValue == null || context.getPropertyValue() == null)
-            return;
-        if (compare(context, minValue, context.getPropertyValue()) > 0) {
-            context.getListener().addError(MIN_VALUE, context);
-        }
-    }
-
-    protected <T extends ValidationListener> void 
validateMaxValue(ValidationContext<T> context) {
-        @SuppressWarnings("unchecked")
-        Comparable<Object> maxValue = (Comparable<Object>) 
context.getMetaProperty().getFeature(MAX_VALUE);
-        if (maxValue == null || context.getPropertyValue() == null)
-            return;
-        if (compare(context, maxValue, context.getPropertyValue()) < 0) {
-            context.getListener().addError(MAX_VALUE, context);
-        }
-    }
-
-    private <T extends ValidationListener> int compare(ValidationContext<T> 
context, Comparable<Object> constraintValue,
-        Object currentValue) {
-        int r;
-        if 
(constraintValue.getClass().isAssignableFrom(currentValue.getClass())) {
-            r = constraintValue.compareTo(context.getPropertyValue());
-        } else if (currentValue instanceof Number) {
-            double dv = ((Number) currentValue).doubleValue();
-            double mdv = ((Number) constraintValue).doubleValue();
-            r = mdv > dv ? 1 : -1;
-        } else {
-            r = 
String.valueOf(constraintValue).compareTo(String.valueOf(currentValue));
-        }
-        return r;
-    }
-
-    protected <T extends ValidationListener> void 
validateMaxLength(ValidationContext<T> context) {
-        Integer maxLength = (Integer) 
context.getMetaProperty().getFeature(Features.Property.MAX_LENGTH);
-        if (maxLength == null)
-            return;
-        if (context.getPropertyValue() == null)
-            return;
-
-        final Object value = context.getPropertyValue();
-        int length = 0;
-        if (value instanceof String) {
-            length = ((String) value).length();
-        } else if (value instanceof Collection<?>) {
-            length = ((Collection<?>) value).size();
-        }
-        if (length > maxLength) {
-            context.getListener().addError(MAX_LENGTH, context);
-        }
-    }
-
-    protected <T extends ValidationListener> void 
validateMinLength(ValidationContext<T> context) {
-        Integer maxLength = (Integer) 
context.getMetaProperty().getFeature(Features.Property.MIN_LENGTH);
-        if (maxLength == null)
-            return;
-        if (context.getPropertyValue() == null)
-            return;
-
-        final Object value = context.getPropertyValue();
-        int length = 0;
-        if (value instanceof String) {
-            length = ((String) value).length();
-        } else if (value instanceof Collection<?>) {
-            length = ((Collection<?>) value).size();
-        }
-        if (length < maxLength) {
-            context.getListener().addError(MIN_LENGTH, context);
-        }
-    }
-
-    protected <T extends ValidationListener> void 
validateMandatory(ValidationContext<T> context) {
-        if (context.getMetaProperty().isMandatory()) {
-            if (context.getPropertyValue() == null) {
-                context.getListener().addError(MANDATORY, context);
-            }
-        }
-    }
-
-    public static StandardValidation getInstance() {
-        return new StandardValidation();
-    }
-}

http://git-wip-us.apache.org/repos/asf/bval/blob/ed299e4f/bval-xstream/src/main/java/org/apache/bval/xml/MetaBeanEnricher.java
----------------------------------------------------------------------
diff --git 
a/bval-xstream/src/main/java/org/apache/bval/xml/MetaBeanEnricher.java 
b/bval-xstream/src/main/java/org/apache/bval/xml/MetaBeanEnricher.java
deleted file mode 100644
index 5246b42..0000000
--- a/bval-xstream/src/main/java/org/apache/bval/xml/MetaBeanEnricher.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- *  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.xml;
-
-import org.apache.bval.model.MetaBean;
-
-import java.util.Map;
-
-/**
- * Description: Interface to merge meta beans<br/>
- */
-public interface MetaBeanEnricher {
-
-    /**
-     * @param infos - the patches to apply
-     * @return all MetaBeans for classes that have a xml descriptor and
-     *         additional the MetaBeans loaded by the given loaders.
-     *         The given loaders may also return patches for MetaBeans that 
have
-     *         also been returned by other loaders. The beans with patches for
-     *         references to patched beans will be copied.
-     */
-    Map<String, MetaBean> enrichCopies(XMLMetaBeanInfos... infos);
-}

http://git-wip-us.apache.org/repos/asf/bval/blob/ed299e4f/bval-xstream/src/main/java/org/apache/bval/xml/XMLFeaturesCapable.java
----------------------------------------------------------------------
diff --git 
a/bval-xstream/src/main/java/org/apache/bval/xml/XMLFeaturesCapable.java 
b/bval-xstream/src/main/java/org/apache/bval/xml/XMLFeaturesCapable.java
deleted file mode 100644
index d06f6d5..0000000
--- a/bval-xstream/src/main/java/org/apache/bval/xml/XMLFeaturesCapable.java
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- *  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.xml;
-
-import com.thoughtworks.xstream.annotations.XStreamImplicit;
-import org.apache.bval.model.FeaturesCapable;
-
-import java.io.Serializable;
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Description: <br/>
- */
-public class XMLFeaturesCapable implements Serializable {
-    /** Serialization version */
-    private static final long serialVersionUID = 1L;
-
-    @XStreamImplicit
-    private List<XMLMetaFeature> features;
-    @XStreamImplicit(itemFieldName = "validator")
-    private List<XMLMetaValidatorReference> validators;
-
-    public List<XMLMetaFeature> getFeatures() {
-        return features;
-    }
-
-    public void setFeatures(List<XMLMetaFeature> features) {
-        this.features = features;
-    }
-
-    public void putFeature(String key, Object value) {
-        XMLMetaFeature anno = findFeature(key);
-        if (features == null)
-            features = new ArrayList<XMLMetaFeature>();
-        if (anno == null) {
-            features.add(new XMLMetaFeature(key, value));
-        } else {
-            anno.setValue(value);
-        }
-    }
-
-    public void removeFeature(String key) {
-        XMLMetaFeature anno = findFeature(key);
-        if (anno != null) {
-            getFeatures().remove(anno);
-        }
-    }
-
-    public Object getFeature(String key) {
-        XMLMetaFeature anno = findFeature(key);
-        return anno == null ? null : anno.getValue();
-    }
-
-    private XMLMetaFeature findFeature(String key) {
-        if (features == null)
-            return null;
-        for (XMLMetaFeature anno : features) {
-            if (key.equals(anno.getKey()))
-                return anno;
-        }
-        return null;
-    }
-
-    public List<XMLMetaValidatorReference> getValidators() {
-        return validators;
-    }
-
-    public void setValidators(List<XMLMetaValidatorReference> validators) {
-        this.validators = validators;
-    }
-
-    public void addValidator(String validatorId) {
-        if (validators == null)
-            validators = new ArrayList<XMLMetaValidatorReference>();
-        validators.add(new XMLMetaValidatorReference(validatorId));
-    }
-
-    public void mergeFeaturesInto(FeaturesCapable fc) {
-        if (getFeatures() != null) {
-            for (XMLMetaFeature each : getFeatures()) {
-                fc.putFeature(each.getKey(), each.getValue());
-            }
-        }
-    }
-}

Reply via email to