You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@bval.apache.org by st...@apache.org on 2016/10/24 21:02:02 UTC
svn commit: r1766445 [2/3] - in /bval/trunk: ./ bundle/ bval-core/
bval-core/src/main/java/org/apache/bval/
bval-core/src/main/java/org/apache/bval/model/
bval-core/src/main/java/org/apache/bval/util/
bval-core/src/main/java/org/apache/bval/util/reflec...
Added: bval/trunk/bval-core/src/main/java/org/apache/bval/util/reflection/TypeUtils.java
URL: http://svn.apache.org/viewvc/bval/trunk/bval-core/src/main/java/org/apache/bval/util/reflection/TypeUtils.java?rev=1766445&view=auto
==============================================================================
--- bval/trunk/bval-core/src/main/java/org/apache/bval/util/reflection/TypeUtils.java (added)
+++ bval/trunk/bval-core/src/main/java/org/apache/bval/util/reflection/TypeUtils.java Mon Oct 24 21:02:02 2016
@@ -0,0 +1,1603 @@
+/*
+ * 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.Set;
+
+import org.apache.bval.util.Validate;
+
+/**
+ * Taken from commons-lang3.
+ *
+ * <p> Utility methods focusing on type inspection, particularly with regard to
+ * generics. </p>
+ *
+ * @since 3.0
+ */
+public class TypeUtils {
+
+ /**
+ * {@link WildcardType} builder.
+ * @since 3.2
+ */
+ 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.
+ * @since 3.2
+ */
+ 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}
+ */
+ @SuppressWarnings( "deprecation" ) // ObjectUtils.hashCode(Object) has been deprecated in 3.2
+ @Override
+ public int hashCode() {
+ int result = 71 << 4;
+ result |= raw.hashCode();
+ result <<= 4;
+ result |= useOwner == null ? 0 : useOwner.hashCode();
+ result <<= 8;
+ result |= Arrays.hashCode(typeArguments);
+ return result;
+ }
+ }
+
+ /**
+ * WildcardType implementation class.
+ * @since 3.2
+ */
+ private static final class WildcardTypeImpl implements WildcardType {
+ private static final Type[] EMPTY_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 = upperBounds != null ? upperBounds : EMPTY_BOUNDS;
+ this.lowerBounds = lowerBounds != null ? lowerBounds : EMPTY_BOUNDS;
+ }
+
+ /**
+ * {@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() {
+ int result = 73 << 8;
+ result |= Arrays.hashCode(upperBounds);
+ result <<= 8;
+ result |= Arrays.hashCode(lowerBounds);
+ return result;
+ }
+ }
+
+ /**
+ * <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.
+ for (final Type bound : ((TypeVariable<?>) type).getBounds()) {
+ if (isAssignable(bound, toClass)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ // the only classes to which a generic array type can be assigned
+ // are class Object and array classes
+ if (type instanceof GenericArrayType) {
+ return toClass.equals(Object.class)
+ || 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
+ * @since 3.2
+ */
+ 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
+ for (final Type bound : getImplicitUpperBounds((WildcardType) type)) {
+ if (isAssignable(bound, toGenericArrayType)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ if (type instanceof TypeVariable<?>) {
+ // probably should remove the following logic and just return false.
+ // type variables cannot specify arrays as bounds.
+ for (final Type bound : getImplicitBounds((TypeVariable<?>) type)) {
+ if (isAssignable(bound, toGenericArrayType)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ 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<TypeVariable<?>, Type>()
+ : new HashMap<TypeVariable<?>, Type>(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<TypeVariable<?>, Type>();
+ }
+
+ // 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 HashMap<TypeVariable<?>, Type> typeVarAssigns = subtypeVarAssigns == null ? new HashMap<TypeVariable<?>, Type>()
+ : new HashMap<TypeVariable<?>, Type>(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<?>) || !((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><K extends java.util.Collection<String> &
+ * java.util.List<String>></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><K extends java.util.List<String>></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<Type>(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
+ * @since 3.2
+ */
+ 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<TypeVariable<?>, Type>(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
+ * @since 3.2
+ */
+ 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
+ * @since 3.2
+ */
+ 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}
+ * @since 3.2
+ */
+ 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}
+ * @since 3.2
+ */
+ public static WildcardTypeBuilder wildcardType() {
+ return new WildcardTypeBuilder();
+ }
+
+ /**
+ * Check equality of types.
+ *
+ * @param t1 the first type
+ * @param t2 the second type
+ * @return boolean
+ * @since 3.2
+ */
+ @SuppressWarnings( "deprecation" ) // ObjectUtils.equals(Object, Object) has been deprecated in 3.2
+ 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
+ * @since 3.2
+ */
+ 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
+ * @since 3.2
+ */
+ 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
+ * @since 3.2
+ */
+ 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
+ * @since 3.2
+ */
+ 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
+ * @since 3.2
+ */
+ 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
+ * @since 3.2
+ */
+ 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
+ * @since 3.2
+ */
+ 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
+ * @since 3.2
+ */
+ 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
+ * @since 3.2
+ */
+ 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
+ * @since 3.2
+ */
+ 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}
+ * @since 3.2
+ */
+ 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;
+ }
+
+}
Propchange: bval/trunk/bval-core/src/main/java/org/apache/bval/util/reflection/TypeUtils.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: bval/trunk/bval-core/src/test/java/org/apache/bval/util/StringUtilsTest.java
URL: http://svn.apache.org/viewvc/bval/trunk/bval-core/src/test/java/org/apache/bval/util/StringUtilsTest.java?rev=1766445&view=auto
==============================================================================
--- bval/trunk/bval-core/src/test/java/org/apache/bval/util/StringUtilsTest.java (added)
+++ bval/trunk/bval-core/src/test/java/org/apache/bval/util/StringUtilsTest.java Mon Oct 24 21:02:02 2016
@@ -0,0 +1,32 @@
+/*
+ * 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;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+public class StringUtilsTest {
+
+ @Test
+ public void testStringSplit() {
+ Assert.assertArrayEquals(new String[0], StringUtils.split(null));
+ Assert.assertArrayEquals(new String[0], StringUtils.split(""));
+ Assert.assertArrayEquals(new String[0], StringUtils.split(" "));
+ Assert.assertArrayEquals(new String[0], StringUtils.split(" \n "));
+ Assert.assertArrayEquals(new String[]{"a", "bbb", "cccc"}, StringUtils.split(" a bbb cccc"));
+ }
+}
Propchange: bval/trunk/bval-core/src/test/java/org/apache/bval/util/StringUtilsTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: bval/trunk/bval-jsr/pom.xml
URL: http://svn.apache.org/viewvc/bval/trunk/bval-jsr/pom.xml?rev=1766445&r1=1766444&r2=1766445&view=diff
==============================================================================
--- bval/trunk/bval-jsr/pom.xml (original)
+++ bval/trunk/bval-jsr/pom.xml Mon Oct 24 21:02:02 2016
@@ -279,42 +279,6 @@
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-shade-plugin</artifactId>
- <configuration>
- <artifactSet>
- <includes>
- <include>org.apache.commons:commons-lang3</include>
- </includes>
- </artifactSet>
- <filters>
- <filter>
- <artifact>org.apache.commons:commons-lang3</artifact>
- <excludes>
- <exclude>META-INF/maven/**</exclude>
- </excludes>
- </filter>
- </filters>
- <relocations>
- <relocation>
- <pattern>org.apache.commons</pattern>
- <shadedPattern>org.apache.bval.jsr._oac</shadedPattern>
- </relocation>
- </relocations>
- <minimizeJar>true</minimizeJar>
- <promoteTransitiveDependencies>true</promoteTransitiveDependencies>
- <createSourcesJar>true</createSourcesJar>
- <shadeSourcesContent>true</shadeSourcesContent>
- </configuration>
- <executions>
- <execution>
- <goals>
- <goal>shade</goal>
- </goals>
- </execution>
- </executions>
- </plugin>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<includes>
Modified: bval/trunk/bval-jsr/src/main/java/org/apache/bval/cdi/BValExtension.java
URL: http://svn.apache.org/viewvc/bval/trunk/bval-jsr/src/main/java/org/apache/bval/cdi/BValExtension.java?rev=1766445&r1=1766444&r2=1766445&view=diff
==============================================================================
--- bval/trunk/bval-jsr/src/main/java/org/apache/bval/cdi/BValExtension.java (original)
+++ bval/trunk/bval-jsr/src/main/java/org/apache/bval/cdi/BValExtension.java Mon Oct 24 21:02:02 2016
@@ -42,7 +42,6 @@ import javax.validation.executable.Valid
import javax.validation.metadata.BeanDescriptor;
import javax.validation.metadata.MethodType;
-import org.apache.commons.lang3.Validate;
import java.lang.reflect.Modifier;
import java.lang.reflect.Type;
@@ -53,6 +52,8 @@ import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
+import org.apache.bval.util.Validate;
+
/**
* CDI {@link Extension} for Apache BVal setup.
*/
Modified: bval/trunk/bval-jsr/src/main/java/org/apache/bval/jsr/AnnotationConstraintBuilder.java
URL: http://svn.apache.org/viewvc/bval/trunk/bval-jsr/src/main/java/org/apache/bval/jsr/AnnotationConstraintBuilder.java?rev=1766445&r1=1766444&r2=1766445&view=diff
==============================================================================
--- bval/trunk/bval-jsr/src/main/java/org/apache/bval/jsr/AnnotationConstraintBuilder.java (original)
+++ bval/trunk/bval-jsr/src/main/java/org/apache/bval/jsr/AnnotationConstraintBuilder.java Mon Oct 24 21:02:02 2016
@@ -21,8 +21,7 @@ package org.apache.bval.jsr;
import org.apache.bval.jsr.groups.GroupsComputer;
import org.apache.bval.jsr.xml.AnnotationProxyBuilder;
import org.apache.bval.util.AccessStrategy;
-import org.apache.commons.lang3.ArrayUtils;
-import org.apache.commons.lang3.reflect.TypeUtils;
+import org.apache.bval.util.reflection.TypeUtils;
import org.apache.commons.weaver.privilizer.Privileged;
import javax.validation.Constraint;
@@ -226,7 +225,7 @@ final class AnnotationConstraintBuilder<
garr = null;
}
- if (ArrayUtils.isEmpty(garr)) {
+ if (garr == null || garr.length == 0) {
garr = GroupsComputer.DEFAULT_GROUP;
}
constraintValidation.setGroups(garr);
Modified: bval/trunk/bval-jsr/src/main/java/org/apache/bval/jsr/AnnotationProcessor.java
URL: http://svn.apache.org/viewvc/bval/trunk/bval-jsr/src/main/java/org/apache/bval/jsr/AnnotationProcessor.java?rev=1766445&r1=1766444&r2=1766445&view=diff
==============================================================================
--- bval/trunk/bval-jsr/src/main/java/org/apache/bval/jsr/AnnotationProcessor.java (original)
+++ bval/trunk/bval-jsr/src/main/java/org/apache/bval/jsr/AnnotationProcessor.java Mon Oct 24 21:02:02 2016
@@ -22,8 +22,8 @@ import org.apache.bval.model.Features;
import org.apache.bval.model.Meta;
import org.apache.bval.model.MetaBean;
import org.apache.bval.util.AccessStrategy;
+import org.apache.bval.util.ObjectUtils;
import org.apache.bval.util.reflection.Reflection;
-import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.weaver.privilizer.Privilizing;
import org.apache.commons.weaver.privilizer.Privilizing.CallTo;
@@ -175,13 +175,13 @@ public final class AnnotationProcessor {
return false;
}
AccessStrategy[] strategies = prop.getFeature(Features.Property.REF_CASCADE);
- if (ArrayUtils.contains(strategies, access)) {
+ if (ObjectUtils.arrayContains(strategies, access)) {
return false;
}
if (strategies == null) {
strategies = new AccessStrategy[] { access };
} else {
- strategies = ArrayUtils.add(strategies, access);
+ strategies = ObjectUtils.arrayAdd(strategies, access);
}
prop.putFeature(Features.Property.REF_CASCADE, strategies);
return true;
Modified: bval/trunk/bval-jsr/src/main/java/org/apache/bval/jsr/ApacheValidationProvider.java
URL: http://svn.apache.org/viewvc/bval/trunk/bval-jsr/src/main/java/org/apache/bval/jsr/ApacheValidationProvider.java?rev=1766445&r1=1766444&r2=1766445&view=diff
==============================================================================
--- bval/trunk/bval-jsr/src/main/java/org/apache/bval/jsr/ApacheValidationProvider.java (original)
+++ bval/trunk/bval-jsr/src/main/java/org/apache/bval/jsr/ApacheValidationProvider.java Mon Oct 24 21:02:02 2016
@@ -25,7 +25,7 @@ import javax.validation.spi.BootstrapSta
import javax.validation.spi.ConfigurationState;
import javax.validation.spi.ValidationProvider;
-import org.apache.commons.lang3.ClassUtils;
+import org.apache.bval.util.reflection.Reflection;
/**
* Description: Implementation of {@link ValidationProvider} for jsr
@@ -81,8 +81,7 @@ public class ApacheValidationProvider im
if (validatorFactoryClassname == null) {
validatorFactoryClass = ApacheValidatorFactory.class;
} else {
- validatorFactoryClass =
- ClassUtils.getClass(validatorFactoryClassname).asSubclass(ValidatorFactory.class);
+ validatorFactoryClass = Reflection.toClass(validatorFactoryClassname).asSubclass(ValidatorFactory.class);
}
} catch (ValidationException ex) {
throw ex;
Modified: bval/trunk/bval-jsr/src/main/java/org/apache/bval/jsr/ApacheValidatorFactory.java
URL: http://svn.apache.org/viewvc/bval/trunk/bval-jsr/src/main/java/org/apache/bval/jsr/ApacheValidatorFactory.java?rev=1766445&r1=1766444&r2=1766445&view=diff
==============================================================================
--- bval/trunk/bval-jsr/src/main/java/org/apache/bval/jsr/ApacheValidatorFactory.java (original)
+++ bval/trunk/bval-jsr/src/main/java/org/apache/bval/jsr/ApacheValidatorFactory.java Mon Oct 24 21:02:02 2016
@@ -27,14 +27,12 @@ import org.apache.bval.jsr.xml.Annotatio
import org.apache.bval.jsr.xml.MetaConstraint;
import org.apache.bval.jsr.xml.ValidationMappingParser;
import org.apache.bval.util.AccessStrategy;
+import org.apache.bval.util.ObjectUtils;
+import org.apache.bval.util.StringUtils;
import org.apache.bval.util.reflection.Reflection;
import org.apache.bval.xml.XMLMetaBeanBuilder;
import org.apache.bval.xml.XMLMetaBeanFactory;
import org.apache.bval.xml.XMLMetaBeanManager;
-import org.apache.commons.lang3.ArrayUtils;
-import org.apache.commons.lang3.ClassUtils;
-import org.apache.commons.lang3.StringUtils;
-import org.apache.commons.lang3.reflect.ConstructorUtils;
import org.apache.commons.weaver.privilizer.Privileged;
import org.apache.commons.weaver.privilizer.Privilizing;
import org.apache.commons.weaver.privilizer.Privilizing.CallTo;
@@ -68,6 +66,7 @@ import java.util.concurrent.ConcurrentMa
*/
@Privilizing(@CallTo(Reflection.class))
public class ApacheValidatorFactory implements ValidatorFactory, Cloneable {
+
private static volatile ApacheValidatorFactory DEFAULT_FACTORY;
private static final ConstraintDefaults DEFAULT_CONSTRAINTS = new ConstraintDefaults();
@@ -350,7 +349,7 @@ public class ApacheValidatorFactory impl
return newInstance(type);
}
try {
- final Class<?> cls = ClassUtils.getClass(type.getName() + "Impl");
+ final Class<?> cls = Reflection.toClass(type.getName() + "Impl");
if (type.isAssignableFrom(cls)) {
@SuppressWarnings("unchecked")
T result = (T) newInstance(cls);
@@ -490,7 +489,7 @@ public class ApacheValidatorFactory impl
}
private static Class<?>[] safeArray(Class<?>... array) {
- return ArrayUtils.isEmpty(array) ? ArrayUtils.EMPTY_CLASS_ARRAY : ArrayUtils.clone(array);
+ return array == null || array.length == 0 ? ObjectUtils. EMPTY_CLASS_ARRAY : array.clone();
}
/**
@@ -513,11 +512,11 @@ public class ApacheValidatorFactory impl
@Privileged
private <F extends MetaBeanFactory> F createMetaBeanFactory(final Class<F> cls) {
try {
- Constructor<F> c = ConstructorUtils.getMatchingAccessibleConstructor(cls, ApacheValidatorFactory.this.getClass());
+ Constructor<F> c = Reflection.getDeclaredConstructor(cls, ApacheValidatorFactory.this.getClass());
if (c != null) {
return c.newInstance(this);
}
- c = ConstructorUtils.getMatchingAccessibleConstructor(cls, getClass());
+ c = Reflection.getDeclaredConstructor(cls, getClass());
if (c != null) {
return c.newInstance(this);
}
Modified: bval/trunk/bval-jsr/src/main/java/org/apache/bval/jsr/BeanDescriptorImpl.java
URL: http://svn.apache.org/viewvc/bval/trunk/bval-jsr/src/main/java/org/apache/bval/jsr/BeanDescriptorImpl.java?rev=1766445&r1=1766444&r2=1766445&view=diff
==============================================================================
--- bval/trunk/bval-jsr/src/main/java/org/apache/bval/jsr/BeanDescriptorImpl.java (original)
+++ bval/trunk/bval-jsr/src/main/java/org/apache/bval/jsr/BeanDescriptorImpl.java Mon Oct 24 21:02:02 2016
@@ -33,7 +33,6 @@ import org.apache.bval.model.MetaPropert
import org.apache.bval.model.Validation;
import org.apache.bval.util.AccessStrategy;
import org.apache.bval.util.reflection.Reflection;
-import org.apache.commons.lang3.ClassUtils;
import org.apache.commons.weaver.privilizer.Privilizing;
import org.apache.commons.weaver.privilizer.Privilizing.CallTo;
@@ -849,7 +848,7 @@ public class BeanDescriptorImpl extends
}
} else {
annotationProcessor.processAnnotation(
- annotation, null, ClassUtils.primitiveToWrapper((Class<?>) access.getJavaType()),
+ annotation, null, Reflection.primitiveToWrapper((Class<?>) access.getJavaType()),
access, validations, true);
}
}
Modified: bval/trunk/bval-jsr/src/main/java/org/apache/bval/jsr/ClassValidator.java
URL: http://svn.apache.org/viewvc/bval/trunk/bval-jsr/src/main/java/org/apache/bval/jsr/ClassValidator.java?rev=1766445&r1=1766444&r2=1766445&view=diff
==============================================================================
--- bval/trunk/bval-jsr/src/main/java/org/apache/bval/jsr/ClassValidator.java (original)
+++ bval/trunk/bval-jsr/src/main/java/org/apache/bval/jsr/ClassValidator.java Mon Oct 24 21:02:02 2016
@@ -63,11 +63,9 @@ import org.apache.bval.model.MetaPropert
import org.apache.bval.model.Validation;
import org.apache.bval.util.AccessStrategy;
import org.apache.bval.util.ValidationHelper;
+import org.apache.bval.util.ObjectUtils;
import org.apache.bval.util.reflection.Reflection;
-import org.apache.commons.lang3.ArrayUtils;
-import org.apache.commons.lang3.ClassUtils;
-import org.apache.commons.lang3.ObjectUtils;
-import org.apache.commons.lang3.reflect.TypeUtils;
+import org.apache.bval.util.reflection.TypeUtils;
import org.apache.commons.weaver.privilizer.Privilizing;
import org.apache.commons.weaver.privilizer.Privilizing.CallTo;
@@ -296,7 +294,7 @@ public class ClassValidator implements C
return newInstance(type);
}
try {
- final Class<?> cls = ClassUtils.getClass(type.getName() + "Impl");
+ final Class<?> cls = Reflection.toClass(type.getName() + "Impl");
if (type.isAssignableFrom(cls)) {
@SuppressWarnings("unchecked")
final Class<? extends T> implClass = (Class<? extends T>) cls;
@@ -1155,7 +1153,9 @@ public class ClassValidator implements C
if (!cascade) {
//TCK doesn't care what type a property is if there are no constraints to validate:
FeaturesCapable meta = prop == null ? context.getMetaBean() : prop;
- if (ArrayUtils.isEmpty(meta.getValidations())) {
+
+ Validation[] validations = meta.getValidations();
+ if (validations == null || validations.length == 0) {
return Collections.<ConstraintViolation<T>> emptySet();
}
}
Modified: bval/trunk/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintAnnotationAttributes.java
URL: http://svn.apache.org/viewvc/bval/trunk/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintAnnotationAttributes.java?rev=1766445&r1=1766444&r2=1766445&view=diff
==============================================================================
--- bval/trunk/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintAnnotationAttributes.java (original)
+++ bval/trunk/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintAnnotationAttributes.java Mon Oct 24 21:02:02 2016
@@ -17,7 +17,7 @@
package org.apache.bval.jsr;
import org.apache.bval.util.reflection.Reflection;
-import org.apache.commons.lang3.reflect.TypeUtils;
+import org.apache.bval.util.reflection.TypeUtils;
import org.apache.commons.weaver.privilizer.Privilizing;
import org.apache.commons.weaver.privilizer.Privilizing.CallTo;
Modified: bval/trunk/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintDefaults.java
URL: http://svn.apache.org/viewvc/bval/trunk/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintDefaults.java?rev=1766445&r1=1766444&r2=1766445&view=diff
==============================================================================
--- bval/trunk/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintDefaults.java (original)
+++ bval/trunk/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintDefaults.java Mon Oct 24 21:02:02 2016
@@ -31,8 +31,8 @@ import java.util.logging.Logger;
import javax.validation.ConstraintValidator;
+import org.apache.bval.util.StringUtils;
import org.apache.bval.util.reflection.Reflection;
-import org.apache.commons.lang3.StringUtils;
import org.apache.commons.weaver.privilizer.Privilizing;
import org.apache.commons.weaver.privilizer.Privilizing.CallTo;
@@ -104,7 +104,7 @@ public class ConstraintDefaults {
final List<Class<?>> classes = new LinkedList<Class<?>>();
for (String className : StringUtils.split((String) entry.getValue(), ',')) {
try {
- classes.add(Reflection.getClass(classloader, className.trim()));
+ classes.add(Reflection.toClass(className.trim(), classloader));
} catch (Exception e) {
log.log(Level.SEVERE, String.format("Cannot find class %s", className), e);
}
Modified: bval/trunk/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintDescriptorImpl.java
URL: http://svn.apache.org/viewvc/bval/trunk/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintDescriptorImpl.java?rev=1766445&r1=1766444&r2=1766445&view=diff
==============================================================================
--- bval/trunk/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintDescriptorImpl.java (original)
+++ bval/trunk/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintDescriptorImpl.java Mon Oct 24 21:02:02 2016
@@ -22,9 +22,6 @@ import javax.validation.ConstraintTarget
import javax.validation.Payload;
import javax.validation.metadata.ConstraintDescriptor;
-import org.apache.commons.lang3.builder.EqualsBuilder;
-import org.apache.commons.lang3.builder.HashCodeBuilder;
-
import java.io.Serializable;
import java.lang.annotation.Annotation;
import java.util.List;
@@ -158,47 +155,48 @@ public class ConstraintDescriptorImpl<T
return reportAsSingleViolation;
}
+
+ /**
+ * generated equals on all fields except hashCode
+ */
@Override
public boolean equals(Object o) {
- if (this == o) {
- return true;
- }
- if (o == null || !getClass().equals(o.getClass())) {
- return false;
- }
-
- @SuppressWarnings("rawtypes")
- final ConstraintDescriptorImpl that = (ConstraintDescriptorImpl) o;
-
- return new EqualsBuilder()
- .append(reportAsSingleViolation, that.reportAsSingleViolation)
- .append(annotation.annotationType(), that.annotation.annotationType())
- .append(attributes, that.attributes)
- .append(composingConstraints, that.composingConstraints)
- .append(constraintValidatorClasses, that.constraintValidatorClasses)
- .append(groups, that.groups)
- .append(payload, that.payload)
- .append(template, that.template)
- .append(validationAppliesTo, that.validationAppliesTo)
- .build();
+ if (this == o) { return true; }
+ if (o == null || getClass() != o.getClass()) { return false; }
+
+ ConstraintDescriptorImpl<?> that = (ConstraintDescriptorImpl<?>) o;
+
+ if (reportAsSingleViolation != that.reportAsSingleViolation) { return false; }
+ if (annotation != null ? !annotation.equals(that.annotation) : that.annotation != null) { return false; }
+ if (groups != null ? !groups.equals(that.groups) : that.groups != null) { return false; }
+ if (payload != null ? !payload.equals(that.payload) : that.payload != null) { return false; }
+ if (constraintValidatorClasses != null ? !constraintValidatorClasses.equals(that.constraintValidatorClasses) : that.constraintValidatorClasses != null) { return false; }
+ if (attributes != null ? !attributes.equals(that.attributes) : that.attributes != null) { return false; }
+ if (composingConstraints != null ? !composingConstraints.equals(that.composingConstraints) : that.composingConstraints != null) { return false; }
+ if (validationAppliesTo != that.validationAppliesTo) { return false; }
+ return template != null ? template.equals(that.template) : that.template == null;
+
}
+
@Override
public int hashCode() {
return hashCode;
}
+ /**
+ * generated hashCode on all fields except hashCode
+ */
private int computeHashCode() {
- return new HashCodeBuilder(1, 31)
- .append(annotation.annotationType())
- .append(groups)
- .append(payload)
- .append(constraintValidatorClasses)
- .append(attributes)
- .append(composingConstraints)
- .append(reportAsSingleViolation)
- .append(validationAppliesTo)
- .append(template)
- .build();
+ int result = annotation != null ? annotation.hashCode() : 0;
+ result = 31 * result + (groups != null ? groups.hashCode() : 0);
+ result = 31 * result + (payload != null ? payload.hashCode() : 0);
+ result = 31 * result + (constraintValidatorClasses != null ? constraintValidatorClasses.hashCode() : 0);
+ result = 31 * result + (attributes != null ? attributes.hashCode() : 0);
+ result = 31 * result + (composingConstraints != null ? composingConstraints.hashCode() : 0);
+ result = 31 * result + (reportAsSingleViolation ? 1 : 0);
+ result = 31 * result + (validationAppliesTo != null ? validationAppliesTo.hashCode() : 0);
+ result = 31 * result + (template != null ? template.hashCode() : 0);
+ return result;
}
}
Modified: bval/trunk/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintValidation.java
URL: http://svn.apache.org/viewvc/bval/trunk/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintValidation.java?rev=1766445&r1=1766444&r2=1766445&view=diff
==============================================================================
--- bval/trunk/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintValidation.java (original)
+++ bval/trunk/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintValidation.java Mon Oct 24 21:02:02 2016
@@ -24,10 +24,10 @@ import org.apache.bval.model.Validation;
import org.apache.bval.model.ValidationContext;
import org.apache.bval.model.ValidationListener;
import org.apache.bval.util.AccessStrategy;
-import org.apache.commons.lang3.ArrayUtils;
-import org.apache.commons.lang3.ClassUtils;
-import org.apache.commons.lang3.StringUtils;
-import org.apache.commons.lang3.reflect.TypeUtils;
+import org.apache.bval.util.ObjectUtils;
+import org.apache.bval.util.StringUtils;
+import org.apache.bval.util.reflection.Reflection;
+import org.apache.bval.util.reflection.TypeUtils;
import javax.validation.ConstraintDefinitionException;
import javax.validation.ConstraintTarget;
@@ -84,7 +84,7 @@ public class ConstraintValidation<T exte
T annotation, Class<?> owner, AccessStrategy access,
boolean reportFromComposite, ConstraintTarget target) {
this.attributes = new HashMap<String, Object>();
- this.validatorClasses = ArrayUtils.clone(validatorClasses);
+ this.validatorClasses = validatorClasses != null ? validatorClasses.clone() : null;
this.annotation = annotation;
this.owner = owner;
this.access = access;
@@ -237,7 +237,7 @@ public class ConstraintValidation<T exte
private <A extends Annotation> ConstraintValidator<A, ? super T> getConstraintValidator(
ConstraintValidatorFactory factory, A annotation,
Class<? extends ConstraintValidator<A, ?>>[] constraintClasses, Class<?> owner, AccessStrategy access) {
- if (ArrayUtils.isNotEmpty(constraintClasses)) {
+ if (ObjectUtils.isNotEmpty(constraintClasses)) {
final Type type = determineTargetedType(owner, access);
/**
@@ -413,7 +413,7 @@ public class ConstraintValidation<T exte
if (type == null) {
return Object.class;
}
- return type instanceof Class<?> ? ClassUtils.primitiveToWrapper((Class<?>) type) : type;
+ return type instanceof Class<?> ? Reflection.primitiveToWrapper((Class<?>) type) : type;
}
/**
Modified: bval/trunk/bval-jsr/src/main/java/org/apache/bval/jsr/DefaultMessageInterpolator.java
URL: http://svn.apache.org/viewvc/bval/trunk/bval-jsr/src/main/java/org/apache/bval/jsr/DefaultMessageInterpolator.java?rev=1766445&r1=1766444&r2=1766445&view=diff
==============================================================================
--- bval/trunk/bval-jsr/src/main/java/org/apache/bval/jsr/DefaultMessageInterpolator.java (original)
+++ bval/trunk/bval-jsr/src/main/java/org/apache/bval/jsr/DefaultMessageInterpolator.java Mon Oct 24 21:02:02 2016
@@ -18,12 +18,12 @@ package org.apache.bval.jsr;
import org.apache.bval.el.MessageEvaluator;
import org.apache.bval.util.reflection.Reflection;
-import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.weaver.privilizer.Privilizing;
import org.apache.commons.weaver.privilizer.Privilizing.CallTo;
import javax.validation.MessageInterpolator;
+import java.util.Arrays;
import java.util.Locale;
import java.util.Map;
import java.util.MissingResourceException;
@@ -231,7 +231,7 @@ public class DefaultMessageInterpolator
Object variable = annotationParameters.get(removeCurlyBrace(parameter));
if (variable != null) {
if (variable.getClass().isArray()) {
- resolvedParameterValue = ArrayUtils.toString(variable);
+ resolvedParameterValue = Arrays.toString((Object[]) variable);
} else {
resolvedParameterValue = variable.toString();
}