[SCM] Helper library for the Java 5 Type branch, upstream, updated. ae87e50125415b818406b61af9aea707eecf4abf
tony mancill
tmancill at debian.org
Wed May 8 04:14:57 UTC 2013
The following commit has been merged in the upstream branch:
commit ae87e50125415b818406b61af9aea707eecf4abf
Author: tony mancill <tmancill at debian.org>
Date: Tue May 7 21:13:21 2013 -0700
Imported Upstream version 0.1.3
diff --git a/pom.xml b/pom.xml
index 063803f..290a7e0 100644
--- a/pom.xml
+++ b/pom.xml
@@ -6,7 +6,7 @@
<groupId>com.googlecode.jtype</groupId>
<artifactId>jtype</artifactId>
<packaging>jar</packaging>
- <version>0.1.1</version>
+ <version>0.1.3</version>
<name>JType</name>
<description>Library for working with the Java 5 type system</description>
@@ -26,9 +26,9 @@
</licenses>
<scm>
- <connection>scm:svn:http://jtype.googlecode.com/svn/tags/0.1.1</connection>
- <developerConnection>scm:svn:https://jtype.googlecode.com/svn/tags/0.1.1</developerConnection>
- <url>http://code.google.com/p/jtype/source/browse/tags/0.1.1</url>
+ <connection>scm:svn:http://jtype.googlecode.com/svn/tags/0.1.3</connection>
+ <developerConnection>scm:svn:https://jtype.googlecode.com/svn/tags/0.1.3</developerConnection>
+ <url>http://code.google.com/p/jtype/source/browse/tags/0.1.3</url>
</scm>
<issueManagement>
@@ -100,6 +100,11 @@
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-release-plugin</artifactId>
+ <version>2.0-beta-9</version>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>2.4.1</version>
</plugin>
@@ -201,10 +206,15 @@
<distributionManagement>
<repository>
- <id>jtype</id>
- <name>JType Maven Repository</name>
- <url>svn:https://jtype.googlecode.com/svn/repository/</url>
+ <id>sonatype-nexus-staging</id>
+ <name>Sonatype Nexus Staging Repository</name>
+ <url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
</repository>
+ <snapshotRepository>
+ <id>sonatype-nexus-snapshots</id>
+ <name>Sonatype Nexus Snapshot Repository</name>
+ <url>https://oss.sonatype.org/content/repositories/snapshots/</url>
+ </snapshotRepository>
<site>
<id>jtype-site</id>
<name>JType Maven Site</name>
diff --git a/src/main/java/com/googlecode/jtype/AbstractTypeVisitor.java b/src/main/java/com/googlecode/jtype/AbstractTypeVisitor.java
new file mode 100644
index 0000000..e35dc99
--- /dev/null
+++ b/src/main/java/com/googlecode/jtype/AbstractTypeVisitor.java
@@ -0,0 +1,139 @@
+/*
+ * Copyright 2009 IIZUKA Software Technologies Ltd
+ *
+ * Licensed 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 com.googlecode.jtype;
+
+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;
+
+/**
+ *
+ *
+ * @author Mark Hobson
+ * @version $Id: AbstractTypeVisitor.java 73 2010-03-24 21:47:29Z markhobson $
+ */
+abstract class AbstractTypeVisitor implements TypeVisitor
+{
+ // TypeVisitor methods ----------------------------------------------------
+
+ /**
+ * {@inheritDoc}
+ */
+ public void visit(Class<?> type)
+ {
+ // no-op
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public <D extends GenericDeclaration> boolean beginVisit(TypeVariable<D> type)
+ {
+ return true;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void visitTypeVariableBound(Type bound, int index)
+ {
+ visit(bound);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public <D extends GenericDeclaration> void endVisit(TypeVariable<D> type)
+ {
+ // no-op
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void visit(GenericArrayType type)
+ {
+ visit(type.getGenericComponentType());
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean beginVisit(ParameterizedType type)
+ {
+ visit(type.getRawType());
+
+ return true;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void visitActualTypeArgument(Type type, int index)
+ {
+ visit(type);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void endVisit(ParameterizedType type)
+ {
+ // no-op
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean beginVisit(WildcardType type)
+ {
+ return true;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void visitUpperBound(Type bound, int index)
+ {
+ visit(bound);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void visitLowerBound(Type bound, int index)
+ {
+ visit(bound);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void endVisit(WildcardType type)
+ {
+ // no-op
+ }
+
+ // protected methods ------------------------------------------------------
+
+ protected void visit(Type type)
+ {
+ TypeUtils.accept(type, this);
+ }
+}
diff --git a/src/main/java/com/googlecode/jtype/ClassUtils.java b/src/main/java/com/googlecode/jtype/ClassUtils.java
index 0827341..db411ad 100644
--- a/src/main/java/com/googlecode/jtype/ClassUtils.java
+++ b/src/main/java/com/googlecode/jtype/ClassUtils.java
@@ -16,16 +16,24 @@
package com.googlecode.jtype;
import java.lang.reflect.Array;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
/**
* Provides utility methods for working with classes.
*
* @author Mark Hobson
- * @version $Id: ClassUtils.java 38 2009-08-26 11:21:03Z markhobson $
+ * @version $Id: ClassUtils.java 82 2010-11-01 11:22:10Z markhobson $
* @see Class
*/
final class ClassUtils
{
+ // constants --------------------------------------------------------------
+
+ private static final Map<String, String> PRIMITIVE_DESCRIPTORS_BY_CLASS_NAME =
+ createPrimitiveDescriptorsByClassName();
+
// constructors -----------------------------------------------------------
private ClassUtils()
@@ -68,4 +76,74 @@ final class ClassUtils
{
return Array.newInstance(componentType, 0).getClass();
}
+
+ public static Class<?> valueOf(String className)
+ {
+ if (isPrimitiveClassName(className))
+ {
+ return valueOfPrimitive(className);
+ }
+
+ ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
+
+ try
+ {
+ return Class.forName(className, true, classLoader);
+ }
+ catch (ClassNotFoundException exception)
+ {
+ return null;
+ }
+ }
+
+ // private methods --------------------------------------------------------
+
+ private static Map<String, String> createPrimitiveDescriptorsByClassName()
+ {
+ Map<String, String> primitiveDescriptorsByClassName = new HashMap<String, String>();
+
+ // from JVM specification 4.3.2
+ // see http://java.sun.com/docs/books/jvms/second_edition/html/ClassFile.doc.html#84645
+ primitiveDescriptorsByClassName.put("byte", "B");
+ primitiveDescriptorsByClassName.put("char", "C");
+ primitiveDescriptorsByClassName.put("double", "D");
+ primitiveDescriptorsByClassName.put("float", "F");
+ primitiveDescriptorsByClassName.put("int", "I");
+ primitiveDescriptorsByClassName.put("long", "J");
+ primitiveDescriptorsByClassName.put("short", "S");
+ primitiveDescriptorsByClassName.put("boolean", "Z");
+
+ return Collections.unmodifiableMap(primitiveDescriptorsByClassName);
+ }
+
+ private static Class<?> valueOfPrimitive(String className)
+ {
+ // cannot load primitives directly so load primitive array type and use component type instead
+
+ String descriptor = getPrimitiveDescriptor(className);
+ String arrayDescriptor = getArrayDescriptor(descriptor);
+ Class<?> arrayType = valueOf(arrayDescriptor);
+
+ return arrayType.getComponentType();
+ }
+
+ private static boolean isPrimitiveClassName(String className)
+ {
+ return PRIMITIVE_DESCRIPTORS_BY_CLASS_NAME.containsKey(className);
+ }
+
+ private static String getPrimitiveDescriptor(String className)
+ {
+ if (!isPrimitiveClassName(className))
+ {
+ throw new IllegalArgumentException("className is not a primitive class name: " + className);
+ }
+
+ return PRIMITIVE_DESCRIPTORS_BY_CLASS_NAME.get(className);
+ }
+
+ private static String getArrayDescriptor(String componentDescriptor)
+ {
+ return "[" + componentDescriptor;
+ }
}
diff --git a/src/main/java/com/googlecode/jtype/DefaultGenericArrayType.java b/src/main/java/com/googlecode/jtype/DefaultGenericArrayType.java
index 0169553..7469884 100644
--- a/src/main/java/com/googlecode/jtype/DefaultGenericArrayType.java
+++ b/src/main/java/com/googlecode/jtype/DefaultGenericArrayType.java
@@ -15,6 +15,9 @@
*/
package com.googlecode.jtype;
+import static com.googlecode.jtype.Utils.checkNotNull;
+
+import java.io.Serializable;
import java.lang.reflect.GenericArrayType;
import java.lang.reflect.Type;
@@ -22,22 +25,29 @@ import java.lang.reflect.Type;
* Default implementation of a generic array type.
*
* @author Mark Hobson
- * @version $Id: DefaultGenericArrayType.java 2 2009-02-02 22:28:39Z markhobson $
+ * @version $Id: DefaultGenericArrayType.java 110 2011-11-23 17:19:43Z markhobson $
* @see GenericArrayType
*/
-class DefaultGenericArrayType implements GenericArrayType
+class DefaultGenericArrayType implements GenericArrayType, Serializable
{
- // TODO: make serializable?
+ // constants --------------------------------------------------------------
+
+ private static final long serialVersionUID = 1L;
// fields -----------------------------------------------------------------
+ /**
+ * The component type of this array.
+ *
+ * @serial
+ */
private final Type componentType;
// constructors -----------------------------------------------------------
public DefaultGenericArrayType(Type componentType)
{
- this.componentType = Utils.checkNotNull(componentType, "componentType");
+ this.componentType = checkNotNull(componentType, "componentType");
}
// GenericArrayType methods -----------------------------------------------
@@ -83,18 +93,6 @@ class DefaultGenericArrayType implements GenericArrayType
@Override
public String toString()
{
- return toString(this);
- }
-
- // public methods ---------------------------------------------------------
-
- public static String toString(GenericArrayType type)
- {
- return toString(type, ClassSerializers.QUALIFIED);
- }
-
- public static String toString(GenericArrayType type, ClassSerializer serializer)
- {
- return TypeUtils.toString(type.getGenericComponentType(), serializer) + "[]";
+ return TypeUtils.toString(this);
}
}
diff --git a/src/main/java/com/googlecode/jtype/DefaultParameterizedType.java b/src/main/java/com/googlecode/jtype/DefaultParameterizedType.java
index 783aeae..c181d11 100644
--- a/src/main/java/com/googlecode/jtype/DefaultParameterizedType.java
+++ b/src/main/java/com/googlecode/jtype/DefaultParameterizedType.java
@@ -15,6 +15,11 @@
*/
package com.googlecode.jtype;
+import static com.googlecode.jtype.Utils.checkNotNull;
+import static com.googlecode.jtype.Utils.nullEquals;
+import static com.googlecode.jtype.Utils.nullHashCode;
+
+import java.io.Serializable;
import java.lang.reflect.MalformedParameterizedTypeException;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
@@ -25,26 +30,43 @@ import java.util.Arrays;
* Default implementation of a parameterized type.
*
* @author Mark Hobson
- * @version $Id: DefaultParameterizedType.java 35 2009-07-03 10:14:37Z markhobson $
+ * @version $Id: DefaultParameterizedType.java 110 2011-11-23 17:19:43Z markhobson $
* @see ParameterizedType
*/
-class DefaultParameterizedType implements ParameterizedType
+class DefaultParameterizedType implements ParameterizedType, Serializable
{
- // TODO: make serializable?
+ // constants --------------------------------------------------------------
+
+ private static final long serialVersionUID = 1L;
// fields -----------------------------------------------------------------
+ /**
+ * The type that this type is a member of.
+ *
+ * @serial
+ */
private final Type ownerType;
+ /**
+ * The class or interface that declared this type.
+ *
+ * @serial
+ */
private final Type rawType;
+ /**
+ * The types representing the actual type arguments to this type.
+ *
+ * @serial
+ */
private final Type[] actualTypeArguments;
// constructors -----------------------------------------------------------
public DefaultParameterizedType(Type ownerType, Class<?> rawType, Type[] actualTypeArguments)
{
- this.rawType = Utils.checkNotNull(rawType, "rawType");
+ this.rawType = checkNotNull(rawType, "rawType");
if (actualTypeArguments == null)
{
@@ -53,6 +75,12 @@ class DefaultParameterizedType implements ParameterizedType
TypeVariable<?>[] typeParameters = rawType.getTypeParameters();
+ // disallow unparameterized raw types
+ if (typeParameters.length == 0)
+ {
+ throw new MalformedParameterizedTypeException();
+ }
+
if (typeParameters.length != actualTypeArguments.length)
{
throw new MalformedParameterizedTypeException();
@@ -101,7 +129,7 @@ class DefaultParameterizedType implements ParameterizedType
@Override
public int hashCode()
{
- int hashCode = Utils.nullHashCode(ownerType);
+ int hashCode = nullHashCode(ownerType);
hashCode = (37 * hashCode) + rawType.hashCode();
hashCode = (37 * hashCode) + Arrays.hashCode(actualTypeArguments);
@@ -126,7 +154,7 @@ class DefaultParameterizedType implements ParameterizedType
return true;
}
- return Utils.nullEquals(ownerType, type.getOwnerType())
+ return nullEquals(ownerType, type.getOwnerType())
&& rawType.equals(type.getRawType())
&& Arrays.equals(actualTypeArguments, type.getActualTypeArguments());
}
@@ -137,61 +165,6 @@ class DefaultParameterizedType implements ParameterizedType
@Override
public String toString()
{
- return toString(this);
- }
-
- // public methods ---------------------------------------------------------
-
- public static String toString(ParameterizedType type)
- {
- return toString(type, ClassSerializers.QUALIFIED);
- }
-
- public static String toString(ParameterizedType type, ClassSerializer serializer)
- {
- StringBuilder builder = new StringBuilder();
-
- Type ownerType = type.getOwnerType();
- String rawTypeString = TypeUtils.toString(type.getRawType(), serializer);
-
- if (ownerType != null)
- {
- String ownerTypeString = TypeUtils.toString(ownerType, serializer);
-
- builder.append(ownerTypeString);
-
- if (rawTypeString.startsWith(ownerTypeString))
- {
- // use simple name for member types
- rawTypeString = rawTypeString.substring(ownerTypeString.length());
- }
- else
- {
- builder.append(".");
- }
- }
-
- builder.append(rawTypeString);
-
- Type[] actualTypeArguments = type.getActualTypeArguments();
-
- if (actualTypeArguments != null && actualTypeArguments.length > 0)
- {
- builder.append("<");
-
- for (int i = 0; i < actualTypeArguments.length; i++)
- {
- if (i > 0)
- {
- builder.append(",");
- }
-
- builder.append(TypeUtils.toString(actualTypeArguments[i], serializer));
- }
-
- builder.append(">");
- }
-
- return builder.toString();
+ return TypeUtils.toString(this);
}
}
diff --git a/src/main/java/com/googlecode/jtype/DefaultTypeVariable.java b/src/main/java/com/googlecode/jtype/DefaultTypeVariable.java
index 68775ef..1f31bf2 100644
--- a/src/main/java/com/googlecode/jtype/DefaultTypeVariable.java
+++ b/src/main/java/com/googlecode/jtype/DefaultTypeVariable.java
@@ -15,6 +15,10 @@
*/
package com.googlecode.jtype;
+import static com.googlecode.jtype.Utils.checkNotNull;
+import static com.googlecode.jtype.Utils.checkTrue;
+
+import java.io.Serializable;
import java.lang.reflect.GenericDeclaration;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
@@ -25,25 +29,40 @@ import java.util.Arrays;
* Default implementation of a type variable.
*
* @author Mark Hobson
- * @version $Id: DefaultTypeVariable.java 42 2009-10-02 14:54:54Z markhobson $
+ * @version $Id: DefaultTypeVariable.java 110 2011-11-23 17:19:43Z markhobson $
* @param <D>
* the type of generic declaration that declared the type variable
* @see TypeVariable
*/
-class DefaultTypeVariable<D extends GenericDeclaration> implements TypeVariable<D>
+class DefaultTypeVariable<D extends GenericDeclaration> implements TypeVariable<D>, Serializable
{
- // TODO: make serializable?
-
// constants --------------------------------------------------------------
private static final Type[] DEFAULT_BOUNDS = new Type[] {Object.class};
+ private static final long serialVersionUID = 1L;
+
// fields -----------------------------------------------------------------
+ /**
+ * The generic declaration that declared this type variable.
+ *
+ * @serial
+ */
private final D declaration;
+ /**
+ * The name of this type variable, as it occurs in the source code.
+ *
+ * @serial
+ */
private final String name;
+ /**
+ * The upper bound(s) of this type variable.
+ *
+ * @serial
+ */
private final Type[] bounds;
// constructors -----------------------------------------------------------
@@ -57,15 +76,14 @@ class DefaultTypeVariable<D extends GenericDeclaration> implements TypeVariable<
// initial bound must be either a class type, an interface type or a type variable
- Utils.checkTrue(isValidFirstBound(bounds[0]), "First bound must be either a class type, an interface type or a "
- + "type variable", bounds[0]);
+ checkTrue(isValidFirstBound(bounds[0]), "First bound must be either a class type, an interface type or a type "
+ + "variable", bounds[0]);
// subsequent bounds must be an interface type
for (int i = 1; i < bounds.length; i++)
{
- Utils.checkTrue(isValidSecondaryBound(bounds[i]), "Secondary bounds must be an interface type: ",
- bounds[i]);
+ checkTrue(isValidSecondaryBound(bounds[i]), "Secondary bounds must be an interface type: ", bounds[i]);
}
// TODO: the erasures of all constituent types of a bound must be pairwise different
@@ -73,8 +91,8 @@ class DefaultTypeVariable<D extends GenericDeclaration> implements TypeVariable<
// TODO: type variable may not be a subtype of two interface types which are different parameterizations of the
// same generic interface
- this.declaration = Utils.checkNotNull(declaration, "declaration");
- this.name = Utils.checkNotNull(name, "name");
+ this.declaration = checkNotNull(declaration, "declaration");
+ this.name = checkNotNull(name, "name");
this.bounds = bounds.clone();
}
@@ -143,30 +161,7 @@ class DefaultTypeVariable<D extends GenericDeclaration> implements TypeVariable<
@Override
public String toString()
{
- return toString(this);
- }
-
- // public methods ---------------------------------------------------------
-
- public static String toString(TypeVariable<?> type)
- {
- return toString(type, ClassSerializers.QUALIFIED);
- }
-
- public static String toString(TypeVariable<?> type, ClassSerializer serializer)
- {
- StringBuilder builder = new StringBuilder();
-
- builder.append(type.getName());
-
- if (!Arrays.equals(DEFAULT_BOUNDS, type.getBounds()))
- {
- builder.append(" extends ");
-
- TypeUtils.appendBounds(builder, type.getBounds(), serializer);
- }
-
- return builder.toString();
+ return TypeUtils.toString(this);
}
// private methods --------------------------------------------------------
diff --git a/src/main/java/com/googlecode/jtype/DefaultWildcardType.java b/src/main/java/com/googlecode/jtype/DefaultWildcardType.java
index 409f27d..9f910ab 100644
--- a/src/main/java/com/googlecode/jtype/DefaultWildcardType.java
+++ b/src/main/java/com/googlecode/jtype/DefaultWildcardType.java
@@ -15,6 +15,9 @@
*/
package com.googlecode.jtype;
+import static com.googlecode.jtype.Utils.checkFalse;
+
+import java.io.Serializable;
import java.lang.reflect.Type;
import java.lang.reflect.WildcardType;
import java.util.Arrays;
@@ -23,23 +26,33 @@ import java.util.Arrays;
* Default implementation of a wildcard type.
*
* @author Mark Hobson
- * @version $Id: DefaultWildcardType.java 2 2009-02-02 22:28:39Z markhobson $
+ * @version $Id: DefaultWildcardType.java 110 2011-11-23 17:19:43Z markhobson $
* @see WildcardType
*/
-class DefaultWildcardType implements WildcardType
+class DefaultWildcardType implements WildcardType, Serializable
{
- // TODO: make serializable?
-
// constants --------------------------------------------------------------
private static final Type[] DEFAULT_UPPER_BOUNDS = new Type[] {Object.class};
private static final Type[] DEFAULT_LOWER_BOUNDS = new Type[0];
+ private static final long serialVersionUID = 1L;
+
// fields -----------------------------------------------------------------
+ /**
+ * The upper bound(s) of this type variable.
+ *
+ * @serial
+ */
private final Type[] upperBounds;
+ /**
+ * The lower bound(s) of this type variable.
+ *
+ * @serial
+ */
private final Type[] lowerBounds;
// constructors -----------------------------------------------------------
@@ -61,7 +74,7 @@ class DefaultWildcardType implements WildcardType
boolean hasUpperBounds = !Arrays.equals(this.upperBounds, DEFAULT_UPPER_BOUNDS);
boolean hasLowerBounds = !Arrays.equals(this.lowerBounds, DEFAULT_LOWER_BOUNDS);
- Utils.checkFalse(hasUpperBounds && hasLowerBounds, "Wildcard type cannot have both upper and lower bounds");
+ checkFalse(hasUpperBounds && hasLowerBounds, "Wildcard type cannot have both upper and lower bounds");
}
// WildcardType methods ---------------------------------------------------
@@ -116,38 +129,6 @@ class DefaultWildcardType implements WildcardType
@Override
public String toString()
{
- return toString(this);
- }
-
- // public methods ---------------------------------------------------------
-
- public static String toString(WildcardType type)
- {
- return toString(type, ClassSerializers.QUALIFIED);
- }
-
- public static String toString(WildcardType type, ClassSerializer serializer)
- {
- StringBuilder builder = new StringBuilder();
-
- builder.append("?");
-
- Type[] lowerBounds = type.getLowerBounds();
- Type[] upperBounds = type.getUpperBounds();
-
- if (!Arrays.equals(DEFAULT_LOWER_BOUNDS, lowerBounds))
- {
- builder.append(" super ");
-
- TypeUtils.appendBounds(builder, lowerBounds, serializer);
- }
- else if (!Arrays.equals(DEFAULT_UPPER_BOUNDS, upperBounds))
- {
- builder.append(" extends ");
-
- TypeUtils.appendBounds(builder, upperBounds, serializer);
- }
-
- return builder.toString();
+ return TypeUtils.toString(this);
}
}
diff --git a/src/main/java/com/googlecode/jtype/Generic.java b/src/main/java/com/googlecode/jtype/Generic.java
index bc689fc..3816d50 100644
--- a/src/main/java/com/googlecode/jtype/Generic.java
+++ b/src/main/java/com/googlecode/jtype/Generic.java
@@ -15,11 +15,19 @@
*/
package com.googlecode.jtype;
+import static com.googlecode.jtype.Utils.checkFalse;
+import static com.googlecode.jtype.Utils.checkNotNull;
+import static com.googlecode.jtype.Utils.checkTrue;
+
+import java.io.Serializable;
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.Collections;
+import java.util.HashMap;
+import java.util.Map;
/**
* Provides a generic type literal.
@@ -44,15 +52,13 @@ import java.lang.reflect.WildcardType;
* {@code add(new ArrayList<String>(), new Generic<List<String>>() }<code>{});</code>
*
* @author Mark Hobson
- * @version $Id: Generic.java 47 2009-10-02 15:59:23Z markhobson $
+ * @version $Id: Generic.java 110 2011-11-23 17:19:43Z markhobson $
* @param <T> the type that this generic type literal represents
* @see Generics
* @see <a href="http://gafter.blogspot.com/2006/12/super-type-tokens.html">Neal Gafter's blog: Super Type Tokens</a>
*/
-public abstract class Generic<T>
+public abstract class Generic<T> implements Serializable
{
- // TODO: make serializable?
-
// classes ----------------------------------------------------------------
private static final class DefaultGeneric<T> extends Generic<T>
@@ -63,8 +69,30 @@ public abstract class Generic<T>
}
}
+ /**
+ * Simple read-only cache for common generics. Implemented as an inner class for lazy instantiation.
+ */
+ private static class GenericCache
+ {
+ private static final Map<Type, Generic<?>> GENERICS_BY_TYPE = createCache();
+
+ public static Generic<?> get(Type type)
+ {
+ return GENERICS_BY_TYPE.get(type);
+ }
+ }
+
+ // constants --------------------------------------------------------------
+
+ private static final long serialVersionUID = 1L;
+
// fields -----------------------------------------------------------------
+ /**
+ * The type that this generic type literal represents.
+ *
+ * @serial
+ */
private final Type type;
// constructors -----------------------------------------------------------
@@ -105,17 +133,33 @@ public abstract class Generic<T>
public static <T> Generic<T> get(Class<T> klass)
{
- return new DefaultGeneric<T>(klass);
+ // guaranteed by definition
+ @SuppressWarnings("unchecked")
+ Generic<T> generic = (Generic<T>) get((Type) klass);
+
+ return generic;
}
public static Generic<?> get(Type type)
{
- return new DefaultGeneric<Object>(type);
+ Generic<?> generic = GenericCache.get(type);
+
+ if (generic == null)
+ {
+ generic = create(type);
+ }
+
+ return generic;
}
@SuppressWarnings("unchecked")
public static <T> Generic<? extends T> get(Class<T> rawType, Type... actualTypeArguments)
{
+ if (actualTypeArguments == null || actualTypeArguments.length == 0)
+ {
+ return get(rawType);
+ }
+
ParameterizedType paramType = Types.parameterizedType(rawType, actualTypeArguments);
return (Generic<? extends T>) get(paramType);
@@ -164,13 +208,42 @@ public abstract class Generic<T>
// private methods --------------------------------------------------------
+ private static Map<Type, Generic<?>> createCache()
+ {
+ Map<Type, Generic<?>> genericsByType = new HashMap<Type, Generic<?>>();
+
+ putCacheEntry(genericsByType, Object.class);
+
+ putCacheEntry(genericsByType, Boolean.class);
+ putCacheEntry(genericsByType, Byte.class);
+ putCacheEntry(genericsByType, Character.class);
+ putCacheEntry(genericsByType, Double.class);
+ putCacheEntry(genericsByType, Float.class);
+ putCacheEntry(genericsByType, Integer.class);
+ putCacheEntry(genericsByType, Long.class);
+ putCacheEntry(genericsByType, Short.class);
+ putCacheEntry(genericsByType, String.class);
+
+ return Collections.unmodifiableMap(genericsByType);
+ }
+
+ private static void putCacheEntry(Map<Type, Generic<?>> genericsByType, Type type)
+ {
+ genericsByType.put(type, create(type));
+ }
+
+ private static Generic<Object> create(Type type)
+ {
+ return new DefaultGeneric<Object>(type);
+ }
+
private static void validateType(Type type)
{
- Utils.checkNotNull(type, "type");
- Utils.checkFalse(type instanceof TypeVariable<?>, "Type variables are not supported: ", type);
- Utils.checkFalse(type instanceof WildcardType, "Wildcard types are not supported: ", type);
- Utils.checkTrue(type instanceof Class<?> || type instanceof ParameterizedType
- || type instanceof GenericArrayType, "Unsupported type: ", type);
+ checkNotNull(type, "type");
+ checkFalse(type instanceof TypeVariable<?>, "Type variables are not supported: ", type);
+ checkFalse(type instanceof WildcardType, "Wildcard types are not supported: ", type);
+ checkTrue(type instanceof Class<?> || type instanceof ParameterizedType || type instanceof GenericArrayType,
+ "Unsupported type: ", type);
}
private Type getActualTypeArgument()
diff --git a/src/main/java/com/googlecode/jtype/Generics.java b/src/main/java/com/googlecode/jtype/Generics.java
index d7bf2d1..7f6bd56 100644
--- a/src/main/java/com/googlecode/jtype/Generics.java
+++ b/src/main/java/com/googlecode/jtype/Generics.java
@@ -31,12 +31,52 @@ import java.util.SortedSet;
* Factory for creating common generics.
*
* @author Mark Hobson
- * @version $Id: Generics.java 2 2009-02-02 22:28:39Z markhobson $
+ * @version $Id: Generics.java 86 2010-11-05 13:23:09Z markhobson $
* @see Generic
*/
@SuppressWarnings("unchecked")
public final class Generics
{
+ // constants --------------------------------------------------------------
+
+ private static final Generic<Comparable<?>> COMPARABLE = (Generic<Comparable<?>>) Generic.get(Comparable.class,
+ Types.unboundedWildcardType());
+
+ private static final Generic<Comparator<?>> COMPARATOR = (Generic<Comparator<?>>) Generic.get(Comparator.class,
+ Types.unboundedWildcardType());
+
+ private static final Generic<Enumeration<?>> ENUMERATION = (Generic<Enumeration<?>>) Generic.get(Enumeration.class,
+ Types.unboundedWildcardType());
+
+ private static final Generic<Iterable<?>> ITERABLE = (Generic<Iterable<?>>) Generic.get(Iterable.class,
+ Types.unboundedWildcardType());
+
+ private static final Generic<Iterator<?>> ITERATOR = (Generic<Iterator<?>>) Generic.get(Iterator.class,
+ Types.unboundedWildcardType());
+
+ private static final Generic<ListIterator<?>> LIST_ITERATOR = (Generic<ListIterator<?>>) Generic.get(
+ ListIterator.class, Types.unboundedWildcardType());
+
+ private static final Generic<Collection<?>> COLLECTION = (Generic<Collection<?>>) Generic.get(Collection.class,
+ Types.unboundedWildcardType());
+
+ private static final Generic<Set<?>> SET = (Generic<Set<?>>) Generic.get(Set.class, Types.unboundedWildcardType());
+
+ private static final Generic<SortedSet<?>> SORTED_SET = (Generic<SortedSet<?>>) Generic.get(SortedSet.class,
+ Types.unboundedWildcardType());
+
+ private static final Generic<List<?>> LIST = (Generic<List<?>>) Generic.get(List.class,
+ Types.unboundedWildcardType());
+
+ private static final Generic<Map<?, ?>> MAP = (Generic<Map<?, ?>>) Generic.get(Map.class,
+ Types.unboundedWildcardType(), Types.unboundedWildcardType());
+
+ private static final Generic<SortedMap<?, ?>> SORTED_MAP = (Generic<SortedMap<?, ?>>) Generic.get(SortedMap.class,
+ Types.unboundedWildcardType(), Types.unboundedWildcardType());
+
+ private static final Generic<Queue<?>> QUEUE = (Generic<Queue<?>>) Generic.get(Queue.class,
+ Types.unboundedWildcardType());
+
// constructors -----------------------------------------------------------
private Generics()
@@ -46,56 +86,131 @@ public final class Generics
// public methods ---------------------------------------------------------
+ public static Generic<Comparable<?>> comparable()
+ {
+ return COMPARABLE;
+ }
+
+ public static <T> Generic<Comparable<T>> comparable(Class<T> type)
+ {
+ return (Generic<Comparable<T>>) Generic.get(Comparable.class, type);
+ }
+
+ public static Generic<Comparator<?>> comparator()
+ {
+ return COMPARATOR;
+ }
+
public static <T> Generic<Comparator<T>> comparator(Class<T> type)
{
return (Generic<Comparator<T>>) Generic.get(Comparator.class, type);
}
+ public static Generic<Enumeration<?>> enumeration()
+ {
+ return ENUMERATION;
+ }
+
public static <E> Generic<Enumeration<E>> enumeration(Class<E> elementClass)
{
return (Generic<Enumeration<E>>) Generic.get(Enumeration.class, elementClass);
}
+ public static Generic<Iterable<?>> iterable()
+ {
+ return ITERABLE;
+ }
+
+ public static <T> Generic<Iterable<T>> iterable(Class<T> elementClass)
+ {
+ return (Generic<Iterable<T>>) Generic.get(Iterable.class, elementClass);
+ }
+
+ public static Generic<Iterator<?>> iterator()
+ {
+ return ITERATOR;
+ }
+
public static <E> Generic<Iterator<E>> iterator(Class<E> elementClass)
{
return (Generic<Iterator<E>>) Generic.get(Iterator.class, elementClass);
}
+ public static Generic<ListIterator<?>> listIterator()
+ {
+ return LIST_ITERATOR;
+ }
+
public static <E> Generic<ListIterator<E>> listIterator(Class<E> elementClass)
{
return (Generic<ListIterator<E>>) Generic.get(ListIterator.class, elementClass);
}
+ public static Generic<Collection<?>> collection()
+ {
+ return COLLECTION;
+ }
+
public static <E> Generic<Collection<E>> collection(Class<E> elementClass)
{
return (Generic<Collection<E>>) Generic.get(Collection.class, elementClass);
}
+ public static Generic<Set<?>> set()
+ {
+ return SET;
+ }
+
public static <E> Generic<Set<E>> set(Class<E> elementClass)
{
return (Generic<Set<E>>) Generic.get(Set.class, elementClass);
}
+ public static Generic<SortedSet<?>> sortedSet()
+ {
+ return SORTED_SET;
+ }
+
public static <E> Generic<SortedSet<E>> sortedSet(Class<E> elementClass)
{
return (Generic<SortedSet<E>>) Generic.get(SortedSet.class, elementClass);
}
+ public static Generic<List<?>> list()
+ {
+ return LIST;
+ }
+
public static <E> Generic<List<E>> list(Class<E> elementClass)
{
return (Generic<List<E>>) Generic.get(List.class, elementClass);
}
+ public static Generic<Map<?, ?>> map()
+ {
+ return MAP;
+ }
+
public static <K, V> Generic<Map<K, V>> map(Class<K> keyClass, Class<V> valueClass)
{
return (Generic<Map<K, V>>) Generic.get(Map.class, keyClass, valueClass);
}
+ public static Generic<SortedMap<?, ?>> sortedMap()
+ {
+ return SORTED_MAP;
+ }
+
public static <K, V> Generic<SortedMap<K, V>> sortedMap(Class<K> keyClass, Class<V> valueClass)
{
return (Generic<SortedMap<K, V>>) Generic.get(SortedMap.class, keyClass, valueClass);
}
+ public static Generic<Queue<?>> queue()
+ {
+ return QUEUE;
+ }
+
public static <E> Generic<Queue<E>> queue(Class<E> elementClass)
{
return (Generic<Queue<E>>) Generic.get(Queue.class, elementClass);
diff --git a/src/main/java/com/googlecode/jtype/SerializingTypeVisitor.java b/src/main/java/com/googlecode/jtype/SerializingTypeVisitor.java
new file mode 100644
index 0000000..3e0d453
--- /dev/null
+++ b/src/main/java/com/googlecode/jtype/SerializingTypeVisitor.java
@@ -0,0 +1,205 @@
+/*
+ * Copyright 2009 IIZUKA Software Technologies Ltd
+ *
+ * Licensed 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 com.googlecode.jtype;
+
+import static com.googlecode.jtype.Utils.checkNotNull;
+
+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;
+
+/**
+ *
+ *
+ * @author Mark Hobson
+ * @version $Id: SerializingTypeVisitor.java 110 2011-11-23 17:19:43Z markhobson $
+ */
+class SerializingTypeVisitor extends AbstractTypeVisitor
+{
+ // fields -----------------------------------------------------------------
+
+ private final ClassSerializer serializer;
+
+ private final StringBuilder builder;
+
+ // constructors -----------------------------------------------------------
+
+ public SerializingTypeVisitor(ClassSerializer serializer)
+ {
+ checkNotNull(serializer, "serializer");
+
+ this.serializer = serializer;
+
+ builder = new StringBuilder();
+ }
+
+ // TypeVisitor methods ----------------------------------------------------
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void visit(Class<?> type)
+ {
+ if (type.isArray())
+ {
+ visit(type.getComponentType());
+
+ builder.append("[]");
+ }
+ else
+ {
+ builder.append(serializer.toString(type));
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public <D extends GenericDeclaration> boolean beginVisit(TypeVariable<D> type)
+ {
+ builder.append(type.getName());
+
+ return true;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void visitTypeVariableBound(Type bound, int index)
+ {
+ if (!(bound == Object.class && index == 0))
+ {
+ builder.append((index == 0) ? " extends " : " & ");
+
+ visit(bound);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void visit(GenericArrayType type)
+ {
+ visit(type.getGenericComponentType());
+
+ builder.append("[]");
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean beginVisit(ParameterizedType type)
+ {
+ Type ownerType = type.getOwnerType();
+
+ if (ownerType != null)
+ {
+ visit(ownerType);
+
+ builder.append(".");
+ }
+
+ visit(type.getRawType());
+
+ if (type.getActualTypeArguments().length > 0)
+ {
+ builder.append("<");
+ }
+
+ return true;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void visitActualTypeArgument(Type type, int index)
+ {
+ if (index > 0)
+ {
+ builder.append(", ");
+ }
+
+ visit(type);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void endVisit(ParameterizedType type)
+ {
+ if (type.getActualTypeArguments().length > 0)
+ {
+ builder.append(">");
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean beginVisit(WildcardType type)
+ {
+ builder.append("?");
+
+ return true;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void visitUpperBound(Type bound, int index)
+ {
+ if (!(bound == Object.class && index == 0))
+ {
+ builder.append((index == 0) ? " extends " : " & ");
+
+ visit(bound);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void visitLowerBound(Type bound, int index)
+ {
+ builder.append((index == 0) ? " super " : " & ");
+
+ visit(bound);
+ }
+
+ // Object methods ---------------------------------------------------------
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String toString()
+ {
+ return builder.toString();
+ }
+}
diff --git a/src/main/java/com/googlecode/jtype/TypeUtils.java b/src/main/java/com/googlecode/jtype/TypeUtils.java
index 85a6632..addd65d 100644
--- a/src/main/java/com/googlecode/jtype/TypeUtils.java
+++ b/src/main/java/com/googlecode/jtype/TypeUtils.java
@@ -15,6 +15,9 @@
*/
package com.googlecode.jtype;
+import static com.googlecode.jtype.Utils.checkNotNull;
+import static com.googlecode.jtype.Utils.checkTrue;
+
import java.io.Serializable;
import java.lang.reflect.GenericArrayType;
import java.lang.reflect.MalformedParameterizedTypeException;
@@ -27,14 +30,14 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.Map;
-import java.util.Set;
import java.util.Map.Entry;
+import java.util.Set;
/**
* Provides utility methods for working with types.
*
* @author Mark Hobson
- * @version $Id: TypeUtils.java 49 2009-10-07 17:10:57Z markhobson $
+ * @version $Id: TypeUtils.java 113 2011-11-25 18:14:23Z markhobson at gmail.com $
*/
public final class TypeUtils
{
@@ -68,10 +71,92 @@ public final class TypeUtils
// public methods ---------------------------------------------------------
+ public static void accept(Type type, TypeVisitor visitor)
+ {
+ checkNotNull(type, "type");
+ checkNotNull(visitor, "visitor");
+
+ if (type instanceof Class<?>)
+ {
+ visitor.visit((Class<?>) type);
+ }
+ else if (type instanceof TypeVariable<?>)
+ {
+ TypeVariable<?> typeVariable = (TypeVariable<?>) type;
+
+ if (visitor.beginVisit(typeVariable))
+ {
+ // visit bounds
+
+ Type[] bounds = typeVariable.getBounds();
+
+ for (int i = 0; i < bounds.length; i++)
+ {
+ visitor.visitTypeVariableBound(bounds[i], i);
+ }
+ }
+
+ visitor.endVisit(typeVariable);
+ }
+ else if (type instanceof GenericArrayType)
+ {
+ visitor.visit((GenericArrayType) type);
+ }
+ else if (type instanceof ParameterizedType)
+ {
+ ParameterizedType parameterizedType = (ParameterizedType) type;
+
+ if (visitor.beginVisit(parameterizedType))
+ {
+ // visit actual type arguments
+
+ Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
+
+ for (int i = 0; i < actualTypeArguments.length; i++)
+ {
+ visitor.visitActualTypeArgument(actualTypeArguments[i], i);
+ }
+ }
+
+ visitor.endVisit(parameterizedType);
+ }
+ else if (type instanceof WildcardType)
+ {
+ WildcardType wildcardType = (WildcardType) type;
+
+ if (visitor.beginVisit(wildcardType))
+ {
+ // visit upper bounds
+
+ Type[] upperBounds = wildcardType.getUpperBounds();
+
+ for (int i = 0; i < upperBounds.length; i++)
+ {
+ visitor.visitUpperBound(upperBounds[i], i);
+ }
+
+ // visit lower bounds
+
+ Type[] lowerBounds = wildcardType.getLowerBounds();
+
+ for (int i = 0; i < lowerBounds.length; i++)
+ {
+ visitor.visitLowerBound(lowerBounds[i], i);
+ }
+ }
+
+ visitor.endVisit(wildcardType);
+ }
+ else
+ {
+ throw new IllegalArgumentException("Unknown type: " + type);
+ }
+ }
+
public static boolean isAssignable(Type supertype, Type type)
{
- Utils.checkNotNull(supertype, "supertype");
- Utils.checkNotNull(type, "type");
+ checkNotNull(supertype, "supertype");
+ checkNotNull(type, "type");
if (supertype.equals(type))
{
@@ -105,6 +190,11 @@ public final class TypeUtils
return isArraySupertype((Class<?>) supertype);
}
+ if (type instanceof WildcardType)
+ {
+ return isClassAssignableToWildcardType((Class<?>) supertype, (WildcardType) type);
+ }
+
return false;
}
@@ -194,7 +284,7 @@ public final class TypeUtils
public static Class<?> getErasedReferenceType(Type type)
{
- Utils.checkTrue(isReferenceType(type), "type is not a reference type: ", type);
+ checkTrue(isReferenceType(type), "type is not a reference type: ", type);
return (Class<?>) getErasedType(type);
}
@@ -214,6 +304,11 @@ public final class TypeUtils
|| (type instanceof GenericArrayType);
}
+ public static boolean isPrimitive(Type type)
+ {
+ return (type instanceof Class<?>) && ((Class<?>) type).isPrimitive();
+ }
+
public static Type getComponentType(Type type)
{
if (type instanceof Class<?>)
@@ -233,7 +328,7 @@ public final class TypeUtils
public static Type getArrayType(Type componentType)
{
- Utils.checkNotNull(componentType, "componentType");
+ checkNotNull(componentType, "componentType");
if (componentType instanceof Class<?>)
{
@@ -243,53 +338,68 @@ public final class TypeUtils
return Types.genericArrayType(componentType);
}
- public static boolean isSimpleParameterizedType(Type type, Class<?> rawType)
+ public static boolean isParameterizedType(Type type, Class<?> rawType)
{
- Utils.checkNotNull(type, "type");
- Utils.checkNotNull(rawType, "rawType");
+ checkNotNull(type, "type");
+ checkNotNull(rawType, "rawType");
- if (!(type instanceof ParameterizedType))
+ ParameterizedType parameterizedType;
+
+ try
{
- return false;
+ parameterizedType = Types.unboundedParameterizedType(rawType);
}
-
- ParameterizedType paramType = (ParameterizedType) type;
-
- Type paramRawType = paramType.getRawType();
-
- if (!(paramRawType instanceof Class<?>))
+ catch (MalformedParameterizedTypeException exception)
{
return false;
}
- Class<?> paramRawClass = (Class<?>) paramRawType;
-
- if (!rawType.isAssignableFrom(paramRawClass))
+ return isAssignable(parameterizedType, type);
+ }
+
+ /**
+ * @deprecated Use {@link #isParameterizedType(Type, Class)} instead.
+ */
+ @Deprecated
+ public static boolean isSimpleParameterizedType(Type type, Class<?> rawType)
+ {
+ if (!isParameterizedType(type, rawType))
{
return false;
}
- Type[] typeArgs = paramType.getActualTypeArguments();
+ Type[] typeArgs = ((ParameterizedType) type).getActualTypeArguments();
return (typeArgs.length == 1);
}
+ /**
+ * @deprecated Use {@link #getActualTypeArgument(Type, int)} instead.
+ */
+ @Deprecated
public static Type getActualTypeArgument(Type type)
{
- Utils.checkNotNull(type, "type");
+ return getActualTypeArgument(type, 0);
+ }
+
+ public static Type getActualTypeArgument(Type type, int argIndex)
+ {
+ checkNotNull(type, "type");
+ checkTrue(type instanceof ParameterizedType, "type must be a ParameterizedType: ", type);
ParameterizedType paramType = (ParameterizedType) type;
Type[] typeArgs = paramType.getActualTypeArguments();
- Utils.checkTrue(typeArgs.length == 1, "type must be a ParameterizedType with one actual type argument: ", type);
+ checkTrue(argIndex >= 0, "argIndex must be non-negative: ", argIndex);
+ checkTrue(argIndex < typeArgs.length, "argIndex must be less than the number of type parameters: ", argIndex);
- return typeArgs[0];
+ return typeArgs[argIndex];
}
public static Type getResolvedSuperclass(Type type)
{
- Utils.checkNotNull(type, "type");
+ checkNotNull(type, "type");
Class<?> rawType = getErasedReferenceType(type);
Type supertype = rawType.getGenericSuperclass();
@@ -304,7 +414,7 @@ public final class TypeUtils
public static Type[] getResolvedInterfaces(Type type)
{
- Utils.checkNotNull(type, "type");
+ checkNotNull(type, "type");
Class<?> rawType = getErasedReferenceType(type);
Type[] interfaces = rawType.getGenericInterfaces();
@@ -318,6 +428,18 @@ public final class TypeUtils
return resolvedInterfaces;
}
+ public static <T> Type getResolvedSupertype(Class<? extends T> type, Class<T> rawSupertype)
+ {
+ Type resolvedSupertype = getResolvedSupertype((Type) type, rawSupertype);
+
+ if (resolvedSupertype == null)
+ {
+ throw new IllegalStateException("type must extend or implement supertype: " + type.getName());
+ }
+
+ return resolvedSupertype;
+ }
+
public static String toString(Type type)
{
return toString(type, ClassSerializers.QUALIFIED);
@@ -325,39 +447,16 @@ public final class TypeUtils
public static String toString(Type type, ClassSerializer serializer)
{
- if (type instanceof Class<?>)
+ if (type == null)
{
- Class<?> klass = (Class<?>) type;
-
- if (klass.isArray())
- {
- return toString(klass.getComponentType(), serializer) + "[]";
- }
-
- return serializer.toString(klass);
+ return String.valueOf(type);
}
- if (type instanceof TypeVariable<?>)
- {
- return DefaultTypeVariable.toString((TypeVariable<?>) type, serializer);
- }
-
- if (type instanceof GenericArrayType)
- {
- return DefaultGenericArrayType.toString((GenericArrayType) type, serializer);
- }
-
- if (type instanceof ParameterizedType)
- {
- return DefaultParameterizedType.toString((ParameterizedType) type, serializer);
- }
+ SerializingTypeVisitor visitor = new SerializingTypeVisitor(serializer);
- if (type instanceof WildcardType)
- {
- return DefaultWildcardType.toString((WildcardType) type, serializer);
- }
+ accept(type, visitor);
- return String.valueOf(type);
+ return visitor.toString();
}
public static String toUnqualifiedString(Type type)
@@ -370,23 +469,6 @@ public final class TypeUtils
return toString(type, ClassSerializers.SIMPLE);
}
- // package methods --------------------------------------------------------
-
- static StringBuilder appendBounds(StringBuilder builder, Type[] bounds, ClassSerializer serializer)
- {
- for (int i = 0; i < bounds.length; i++)
- {
- if (i > 0)
- {
- builder.append(" & ");
- }
-
- builder.append(toString(bounds[i], serializer));
- }
-
- return builder;
- }
-
// private methods --------------------------------------------------------
private static void putPrimitiveSubtypes(Map<Class<?>, Set<Class<?>>> subtypesByPrimitive, Class<?> primitiveType,
@@ -414,6 +496,19 @@ public final class TypeUtils
return supertype.isAssignableFrom(type);
}
+ private static boolean isClassAssignableToWildcardType(Class<?> supertype, WildcardType type)
+ {
+ for (Type upperBound : type.getUpperBounds())
+ {
+ if (!isAssignable(supertype, upperBound))
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
private static boolean isParameterizedTypeAssignable(ParameterizedType supertype, ParameterizedType type)
{
Type rawSupertype = supertype.getRawType();
@@ -632,7 +727,7 @@ public final class TypeUtils
private static <K, V> Map<K, V> normalize(Map<K, V> map)
{
- // TODO: will this cause an infinite look with recursive bounds?
+ // TODO: will this cause an infinite loop with recursive bounds?
for (Entry<K, V> entry : map.entrySet())
{
@@ -649,4 +744,37 @@ public final class TypeUtils
return map;
}
+
+ private static Type getResolvedSupertype(Type type, Class<?> rawSupertype)
+ {
+ Class<?> rawCurrentType = TypeUtils.getErasedReferenceType(type);
+
+ if (rawSupertype.equals(rawCurrentType))
+ {
+ return type;
+ }
+
+ // try interfaces
+
+ for (Type interfaceType : TypeUtils.getResolvedInterfaces(type))
+ {
+ Type resolvedType = getResolvedSupertype(interfaceType, rawSupertype);
+
+ if (resolvedType != null)
+ {
+ return resolvedType;
+ }
+ }
+
+ // try superclass
+
+ Type supertype = TypeUtils.getResolvedSuperclass(type);
+
+ if (supertype == null)
+ {
+ return null;
+ }
+
+ return getResolvedSupertype(supertype, rawSupertype);
+ }
}
diff --git a/src/main/java/com/googlecode/jtype/TypeVisitor.java b/src/main/java/com/googlecode/jtype/TypeVisitor.java
new file mode 100644
index 0000000..09e465d
--- /dev/null
+++ b/src/main/java/com/googlecode/jtype/TypeVisitor.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2009 IIZUKA Software Technologies Ltd
+ *
+ * Licensed 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 com.googlecode.jtype;
+
+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;
+
+/**
+ *
+ *
+ * @author Mark Hobson
+ * @version $Id: TypeVisitor.java 111 2011-11-23 17:25:02Z markhobson $
+ */
+public interface TypeVisitor
+{
+ void visit(Class<?> type);
+
+ // TODO: rename to visit
+ <D extends GenericDeclaration> boolean beginVisit(TypeVariable<D> type);
+
+ void visitTypeVariableBound(Type bound, int index);
+
+ <D extends GenericDeclaration> void endVisit(TypeVariable<D> type);
+
+ void visit(GenericArrayType type);
+
+ // TODO: rename to visit
+ boolean beginVisit(ParameterizedType type);
+
+ void visitActualTypeArgument(Type type, int index);
+
+ void endVisit(ParameterizedType type);
+
+ // TODO: rename to visit
+ boolean beginVisit(WildcardType type);
+
+ void visitUpperBound(Type bound, int index);
+
+ void visitLowerBound(Type bound, int index);
+
+ void endVisit(WildcardType type);
+}
diff --git a/src/main/java/com/googlecode/jtype/Types.java b/src/main/java/com/googlecode/jtype/Types.java
index ea64d23..2c718cc 100644
--- a/src/main/java/com/googlecode/jtype/Types.java
+++ b/src/main/java/com/googlecode/jtype/Types.java
@@ -15,6 +15,8 @@
*/
package com.googlecode.jtype;
+import static com.googlecode.jtype.Utils.checkNotNull;
+
import java.lang.reflect.GenericArrayType;
import java.lang.reflect.GenericDeclaration;
import java.lang.reflect.MalformedParameterizedTypeException;
@@ -22,6 +24,7 @@ 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.Map;
@@ -33,13 +36,15 @@ import java.util.regex.Pattern;
* Factory for creating types.
*
* @author Mark Hobson
- * @version $Id: Types.java 37 2009-07-24 11:27:39Z markhobson $
+ * @version $Id: Types.java 110 2011-11-23 17:19:43Z markhobson $
* @see Type
*/
public final class Types
{
// constants --------------------------------------------------------------
+ private static final WildcardType UNBOUNDED_WILDCARD_TYPE = wildcardType(null, null);
+
private static final Pattern ARRAY_PATTERN = Pattern.compile("\\[\\s*\\]$");
private static final Pattern UPPER_BOUND_PATTERN = Pattern.compile("^\\?\\s+extends\\s+");
@@ -95,7 +100,8 @@ public final class Types
* the actual type arguments
* @return the parameterized type
* @throws MalformedParameterizedTypeException
- * if the number of actual type arguments differs from those defined on the raw type
+ * if the raw type is not a parameterized type or the number of actual type arguments differs from those
+ * defined on the raw type
*/
public static ParameterizedType parameterizedType(Class<?> rawType, Type... actualTypeArguments)
{
@@ -103,13 +109,34 @@ public final class Types
}
/**
+ * Creates a parameterized type for the specified raw type with unbounded wildcard actual type arguments.
+ *
+ * @param rawType
+ * the raw type
+ * @return the parameterized type
+ * @throws MalformedParameterizedTypeException
+ * if the raw type is not a parameterized type
+ */
+ public static ParameterizedType unboundedParameterizedType(Class<?> rawType)
+ {
+ checkNotNull(rawType, "rawType");
+
+ int typeParameterCount = rawType.getTypeParameters().length;
+
+ Type[] actualTypeArguments = new Type[typeParameterCount];
+ Arrays.fill(actualTypeArguments, unboundedWildcardType());
+
+ return parameterizedType(rawType, actualTypeArguments);
+ }
+
+ /**
* Creates an unbounded wildcard type.
*
* @return the wildcard type
*/
public static WildcardType unboundedWildcardType()
{
- return wildcardType(null, null);
+ return UNBOUNDED_WILDCARD_TYPE;
}
/**
@@ -121,7 +148,7 @@ public final class Types
*/
public static WildcardType upperBoundedWildcardType(Type upperBound)
{
- Utils.checkNotNull(upperBound, "upperBound");
+ checkNotNull(upperBound, "upperBound");
return wildcardType(new Type[] {upperBound}, null);
}
@@ -135,7 +162,7 @@ public final class Types
*/
public static WildcardType lowerBoundedWildcardType(Type lowerBound)
{
- Utils.checkNotNull(lowerBound, "lowerBound");
+ checkNotNull(lowerBound, "lowerBound");
return wildcardType(null, new Type[] {lowerBound});
}
@@ -149,7 +176,7 @@ public final class Types
*/
public static Type valueOf(String typeName)
{
- return valueOf(typeName, Collections.<String>emptySet());
+ return valueOf(typeName, (Set<String>) null);
}
/**
@@ -165,6 +192,27 @@ public final class Types
*/
public static Type valueOf(String typeName, Set<String> imports)
{
+ checkNotNull(typeName, "typeName");
+
+ Map<String, String> importMap = createImportMap(imports);
+
+ return valueOf(typeName, importMap);
+ }
+
+ // private methods --------------------------------------------------------
+
+ private static WildcardType wildcardType(Type[] upperBounds, Type[] lowerBounds)
+ {
+ return new DefaultWildcardType(upperBounds, lowerBounds);
+ }
+
+ private static Map<String, String> createImportMap(Set<String> imports)
+ {
+ if (imports == null)
+ {
+ return Collections.emptyMap();
+ }
+
Map<String, String> importMap = new HashMap<String, String>();
for (String className : imports)
@@ -180,14 +228,7 @@ public final class Types
importMap.put(simpleClassName, className);
}
- return valueOf(typeName, importMap);
- }
-
- // private methods --------------------------------------------------------
-
- private static WildcardType wildcardType(Type[] upperBounds, Type[] lowerBounds)
- {
- return new DefaultWildcardType(upperBounds, lowerBounds);
+ return importMap;
}
private static Type valueOf(String typeName, Map<String, String> imports)
@@ -248,7 +289,7 @@ public final class Types
private static Class<?> parseClass(String className, Map<String, String> imports)
{
- Class<?> klass = parseClass(className);
+ Class<?> klass = ClassUtils.valueOf(className);
if (klass != null)
{
@@ -259,7 +300,7 @@ public final class Types
{
String qualifiedClassName = imports.get(className);
- klass = parseClass(qualifiedClassName);
+ klass = ClassUtils.valueOf(qualifiedClassName);
if (klass != null)
{
@@ -270,20 +311,6 @@ public final class Types
throw new IllegalArgumentException("Class not found: " + className);
}
- private static Class<?> parseClass(String className)
- {
- ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
-
- try
- {
- return Class.forName(className, true, classLoader);
- }
- catch (ClassNotFoundException exception)
- {
- return null;
- }
- }
-
private static WildcardType parseWildcardType(String typeName, Map<String, String> imports)
{
Type[] upperBounds;
diff --git a/src/test/java/com/googlecode/jtype/ClassUtilsTest.java b/src/test/java/com/googlecode/jtype/ClassUtilsTest.java
index 4332495..e3e8d99 100644
--- a/src/test/java/com/googlecode/jtype/ClassUtilsTest.java
+++ b/src/test/java/com/googlecode/jtype/ClassUtilsTest.java
@@ -23,7 +23,7 @@ import org.junit.Test;
* Tests {@code ClassUtils}.
*
* @author Mark Hobson
- * @version $Id: ClassUtilsTest.java 36 2009-07-03 11:18:03Z markhobson $
+ * @version $Id: ClassUtilsTest.java 82 2010-11-01 11:22:10Z markhobson $
* @see ClassUtils
*/
public class ClassUtilsTest
@@ -83,4 +83,58 @@ public class ClassUtilsTest
{
assertEquals("E", ClassUtils.getSimpleClassName("a.b.C$D$E"));
}
+
+ @Test
+ public void valueOfWithBooleanPrimitive()
+ {
+ assertEquals(Boolean.TYPE, ClassUtils.valueOf("boolean"));
+ }
+
+ @Test
+ public void valueOfWithBytePrimitive()
+ {
+ assertEquals(Byte.TYPE, ClassUtils.valueOf("byte"));
+ }
+
+ @Test
+ public void valueOfWithCharPrimitive()
+ {
+ assertEquals(Character.TYPE, ClassUtils.valueOf("char"));
+ }
+
+ @Test
+ public void valueOfWithDoublePrimitive()
+ {
+ assertEquals(Double.TYPE, ClassUtils.valueOf("double"));
+ }
+
+ @Test
+ public void valueOfWithFloatPrimitive()
+ {
+ assertEquals(Float.TYPE, ClassUtils.valueOf("float"));
+ }
+
+ @Test
+ public void valueOfWithIntPrimitive()
+ {
+ assertEquals(Integer.TYPE, ClassUtils.valueOf("int"));
+ }
+
+ @Test
+ public void valueOfWithLongPrimitive()
+ {
+ assertEquals(Long.TYPE, ClassUtils.valueOf("long"));
+ }
+
+ @Test
+ public void valueOfWithShortPrimitive()
+ {
+ assertEquals(Short.TYPE, ClassUtils.valueOf("short"));
+ }
+
+ @Test
+ public void valueOfWithClass()
+ {
+ assertEquals(Integer.class, ClassUtils.valueOf("java.lang.Integer"));
+ }
}
diff --git a/src/test/java/com/googlecode/jtype/DefaultGenericArrayTypeTest.java b/src/test/java/com/googlecode/jtype/DefaultGenericArrayTypeTest.java
index 23f5ff5..49cc752 100644
--- a/src/test/java/com/googlecode/jtype/DefaultGenericArrayTypeTest.java
+++ b/src/test/java/com/googlecode/jtype/DefaultGenericArrayTypeTest.java
@@ -15,9 +15,11 @@
*/
package com.googlecode.jtype;
+import static com.googlecode.jtype.test.SerializableAssert.assertSerializable;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
+import java.io.IOException;
import java.lang.reflect.GenericArrayType;
import org.junit.Test;
@@ -26,7 +28,7 @@ import org.junit.Test;
* Tests {@code DefaultGenericArrayType}.
*
* @author Mark Hobson
- * @version $Id: DefaultGenericArrayTypeTest.java 2 2009-02-02 22:28:39Z markhobson $
+ * @version $Id: DefaultGenericArrayTypeTest.java 115 2011-11-25 18:17:40Z markhobson at gmail.com $
* @see DefaultGenericArrayType
*/
public class DefaultGenericArrayTypeTest
@@ -98,4 +100,12 @@ public class DefaultGenericArrayTypeTest
assertEquals("java.lang.Integer[]", genericArrayType.toString());
}
+
+ @Test
+ public void serializable() throws IOException, ClassNotFoundException
+ {
+ GenericArrayType type = new DefaultGenericArrayType(Integer.class);
+
+ assertSerializable(type);
+ }
}
diff --git a/src/test/java/com/googlecode/jtype/DefaultParameterizedTypeTest.java b/src/test/java/com/googlecode/jtype/DefaultParameterizedTypeTest.java
index 1942331..c60d77f 100644
--- a/src/test/java/com/googlecode/jtype/DefaultParameterizedTypeTest.java
+++ b/src/test/java/com/googlecode/jtype/DefaultParameterizedTypeTest.java
@@ -15,11 +15,13 @@
*/
package com.googlecode.jtype;
+import static com.googlecode.jtype.test.SerializableAssert.assertSerializable;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
+import java.io.IOException;
import java.lang.reflect.MalformedParameterizedTypeException;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
@@ -33,7 +35,7 @@ import org.junit.Test;
* Tests {@code DefaultParameterizedType}.
*
* @author Mark Hobson
- * @version $Id: DefaultParameterizedTypeTest.java 35 2009-07-03 10:14:37Z markhobson $
+ * @version $Id: DefaultParameterizedTypeTest.java 115 2011-11-25 18:17:40Z markhobson at gmail.com $
* @see DefaultParameterizedType
*/
public class DefaultParameterizedTypeTest
@@ -76,14 +78,10 @@ public class DefaultParameterizedTypeTest
}
}
- @Test
- public void constructorWithNullActualTypeArguments()
+ @Test(expected = MalformedParameterizedTypeException.class)
+ public void constructorWithUnparameterizedRawType()
{
- ParameterizedType type = new DefaultParameterizedType(null, String.class, null);
-
- assertNull(type.getOwnerType());
- assertEquals(String.class, type.getRawType());
- assertArrayEquals(new Type[0], type.getActualTypeArguments());
+ new DefaultParameterizedType(null, String.class, null);
}
@Test(expected = MalformedParameterizedTypeException.class)
@@ -114,15 +112,6 @@ public class DefaultParameterizedTypeTest
}
@Test
- public void hashCodeWithNullActualTypeArguments()
- {
- ParameterizedType type1 = new DefaultParameterizedType(null, String.class, null);
- ParameterizedType type2 = new DefaultParameterizedType(null, String.class, null);
-
- assertEquals(type1.hashCode(), type2.hashCode());
- }
-
- @Test
public void equalsWhenEqual()
{
ParameterizedType type1 = new DefaultParameterizedType(Map.class, Map.Entry.class,
@@ -152,15 +141,6 @@ public class DefaultParameterizedTypeTest
}
@Test
- public void equalsWithNullActualTypeArguments()
- {
- ParameterizedType type1 = new DefaultParameterizedType(null, String.class, null);
- ParameterizedType type2 = new DefaultParameterizedType(null, String.class, null);
-
- assertEquals(type1, type2);
- }
-
- @Test
public void equalsWithUnequalOwnerType()
{
ParameterizedType type1 = new DefaultParameterizedType(Map.class, Map.Entry.class,
@@ -196,15 +176,7 @@ public class DefaultParameterizedTypeTest
ParameterizedType type = new DefaultParameterizedType(Map.class, Map.Entry.class,
new Type[] {String.class, Integer.class});
- assertEquals("java.util.Map$Entry<java.lang.String,java.lang.Integer>", type.toString());
- }
-
- @Test
- public void toStringWithRawType()
- {
- ParameterizedType type = new DefaultParameterizedType(null, String.class, null);
-
- assertEquals("java.lang.String", type.toString());
+ assertEquals("java.util.Map.java.util.Map$Entry<java.lang.String, java.lang.Integer>", type.toString());
}
@Test
@@ -221,6 +193,15 @@ public class DefaultParameterizedTypeTest
ParameterizedType type = new DefaultParameterizedType(null, Map.class,
new Type[] {String.class, Integer.class});
- assertEquals("java.util.Map<java.lang.String,java.lang.Integer>", type.toString());
+ assertEquals("java.util.Map<java.lang.String, java.lang.Integer>", type.toString());
+ }
+
+ @Test
+ public void serializable() throws IOException, ClassNotFoundException
+ {
+ ParameterizedType type = new DefaultParameterizedType(Map.class, Map.Entry.class,
+ new Type[] {String.class, Integer.class});
+
+ assertSerializable(type);
}
}
diff --git a/src/test/java/com/googlecode/jtype/DefaultTypeVariableTest.java b/src/test/java/com/googlecode/jtype/DefaultTypeVariableTest.java
index 34dfbe3..253ba2f 100644
--- a/src/test/java/com/googlecode/jtype/DefaultTypeVariableTest.java
+++ b/src/test/java/com/googlecode/jtype/DefaultTypeVariableTest.java
@@ -15,10 +15,12 @@
*/
package com.googlecode.jtype;
+import static com.googlecode.jtype.test.SerializableAssert.assertSerializable;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
+import java.io.IOException;
import java.io.Serializable;
import java.lang.reflect.Constructor;
import java.lang.reflect.GenericDeclaration;
@@ -35,7 +37,7 @@ import org.junit.Test;
* Tests {@code DefaultTypeVariable}.
*
* @author Mark Hobson
- * @version $Id: DefaultTypeVariableTest.java 42 2009-10-02 14:54:54Z markhobson $
+ * @version $Id: DefaultTypeVariableTest.java 115 2011-11-25 18:17:40Z markhobson at gmail.com $
* @see DefaultTypeVariable
*/
public class DefaultTypeVariableTest
@@ -284,6 +286,15 @@ public class DefaultTypeVariableTest
assertEquals("T extends java.lang.Number & java.lang.Comparable", typeVariable.toString());
}
+ @Test
+ public void serializable() throws IOException, ClassNotFoundException
+ {
+ TypeVariable<Class<?>> type = new DefaultTypeVariable<Class<?>>(getClass(), "T",
+ new Type[] {Number.class, Comparable.class});
+
+ assertSerializable(type);
+ }
+
// private methods --------------------------------------------------------
private static <D extends GenericDeclaration> void assertConstructor(D declaration, String name, Type... bounds)
diff --git a/src/test/java/com/googlecode/jtype/DefaultWildcardTypeTest.java b/src/test/java/com/googlecode/jtype/DefaultWildcardTypeTest.java
index ae79af0..8089da5 100644
--- a/src/test/java/com/googlecode/jtype/DefaultWildcardTypeTest.java
+++ b/src/test/java/com/googlecode/jtype/DefaultWildcardTypeTest.java
@@ -15,10 +15,12 @@
*/
package com.googlecode.jtype;
+import static com.googlecode.jtype.test.SerializableAssert.assertSerializable;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
+import java.io.IOException;
import java.lang.reflect.Type;
import java.lang.reflect.WildcardType;
@@ -28,7 +30,7 @@ import org.junit.Test;
* Tests {@code DefaultWildcardType}.
*
* @author Mark Hobson
- * @version $Id: DefaultWildcardTypeTest.java 2 2009-02-02 22:28:39Z markhobson $
+ * @version $Id: DefaultWildcardTypeTest.java 115 2011-11-25 18:17:40Z markhobson at gmail.com $
* @see DefaultWildcardType
*/
public class DefaultWildcardTypeTest
@@ -169,4 +171,12 @@ public class DefaultWildcardTypeTest
assertEquals("? super java.lang.Integer & java.lang.Number", wildcardType.toString());
}
+
+ @Test
+ public void serializable() throws IOException, ClassNotFoundException
+ {
+ WildcardType type = new DefaultWildcardType(null, new Type[] {Integer.class});
+
+ assertSerializable(type);
+ }
}
diff --git a/src/test/java/com/googlecode/jtype/GenericTest.java b/src/test/java/com/googlecode/jtype/GenericTest.java
index dc579c7..958a05d 100644
--- a/src/test/java/com/googlecode/jtype/GenericTest.java
+++ b/src/test/java/com/googlecode/jtype/GenericTest.java
@@ -15,13 +15,18 @@
*/
package com.googlecode.jtype;
+import static com.googlecode.jtype.test.SerializableAssert.assertSerializable;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
+import java.io.IOException;
+import java.io.Serializable;
import java.lang.reflect.GenericArrayType;
import java.lang.reflect.GenericDeclaration;
import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
import java.util.List;
import java.util.Map;
@@ -32,11 +37,13 @@ import org.junit.Test;
* Tests {@code Generic}.
*
* @author Mark Hobson
- * @version $Id: GenericTest.java 31 2009-04-30 15:02:29Z markhobson $
+ * @version $Id: GenericTest.java 115 2011-11-25 18:17:40Z markhobson at gmail.com $
* @see Generic
*/
-public class GenericTest
+public class GenericTest implements Serializable
{
+ // test is serializable with transient fields for serializableWhenSubclassed
+
// classes ----------------------------------------------------------------
private static class GenericSubclass<T> extends Generic<T>
@@ -46,7 +53,7 @@ public class GenericTest
// fields -----------------------------------------------------------------
- private GenericDeclaration declaration;
+ private transient GenericDeclaration declaration;
// public methods ---------------------------------------------------------
@@ -108,6 +115,32 @@ public class GenericTest
}
@Test
+ public void getWithClassIsSerializable() throws IOException, ClassNotFoundException
+ {
+ assertSerializable(Generic.get(String.class));
+ }
+
+ @Test
+ public void getWithRawTypeAndActualTypeArguments()
+ {
+ ParameterizedType parameterizedType = Types.parameterizedType(List.class, String.class);
+
+ assertEquals(parameterizedType, Generic.get(List.class, String.class).getType());
+ }
+
+ @Test
+ public void getWithRawTypeAndNullActualTypeArguments()
+ {
+ assertEquals(String.class, Generic.get(String.class, (Type[]) null).getType());
+ }
+
+ @Test
+ public void getWithRawTypeAndEmptyActualTypeArguments()
+ {
+ assertEquals(String.class, Generic.get(String.class, new Type[0]).getType());
+ }
+
+ @Test
public void getWithParameterizedType()
{
ParameterizedType parameterizedType = Types.parameterizedType(List.class, String.class);
@@ -154,6 +187,66 @@ public class GenericTest
}
@Test
+ public void getWithObjectClassIsCached()
+ {
+ assertSame(Generic.get(Object.class), Generic.get(Object.class));
+ }
+
+ @Test
+ public void getWithBooleanClassIsCached()
+ {
+ assertSame(Generic.get(Boolean.class), Generic.get(Boolean.class));
+ }
+
+ @Test
+ public void getWithByteClassIsCached()
+ {
+ assertSame(Generic.get(Byte.class), Generic.get(Byte.class));
+ }
+
+ @Test
+ public void getWithCharacterClassIsCached()
+ {
+ assertSame(Generic.get(Character.class), Generic.get(Character.class));
+ }
+
+ @Test
+ public void getWithDoubleClassIsCached()
+ {
+ assertSame(Generic.get(Double.class), Generic.get(Double.class));
+ }
+
+ @Test
+ public void getWithFloatClassIsCached()
+ {
+ assertSame(Generic.get(Float.class), Generic.get(Float.class));
+ }
+
+ @Test
+ public void getWithIntegerClassIsCached()
+ {
+ assertSame(Generic.get(Integer.class), Generic.get(Integer.class));
+ }
+
+ @Test
+ public void getWithLongClassIsCached()
+ {
+ assertSame(Generic.get(Long.class), Generic.get(Long.class));
+ }
+
+ @Test
+ public void getWithShortClassIsCached()
+ {
+ assertSame(Generic.get(Short.class), Generic.get(Short.class));
+ }
+
+ @Test
+ public void getWithStringClassIsCached()
+ {
+ assertSame(Generic.get(String.class), Generic.get(String.class));
+ }
+
+ @Test
public void valueOfWithClass()
{
assertEquals(String.class, Generic.valueOf("java.lang.String").getType());
@@ -265,4 +358,10 @@ public class GenericTest
{
assertEquals("List<String>", new Generic<List<String>>() {/**/}.toUnqualifiedString());
}
+
+ @Test
+ public void serializableWhenSubclassed() throws IOException, ClassNotFoundException
+ {
+ assertSerializable(new Generic<String>() {/**/});
+ }
}
diff --git a/src/test/java/com/googlecode/jtype/GenericsTest.java b/src/test/java/com/googlecode/jtype/GenericsTest.java
index edc1ac9..01e98b3 100644
--- a/src/test/java/com/googlecode/jtype/GenericsTest.java
+++ b/src/test/java/com/googlecode/jtype/GenericsTest.java
@@ -35,7 +35,7 @@ import org.junit.Test;
* Tests {@code Generics}.
*
* @author Mark Hobson
- * @version $Id: GenericsTest.java 2 2009-02-02 22:28:39Z markhobson $
+ * @version $Id: GenericsTest.java 86 2010-11-05 13:23:09Z markhobson $
* @see Generics
*/
public class GenericsTest
@@ -43,68 +43,158 @@ public class GenericsTest
// tests ------------------------------------------------------------------
@Test
+ public void comparable()
+ {
+ assertEquals(new Generic<Comparable<?>>() {/**/}, Generics.comparable());
+ }
+
+ @Test
+ public void comparableWithClass()
+ {
+ assertEquals(new Generic<Comparable<String>>() {/**/}, Generics.comparable(String.class));
+ }
+
+ @Test
public void comparator()
{
+ assertEquals(new Generic<Comparator<?>>() {/**/}, Generics.comparator());
+ }
+
+ @Test
+ public void comparatorWithClass()
+ {
assertEquals(new Generic<Comparator<String>>() {/**/}, Generics.comparator(String.class));
}
@Test
public void enumeration()
{
+ assertEquals(new Generic<Enumeration<?>>() {/**/}, Generics.enumeration());
+ }
+
+ @Test
+ public void enumerationWithClass()
+ {
assertEquals(new Generic<Enumeration<String>>() {/**/}, Generics.enumeration(String.class));
}
@Test
+ public void iterable()
+ {
+ assertEquals(new Generic<Iterable<?>>() {/**/}, Generics.iterable());
+ }
+
+ @Test
+ public void iterableWithClass()
+ {
+ assertEquals(new Generic<Iterable<String>>() {/**/}, Generics.iterable(String.class));
+ }
+
+ @Test
public void iterator()
{
+ assertEquals(new Generic<Iterator<?>>() {/**/}, Generics.iterator());
+ }
+
+ @Test
+ public void iteratorWithClass()
+ {
assertEquals(new Generic<Iterator<String>>() {/**/}, Generics.iterator(String.class));
}
@Test
public void listIterator()
{
+ assertEquals(new Generic<ListIterator<?>>() {/**/}, Generics.listIterator());
+ }
+
+ @Test
+ public void listIteratorWithClass()
+ {
assertEquals(new Generic<ListIterator<String>>() {/**/}, Generics.listIterator(String.class));
}
@Test
public void collection()
{
+ assertEquals(new Generic<Collection<?>>() {/**/}, Generics.collection());
+ }
+
+ @Test
+ public void collectionWithClass()
+ {
assertEquals(new Generic<Collection<String>>() {/**/}, Generics.collection(String.class));
}
@Test
public void set()
{
+ assertEquals(new Generic<Set<?>>() {/**/}, Generics.set());
+ }
+
+ @Test
+ public void setWithClass()
+ {
assertEquals(new Generic<Set<String>>() {/**/}, Generics.set(String.class));
}
@Test
public void sortedSet()
{
+ assertEquals(new Generic<SortedSet<?>>() {/**/}, Generics.sortedSet());
+ }
+
+ @Test
+ public void sortedSetWithClass()
+ {
assertEquals(new Generic<SortedSet<String>>() {/**/}, Generics.sortedSet(String.class));
}
@Test
public void list()
{
+ assertEquals(new Generic<List<?>>() {/**/}, Generics.list());
+ }
+
+ @Test
+ public void listWithClass()
+ {
assertEquals(new Generic<List<String>>() {/**/}, Generics.list(String.class));
}
@Test
public void map()
{
+ assertEquals(new Generic<Map<?, ?>>() {/**/}, Generics.map());
+ }
+
+ @Test
+ public void mapWithClasses()
+ {
assertEquals(new Generic<Map<String, Integer>>() {/**/}, Generics.map(String.class, Integer.class));
}
@Test
public void sortedMap()
{
+ assertEquals(new Generic<SortedMap<?, ?>>() {/**/}, Generics.sortedMap());
+ }
+
+ @Test
+ public void sortedMapWithClasses()
+ {
assertEquals(new Generic<SortedMap<String, Integer>>() {/**/}, Generics.sortedMap(String.class, Integer.class));
}
@Test
public void queue()
{
+ assertEquals(new Generic<Queue<?>>() {/**/}, Generics.queue());
+ }
+
+ @Test
+ public void queueWithClass()
+ {
assertEquals(new Generic<Queue<String>>() {/**/}, Generics.queue(String.class));
}
}
diff --git a/src/test/java/com/googlecode/jtype/TypeUtilsGetResolvedSupertypeTest.java b/src/test/java/com/googlecode/jtype/TypeUtilsGetResolvedSupertypeTest.java
new file mode 100644
index 0000000..0005212
--- /dev/null
+++ b/src/test/java/com/googlecode/jtype/TypeUtilsGetResolvedSupertypeTest.java
@@ -0,0 +1,134 @@
+/*
+ * Copyright 2011 IIZUKA Software Technologies Ltd
+ *
+ * Licensed 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 com.googlecode.jtype;
+
+import static com.googlecode.jtype.Types.parameterizedType;
+import static com.googlecode.jtype.Types.typeVariable;
+import static org.junit.Assert.assertEquals;
+
+import java.lang.reflect.Type;
+import java.util.Set;
+
+import com.googlecode.jtype.test.AbstractTypeTest;
+
+import org.junit.Test;
+
+/**
+ * Tests {@code TypeUtils.getResolvedSupertype}.
+ *
+ * @author Mark Hobson
+ * @version $Id: TypeUtilsGetResolvedSupertypeTest.java 115 2011-11-25 18:17:40Z markhobson at gmail.com $
+ * @see TypeUtils#getResolvedSupertype(Class, Class)
+ */
+public class TypeUtilsGetResolvedSupertypeTest extends AbstractTypeTest
+{
+ // types ------------------------------------------------------------------
+
+ private static class DummyClass
+ {
+ // simple subtype
+ }
+
+ private static interface IFake<T>
+ {
+ // simple subtype
+ }
+
+ private static class Fake implements IFake<DummyClass>
+ {
+ // simple subtype
+ }
+
+ private static class ParameterizedTypeFake implements IFake<IFake<?>>
+ {
+ // simple subtype
+ }
+
+ private static class TypeVariableFake<T> implements IFake<T>
+ {
+ // simple subtype
+ }
+
+ private static class SubFake extends Fake
+ {
+ // simple subtype
+ }
+
+ private static interface IFake2<T> extends IFake<T>
+ {
+ // simple subtype
+ }
+
+ private static class Fake2 implements IFake2<DummyClass>
+ {
+ // simple subtype
+ }
+
+ // AbstractTypeTest methods -----------------------------------------------
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected void addImports(Set<Class<?>> imports)
+ {
+ imports.add(DummyClass.class);
+ imports.add(IFake.class);
+ }
+
+ // tests ------------------------------------------------------------------
+
+ @Test
+ public void getResolvedSupertypeWithClassImplementation()
+ {
+ Type actual = TypeUtils.getResolvedSupertype(Fake.class, IFake.class);
+
+ assertEquals(type("IFake<DummyClass>"), actual);
+ }
+
+ @Test
+ public void getResolvedSupertypeWithParameterizedTypeImplementation()
+ {
+ Type actual = TypeUtils.getResolvedSupertype(ParameterizedTypeFake.class, IFake.class);
+
+ assertEquals(type("IFake<IFake<?>>"), actual);
+ }
+
+ @Test
+ public void getResolvedSupertypeWithTypeVariableImplementation()
+ {
+ Type actual = TypeUtils.getResolvedSupertype(TypeVariableFake.class, IFake.class);
+
+ Type expected = parameterizedType(IFake.class, typeVariable(TypeVariableFake.class, "T"));
+ assertEquals(expected, actual);
+ }
+
+ @Test
+ public void getResolvedSupertypeWithSuperclassClassImplementation()
+ {
+ Type actual = TypeUtils.getResolvedSupertype(SubFake.class, IFake.class);
+
+ assertEquals(type("IFake<DummyClass>"), actual);
+ }
+
+ @Test
+ public void getResolvedSupertypeWithSuperinterfaceClassImplementation()
+ {
+ Type actual = TypeUtils.getResolvedSupertype(Fake2.class, IFake.class);
+
+ assertEquals(type("IFake<DummyClass>"), actual);
+ }
+}
diff --git a/src/test/java/com/googlecode/jtype/TypeUtilsTest.java b/src/test/java/com/googlecode/jtype/TypeUtilsTest.java
index 802321a..828f5e4 100644
--- a/src/test/java/com/googlecode/jtype/TypeUtilsTest.java
+++ b/src/test/java/com/googlecode/jtype/TypeUtilsTest.java
@@ -48,11 +48,14 @@ import org.junit.Test;
* Tests {@code TypeUtils}.
*
* @author Mark Hobson
- * @version $Id: TypeUtilsTest.java 48 2009-10-02 16:57:38Z markhobson $
+ * @version $Id: TypeUtilsTest.java 114 2011-11-25 18:15:48Z markhobson at gmail.com $
* @see TypeUtils
*/
public class TypeUtilsTest
{
+ // TODO: split into smaller test cases
+ // TODO: use local types rather than JDK classes in tests
+
// classes ----------------------------------------------------------------
private static class IntegerArrayList extends ArrayList<Integer>
@@ -467,6 +470,30 @@ public class TypeUtilsTest
}
/**
+ * Tests that parameterized type upper bounded wildcard type arguments are assignable to wildcard types.
+ *
+ * {@literal List<?> <: List<? extends Number>}
+ */
+ @Test
+ public void isAssignableWithWildcardParameterizedTypeFromUpperBoundedWildcardParameterizedType()
+ {
+ assertAsymmetricallyAssignable(valueOf("List<?>"), valueOf("List<? extends Number>"));
+ }
+
+ /**
+ * Tests that parameterized type lower bounded wildcard type arguments are assignable to wildcard types.
+ *
+ * {@literal List<?> <: List<? super Number>}
+ */
+ // TODO: fix
+ @Ignore
+ @Test
+ public void isAssignableWithWildcardParameterizedTypeFromLowerBoundedWildcardParameterizedType()
+ {
+ assertAsymmetricallyAssignable(valueOf("List<?>"), valueOf("List<? super Number>"));
+ }
+
+ /**
* Tests that parameterized type arguments are assignable to wildcard types on their upper bound.
*
* {@literal List<? extends Number> <: List<Number>}
@@ -503,8 +530,6 @@ public class TypeUtilsTest
/**
* {@literal List<? extends Number> <: List<? extends Integer>}
*/
- // TODO: fix
- @Ignore
@Test
public void isAssignableWithUpperBoundedWildcardParameterizedTypeFromInBoundsUpperBoundedWildcardParameterizedType()
{
@@ -665,6 +690,94 @@ public class TypeUtilsTest
assertAssignable(Collection.class, type);
}
+ /**
+ * Tests that unbounded wildcards are assignable to Object.
+ *
+ * {@literal Object <: ?}
+ */
+ @Test
+ public void isAssignableWithObjectFromUnboundedWildcardType()
+ {
+ assertAssignable(Object.class, Types.unboundedWildcardType());
+ }
+
+ /**
+ * Tests that upper bounded wildcards are assignable to their upper bound.
+ *
+ * {@literal Number <: ? extends Number}
+ */
+ @Test
+ public void isAssignableWithBoundFromUpperBoundedWildcardType()
+ {
+ assertAssignable(Number.class, Types.upperBoundedWildcardType(Number.class));
+ }
+
+ /**
+ * Tests that upper bounded wildcards are assignable to supertypes of their upper bound.
+ *
+ * {@literal Number <: ? extends Integer}
+ */
+ @Test
+ public void isAssignableWithBoundSupertypeFromUpperBoundedWildcardType()
+ {
+ assertAssignable(Number.class, Types.upperBoundedWildcardType(Integer.class));
+ }
+
+ /**
+ * Tests that upper bounded wildcards are not assignable to subtypes of their upper bound.
+ *
+ * {@literal Integer !<: ? extends Number}
+ */
+ @Test
+ public void isAssignableWithBoundSubtypeFromUpperBoundedWildcardType()
+ {
+ assertUnassignable(Integer.class, Types.upperBoundedWildcardType(Number.class));
+ }
+
+ /**
+ * Tests that lower bounded wildcards are assignable to Object.
+ *
+ * {@literal Object <: ? super Number}
+ */
+ @Test
+ public void isAssignableWithObjectFromLowerBoundedWildcardType()
+ {
+ assertAssignable(Object.class, Types.lowerBoundedWildcardType(Number.class));
+ }
+
+ /**
+ * Tests that lower bounded wildcards are not assignable to their lower bound.
+ *
+ * {@literal Number !<: ? super Number}
+ */
+ @Test
+ public void isAssignableWithBoundFromLowerBoundedWildcardType()
+ {
+ assertUnassignable(Number.class, Types.lowerBoundedWildcardType(Number.class));
+ }
+
+ /**
+ * Tests that lower bounded wildcards are not assignable to supertypes of their lower bound.
+ *
+ * {@literal Number !<: ? super Integer}
+ */
+ @Test
+ public void isAssignableWithBoundSupertypeFromLowerBoundedWildcardType()
+ {
+ assertUnassignable(Number.class, Types.lowerBoundedWildcardType(Integer.class));
+ }
+
+ /**
+ * Tests that upper bounded wildcards are not assignable to subtypes of their upper bound.
+ *
+ * {@literal Integer <: ? super Number}
+ */
+ @Test
+ public void isAssignableWithBoundSubtypeFromLowerBoundedWildcardType()
+ {
+ assertUnassignable(Integer.class, Types.lowerBoundedWildcardType(Number.class));
+ }
+
// isInstance tests -------------------------------------------------------
@Test(expected = NullPointerException.class)
@@ -948,6 +1061,58 @@ public class TypeUtilsTest
assertFalse(TypeUtils.isArray(Types.unboundedWildcardType()));
}
+ // isPrimitive tests ------------------------------------------------------
+
+ @Test
+ public void isPrimitiveWithNull()
+ {
+ assertFalse(TypeUtils.isPrimitive(null));
+ }
+
+ @Test
+ public void isPrimitiveWithPrimitives()
+ {
+ assertTrue(TypeUtils.isPrimitive(Boolean.TYPE));
+ assertTrue(TypeUtils.isPrimitive(Character.TYPE));
+ assertTrue(TypeUtils.isPrimitive(Byte.TYPE));
+ assertTrue(TypeUtils.isPrimitive(Short.TYPE));
+ assertTrue(TypeUtils.isPrimitive(Integer.TYPE));
+ assertTrue(TypeUtils.isPrimitive(Long.TYPE));
+ assertTrue(TypeUtils.isPrimitive(Float.TYPE));
+ assertTrue(TypeUtils.isPrimitive(Double.TYPE));
+ assertTrue(TypeUtils.isPrimitive(Void.TYPE));
+ }
+
+ @Test
+ public void isPrimitiveWithClass()
+ {
+ assertFalse(TypeUtils.isPrimitive(Integer.class));
+ }
+
+ @Test
+ public void isPrimitiveWithTypeVariable()
+ {
+ assertFalse(TypeUtils.isPrimitive(Types.typeVariable(declaration, "T")));
+ }
+
+ @Test
+ public void isPrimitiveWithGenericArrayType()
+ {
+ assertFalse(TypeUtils.isPrimitive(Types.genericArrayType(Integer.class)));
+ }
+
+ @Test
+ public void isPrimitiveWithParameterizedType()
+ {
+ assertFalse(TypeUtils.isPrimitive(Types.parameterizedType(List.class, Integer.class)));
+ }
+
+ @Test
+ public void isPrimitiveWithWildcardType()
+ {
+ assertFalse(TypeUtils.isPrimitive(Types.unboundedWildcardType()));
+ }
+
// getComponentType tests -------------------------------------------------
@Test
@@ -1034,6 +1199,50 @@ public class TypeUtilsTest
TypeUtils.getArrayType(Types.unboundedWildcardType()));
}
+ // isParameterizedType tests ----------------------------------------------
+
+ @Test(expected = NullPointerException.class)
+ public void isParameterizedTypeWithNullType()
+ {
+ TypeUtils.isParameterizedType(null, List.class);
+ }
+
+ @Test(expected = NullPointerException.class)
+ public void isParameterizedTypeWithNullRawType()
+ {
+ TypeUtils.isParameterizedType(List.class, null);
+ }
+
+ @Test
+ public void isParameterizedTypeWithSameRawType()
+ {
+ assertTrue(TypeUtils.isParameterizedType(valueOf("List<Integer>"), List.class));
+ }
+
+ @Test
+ public void isParameterizedTypeWithSuperRawType()
+ {
+ assertTrue(TypeUtils.isParameterizedType(valueOf("List<Integer>"), Collection.class));
+ }
+
+ @Test
+ public void isParameterizedTypeWithUnassignableRawType()
+ {
+ assertFalse(TypeUtils.isParameterizedType(valueOf("List<Integer>"), Number.class));
+ }
+
+ @Test
+ public void isParameterizedTypeWithClass()
+ {
+ assertFalse(TypeUtils.isParameterizedType(List.class, List.class));
+ }
+
+ @Test
+ public void isParameterizedTypeWithParameterizedTypeArgument()
+ {
+ assertTrue(TypeUtils.isParameterizedType(valueOf("List<List<Integer>>"), List.class));
+ }
+
// isSimpleParameterizedType tests ----------------------------------------
@Test(expected = NullPointerException.class)
@@ -1092,6 +1301,48 @@ public class TypeUtilsTest
assertEquals(Integer.class, TypeUtils.getActualTypeArgument(valueOf("List<Integer>")));
}
+ @Test(expected = IllegalArgumentException.class)
+ public void getActualTypeArgumentWithUnparameterizedType()
+ {
+ TypeUtils.getActualTypeArgument(Integer.class);
+ }
+
+ @Test(expected = NullPointerException.class)
+ public void getActualTypeArgumentIndexWithNull()
+ {
+ TypeUtils.getActualTypeArgument(null, 0);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void getActualTypeArgumentIndexWithUnparameterizedType()
+ {
+ TypeUtils.getActualTypeArgument(Integer.class, 0);
+ }
+
+ @Test
+ public void getActualTypeArgumentIndexWithFirstIndex()
+ {
+ assertEquals(Integer.class, TypeUtils.getActualTypeArgument(valueOf("List<Integer>"), 0));
+ }
+
+ @Test
+ public void getActualTypeArgumentIndexWithSecondIndex()
+ {
+ assertEquals(Number.class, TypeUtils.getActualTypeArgument(valueOf("Map<Integer, Number>"), 1));
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void getActualTypeArgumentIndexWithNegativeIndex()
+ {
+ TypeUtils.getActualTypeArgument(valueOf("List<Integer>"), -1);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void getActualTypeArgumentIndexWithOutOfBoundsIndex()
+ {
+ TypeUtils.getActualTypeArgument(valueOf("List<Integer>"), 1);
+ }
+
// getResolvedSuperclass tests ---------------------------------------------
@Test
@@ -1251,6 +1502,12 @@ public class TypeUtilsTest
}
@Test
+ public void toStringWithMultidimensionalArrayClass()
+ {
+ assertEquals("java.lang.Integer[][]", TypeUtils.toString(Integer[][].class));
+ }
+
+ @Test
public void toStringWithUnboundedTypeVariable()
{
assertEquals("T", TypeUtils.toString(Types.typeVariable(declaration, "T")));
diff --git a/src/test/java/com/googlecode/jtype/TypesTest.java b/src/test/java/com/googlecode/jtype/TypesTest.java
index 9155f60..168fa92 100644
--- a/src/test/java/com/googlecode/jtype/TypesTest.java
+++ b/src/test/java/com/googlecode/jtype/TypesTest.java
@@ -15,10 +15,12 @@
*/
package com.googlecode.jtype;
-import static org.junit.Assert.assertArrayEquals;
+import static com.googlecode.jtype.test.TypeAssert.assertGenericArrayType;
+import static com.googlecode.jtype.test.TypeAssert.assertParameterizedType;
+import static com.googlecode.jtype.test.TypeAssert.assertTypeVariable;
+import static com.googlecode.jtype.test.TypeAssert.assertWildcardType;
import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertSame;
import java.lang.reflect.Constructor;
import java.lang.reflect.GenericArrayType;
@@ -48,7 +50,7 @@ import org.junit.runner.RunWith;
* Tests {@code Types}.
*
* @author Mark Hobson
- * @version $Id: TypesTest.java 37 2009-07-24 11:27:39Z markhobson $
+ * @version $Id: TypesTest.java 115 2011-11-25 18:17:40Z markhobson at gmail.com $
* @see Types
*/
@RunWith(JMock.class)
@@ -100,11 +102,8 @@ public class TypesTest
Constructor<TypesTest> constructor = TypesTest.class.getConstructor();
TypeVariable<Constructor<TypesTest>> typeVariable = Types.typeVariable(constructor, "T");
-
- assertNotNull(typeVariable);
- assertEquals(constructor, typeVariable.getGenericDeclaration());
- assertEquals("T", typeVariable.getName());
- assertArrayEquals(new Type[] {Object.class}, typeVariable.getBounds());
+
+ assertTypeVariable(constructor, "T", new Type[] {Object.class}, typeVariable);
}
@Test
@@ -115,10 +114,7 @@ public class TypesTest
TypeVariable<Constructor<TypesTest>> typeVariable = Types.typeVariable(constructor, "T", Number.class,
Comparable.class);
- assertNotNull(typeVariable);
- assertEquals(constructor, typeVariable.getGenericDeclaration());
- assertEquals("T", typeVariable.getName());
- assertArrayEquals(new Type[] {Number.class, Comparable.class}, typeVariable.getBounds());
+ assertTypeVariable(constructor, "T", new Type[] {Number.class, Comparable.class}, typeVariable);
}
// genericArrayType tests -------------------------------------------------
@@ -128,8 +124,7 @@ public class TypesTest
{
GenericArrayType type = Types.genericArrayType(Integer.class);
- assertNotNull(type);
- assertEquals(Integer.class, type.getGenericComponentType());
+ assertGenericArrayType(Integer.class, type);
}
@Test(expected = NullPointerException.class)
@@ -154,10 +149,7 @@ public class TypesTest
{
ParameterizedType type = Types.parameterizedType(Map.class, new Type[] {String.class, Integer.class});
- assertNotNull(type);
- assertEquals(Map.class, type.getRawType());
- assertNull(type.getOwnerType());
- assertArrayEquals(new Type[] {String.class, Integer.class}, type.getActualTypeArguments());
+ assertParameterizedType(Map.class, new Type[] {String.class, Integer.class}, type);
assertEquals(type, stringIntegerMapType);
assertEquals(stringIntegerMapType, type);
@@ -178,15 +170,10 @@ public class TypesTest
}
}
- @Test
- public void parameterizedTypeWithNoActualTypeArguments()
+ @Test(expected = MalformedParameterizedTypeException.class)
+ public void parameterizedTypeWithUnparameterizedRawType()
{
- ParameterizedType type = Types.parameterizedType(Integer.class);
-
- assertNotNull(type);
- assertEquals(Integer.class, type.getRawType());
- assertNull(type.getOwnerType());
- assertArrayEquals(new Type[0], type.getActualTypeArguments());
+ Types.parameterizedType(Integer.class);
}
@Test(expected = MalformedParameterizedTypeException.class)
@@ -195,21 +182,55 @@ public class TypesTest
Types.parameterizedType(Map.class, String.class);
}
+ @Test
+ public void unboundedParameterizedType()
+ {
+ ParameterizedType type = Types.unboundedParameterizedType(Map.class);
+
+ Type[] expectedActualTypeArguments = new Type[] {Types.unboundedWildcardType(), Types.unboundedWildcardType()};
+ assertParameterizedType(Map.class, expectedActualTypeArguments, type);
+ }
+
+ @Test(expected = NullPointerException.class)
+ public void unboundedParameterizedTypeWithNullRawType()
+ {
+ try
+ {
+ Types.unboundedParameterizedType(null);
+ }
+ catch (NullPointerException exception)
+ {
+ assertEquals("rawType cannot be null", exception.getMessage());
+
+ throw exception;
+ }
+ }
+
+ @Test(expected = MalformedParameterizedTypeException.class)
+ public void unboundedParameterizedTypeWithUnparameterizedRawType()
+ {
+ Types.unboundedParameterizedType(Integer.class);
+ }
+
// unboundedWildcardType tests --------------------------------------------
@Test
public void unboundedWildcardType()
{
WildcardType type = Types.unboundedWildcardType();
-
- assertNotNull(type);
- assertArrayEquals(new Type[] {Object.class}, type.getUpperBounds());
- assertArrayEquals(new Type[0], type.getLowerBounds());
+
+ assertWildcardType(new Type[] {Object.class}, new Type[0], type);
assertEquals(type, unboundedWildcardType);
assertEquals(unboundedWildcardType, type);
}
+ @Test
+ public void unboundedWildcardTypeIsCached()
+ {
+ assertSame(Types.unboundedWildcardType(), Types.unboundedWildcardType());
+ }
+
// upperBoundedWildcardType tests -----------------------------------------
@Test
@@ -217,9 +238,7 @@ public class TypesTest
{
WildcardType type = Types.upperBoundedWildcardType(Number.class);
- assertNotNull(type);
- assertArrayEquals(new Type[] {Number.class}, type.getUpperBounds());
- assertArrayEquals(new Type[0], type.getLowerBounds());
+ assertWildcardType(new Type[] {Number.class}, new Type[0], type);
assertEquals(type, numberUpperBoundedWildcardType);
assertEquals(numberUpperBoundedWildcardType, type);
@@ -247,9 +266,7 @@ public class TypesTest
{
WildcardType type = Types.lowerBoundedWildcardType(Integer.class);
- assertNotNull(type);
- assertArrayEquals(new Type[] {Object.class}, type.getUpperBounds());
- assertArrayEquals(new Type[] {Integer.class}, type.getLowerBounds());
+ assertWildcardType(new Type[] {Object.class}, new Type[] {Integer.class}, type);
assertEquals(type, integerLowerBoundedWildcardType);
assertEquals(integerLowerBoundedWildcardType, type);
@@ -273,6 +290,54 @@ public class TypesTest
// valueOf tests ----------------------------------------------------------
@Test
+ public void valueOfWithBooleanPrimitive()
+ {
+ assertEquals(Boolean.TYPE, Types.valueOf("boolean"));
+ }
+
+ @Test
+ public void valueOfWithBytePrimitive()
+ {
+ assertEquals(Byte.TYPE, Types.valueOf("byte"));
+ }
+
+ @Test
+ public void valueOfWithCharPrimitive()
+ {
+ assertEquals(Character.TYPE, Types.valueOf("char"));
+ }
+
+ @Test
+ public void valueOfWithDoublePrimitive()
+ {
+ assertEquals(Double.TYPE, Types.valueOf("double"));
+ }
+
+ @Test
+ public void valueOfWithFloatPrimitive()
+ {
+ assertEquals(Float.TYPE, Types.valueOf("float"));
+ }
+
+ @Test
+ public void valueOfWithIntPrimitive()
+ {
+ assertEquals(Integer.TYPE, Types.valueOf("int"));
+ }
+
+ @Test
+ public void valueOfWithLongPrimitive()
+ {
+ assertEquals(Long.TYPE, Types.valueOf("long"));
+ }
+
+ @Test
+ public void valueOfWithShortPrimitive()
+ {
+ assertEquals(Short.TYPE, Types.valueOf("short"));
+ }
+
+ @Test
public void valueOfWithClass()
{
assertEquals(Integer.class, Types.valueOf("java.lang.Integer"));
@@ -351,6 +416,13 @@ public class TypesTest
public void valueOfWithMultipleArgumentParameterizedType()
{
assertEquals(Types.parameterizedType(Map.class, String.class, Integer.class),
+ Types.valueOf("java.util.Map<java.lang.String, java.lang.Integer>"));
+ }
+
+ @Test
+ public void valueOfWithMultipleArgumentParameterizedTypeAndNoWhitespace()
+ {
+ assertEquals(Types.parameterizedType(Map.class, String.class, Integer.class),
Types.valueOf("java.util.Map<java.lang.String,java.lang.Integer>"));
}
@@ -365,7 +437,7 @@ public class TypesTest
public void valueOfWithMultipleUnboundedWildcardParameterizedType()
{
assertEquals(Types.parameterizedType(Map.class, Types.unboundedWildcardType(), Types.unboundedWildcardType()),
- Types.valueOf("java.util.Map<?,?>"));
+ Types.valueOf("java.util.Map<?, ?>"));
}
@Test(expected = MalformedParameterizedTypeException.class)
@@ -388,7 +460,7 @@ public class TypesTest
Types.parameterizedType(List.class, Integer.class));
assertEquals(expected,
- Types.valueOf("java.util.Map<java.util.List<java.lang.String>,java.util.List<java.lang.Integer>>"));
+ Types.valueOf("java.util.Map<java.util.List<java.lang.String>, java.util.List<java.lang.Integer>>"));
}
@Test
@@ -427,6 +499,12 @@ public class TypesTest
assertEquals(Types.lowerBoundedWildcardType(Integer.class), Types.valueOf(" ? super java.lang.Integer "));
}
+ @Test(expected = NullPointerException.class)
+ public void valueOfWithNullTypeName()
+ {
+ Types.valueOf(null);
+ }
+
@Test
public void valueOfWithClassAndImportContext()
{
@@ -505,6 +583,12 @@ public class TypesTest
assertEquals(Types.upperBoundedWildcardType(Number.class), Types.valueOf("? extends Number", importContext));
}
+ @Test
+ public void valueOfWithClassAndNullImportContext()
+ {
+ assertEquals(Integer.class, Types.valueOf("java.lang.Integer", null));
+ }
+
// private methods --------------------------------------------------------
private Type getFieldType(String name) throws NoSuchFieldException
diff --git a/src/test/java/com/googlecode/jtype/test/AbstractTypeTest.java b/src/test/java/com/googlecode/jtype/test/AbstractTypeTest.java
new file mode 100644
index 0000000..a15c375
--- /dev/null
+++ b/src/test/java/com/googlecode/jtype/test/AbstractTypeTest.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2011 IIZUKA Software Technologies Ltd
+ *
+ * Licensed 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 com.googlecode.jtype.test;
+
+import java.lang.reflect.Type;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+import com.googlecode.jtype.Types;
+
+import org.junit.Before;
+
+/**
+ * Provides support for testing with types.
+ *
+ * @author Mark Hobson
+ * @version $Id: AbstractTypeTest.java 115 2011-11-25 18:17:40Z markhobson at gmail.com $
+ */
+public abstract class AbstractTypeTest
+{
+ // fields -----------------------------------------------------------------
+
+ private Set<String> imports;
+
+ // public methods ---------------------------------------------------------
+
+ @Before
+ public final void setUpAbstractTypeTest()
+ {
+ imports = Collections.unmodifiableSet(new HashSet<String>(createImports()));
+ }
+
+ // protected methods ------------------------------------------------------
+
+ protected void addImports(Set<Class<?>> imports)
+ {
+ // no-op
+ }
+
+ protected final Type type(String typeName)
+ {
+ return Types.valueOf(typeName, imports);
+ }
+
+ // private methods --------------------------------------------------------
+
+ private Set<String> createImports()
+ {
+ Set<Class<?>> classImports = new HashSet<Class<?>>();
+ addImports(classImports);
+ return toClassNames(classImports);
+ }
+
+ private static Set<String> toClassNames(Collection<Class<?>> classes)
+ {
+ Set<String> names = new HashSet<String>();
+
+ for (Class<?> klass : classes)
+ {
+ names.add(klass.getName());
+ }
+
+ return names;
+ }
+}
diff --git a/src/test/java/com/googlecode/jtype/test/SerializableAssert.java b/src/test/java/com/googlecode/jtype/test/SerializableAssert.java
new file mode 100644
index 0000000..9ac64ef
--- /dev/null
+++ b/src/test/java/com/googlecode/jtype/test/SerializableAssert.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2010 IIZUKA Software Technologies Ltd
+ *
+ * Licensed 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 com.googlecode.jtype.test;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+
+/**
+ * Provides custom assertions for testing serializable objects.
+ *
+ * @author Mark Hobson
+ * @version $Id: SerializableAssert.java 115 2011-11-25 18:17:40Z markhobson at gmail.com $
+ */
+public final class SerializableAssert
+{
+ // constructors -----------------------------------------------------------
+
+ private SerializableAssert()
+ {
+ throw new AssertionError();
+ }
+
+ // public methods ---------------------------------------------------------
+
+ public static void assertSerializable(Object object) throws IOException, ClassNotFoundException
+ {
+ byte[] bytes = serialize(object);
+ Object actual = deserialize(bytes);
+
+ assertEquals("Serialized object", object, actual);
+ }
+
+ // private methods --------------------------------------------------------
+
+ private static byte[] serialize(Object object) throws IOException
+ {
+ ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
+ ObjectOutputStream objectOut = new ObjectOutputStream(byteOut);
+
+ try
+ {
+ objectOut.writeObject(object);
+ }
+ finally
+ {
+ objectOut.close();
+ }
+
+ return byteOut.toByteArray();
+ }
+
+ private static Object deserialize(byte[] bytes) throws IOException, ClassNotFoundException
+ {
+ ByteArrayInputStream byteIn = new ByteArrayInputStream(bytes);
+ ObjectInputStream objectIn = new ObjectInputStream(byteIn);
+
+ try
+ {
+ return objectIn.readObject();
+ }
+ finally
+ {
+ objectIn.close();
+ }
+ }
+}
diff --git a/src/test/java/com/googlecode/jtype/test/TypeAssert.java b/src/test/java/com/googlecode/jtype/test/TypeAssert.java
new file mode 100644
index 0000000..b3a2867
--- /dev/null
+++ b/src/test/java/com/googlecode/jtype/test/TypeAssert.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2011 IIZUKA Software Technologies Ltd
+ *
+ * Licensed 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 com.googlecode.jtype.test;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+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;
+
+/**
+ * Provides custom assertions for testing types.
+ *
+ * @author Mark Hobson
+ * @version $Id: TypeAssert.java 115 2011-11-25 18:17:40Z markhobson at gmail.com $
+ */
+public final class TypeAssert
+{
+ // constructors -----------------------------------------------------------
+
+ private TypeAssert()
+ {
+ throw new AssertionError();
+ }
+
+ // public methods ---------------------------------------------------------
+
+ public static <D extends GenericDeclaration> void assertTypeVariable(D expectedGenericDeclaration,
+ String expectedName, Type[] expectedBounds, TypeVariable<D> actual)
+ {
+ assertNotNull(actual);
+ assertEquals("Generic declaration", expectedGenericDeclaration, actual.getGenericDeclaration());
+ assertEquals("Name", expectedName, actual.getName());
+ assertArrayEquals("Bounds", expectedBounds, actual.getBounds());
+ }
+
+ public static void assertGenericArrayType(Type expectedComponentType, GenericArrayType actual)
+ {
+ assertNotNull(actual);
+ assertEquals("Component type", expectedComponentType, actual.getGenericComponentType());
+ }
+
+ public static void assertParameterizedType(Class<?> expectedRawType, Type[] expectedActualTypeArguments,
+ ParameterizedType actual)
+ {
+ assertParameterizedType(null, expectedRawType, expectedActualTypeArguments, actual);
+ }
+
+ public static void assertParameterizedType(Type expectedOwnerType, Class<?> expectedRawType,
+ Type[] expectedActualTypeArguments, ParameterizedType actual)
+ {
+ assertNotNull(actual);
+ assertEquals("Owner type", expectedOwnerType, actual.getOwnerType());
+ assertEquals("Raw type", expectedRawType, actual.getRawType());
+ assertArrayEquals("Actual type arguments", expectedActualTypeArguments, actual.getActualTypeArguments());
+ }
+
+ public static void assertWildcardType(Type[] expectedUpperBounds, Type[] expectedLowerBounds, WildcardType actual)
+ {
+ assertNotNull(actual);
+ assertArrayEquals("Upper bounds", expectedUpperBounds, actual.getUpperBounds());
+ assertArrayEquals("Lower bounds", expectedLowerBounds, actual.getLowerBounds());
+ }
+}
--
Helper library for the Java 5 Type
More information about the pkg-java-commits
mailing list