You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by si...@apache.org on 2012/02/06 20:56:43 UTC
svn commit: r1241133 [1/2] - in /commons/sandbox/beanutils2/trunk: ./
src/main/java/org/apache/commons/beanutils2/type/
src/test/java/org/apache/commons/beanutils2/type/
Author: simonetripodi
Date: Mon Feb 6 19:56:42 2012
New Revision: 1241133
URL: http://svn.apache.org/viewvc?rev=1241133&view=rev
Log:
extracted, cleaned, polished and retailed the TypeLyteral framework from Google Guice, to better manipulate types handling
Added:
commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/type/
commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/type/CompositeType.java (with props)
commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/type/GenericArrayTypeImpl.java (with props)
commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/type/MoreTypes.java (with props)
commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/type/Objects.java (with props)
commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/type/ParameterizedTypeImpl.java (with props)
commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/type/TypeLiteral.java (with props)
commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/type/Types.java (with props)
commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/type/WildcardTypeImpl.java (with props)
commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/type/package-info.java (with props)
commons/sandbox/beanutils2/trunk/src/test/java/org/apache/commons/beanutils2/type/
commons/sandbox/beanutils2/trunk/src/test/java/org/apache/commons/beanutils2/type/Asserts.java (with props)
commons/sandbox/beanutils2/trunk/src/test/java/org/apache/commons/beanutils2/type/TypeLiteralTest.java (with props)
commons/sandbox/beanutils2/trunk/src/test/java/org/apache/commons/beanutils2/type/TypeLiteralTypeResolutionTest.java (with props)
commons/sandbox/beanutils2/trunk/src/test/java/org/apache/commons/beanutils2/type/TypesTest.java (with props)
Modified:
commons/sandbox/beanutils2/trunk/pom.xml
Modified: commons/sandbox/beanutils2/trunk/pom.xml
URL: http://svn.apache.org/viewvc/commons/sandbox/beanutils2/trunk/pom.xml?rev=1241133&r1=1241132&r2=1241133&view=diff
==============================================================================
--- commons/sandbox/beanutils2/trunk/pom.xml (original)
+++ commons/sandbox/beanutils2/trunk/pom.xml Mon Feb 6 19:56:42 2012
@@ -91,6 +91,12 @@
<version>4.10</version>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>com.google.guava</groupId>
+ <artifactId>guava</artifactId>
+ <version>11.0.1</version>
+ <scope>test</scope>
+ </dependency>
</dependencies>
<build>
Added: commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/type/CompositeType.java
URL: http://svn.apache.org/viewvc/commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/type/CompositeType.java?rev=1241133&view=auto
==============================================================================
--- commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/type/CompositeType.java (added)
+++ commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/type/CompositeType.java Mon Feb 6 19:56:42 2012
@@ -0,0 +1,29 @@
+package org.apache.commons.beanutils2.type;
+
+/*
+ * 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.
+ */
+
+/** A type formed from other types, such as arrays, parameterized types or wildcard types */
+interface CompositeType
+{
+
+ /** Returns true if there are no type variables in this type. */
+ boolean isFullySpecified();
+
+}
Propchange: commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/type/CompositeType.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/type/CompositeType.java
------------------------------------------------------------------------------
svn:keywords = Date Author Id Revision HeadURL
Propchange: commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/type/CompositeType.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/type/GenericArrayTypeImpl.java
URL: http://svn.apache.org/viewvc/commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/type/GenericArrayTypeImpl.java?rev=1241133&view=auto
==============================================================================
--- commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/type/GenericArrayTypeImpl.java (added)
+++ commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/type/GenericArrayTypeImpl.java Mon Feb 6 19:56:42 2012
@@ -0,0 +1,69 @@
+package org.apache.commons.beanutils2.type;
+
+/*
+ * 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.
+ */
+
+import static org.apache.commons.beanutils2.type.MoreTypes.typeToString;
+
+import java.io.Serializable;
+import java.lang.reflect.GenericArrayType;
+import java.lang.reflect.Type;
+
+final class GenericArrayTypeImpl
+ implements GenericArrayType, Serializable, CompositeType
+{
+
+ private static final long serialVersionUID = 0;
+
+ private final Type componentType;
+
+ public GenericArrayTypeImpl( Type componentType )
+ {
+ this.componentType = MoreTypes.canonicalize( componentType );
+ }
+
+ public Type getGenericComponentType()
+ {
+ return componentType;
+ }
+
+ public boolean isFullySpecified()
+ {
+ return MoreTypes.isFullySpecified( componentType );
+ }
+
+ @Override
+ public boolean equals( Object o )
+ {
+ return o instanceof GenericArrayType && MoreTypes.equals( this, (GenericArrayType) o );
+ }
+
+ @Override
+ public int hashCode()
+ {
+ return componentType.hashCode();
+ }
+
+ @Override
+ public String toString()
+ {
+ return typeToString( componentType ) + "[]";
+ }
+
+}
\ No newline at end of file
Propchange: commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/type/GenericArrayTypeImpl.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/type/GenericArrayTypeImpl.java
------------------------------------------------------------------------------
svn:keywords = Date Author Id Revision HeadURL
Propchange: commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/type/GenericArrayTypeImpl.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/type/MoreTypes.java
URL: http://svn.apache.org/viewvc/commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/type/MoreTypes.java?rev=1241133&view=auto
==============================================================================
--- commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/type/MoreTypes.java (added)
+++ commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/type/MoreTypes.java Mon Feb 6 19:56:42 2012
@@ -0,0 +1,362 @@
+package org.apache.commons.beanutils2.type;
+
+/*
+ * 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.
+ */
+
+import static org.apache.commons.beanutils2.type.Objects.equal;
+import static org.apache.commons.beanutils2.internal.Assertions.checkArgument;
+
+import java.io.Serializable;
+import java.lang.reflect.Array;
+import java.lang.reflect.GenericArrayType;
+import java.lang.reflect.GenericDeclaration;
+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.HashMap;
+import java.util.Map;
+import java.util.NoSuchElementException;
+
+/**
+ * Static methods for working with types that we aren't publishing in the public {@code Types} API.
+ *
+ * @author jessewilson@google.com (Jesse Wilson)
+ */
+final class MoreTypes
+{
+
+ public static final Type[] EMPTY_TYPE_ARRAY = new Type[] {};
+
+ private MoreTypes()
+ {
+ }
+
+ private static final Map<TypeLiteral<?>, TypeLiteral<?>> PRIMITIVE_TO_WRAPPER =
+ new HashMap<TypeLiteral<?>, TypeLiteral<?>>();
+
+ static
+ {
+ register( boolean.class, Boolean.class );
+ register( byte.class, Byte.class );
+ register( short.class, Short.class );
+ register( int.class, Integer.class );
+ register( long.class, Long.class );
+ register( float.class, Float.class );
+ register( double.class, Double.class );
+ register( char.class, Character.class );
+ register( void.class, Void.class );
+ }
+
+ private static void register( Class<?> primitive, Class<?> wrapper )
+ {
+ PRIMITIVE_TO_WRAPPER.put( TypeLiteral.get( primitive ), TypeLiteral.get( wrapper ) );
+ }
+
+ /**
+ * Returns an type that's appropriate for use in a key.
+ * <p>
+ * If the raw type of {@code typeLiteral} is a {@code javax.inject.Provider}, this returns a
+ * {@code com.google.inject.Provider} with the same type parameters.
+ * <p>
+ * If the type is a primitive, the corresponding wrapper type will be returned.
+ *
+ * @throws IllegalArgumentException if {@code type} contains a type variable
+ */
+ public static <T> TypeLiteral<T> canonicalizeForKey( TypeLiteral<T> typeLiteral )
+ {
+ Type type = typeLiteral.getType();
+ checkArgument( isFullySpecified( type ), "%s cannot be used as a key; It is not fully specified.", type );
+
+ @SuppressWarnings( "unchecked" )
+ TypeLiteral<T> wrappedPrimitives = (TypeLiteral<T>) PRIMITIVE_TO_WRAPPER.get( typeLiteral );
+ return wrappedPrimitives != null ? wrappedPrimitives : typeLiteral;
+ }
+
+ /**
+ * Returns true if {@code type} is free from type variables.
+ */
+ static boolean isFullySpecified( Type type )
+ {
+ if ( type instanceof Class )
+ {
+ return true;
+
+ }
+ else if ( type instanceof CompositeType )
+ {
+ return ( (CompositeType) type ).isFullySpecified();
+
+ }
+ else if ( type instanceof TypeVariable )
+ {
+ return false;
+
+ }
+ else
+ {
+ return ( (CompositeType) canonicalize( type ) ).isFullySpecified();
+ }
+ }
+
+ /**
+ * Returns a type that is functionally equal but not necessarily equal according to {@link Object#equals(Object)
+ * Object.equals()}. The returned type is {@link Serializable}.
+ */
+ public static Type canonicalize( Type type )
+ {
+ if ( type instanceof Class )
+ {
+ Class<?> c = (Class<?>) type;
+ return c.isArray() ? new GenericArrayTypeImpl( canonicalize( c.getComponentType() ) ) : c;
+ }
+ else if ( type instanceof CompositeType )
+ {
+ return type;
+ }
+ else if ( type instanceof ParameterizedType )
+ {
+ ParameterizedType p = (ParameterizedType) type;
+ return new ParameterizedTypeImpl( p.getOwnerType(), p.getRawType(), p.getActualTypeArguments() );
+ }
+ else if ( type instanceof GenericArrayType )
+ {
+ GenericArrayType g = (GenericArrayType) type;
+ return new GenericArrayTypeImpl( g.getGenericComponentType() );
+ }
+ else if ( type instanceof WildcardType )
+ {
+ WildcardType w = (WildcardType) type;
+ return new WildcardTypeImpl( w.getUpperBounds(), w.getLowerBounds() );
+ }
+ // type is either serializable as-is or unsupported
+ return type;
+ }
+
+ public static Class<?> getRawType( Type type )
+ {
+ if ( type instanceof Class<?> )
+ {
+ // type is a normal class.
+ return (Class<?>) type;
+ }
+ else if ( type instanceof ParameterizedType )
+ {
+ ParameterizedType parameterizedType = (ParameterizedType) type;
+
+ // I'm not exactly sure why getRawType() returns Type instead of Class.
+ // Neal isn't either but suspects some pathological case related
+ // to nested classes exists.
+ Type rawType = parameterizedType.getRawType();
+ checkArgument( rawType instanceof Class, "Expected a Class, but <%s> is of type %s", type,
+ type.getClass().getName() );
+ return (Class<?>) rawType;
+ }
+ else if ( type instanceof GenericArrayType )
+ {
+ Type componentType = ( (GenericArrayType) type ).getGenericComponentType();
+ return Array.newInstance( getRawType( componentType ), 0 ).getClass();
+ }
+ else if ( type instanceof TypeVariable )
+ {
+ // we could use the variable's bounds, but that'll won't work if there are multiple.
+ // having a raw type that's more general than necessary is okay
+ return Object.class;
+ }
+
+ throw new IllegalArgumentException( "Expected a Class, ParameterizedType, or GenericArrayType, but <" + type
+ + "> is of type " + type.getClass().getName() );
+ }
+
+ /**
+ * Returns true if {@code a} and {@code b} are equal.
+ */
+ public static boolean equals( Type a, Type b )
+ {
+ if ( a == b )
+ {
+ // also handles (a == null && b == null)
+ return true;
+ }
+ else if ( a instanceof Class )
+ {
+ // Class already specifies equals().
+ return a.equals( b );
+ }
+ else if ( a instanceof ParameterizedType )
+ {
+ if ( !( b instanceof ParameterizedType ) )
+ {
+ return false;
+ }
+
+ // TODO: save a .clone() call
+ ParameterizedType pa = (ParameterizedType) a;
+ ParameterizedType pb = (ParameterizedType) b;
+ return equal( pa.getOwnerType(), pb.getOwnerType() ) && pa.getRawType().equals( pb.getRawType() )
+ && Arrays.equals( pa.getActualTypeArguments(), pb.getActualTypeArguments() );
+ }
+ else if ( a instanceof GenericArrayType )
+ {
+ if ( !( b instanceof GenericArrayType ) )
+ {
+ return false;
+ }
+
+ GenericArrayType ga = (GenericArrayType) a;
+ GenericArrayType gb = (GenericArrayType) b;
+ return equals( ga.getGenericComponentType(), gb.getGenericComponentType() );
+ }
+ else if ( a instanceof WildcardType )
+ {
+ if ( !( b instanceof WildcardType ) )
+ {
+ return false;
+ }
+
+ WildcardType wa = (WildcardType) a;
+ WildcardType wb = (WildcardType) b;
+ return Arrays.equals( wa.getUpperBounds(), wb.getUpperBounds() )
+ && Arrays.equals( wa.getLowerBounds(), wb.getLowerBounds() );
+ }
+ else if ( a instanceof TypeVariable )
+ {
+ if ( !( b instanceof TypeVariable ) )
+ {
+ return false;
+ }
+ TypeVariable<?> va = (TypeVariable<?>) a;
+ TypeVariable<?> vb = (TypeVariable<?>) b;
+ return va.getGenericDeclaration() == vb.getGenericDeclaration() && va.getName().equals( vb.getName() );
+ }
+
+ // This isn't a type we support. Could be a generic array type, wildcard type, etc.
+ return false;
+ }
+
+ static int hashCodeOrZero( Object o )
+ {
+ return o != null ? o.hashCode() : 0;
+ }
+
+ public static String typeToString( Type type )
+ {
+ return type instanceof Class ? ( (Class<?>) type ).getName() : type.toString();
+ }
+
+ /**
+ * Returns the generic supertype for {@code supertype}. For example, given a class {@code IntegerSet}, the result
+ * for when supertype is {@code Set.class} is {@code Set<Integer>} and the result when the supertype is
+ * {@code Collection.class} is {@code Collection<Integer>}.
+ */
+ public static Type getGenericSupertype( Type type, Class<?> rawType, Class<?> toResolve )
+ {
+ if ( toResolve == rawType )
+ {
+ return type;
+ }
+
+ // we skip searching through interfaces if unknown is an interface
+ if ( toResolve.isInterface() )
+ {
+ Class<?>[] interfaces = rawType.getInterfaces();
+ for ( int i = 0, length = interfaces.length; i < length; i++ )
+ {
+ if ( interfaces[i] == toResolve )
+ {
+ return rawType.getGenericInterfaces()[i];
+ }
+ else if ( toResolve.isAssignableFrom( interfaces[i] ) )
+ {
+ return getGenericSupertype( rawType.getGenericInterfaces()[i], interfaces[i], toResolve );
+ }
+ }
+ }
+
+ // check our supertypes
+ if ( !rawType.isInterface() )
+ {
+ while ( rawType != Object.class )
+ {
+ Class<?> rawSupertype = rawType.getSuperclass();
+ if ( rawSupertype == toResolve )
+ {
+ return rawType.getGenericSuperclass();
+ }
+ else if ( toResolve.isAssignableFrom( rawSupertype ) )
+ {
+ return getGenericSupertype( rawType.getGenericSuperclass(), rawSupertype, toResolve );
+ }
+ rawType = rawSupertype;
+ }
+ }
+
+ // we can't resolve this further
+ return toResolve;
+ }
+
+ public static Type resolveTypeVariable( Type type, Class<?> rawType, TypeVariable<?> unknown )
+ {
+ Class<?> declaredByRaw = declaringClassOf( unknown );
+
+ // we can't reduce this further
+ if ( declaredByRaw == null )
+ {
+ return unknown;
+ }
+
+ Type declaredBy = getGenericSupertype( type, rawType, declaredByRaw );
+ if ( declaredBy instanceof ParameterizedType )
+ {
+ int index = indexOf( declaredByRaw.getTypeParameters(), unknown );
+ return ( (ParameterizedType) declaredBy ).getActualTypeArguments()[index];
+ }
+
+ return unknown;
+ }
+
+ private static int indexOf( Object[] array, Object toFind )
+ {
+ for ( int i = 0; i < array.length; i++ )
+ {
+ if ( toFind.equals( array[i] ) )
+ {
+ return i;
+ }
+ }
+ throw new NoSuchElementException();
+ }
+
+ /**
+ * Returns the declaring class of {@code typeVariable}, or {@code null} if it was not declared by a class.
+ */
+ private static Class<?> declaringClassOf( TypeVariable<?> typeVariable )
+ {
+ GenericDeclaration genericDeclaration = typeVariable.getGenericDeclaration();
+ return genericDeclaration instanceof Class ? (Class<?>) genericDeclaration : null;
+ }
+
+ static void checkNotPrimitive( Type type, String use )
+ {
+ checkArgument( !( type instanceof Class<?> ) || !( (Class<?>) type ).isPrimitive(),
+ "Primitive types are not allowed in %s: %s", use, type );
+ }
+
+}
Propchange: commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/type/MoreTypes.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/type/MoreTypes.java
------------------------------------------------------------------------------
svn:keywords = Date Author Id Revision HeadURL
Propchange: commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/type/MoreTypes.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/type/Objects.java
URL: http://svn.apache.org/viewvc/commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/type/Objects.java?rev=1241133&view=auto
==============================================================================
--- commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/type/Objects.java (added)
+++ commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/type/Objects.java Mon Feb 6 19:56:42 2012
@@ -0,0 +1,48 @@
+package org.apache.commons.beanutils2.type;
+
+/*
+ * 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.
+ */
+
+final class Objects
+{
+
+ private Objects()
+ {
+ // do nothing
+ }
+
+ /**
+ * Determines whether two possibly-null objects are equal. Returns:
+ *
+ * <ul>
+ * <li>{@code true} if {@code a} and {@code b} are both null.
+ * <li>{@code true} if {@code a} and {@code b} are both non-null and they are
+ * equal according to {@link Object#equals(Object)}.
+ * <li>{@code false} in all other situations.
+ * </ul>
+ *
+ * <p>This assumes that any non-null objects passed to this function conform
+ * to the {@code equals()} contract.
+ */
+ public static boolean equal( Object a, Object b )
+ {
+ return a == b || ( a != null && a.equals( b ) );
+ }
+
+}
Propchange: commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/type/Objects.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/type/Objects.java
------------------------------------------------------------------------------
svn:keywords = Date Author Id Revision HeadURL
Propchange: commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/type/Objects.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/type/ParameterizedTypeImpl.java
URL: http://svn.apache.org/viewvc/commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/type/ParameterizedTypeImpl.java?rev=1241133&view=auto
==============================================================================
--- commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/type/ParameterizedTypeImpl.java (added)
+++ commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/type/ParameterizedTypeImpl.java Mon Feb 6 19:56:42 2012
@@ -0,0 +1,138 @@
+package org.apache.commons.beanutils2.type;
+
+/*
+ * 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.
+ */
+
+import static org.apache.commons.beanutils2.type.MoreTypes.canonicalize;
+import static org.apache.commons.beanutils2.type.MoreTypes.checkNotPrimitive;
+import static org.apache.commons.beanutils2.type.MoreTypes.hashCodeOrZero;
+import static org.apache.commons.beanutils2.type.MoreTypes.typeToString;
+import static org.apache.commons.beanutils2.internal.Assertions.checkArgument;
+import static org.apache.commons.beanutils2.internal.Assertions.checkNotNull;
+
+import java.io.Serializable;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.util.Arrays;
+
+final class ParameterizedTypeImpl
+ implements ParameterizedType, Serializable, CompositeType
+{
+
+ private static final long serialVersionUID = 0;
+
+ private final Type ownerType;
+
+ private final Type rawType;
+
+ private final Type[] typeArguments;
+
+ public ParameterizedTypeImpl( Type ownerType, Type rawType, Type... typeArguments )
+ {
+ // require an owner type if the raw type needs it
+ if ( rawType instanceof Class<?> )
+ {
+ Class<?> rawTypeAsClass = (Class<?>) rawType;
+ checkArgument( ownerType != null || rawTypeAsClass.getEnclosingClass() == null,
+ "No owner type for enclosed %s", rawType );
+ checkArgument( ownerType == null || rawTypeAsClass.getEnclosingClass() != null,
+ "Owner type for unenclosed %s", rawType );
+ }
+
+ this.ownerType = ownerType == null ? null : canonicalize( ownerType );
+ this.rawType = canonicalize( rawType );
+ this.typeArguments = typeArguments.clone();
+ for ( int t = 0; t < this.typeArguments.length; t++ )
+ {
+ checkNotNull( this.typeArguments[t], "type parameter" );
+ checkNotPrimitive( this.typeArguments[t], "type parameters" );
+ this.typeArguments[t] = canonicalize( this.typeArguments[t] );
+ }
+ }
+
+ public Type[] getActualTypeArguments()
+ {
+ return typeArguments.clone();
+ }
+
+ public Type getRawType()
+ {
+ return rawType;
+ }
+
+ public Type getOwnerType()
+ {
+ return ownerType;
+ }
+
+ public boolean isFullySpecified()
+ {
+ if ( ownerType != null && !MoreTypes.isFullySpecified( ownerType ) )
+ {
+ return false;
+ }
+
+ if ( !MoreTypes.isFullySpecified( rawType ) )
+ {
+ return false;
+ }
+
+ for ( Type type : typeArguments )
+ {
+ if ( !MoreTypes.isFullySpecified( type ) )
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ @Override
+ public boolean equals( Object other )
+ {
+ return other instanceof ParameterizedType && MoreTypes.equals( this, (ParameterizedType) other );
+ }
+
+ @Override
+ public int hashCode()
+ {
+ return Arrays.hashCode( typeArguments ) ^ rawType.hashCode() ^ hashCodeOrZero( ownerType );
+ }
+
+ @Override
+ public String toString()
+ {
+ StringBuilder stringBuilder = new StringBuilder( 30 * ( typeArguments.length + 1 ) );
+ stringBuilder.append( typeToString( rawType ) );
+
+ if ( typeArguments.length == 0 )
+ {
+ return stringBuilder.toString();
+ }
+
+ stringBuilder.append( "<" ).append( typeToString( typeArguments[0] ) );
+ for ( int i = 1; i < typeArguments.length; i++ )
+ {
+ stringBuilder.append( ", " ).append( typeToString( typeArguments[i] ) );
+ }
+ return stringBuilder.append( ">" ).toString();
+ }
+
+}
Propchange: commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/type/ParameterizedTypeImpl.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/type/ParameterizedTypeImpl.java
------------------------------------------------------------------------------
svn:keywords = Date Author Id Revision HeadURL
Propchange: commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/type/ParameterizedTypeImpl.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/type/TypeLiteral.java
URL: http://svn.apache.org/viewvc/commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/type/TypeLiteral.java?rev=1241133&view=auto
==============================================================================
--- commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/type/TypeLiteral.java (added)
+++ commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/type/TypeLiteral.java Mon Feb 6 19:56:42 2012
@@ -0,0 +1,384 @@
+package org.apache.commons.beanutils2.type;
+
+/*
+ * 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.
+ */
+
+import static java.util.Arrays.asList;
+import static java.util.Collections.unmodifiableList;
+import static org.apache.commons.beanutils2.type.MoreTypes.canonicalize;
+import static org.apache.commons.beanutils2.type.MoreTypes.getGenericSupertype;
+import static org.apache.commons.beanutils2.type.MoreTypes.resolveTypeVariable;
+import static org.apache.commons.beanutils2.type.MoreTypes.typeToString;
+import static org.apache.commons.beanutils2.internal.Assertions.checkArgument;
+import static org.apache.commons.beanutils2.internal.Assertions.checkNotNull;
+import static org.apache.commons.beanutils2.type.Types.arrayOf;
+import static org.apache.commons.beanutils2.type.Types.newParameterizedTypeWithOwner;
+import static org.apache.commons.beanutils2.type.Types.subtypeOf;
+import static org.apache.commons.beanutils2.type.Types.supertypeOf;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.GenericArrayType;
+import java.lang.reflect.Member;
+import java.lang.reflect.Method;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.lang.reflect.TypeVariable;
+import java.lang.reflect.WildcardType;
+import java.util.List;
+
+/**
+ * Represents a generic type {@code T}. Java doesn't yet provide a way to represent generic types, so this class does.
+ * Forces clients to create a subclass of this class which enables retrieval the type information even at runtime.
+ * <p>
+ * For example, to create a type literal for {@code List<String>}, you can create an empty anonymous inner class:
+ * <p>
+ * {@code TypeLiteral<List<String>> list = new TypeLiteral<List<String>>() ;}
+ * <p>
+ * Along with modeling generic types, this class can resolve type parameters. For example, to figure out what type
+ * {@code keySet()} returns on a {@code Map<Integer, String>}, use this code:
+ *
+ * <pre>
+ * {@code
+ *
+ * TypeLiteral<Map<Integer, String>> mapType
+ * = new TypeLiteral<Map<Integer, String>>() {};
+ * TypeLiteral<?> keySetType
+ * = mapType.getReturnType(Map.class.getMethod("keySet"));
+ * System.out.println(keySetType); // prints "Set<Integer>"}
+ * </pre>
+ *
+ * @author crazybob@google.com (Bob Lee)
+ * @author jessewilson@google.com (Jesse Wilson)
+ */
+public class TypeLiteral<T>
+{
+
+ final Class<? super T> rawType;
+
+ final Type type;
+
+ final int hashCode;
+
+ /**
+ * Constructs a new type literal. Derives represented class from type parameter.
+ * <p>
+ * Clients create an empty anonymous subclass. Doing so embeds the type parameter in the anonymous class's type
+ * hierarchy so we can reconstitute it at runtime despite erasure.
+ */
+ @SuppressWarnings( "unchecked" )
+ protected TypeLiteral()
+ {
+ this.type = getSuperclassTypeParameter( getClass() );
+ this.rawType = (Class<? super T>) MoreTypes.getRawType( type );
+ this.hashCode = type.hashCode();
+ }
+
+ /**
+ * Unsafe. Constructs a type literal manually.
+ */
+ @SuppressWarnings( "unchecked" )
+ TypeLiteral( Type type )
+ {
+ this.type = canonicalize( checkNotNull( type, "type" ) );
+ this.rawType = (Class<? super T>) MoreTypes.getRawType( this.type );
+ this.hashCode = this.type.hashCode();
+ }
+
+ /**
+ * Returns the type from super class's type parameter in {@link MoreTypes#canonicalize(Type) canonical form}.
+ */
+ static Type getSuperclassTypeParameter( Class<?> subclass )
+ {
+ Type superclass = subclass.getGenericSuperclass();
+ if ( superclass instanceof Class )
+ {
+ throw new RuntimeException( "Missing type parameter." );
+ }
+ ParameterizedType parameterized = (ParameterizedType) superclass;
+ return canonicalize( parameterized.getActualTypeArguments()[0] );
+ }
+
+ /**
+ * Gets type literal from super class's type parameter.
+ */
+ static TypeLiteral<?> fromSuperclassTypeParameter( Class<?> subclass )
+ {
+ return new TypeLiteral<Object>( getSuperclassTypeParameter( subclass ) );
+ }
+
+ /**
+ * Returns the raw (non-generic) type for this type.
+ *
+ * @since 2.0
+ */
+ public final Class<? super T> getRawType()
+ {
+ return rawType;
+ }
+
+ /**
+ * Gets underlying {@code Type} instance.
+ */
+ public final Type getType()
+ {
+ return type;
+ }
+
+ @Override
+ public final int hashCode()
+ {
+ return this.hashCode;
+ }
+
+ @Override
+ public final boolean equals( Object o )
+ {
+ return o instanceof TypeLiteral<?> && MoreTypes.equals( type, ( (TypeLiteral<?>) o ).type );
+ }
+
+ @Override
+ public final String toString()
+ {
+ return typeToString( type );
+ }
+
+ /**
+ * Gets type literal for the given {@code Type} instance.
+ */
+ public static TypeLiteral<?> get( Type type )
+ {
+ return new TypeLiteral<Object>( type );
+ }
+
+ /**
+ * Gets type literal for the given {@code Class} instance.
+ */
+ public static <T> TypeLiteral<T> get( Class<T> type )
+ {
+ return new TypeLiteral<T>( type );
+ }
+
+ /** Returns an immutable list of the resolved types. */
+ private List<TypeLiteral<?>> resolveAll( Type[] types )
+ {
+ TypeLiteral<?>[] result = new TypeLiteral<?>[types.length];
+ for ( int t = 0; t < types.length; t++ )
+ {
+ result[t] = resolve( types[t] );
+ }
+ return unmodifiableList( asList( result ) );
+ }
+
+ /**
+ * Resolves known type parameters in {@code toResolve} and returns the result.
+ */
+ TypeLiteral<?> resolve( Type toResolve )
+ {
+ return TypeLiteral.get( resolveType( toResolve ) );
+ }
+
+ Type resolveType( Type toResolve )
+ {
+ // this implementation is made a little more complicated in an attempt to avoid object-creation
+ while ( true )
+ {
+ if ( toResolve instanceof TypeVariable )
+ {
+ TypeVariable<?> original = (TypeVariable<?>) toResolve;
+ toResolve = resolveTypeVariable( type, rawType, original );
+ if ( toResolve == original )
+ {
+ return toResolve;
+ }
+
+ }
+ else if ( toResolve instanceof GenericArrayType )
+ {
+ GenericArrayType original = (GenericArrayType) toResolve;
+ Type componentType = original.getGenericComponentType();
+ Type newComponentType = resolveType( componentType );
+ return componentType == newComponentType ? original : arrayOf( newComponentType );
+
+ }
+ else if ( toResolve instanceof ParameterizedType )
+ {
+ ParameterizedType original = (ParameterizedType) toResolve;
+ Type ownerType = original.getOwnerType();
+ Type newOwnerType = resolveType( ownerType );
+ boolean changed = newOwnerType != ownerType;
+
+ Type[] args = original.getActualTypeArguments();
+ for ( int t = 0, length = args.length; t < length; t++ )
+ {
+ Type resolvedTypeArgument = resolveType( args[t] );
+ if ( resolvedTypeArgument != args[t] )
+ {
+ if ( !changed )
+ {
+ args = args.clone();
+ changed = true;
+ }
+ args[t] = resolvedTypeArgument;
+ }
+ }
+
+ return changed ? newParameterizedTypeWithOwner( newOwnerType, original.getRawType(), args )
+ : original;
+
+ }
+ else if ( toResolve instanceof WildcardType )
+ {
+ WildcardType original = (WildcardType) toResolve;
+ Type[] originalLowerBound = original.getLowerBounds();
+ Type[] originalUpperBound = original.getUpperBounds();
+
+ if ( originalLowerBound.length == 1 )
+ {
+ Type lowerBound = resolveType( originalLowerBound[0] );
+ if ( lowerBound != originalLowerBound[0] )
+ {
+ return supertypeOf( lowerBound );
+ }
+ }
+ else if ( originalUpperBound.length == 1 )
+ {
+ Type upperBound = resolveType( originalUpperBound[0] );
+ if ( upperBound != originalUpperBound[0] )
+ {
+ return subtypeOf( upperBound );
+ }
+ }
+ return original;
+
+ }
+ else
+ {
+ return toResolve;
+ }
+ }
+ }
+
+ /**
+ * Returns the generic form of {@code supertype}. For example, if this is {@code ArrayList<String>}, this returns
+ * {@code Iterable<String>} given the input {@code Iterable.class}.
+ *
+ * @param supertype a superclass of, or interface implemented by, this.
+ * @since 2.0
+ */
+ public TypeLiteral<?> getSupertype( Class<?> supertype )
+ {
+ checkArgument( supertype.isAssignableFrom( rawType ), "%s is not a supertype of %s", supertype, this.type );
+ return resolve( getGenericSupertype( type, rawType, supertype ) );
+ }
+
+ /**
+ * Returns the resolved generic type of {@code field}.
+ *
+ * @param field a field defined by this or any superclass.
+ * @since 2.0
+ */
+ public TypeLiteral<?> getFieldType( Field field )
+ {
+ checkArgument( field.getDeclaringClass().isAssignableFrom( rawType ), "%s is not defined by a supertype of %s",
+ field, type );
+ return resolve( field.getGenericType() );
+ }
+
+ /**
+ * Returns the resolved generic parameter types of {@code methodOrConstructor}.
+ *
+ * @param methodOrConstructor a method or constructor defined by this or any supertype.
+ * @since 2.0
+ */
+ public List<TypeLiteral<?>> getParameterTypes( Member methodOrConstructor )
+ {
+ Type[] genericParameterTypes;
+
+ if ( methodOrConstructor instanceof Method )
+ {
+ Method method = (Method) methodOrConstructor;
+ checkArgument( method.getDeclaringClass().isAssignableFrom( rawType ),
+ "%s is not defined by a supertype of %s", method, type );
+ genericParameterTypes = method.getGenericParameterTypes();
+
+ }
+ else if ( methodOrConstructor instanceof Constructor )
+ {
+ Constructor<?> constructor = (Constructor<?>) methodOrConstructor;
+ checkArgument( constructor.getDeclaringClass().isAssignableFrom( rawType ),
+ "%s does not construct a supertype of %s", constructor, type );
+ genericParameterTypes = constructor.getGenericParameterTypes();
+
+ }
+ else
+ {
+ throw new IllegalArgumentException( "Not a method or a constructor: " + methodOrConstructor );
+ }
+
+ return resolveAll( genericParameterTypes );
+ }
+
+ /**
+ * Returns the resolved generic exception types thrown by {@code constructor}.
+ *
+ * @param methodOrConstructor a method or constructor defined by this or any supertype.
+ * @since 2.0
+ */
+ public List<TypeLiteral<?>> getExceptionTypes( Member methodOrConstructor )
+ {
+ Type[] genericExceptionTypes;
+
+ if ( methodOrConstructor instanceof Method )
+ {
+ Method method = (Method) methodOrConstructor;
+ checkArgument( method.getDeclaringClass().isAssignableFrom( rawType ),
+ "%s is not defined by a supertype of %s", method, type );
+ genericExceptionTypes = method.getGenericExceptionTypes();
+
+ }
+ else if ( methodOrConstructor instanceof Constructor )
+ {
+ Constructor<?> constructor = (Constructor<?>) methodOrConstructor;
+ checkArgument( constructor.getDeclaringClass().isAssignableFrom( rawType ),
+ "%s does not construct a supertype of %s", constructor, type );
+ genericExceptionTypes = constructor.getGenericExceptionTypes();
+
+ }
+ else
+ {
+ throw new IllegalArgumentException( "Not a method or a constructor: " + methodOrConstructor );
+ }
+
+ return resolveAll( genericExceptionTypes );
+ }
+
+ /**
+ * Returns the resolved generic return type of {@code method}.
+ *
+ * @param method a method defined by this or any supertype.
+ * @since 2.0
+ */
+ public TypeLiteral<?> getReturnType( Method method )
+ {
+ checkArgument( method.getDeclaringClass().isAssignableFrom( rawType ),
+ "%s is not defined by a supertype of %s", method, type );
+ return resolve( method.getGenericReturnType() );
+ }
+}
Propchange: commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/type/TypeLiteral.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/type/TypeLiteral.java
------------------------------------------------------------------------------
svn:keywords = Date Author Id Revision HeadURL
Propchange: commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/type/TypeLiteral.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/type/Types.java
URL: http://svn.apache.org/viewvc/commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/type/Types.java?rev=1241133&view=auto
==============================================================================
--- commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/type/Types.java (added)
+++ commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/type/Types.java Mon Feb 6 19:56:42 2012
@@ -0,0 +1,125 @@
+package org.apache.commons.beanutils2.type;
+
+/*
+ * 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.
+ */
+
+import java.lang.reflect.GenericArrayType;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.lang.reflect.WildcardType;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Static methods for working with types.
+ *
+ * @author crazybob@google.com (Bob Lee)
+ * @since 2.0
+ */
+final class Types
+{
+ private Types()
+ {
+ }
+
+ /**
+ * Returns a new parameterized type, applying {@code typeArguments} to {@code rawType}. The returned type does not
+ * have an owner type.
+ *
+ * @return a {@link java.io.Serializable serializable} parameterized type.
+ */
+ public static ParameterizedType newParameterizedType( Type rawType, Type... typeArguments )
+ {
+ return newParameterizedTypeWithOwner( null, rawType, typeArguments );
+ }
+
+ /**
+ * Returns a new parameterized type, applying {@code typeArguments} to {@code rawType} and enclosed by
+ * {@code ownerType}.
+ *
+ * @return a {@link java.io.Serializable serializable} parameterized type.
+ */
+ public static ParameterizedType newParameterizedTypeWithOwner( Type ownerType, Type rawType, Type... typeArguments )
+ {
+ return new ParameterizedTypeImpl( ownerType, rawType, typeArguments );
+ }
+
+ /**
+ * Returns an array type whose elements are all instances of {@code componentType}.
+ *
+ * @return a {@link java.io.Serializable serializable} generic array type.
+ */
+ public static GenericArrayType arrayOf( Type componentType )
+ {
+ return new GenericArrayTypeImpl( componentType );
+ }
+
+ /**
+ * Returns a type that represents an unknown type that extends {@code bound}. For example, if {@code bound} is
+ * {@code CharSequence.class}, this returns {@code ? extends CharSequence}. If {@code bound} is {@code Object.class}
+ * , this returns {@code ?}, which is shorthand for {@code ? extends Object}.
+ */
+ public static WildcardType subtypeOf( Type bound )
+ {
+ return new WildcardTypeImpl( new Type[] { bound }, MoreTypes.EMPTY_TYPE_ARRAY );
+ }
+
+ /**
+ * Returns a type that represents an unknown supertype of {@code bound}. For example, if {@code bound} is
+ * {@code String.class}, this returns {@code ?
+ * super String}.
+ */
+ public static WildcardType supertypeOf( Type bound )
+ {
+ return new WildcardTypeImpl( new Type[] { Object.class }, new Type[] { bound } );
+ }
+
+ /**
+ * Returns a type modelling a {@link List} whose elements are of type {@code elementType}.
+ *
+ * @return a {@link java.io.Serializable serializable} parameterized type.
+ */
+ public static ParameterizedType listOf( Type elementType )
+ {
+ return newParameterizedType( List.class, elementType );
+ }
+
+ /**
+ * Returns a type modelling a {@link Set} whose elements are of type {@code elementType}.
+ *
+ * @return a {@link java.io.Serializable serializable} parameterized type.
+ */
+ public static ParameterizedType setOf( Type elementType )
+ {
+ return newParameterizedType( Set.class, elementType );
+ }
+
+ /**
+ * Returns a type modelling a {@link Map} whose keys are of type {@code keyType} and whose values are of type
+ * {@code valueType}.
+ *
+ * @return a {@link java.io.Serializable serializable} parameterized type.
+ */
+ public static ParameterizedType mapOf( Type keyType, Type valueType )
+ {
+ return newParameterizedType( Map.class, keyType, valueType );
+ }
+
+}
Propchange: commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/type/Types.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/type/Types.java
------------------------------------------------------------------------------
svn:keywords = Date Author Id Revision HeadURL
Propchange: commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/type/Types.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/type/WildcardTypeImpl.java
URL: http://svn.apache.org/viewvc/commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/type/WildcardTypeImpl.java?rev=1241133&view=auto
==============================================================================
--- commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/type/WildcardTypeImpl.java (added)
+++ commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/type/WildcardTypeImpl.java Mon Feb 6 19:56:42 2012
@@ -0,0 +1,117 @@
+package org.apache.commons.beanutils2.type;
+
+/*
+ * 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.
+ */
+
+import static org.apache.commons.beanutils2.type.MoreTypes.EMPTY_TYPE_ARRAY;
+import static org.apache.commons.beanutils2.type.MoreTypes.canonicalize;
+import static org.apache.commons.beanutils2.type.MoreTypes.checkNotPrimitive;
+import static org.apache.commons.beanutils2.type.MoreTypes.typeToString;
+import static org.apache.commons.beanutils2.internal.Assertions.checkArgument;
+import static org.apache.commons.beanutils2.internal.Assertions.checkNotNull;
+
+import java.io.Serializable;
+import java.lang.reflect.Type;
+import java.lang.reflect.WildcardType;
+
+
+/**
+ * The WildcardType interface supports multiple upper bounds and multiple lower bounds. We only support what the Java 6
+ * language needs - at most one bound. If a lower bound is set, the upper bound must be Object.class.
+ */
+final class WildcardTypeImpl
+ implements WildcardType, Serializable, CompositeType
+{
+
+ private static final long serialVersionUID = 0;
+
+ private final Type upperBound;
+
+ private final Type lowerBound;
+
+ public WildcardTypeImpl( Type[] upperBounds, Type[] lowerBounds )
+ {
+ checkArgument( lowerBounds.length <= 1, "Must have at most one lower bound." );
+ checkArgument( upperBounds.length == 1, "Must have exactly one upper bound." );
+
+ if ( lowerBounds.length == 1 )
+ {
+ checkNotNull( lowerBounds[0], "lowerBound" );
+ checkNotPrimitive( lowerBounds[0], "wildcard bounds" );
+ checkArgument( upperBounds[0] == Object.class, "bounded both ways" );
+ this.lowerBound = canonicalize( lowerBounds[0] );
+ this.upperBound = Object.class;
+
+ }
+ else
+ {
+ checkNotNull( upperBounds[0], "upperBound" );
+ checkNotPrimitive( upperBounds[0], "wildcard bounds" );
+ this.lowerBound = null;
+ this.upperBound = canonicalize( upperBounds[0] );
+ }
+ }
+
+ public Type[] getUpperBounds()
+ {
+ return new Type[] { upperBound };
+ }
+
+ public Type[] getLowerBounds()
+ {
+ return lowerBound != null ? new Type[] { lowerBound } : EMPTY_TYPE_ARRAY;
+ }
+
+ public boolean isFullySpecified()
+ {
+ return MoreTypes.isFullySpecified( upperBound )
+ && ( lowerBound == null || MoreTypes.isFullySpecified( lowerBound ) );
+ }
+
+ @Override
+ public boolean equals( Object other )
+ {
+ return other instanceof WildcardType && MoreTypes.equals( this, (WildcardType) other );
+ }
+
+ @Override
+ public int hashCode()
+ {
+ // this equals Arrays.hashCode(getLowerBounds()) ^ Arrays.hashCode(getUpperBounds());
+ return ( lowerBound != null ? 31 + lowerBound.hashCode() : 1 ) ^ ( 31 + upperBound.hashCode() );
+ }
+
+ @Override
+ public String toString()
+ {
+ if ( lowerBound != null )
+ {
+ return "? super " + typeToString( lowerBound );
+ }
+ else if ( upperBound == Object.class )
+ {
+ return "?";
+ }
+ else
+ {
+ return "? extends " + typeToString( upperBound );
+ }
+ }
+
+}
Propchange: commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/type/WildcardTypeImpl.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/type/WildcardTypeImpl.java
------------------------------------------------------------------------------
svn:keywords = Date Author Id Revision HeadURL
Propchange: commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/type/WildcardTypeImpl.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/type/package-info.java
URL: http://svn.apache.org/viewvc/commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/type/package-info.java?rev=1241133&view=auto
==============================================================================
--- commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/type/package-info.java (added)
+++ commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/type/package-info.java Mon Feb 6 19:56:42 2012
@@ -0,0 +1,23 @@
+/**
+ * The {@code TypeLiteral} framework, extracted from Google Guice.
+ */
+package org.apache.commons.beanutils2.type;
+
+/*
+ * 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.
+ */
Propchange: commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/type/package-info.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/type/package-info.java
------------------------------------------------------------------------------
svn:keywords = Date Author Id Revision HeadURL
Propchange: commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/type/package-info.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: commons/sandbox/beanutils2/trunk/src/test/java/org/apache/commons/beanutils2/type/Asserts.java
URL: http://svn.apache.org/viewvc/commons/sandbox/beanutils2/trunk/src/test/java/org/apache/commons/beanutils2/type/Asserts.java?rev=1241133&view=auto
==============================================================================
--- commons/sandbox/beanutils2/trunk/src/test/java/org/apache/commons/beanutils2/type/Asserts.java (added)
+++ commons/sandbox/beanutils2/trunk/src/test/java/org/apache/commons/beanutils2/type/Asserts.java Mon Feb 6 19:56:42 2012
@@ -0,0 +1,134 @@
+package org.apache.commons.beanutils2.type;
+
+/*
+ * 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.
+ */
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertNotNull;
+import static junit.framework.Assert.assertTrue;
+
+import junit.framework.Assert;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.NotSerializableException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+
+/**
+ * @author jessewilson@google.com (Jesse Wilson)
+ */
+public class Asserts
+{
+ private Asserts()
+ {
+ }
+
+ /**
+ * Fails unless {@code expected.equals(actual)}, {@code actual.equals(expected)} and their hash codes are equal.
+ * This is useful for testing the equals method itself.
+ */
+ public static void assertEqualsBothWays( Object expected, Object actual )
+ {
+ assertNotNull( expected );
+ assertNotNull( actual );
+ assertTrue( "expected.equals(actual)", expected.equals( actual ) );
+ assertTrue( "actual.equals(expected)", actual.equals( expected ) );
+ assertEquals( "hashCode", expected.hashCode(), actual.hashCode() );
+ }
+
+ /**
+ * Fails unless {@code text} includes all {@code substrings}, in order.
+ */
+ public static void assertContains( String text, String... substrings )
+ {
+ /*
+ * if[NO_AOP] // when we strip out bytecode manipulation, we lose the ability to generate some source lines. if
+ * (text.contains("(Unknown Source)")) { return; } end[NO_AOP]
+ */
+
+ int startingFrom = 0;
+ for ( String substring : substrings )
+ {
+ int index = text.indexOf( substring, startingFrom );
+ assertTrue( String.format( "Expected \"%s\" to contain substring \"%s\"", text, substring ),
+ index >= startingFrom );
+ startingFrom = index + substring.length();
+ }
+
+ String lastSubstring = substrings[substrings.length - 1];
+ assertTrue( String.format( "Expected \"%s\" to contain substring \"%s\" only once),", text, lastSubstring ),
+ text.indexOf( lastSubstring, startingFrom ) == -1 );
+ }
+
+ /**
+ * Fails unless {@code object} doesn't equal itself when reserialized.
+ */
+ public static void assertEqualWhenReserialized( Object object )
+ throws IOException
+ {
+ Object reserialized = reserialize( object );
+ assertEquals( object, reserialized );
+ assertEquals( object.hashCode(), reserialized.hashCode() );
+ }
+
+ /**
+ * Fails unless {@code object} has the same toString value when reserialized.
+ */
+ public static void assertSimilarWhenReserialized( Object object )
+ throws IOException
+ {
+ Object reserialized = reserialize( object );
+ assertEquals( object.toString(), reserialized.toString() );
+ }
+
+ public static <E> E reserialize( E original )
+ throws IOException
+ {
+ try
+ {
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ new ObjectOutputStream( out ).writeObject( original );
+ ByteArrayInputStream in = new ByteArrayInputStream( out.toByteArray() );
+ @SuppressWarnings( "unchecked" )
+ // the reserialized type is assignable
+ E reserialized = (E) new ObjectInputStream( in ).readObject();
+ return reserialized;
+ }
+ catch ( ClassNotFoundException e )
+ {
+ throw new RuntimeException( e );
+ }
+ }
+
+ public static void assertNotSerializable( Object object )
+ throws IOException
+ {
+ try
+ {
+ reserialize( object );
+ Assert.fail();
+ }
+ catch ( NotSerializableException expected )
+ {
+ }
+ }
+
+}
Propchange: commons/sandbox/beanutils2/trunk/src/test/java/org/apache/commons/beanutils2/type/Asserts.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: commons/sandbox/beanutils2/trunk/src/test/java/org/apache/commons/beanutils2/type/Asserts.java
------------------------------------------------------------------------------
svn:keywords = Date Author Id Revision HeadURL
Propchange: commons/sandbox/beanutils2/trunk/src/test/java/org/apache/commons/beanutils2/type/Asserts.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: commons/sandbox/beanutils2/trunk/src/test/java/org/apache/commons/beanutils2/type/TypeLiteralTest.java
URL: http://svn.apache.org/viewvc/commons/sandbox/beanutils2/trunk/src/test/java/org/apache/commons/beanutils2/type/TypeLiteralTest.java?rev=1241133&view=auto
==============================================================================
--- commons/sandbox/beanutils2/trunk/src/test/java/org/apache/commons/beanutils2/type/TypeLiteralTest.java (added)
+++ commons/sandbox/beanutils2/trunk/src/test/java/org/apache/commons/beanutils2/type/TypeLiteralTest.java Mon Feb 6 19:56:42 2012
@@ -0,0 +1,271 @@
+package org.apache.commons.beanutils2.type;
+
+/*
+ * 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.
+ */
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.fail;
+import static org.apache.commons.beanutils2.type.Asserts.assertEqualsBothWays;
+import static org.apache.commons.beanutils2.type.Asserts.assertNotSerializable;
+
+import java.io.IOException;
+import java.lang.reflect.Type;
+import java.lang.reflect.TypeVariable;
+import java.util.List;
+
+import org.junit.Test;
+import org.apache.commons.beanutils2.type.TypeLiteral;
+import org.apache.commons.beanutils2.type.Types;
+
+import com.google.common.collect.ImmutableList;
+
+/**
+ * @author crazybob@google.com (Bob Lee)
+ */
+public class TypeLiteralTest
+{
+
+ @Test
+ public void testWithParameterizedType()
+ {
+ TypeLiteral<List<String>> a = new TypeLiteral<List<String>>()
+ {
+ };
+ TypeLiteral<List<String>> b = new TypeLiteral<List<String>>( Types.listOf( String.class ) )
+ {
+ };
+ assertEqualsBothWays( a, b );
+ }
+
+ @Test
+ public void testEquality()
+ {
+ TypeLiteral<List<String>> t1 = new TypeLiteral<List<String>>()
+ {
+ };
+ TypeLiteral<List<String>> t2 = new TypeLiteral<List<String>>()
+ {
+ };
+ TypeLiteral<List<Integer>> t3 = new TypeLiteral<List<Integer>>()
+ {
+ };
+ TypeLiteral<String> t4 = new TypeLiteral<String>()
+ {
+ };
+
+ assertEqualsBothWays( t1, t2 );
+
+ assertFalse( t2.equals( t3 ) );
+ assertFalse( t3.equals( t2 ) );
+
+ assertFalse( t2.equals( t4 ) );
+ assertFalse( t4.equals( t2 ) );
+
+ TypeLiteral<String> t5 = TypeLiteral.get( String.class );
+ assertEqualsBothWays( t4, t5 );
+ }
+
+ public List<? extends CharSequence> wildcardExtends;
+
+ @Test
+ public void testWithWildcardType()
+ throws NoSuchFieldException, IOException
+ {
+ TypeLiteral<?> a = TypeLiteral.get( getClass().getField( "wildcardExtends" ).getGenericType() );
+ TypeLiteral<?> b = TypeLiteral.get( Types.listOf( Types.subtypeOf( CharSequence.class ) ) );
+ TypeLiteral<?> c = new TypeLiteral<List<? extends CharSequence>>()
+ {
+ };
+ assertEqualsBothWays( a, b );
+ assertEqualsBothWays( b, c );
+ assertEquals( "java.util.List<? extends java.lang.CharSequence>", a.toString() );
+ assertEquals( "java.util.List<? extends java.lang.CharSequence>", b.toString() );
+ assertEquals( "java.util.List<? extends java.lang.CharSequence>", c.toString() );
+ assertNotSerializable( a );
+ assertNotSerializable( b );
+ assertNotSerializable( c );
+ }
+
+ @Test
+ public void testMissingTypeParameter()
+ {
+ try
+ {
+ new TypeLiteral()
+ {
+ };
+ fail();
+ }
+ catch ( RuntimeException e )
+ { /* expected */
+ }
+ }
+
+ @Test
+ public void testTypesInvolvingArraysForEquality()
+ {
+ TypeLiteral<String[]> stringArray = new TypeLiteral<String[]>()
+ {
+ };
+ assertEquals( stringArray, new TypeLiteral<String[]>()
+ {
+ } );
+
+ TypeLiteral<List<String[]>> listOfStringArray = new TypeLiteral<List<String[]>>()
+ {
+ };
+ assertEquals( listOfStringArray, new TypeLiteral<List<String[]>>()
+ {
+ } );
+ }
+
+ @Test
+ public void testEqualityOfGenericArrayAndClassArray()
+ {
+ TypeLiteral<String[]> arrayAsClass = TypeLiteral.get( String[].class );
+ TypeLiteral<String[]> arrayAsType = new TypeLiteral<String[]>()
+ {
+ };
+ assertEquals( arrayAsClass, arrayAsType );
+ }
+
+ @Test
+ public void testEqualityOfMultidimensionalGenericArrayAndClassArray()
+ {
+ TypeLiteral<String[][][]> arrayAsClass = TypeLiteral.get( String[][][].class );
+ TypeLiteral<String[][][]> arrayAsType = new TypeLiteral<String[][][]>()
+ {
+ };
+ assertEquals( arrayAsClass, arrayAsType );
+ }
+
+ @Test
+ public void testTypeLiteralsMustHaveRawTypes()
+ {
+ try
+ {
+ TypeLiteral.get( Types.subtypeOf( Runnable.class ) );
+ fail();
+ }
+ catch ( IllegalArgumentException expected )
+ {
+ Asserts.assertContains( expected.getMessage(), "Expected a Class, ParameterizedType, or "
+ + "GenericArrayType, but <? extends java.lang.Runnable> is of type "
+ + "org.apache.commons.beanutils2.type.WildcardTypeImpl" );
+ }
+ }
+
+ /**
+ * Unlike Key, TypeLiteral retains full type information and differentiates between {@code int.class} and
+ * {@code Integer.class}.
+ */
+ @Test
+ public void testDifferentiationBetweenWrappersAndPrimitives()
+ {
+ Class[] primitives =
+ new Class[] { boolean.class, byte.class, short.class, int.class, long.class, float.class, double.class,
+ char.class, void.class };
+ Class[] wrappers =
+ new Class[] { Boolean.class, Byte.class, Short.class, Integer.class, Long.class, Float.class, Double.class,
+ Character.class, Void.class };
+
+ for ( int t = 0; t < primitives.length; t++ )
+ {
+ @SuppressWarnings( "unchecked" )
+ TypeLiteral primitiveTl = TypeLiteral.get( primitives[t] );
+ @SuppressWarnings( "unchecked" )
+ TypeLiteral wrapperTl = TypeLiteral.get( wrappers[t] );
+
+ assertFalse( primitiveTl.equals( wrapperTl ) );
+ assertEquals( primitives[t], primitiveTl.getType() );
+ assertEquals( wrappers[t], wrapperTl.getType() );
+ assertEquals( primitives[t], primitiveTl.getRawType() );
+ assertEquals( wrappers[t], wrapperTl.getRawType() );
+ }
+ }
+
+ @Test
+ public void testSerialization()
+ throws IOException
+ {
+ assertNotSerializable( new TypeLiteral<List<String>>()
+ {
+ } );
+ }
+
+ @Test
+ public void testTypeVariableWithNoBound()
+ {
+ TypeVariable<Class<HasTypeParameters>>[] typeVariables = HasTypeParameters.class.getTypeParameters();
+
+ TypeLiteral<?> aTl = TypeLiteral.get( typeVariables[0] );
+ assertEquals( Object.class, aTl.getRawType() );
+ assertEquals( "A", aTl.toString() );
+ TypeVariable<?> aTv = (TypeVariable) aTl.getType();
+ assertEquals( HasTypeParameters.class, aTv.getGenericDeclaration() );
+ assertEquals( "A", aTv.getName() );
+ assertEquals( ImmutableList.<Type> of( Object.class ), ImmutableList.copyOf( aTv.getBounds() ) );
+ assertEquals( "A", aTv.toString() );
+ assertEqualsBothWays( aTl, TypeLiteral.get( HasTypeParameters.class.getTypeParameters()[0] ) );
+ }
+
+ @Test
+ public void testTypeVariablesWithSingleBound()
+ {
+ TypeVariable<Class<HasTypeParameters>>[] typeVariables = HasTypeParameters.class.getTypeParameters();
+
+ TypeLiteral<?> cTl = TypeLiteral.get( typeVariables[2] );
+ assertEquals( Object.class, cTl.getRawType() );
+ assertEquals( "C", cTl.toString() );
+ TypeVariable<?> cTv = (TypeVariable) cTl.getType();
+ assertEquals( HasTypeParameters.class, cTv.getGenericDeclaration() );
+ assertEquals( "C", cTv.getName() );
+ assertEquals( ImmutableList.<Type> of( Runnable.class ), ImmutableList.copyOf( cTv.getBounds() ) );
+ assertEquals( "C", cTv.toString() );
+ assertEqualsBothWays( cTl, TypeLiteral.get( HasTypeParameters.class.getTypeParameters()[2] ) );
+ }
+
+ @Test
+ public void testTypeVariableWithMultipleBounds()
+ {
+ TypeVariable<Class<HasTypeParameters>>[] typeVariables = HasTypeParameters.class.getTypeParameters();
+
+ TypeLiteral<?> bTl = TypeLiteral.get( typeVariables[1] );
+ assertEquals( Object.class, bTl.getRawType() );
+ assertEquals( "B", bTl.toString() );
+ TypeVariable<?> bTv = (TypeVariable) bTl.getType();
+ assertEquals( HasTypeParameters.class, bTv.getGenericDeclaration() );
+ assertEquals( "B", bTv.getName() );
+ assertEquals( ImmutableList.<Type> of( Types.listOf( typeVariables[0] ), Runnable.class ),
+ ImmutableList.copyOf( bTv.getBounds() ) );
+ assertEquals( "B", bTv.toString() );
+ assertEqualsBothWays( bTl, TypeLiteral.get( HasTypeParameters.class.getTypeParameters()[1] ) );
+ }
+
+ class HasTypeParameters<A, B extends List<A> & Runnable, C extends Runnable>
+ {
+ A a;
+
+ B b;
+
+ C c;
+ }
+
+}
Propchange: commons/sandbox/beanutils2/trunk/src/test/java/org/apache/commons/beanutils2/type/TypeLiteralTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: commons/sandbox/beanutils2/trunk/src/test/java/org/apache/commons/beanutils2/type/TypeLiteralTest.java
------------------------------------------------------------------------------
svn:keywords = Date Author Id Revision HeadURL
Propchange: commons/sandbox/beanutils2/trunk/src/test/java/org/apache/commons/beanutils2/type/TypeLiteralTest.java
------------------------------------------------------------------------------
svn:mime-type = text/plain