Bug 498757: extract re-usable TypeArguments utility methods
diff --git a/org.eclipse.sisu.plexus/src/org/eclipse/sisu/plexus/CompositeBeanHelper.java b/org.eclipse.sisu.plexus/src/org/eclipse/sisu/plexus/CompositeBeanHelper.java
index 7890527..4c9b963 100644
--- a/org.eclipse.sisu.plexus/src/org/eclipse/sisu/plexus/CompositeBeanHelper.java
+++ b/org.eclipse.sisu.plexus/src/org/eclipse/sisu/plexus/CompositeBeanHelper.java
@@ -11,14 +11,10 @@
package org.eclipse.sisu.plexus;
import java.lang.reflect.Field;
-import java.lang.reflect.GenericArrayType;
import java.lang.reflect.Member;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
-import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
-import java.lang.reflect.TypeVariable;
-import java.lang.reflect.WildcardType;
import java.security.AccessController;
import java.security.PrivilegedAction;
@@ -40,12 +36,6 @@
public final class CompositeBeanHelper
{
// ----------------------------------------------------------------------
- // Constants
- // ----------------------------------------------------------------------
-
- private static final Type[] NO_TYPES = {};
-
- // ----------------------------------------------------------------------
// Implementation fields
// ----------------------------------------------------------------------
@@ -264,7 +254,7 @@
final ConfigurationConverter converter = lookup.lookupConverterForType( rawPropertyType );
if ( !( genericPropertyType instanceof Class<?> ) && converter instanceof ParameterizedConfigurationConverter )
{
- final Type[] propertyTypeArgs = getTypeArguments( genericPropertyType );
+ final Type[] propertyTypeArgs = TypeArguments.get( genericPropertyType );
return ( (ParameterizedConfigurationConverter) converter ).fromConfiguration( lookup, configuration,
rawPropertyType,
propertyTypeArgs, beanType,
@@ -274,37 +264,6 @@
listener );
}
- private static Type[] getTypeArguments( final Type type )
- {
- if ( type instanceof ParameterizedType )
- {
- final Type[] typeArguments = ( (ParameterizedType) type ).getActualTypeArguments();
- for ( int i = 0; i < typeArguments.length; i++ )
- {
- typeArguments[i] = expandType( typeArguments[i] );
- }
- return typeArguments;
- }
- if ( type instanceof GenericArrayType )
- {
- return new Type[] { expandType( ( (GenericArrayType) type ).getGenericComponentType() ) };
- }
- return NO_TYPES;
- }
-
- private static Type expandType( final Type type )
- {
- if ( type instanceof WildcardType )
- {
- return ( (WildcardType) type ).getUpperBounds()[0];
- }
- if ( type instanceof TypeVariable<?> )
- {
- return ( (TypeVariable<?>) type ).getBounds()[0];
- }
- return type;
- }
-
private static Method findMethod( final Class<?> beanType, final Type[] paramTypeHolder, final String methodName )
{
for ( final Method m : beanType.getMethods() )
diff --git a/org.eclipse.sisu.plexus/src/org/eclipse/sisu/plexus/TypeArguments.java b/org.eclipse.sisu.plexus/src/org/eclipse/sisu/plexus/TypeArguments.java
new file mode 100644
index 0000000..e37609d
--- /dev/null
+++ b/org.eclipse.sisu.plexus/src/org/eclipse/sisu/plexus/TypeArguments.java
@@ -0,0 +1,115 @@
+/*******************************************************************************
+ * Copyright (c) 2010-present Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Stuart McCulloch (Sonatype, Inc.) - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.sisu.plexus;
+
+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;
+
+/**
+ * Utility methods for dealing with generic type arguments.
+ */
+public final class TypeArguments
+{
+ // ----------------------------------------------------------------------
+ // Constants
+ // ----------------------------------------------------------------------
+
+ private static final Type OBJECT_TYPE = Object.class;
+
+ private static final Type[] NO_TYPES = {};
+
+ // ----------------------------------------------------------------------
+ // Constructors
+ // ----------------------------------------------------------------------
+
+ private TypeArguments()
+ {
+ // static utility class, not allowed to create instances
+ }
+
+ // ----------------------------------------------------------------------
+ // Utility methods
+ // ----------------------------------------------------------------------
+
+ /**
+ * Get all type arguments from a generic type, for example {@code [Foo,Bar]} from {@code Map<Foo,Bar>}.
+ *
+ * @param type The generic type
+ * @return Array of type arguments
+ */
+ public static Type[] get( final Type type )
+ {
+ if ( type instanceof ParameterizedType )
+ {
+ final Type[] argumentTypes = ( (ParameterizedType) type ).getActualTypeArguments();
+ for ( int i = 0; i < argumentTypes.length; i++ )
+ {
+ argumentTypes[i] = expand( argumentTypes[i] );
+ }
+ return argumentTypes;
+ }
+ if ( type instanceof GenericArrayType )
+ {
+ return new Type[] { expand( ( (GenericArrayType) type ).getGenericComponentType() ) };
+ }
+ return NO_TYPES;
+ }
+
+ /**
+ * Get an indexed type argument from a generic type, for example {@code Bar} from {@code Map<Foo,Bar>}.
+ *
+ * @param type The generic type
+ * @param index The argument index
+ * @return Indexed type argument; {@code Object.class} if the given type is a raw class
+ */
+ public static Type get( final Type type, final int index )
+ {
+ if ( type instanceof ParameterizedType )
+ {
+ return expand( ( (ParameterizedType) type ).getActualTypeArguments()[index] );
+ }
+ if ( type instanceof GenericArrayType )
+ {
+ if ( 0 == index )
+ {
+ return expand( ( (GenericArrayType) type ).getGenericComponentType() );
+ }
+ throw new ArrayIndexOutOfBoundsException( index );
+ }
+ return OBJECT_TYPE;
+ }
+
+ // ----------------------------------------------------------------------
+ // Implementation methods
+ // ----------------------------------------------------------------------
+
+ /**
+ * Expands wild-card types where possible, for example {@code Bar} from {@code ? extends Bar}.
+ *
+ * @param type The generic type
+ * @return Widened type that is still assignment-compatible with the original.
+ */
+ private static Type expand( final Type type )
+ {
+ if ( type instanceof WildcardType )
+ {
+ return ( (WildcardType) type ).getUpperBounds()[0];
+ }
+ if ( type instanceof TypeVariable<?> )
+ {
+ return ( (TypeVariable<?>) type ).getBounds()[0];
+ }
+ return type;
+ }
+}