http://git-wip-us.apache.org/repos/asf/bval/blob/ed299e4f/bval-core/src/main/java/org/apache/bval/util/reflection/TypeUtils.java ---------------------------------------------------------------------- diff --git a/bval-core/src/main/java/org/apache/bval/util/reflection/TypeUtils.java b/bval-core/src/main/java/org/apache/bval/util/reflection/TypeUtils.java deleted file mode 100644 index a75e1ad..0000000 --- a/bval-core/src/main/java/org/apache/bval/util/reflection/TypeUtils.java +++ /dev/null @@ -1,1557 +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.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><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<>(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-core/src/test/java/org/apache/bval/ValidationResultsTest.java ---------------------------------------------------------------------- diff --git a/bval-core/src/test/java/org/apache/bval/ValidationResultsTest.java b/bval-core/src/test/java/org/apache/bval/ValidationResultsTest.java deleted file mode 100644 index 785621e..0000000 --- a/bval-core/src/test/java/org/apache/bval/ValidationResultsTest.java +++ /dev/null @@ -1,52 +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; - -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - -import org.apache.bval.model.MetaProperty; -import org.junit.Before; -import org.junit.Test; - -/** - * ValidationResults Tester. - */ -public class ValidationResultsTest { - private ValidationResults results; - - @Before - public void setUp() throws Exception { - results = new ValidationResults(); - } - - @Test - public void testValidationResults() throws Exception { - assertTrue(results.isEmpty()); - BeanValidationContext<ValidationResults> ctx = new BeanValidationContext<ValidationResults>(results); - ctx.setBean(this); - ctx.setMetaProperty(new MetaProperty()); - ctx.getMetaProperty().setName("prop"); - results.addError("test", ctx); - assertFalse(results.isEmpty()); - assertTrue(results.hasErrorForReason("test")); - assertTrue(results.hasError(this, "prop")); - assertTrue(results.hasError(this, null)); - assertFalse(results.hasError(this, "prop2")); - } - -} http://git-wip-us.apache.org/repos/asf/bval/blob/ed299e4f/bval-core/src/test/java/org/apache/bval/model/ExampleEnum.java ---------------------------------------------------------------------- diff --git a/bval-core/src/test/java/org/apache/bval/model/ExampleEnum.java b/bval-core/src/test/java/org/apache/bval/model/ExampleEnum.java deleted file mode 100644 index 10f87a9..0000000 --- a/bval-core/src/test/java/org/apache/bval/model/ExampleEnum.java +++ /dev/null @@ -1,27 +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.model; - -/** - * Description: <br> - * User: roman.stumm<br> - * Date: 17.06.2010<br> - * Time: 18:00:12<br> - */ -public enum ExampleEnum { - VALUE1, VALUE2, VALUE3 -} http://git-wip-us.apache.org/repos/asf/bval/blob/ed299e4f/bval-core/src/test/java/org/apache/bval/model/MetaPropertyTest.java ---------------------------------------------------------------------- diff --git a/bval-core/src/test/java/org/apache/bval/model/MetaPropertyTest.java b/bval-core/src/test/java/org/apache/bval/model/MetaPropertyTest.java deleted file mode 100644 index 88a34ba..0000000 --- a/bval-core/src/test/java/org/apache/bval/model/MetaPropertyTest.java +++ /dev/null @@ -1,43 +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.model; - -import static org.junit.Assert.assertEquals; - -import org.junit.Test; - -/** - * MetaProperty Tester. - * - * @author <Authors name> - * @since <pre>02/12/2009</pre> - * @version 1.0 - */ -public class MetaPropertyTest { - - @Test - public void testGetTypeClass() throws Exception { - MetaProperty prop = new MetaProperty(); - prop.setType(String.class); - assertEquals(String.class, prop.getTypeClass()); - assertEquals(String.class, prop.getType()); - prop.setType(new DynaTypeEnum(ExampleEnum.class, ExampleEnum.VALUE1.name(), ExampleEnum.VALUE3.name())); - assertEquals(ExampleEnum.class, prop.getTypeClass()); - assertEquals(2, ((DynaTypeEnum) prop.getType()).getEnumConstants().length); - } - -} http://git-wip-us.apache.org/repos/asf/bval/blob/ed299e4f/bval-core/src/test/java/org/apache/bval/util/StringUtilsTest.java ---------------------------------------------------------------------- diff --git a/bval-core/src/test/java/org/apache/bval/util/StringUtilsTest.java b/bval-core/src/test/java/org/apache/bval/util/StringUtilsTest.java deleted file mode 100644 index 1939081..0000000 --- a/bval-core/src/test/java/org/apache/bval/util/StringUtilsTest.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.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")); - } -} http://git-wip-us.apache.org/repos/asf/bval/blob/ed299e4f/bval-core/src/test/resources/log4j.xml ---------------------------------------------------------------------- diff --git a/bval-core/src/test/resources/log4j.xml b/bval-core/src/test/resources/log4j.xml deleted file mode 100644 index 3c4bb67..0000000 --- a/bval-core/src/test/resources/log4j.xml +++ /dev/null @@ -1,41 +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. ---> -<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd"> - -<!-- ===================================================================== --> -<!-- --> -<!-- Log4j Configuration --> -<!-- --> -<!-- ===================================================================== --> - -<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/" debug="false"> - - <appender name="CONSOLE" class="org.apache.log4j.ConsoleAppender"> - <param name="Threshold" value="DEBUG"/> - <layout class="org.apache.log4j.PatternLayout"> - <param name="ConversionPattern" value="%d %-5p %c - %m%n"/> - </layout> - </appender> - - <root> - <appender-ref ref="CONSOLE"/> - </root> - -</log4j:configuration> http://git-wip-us.apache.org/repos/asf/bval/blob/ed299e4f/bval-json/pom.xml ---------------------------------------------------------------------- diff --git a/bval-json/pom.xml b/bval-json/pom.xml deleted file mode 100644 index 59dcb17..0000000 --- a/bval-json/pom.xml +++ /dev/null @@ -1,76 +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-json</artifactId> - <name>Apache BVal :: bval-json (optional)</name> - <packaging>bundle</packaging> - - <description>BVal - Optional JSON Component</description> - - <dependencies> - <dependency> - <groupId>org.apache.bval</groupId> - <artifactId>bval-core</artifactId> - <version>${project.version}</version> - </dependency> - <dependency> - <groupId>org.apache.bval</groupId> - <artifactId>bval-xstream</artifactId> - <version>${project.version}</version> - </dependency> - <dependency> - <groupId>org.freemarker</groupId> - <artifactId>freemarker</artifactId> - </dependency> - <dependency> - <groupId>junit</groupId> - <artifactId>junit</artifactId> - <scope>test</scope> - </dependency> - <dependency> - <groupId>org.apache.bval</groupId> - <artifactId>bval-core</artifactId> - <version>${project.version}</version> - <type>test-jar</type> - <scope>test</scope> - </dependency> - <dependency> - <groupId>org.apache.bval</groupId> - <artifactId>bval-xstream</artifactId> - <version>${project.version}</version> - <type>test-jar</type> - <scope>test</scope> - </dependency> - </dependencies> - -</project> - http://git-wip-us.apache.org/repos/asf/bval/blob/ed299e4f/bval-json/src/main/appended-resources/META-INF/NOTICE.vm ---------------------------------------------------------------------- diff --git a/bval-json/src/main/appended-resources/META-INF/NOTICE.vm b/bval-json/src/main/appended-resources/META-INF/NOTICE.vm deleted file mode 100644 index 9a0c1ee..0000000 --- a/bval-json/src/main/appended-resources/META-INF/NOTICE.vm +++ /dev/null @@ -1,25 +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. -## - -The following copyright notice(s) were affixed to portions of this code -with which this file is now or was at one time distributed. - -This product includes software developed by agimatec GmbH. -Copyright 2007-2010 Agimatec GmbH. All rights reserved. - http://git-wip-us.apache.org/repos/asf/bval/blob/ed299e4f/bval-json/src/main/java/org/apache/bval/json/JSONGenerator.java ---------------------------------------------------------------------- diff --git a/bval-json/src/main/java/org/apache/bval/json/JSONGenerator.java b/bval-json/src/main/java/org/apache/bval/json/JSONGenerator.java deleted file mode 100644 index 11c668b..0000000 --- a/bval-json/src/main/java/org/apache/bval/json/JSONGenerator.java +++ /dev/null @@ -1,76 +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.json; - -import freemarker.template.Configuration; -import freemarker.template.Template; -import freemarker.template.TemplateException; -import org.apache.bval.model.MetaBean; - -import java.io.IOException; -import java.io.StringWriter; -import java.io.Writer; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - * Description: Generate a JSON String for a collection of {@link MetaBean}s. - * This implementation uses a freemarker template to generate the output.<br/> - * - * This is an optional module which requires the freemarker dependency - * and template resource file "bean-infos-json.ftl" with it. - */ -public class JSONGenerator { - private final Template template; - - public JSONGenerator() throws IOException { - this("bean-infos-json.ftl"); - } - - public JSONGenerator(String templateName) throws IOException { - Configuration freemarker = new Configuration(); - freemarker.setNumberFormat("0.######"); // prevent locale-sensitive number format - freemarker.setClassForTemplateLoading(getClass(), ""); - template = freemarker.getTemplate(templateName); - } - - public JSONGenerator(Template template) { - this.template = template; - } - - public String toJSON(MetaBean metaBean) throws IOException, TemplateException { - List<MetaBean> metaBeans = new ArrayList<MetaBean>(1); - metaBeans.add(metaBean); - return toJSON(metaBeans); - } - - public String toJSON(Collection<MetaBean> metaBeans) throws IOException, TemplateException { - final StringWriter out = new StringWriter(); - toJSON(metaBeans, out); - return out.toString(); - } - - public void toJSON(Collection<MetaBean> metaBeans, Writer out) throws IOException, TemplateException { - Map<String, Object> rootMap = new HashMap<String, Object>(); - rootMap.put("metaBeans", metaBeans); - rootMap.put("generator", this); - template.process(rootMap, out); - } -} http://git-wip-us.apache.org/repos/asf/bval/blob/ed299e4f/bval-json/src/main/resources/org/apache/bval/json/bean-infos-json.ftl ---------------------------------------------------------------------- diff --git a/bval-json/src/main/resources/org/apache/bval/json/bean-infos-json.ftl b/bval-json/src/main/resources/org/apache/bval/json/bean-infos-json.ftl deleted file mode 100644 index 63012ad..0000000 --- a/bval-json/src/main/resources/org/apache/bval/json/bean-infos-json.ftl +++ /dev/null @@ -1,85 +0,0 @@ -bval.namespace("bval.metadata"); - -<#-- - 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. ---> - - -(function(){ -<#assign var = 0> -<#assign varrefs = {}> - -<#list metaBeans as metaBean> -<#assign varrefs = varrefs + {metaBean.id : var}> -var metaBean${var} = { - "id" : "${metaBean.id}", - <#if metaBean.beanClass??>"beanClass" : "${metaBean.beanClass.name}",</#if> - <#if metaBean.name??>"name" : "${metaBean.name}",</#if> - "features" :{<#rt/> - <#list metaBean.features?keys as featureKey> - <#assign value = metaBean.features[featureKey]> - "${featureKey}" : <#if - value?is_string>"${value}"<#elseif - value?is_boolean>${value?string}<#elseif - value?is_number>${value}<#elseif - value?is_date>${value?string.full}<#elseif - !(value??)>null<#elseif value?is_sequence>[<#list value as v>"${v}"<#if v_has_next>,</#if></#list>]<#elseif - value?is_hash>{<#list value?keys as key>"${key}" : "${value[key]}"<#if key_has_next>,</#if></#list>}<#else - >"?"</#if><#rt/><#if - featureKey_has_next>,</#if> - </#list> - <#lt/>}, - "properties" :{ - <#list metaBean.properties as property> - "${property.name}":{ - "name" : "${property.name}", - <#if property.type??>"type" : "${property.type}",</#if> - <#if property.typeClass??>"typeClass" : "${property.typeClass.name}",</#if> - "features" : {<#if property.type?? && - property.type.enum!false>"enum" : {<#list property.type.enumConstants as enum>"${enum.name()}": "${enum.name()}"<#if enum_has_next>, </#if></#list>}<#if property.features?size > 0>,</#if></#if><#list - property.features?keys as featureKey> - <#assign value = property.features[featureKey]> - "${featureKey}" : <#rt/><#if - value?is_string>"${value}"<#elseif - value?is_boolean>${value?string}<#elseif - value?is_number>${value}<#elseif - value?is_date>${value?string.full}<#elseif - !(value??)>null<#elseif value?is_sequence>[<#list value as v>"${v}"<#if v_has_next>,</#if></#list>]<#elseif - value?is_hash_ex>{<#list value?keys as key>"${key}" : "${value[key]}"<#if key_has_next>,</#if></#list>}<#else - >"?"</#if><#rt/><#if featureKey_has_next>,</#if> - </#list> - } - }<#if property_has_next>,</#if> - </#list> - } -}; -<#assign var = var + 1> -</#list> - -<#assign var = 0> -<#list metaBeans as metaBean><#list - metaBean.properties as property><#if - property.metaBean?? && varrefs[property.metaBean.id]??> -metaBean${var}.properties.${property.name}.metaBean = metaBean${varrefs[property.metaBean.id]}; -</#if></#list><#assign var = var + 1></#list><#assign var = 0> -bval.metadata.metaBeans = { -<#list metaBeans as metaBean> - "${metaBean.id}" : metaBean${var}<#if metaBean_has_next>,</#if> - <#assign var = var + 1> -</#list>}; -})(); http://git-wip-us.apache.org/repos/asf/bval/blob/ed299e4f/bval-json/src/test/java/org/apache/bval/json/JSONGeneratorTest.java ---------------------------------------------------------------------- diff --git a/bval-json/src/test/java/org/apache/bval/json/JSONGeneratorTest.java b/bval-json/src/test/java/org/apache/bval/json/JSONGeneratorTest.java deleted file mode 100644 index ab24d93..0000000 --- a/bval-json/src/test/java/org/apache/bval/json/JSONGeneratorTest.java +++ /dev/null @@ -1,104 +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.json; - -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; - -import java.util.ArrayList; -import java.util.List; - -import org.apache.bval.example.BusinessEnum; -import org.apache.bval.example.BusinessObject; -import org.apache.bval.example.BusinessObjectAddress; -import org.apache.bval.model.DynaTypeEnum; -import org.apache.bval.model.MetaBean; -import org.apache.bval.model.MetaProperty; -import org.apache.bval.xml.XMLMetaBeanManager; -import org.apache.bval.xml.XMLMetaBeanURLLoader; -import org.junit.Before; -import org.junit.Test; - -/** - * Description: <br> - * Author: roman.stumm<br> - */ -public class JSONGeneratorTest { - private XMLMetaBeanManager mbm; - - @Before - public void setUp() throws Exception { - mbm = new XMLMetaBeanManager(); - mbm.addLoader(new XMLMetaBeanURLLoader(BusinessObject.class.getResource("test-beanInfos.xml"))); - } - - @Test - public void testBeanInfosCustomPatchGenerated() throws Exception { - MetaBean mbean = mbm.findForClass(BusinessObject.class); - MetaProperty mprop = mbean.getProperty("lastName"); - assertTrue(mprop.isMandatory()); - - mbm.getCache().removeFromCache(mbean); - mbm.addLoader(new XMLMetaBeanURLLoader(BusinessObject.class.getResource("test-beanInfos-custom.xml"))); - mbean = mbm.findForClass(BusinessObject.class); - mprop = mbean.getProperty("lastName"); - assertTrue(!mprop.isMandatory()); - - JSONGenerator converter = new JSONGenerator(); - - List<MetaBean> metaBeans = new ArrayList<MetaBean>(2); - metaBeans.add(mbean); - MetaBean mbean2 = mbm.findForId("UnknownObject"); - metaBeans.add(mbean2); - String json = converter.toJSON(metaBeans); - assertNotNull(json); - } - - @Test - public void testJSON() throws Exception { - MetaBean info = mbm.findForClass(BusinessObject.class); - MetaBean info2 = info.getProperty("address").getMetaBean(); - - // empty default bean without xml backup - MetaBean info3 = mbm.findForClass(BusinessObjectAddress.class); - JSONGenerator converter = new JSONGenerator(); - - List<MetaBean> metaBeans = new ArrayList<MetaBean>(2); - metaBeans.add(info); - metaBeans.add(info2); - metaBeans.add(info3); - String json = converter.toJSON(metaBeans); - assertNotNull(json); - } - - @Test - public void testJSON_dynaTypeEnum() throws Exception { - MetaBean info = mbm.findForClass(BusinessObject.class); - MetaProperty choice = info.getProperty("choice"); - choice.setType(new DynaTypeEnum(BusinessEnum.class, "CUSTOM_1", "CUSTOM_2")); - - JSONGenerator converter = new JSONGenerator(); - - List<MetaBean> metaBeans = new ArrayList<MetaBean>(1); - metaBeans.add(info); - String json = converter.toJSON(metaBeans); - assertNotNull(json); - assertTrue(json.indexOf("CUSTOM_1") > 0); - assertTrue(json.indexOf("CUSTOM_2") > 0); - assertTrue(json.indexOf("VALUE1") < 0); - } -}
