/*
* Copyright (c) 2011 Google Inc.
*
* 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.google.api.client.util;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables;
import junit.framework.TestCase;
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.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Stack;
import java.util.TreeMap;
import java.util.Vector;
/**
* Tests {@link Types}.
*
* @author Yaniv Inbar
*/
public class TypesTest extends TestCase {
public void testIsAssignableToOrFrom() {
assertTrue(Types.isAssignableToOrFrom(String.class, Object.class));
assertTrue(Types.isAssignableToOrFrom(String.class, String.class));
assertTrue(Types.isAssignableToOrFrom(Object.class, String.class));
assertFalse(Types.isAssignableToOrFrom(String.class, List.class));
}
static class Foo {
}
public void testNewInstance() {
assertEquals(Object.class, Types.newInstance(Object.class).getClass());
assertEquals(String.class, Types.newInstance(String.class).getClass());
assertEquals(Foo.class, Types.newInstance(Foo.class).getClass());
try {
Types.newInstance(int.class);
fail("expected " + IllegalArgumentException.class);
} catch (IllegalArgumentException e) {
}
try {
Types.newInstance(String[].class);
fail("expected " + IllegalArgumentException.class);
} catch (IllegalArgumentException e) {
}
try {
Types.newInstance(Void.class);
fail("expected " + IllegalArgumentException.class);
} catch (IllegalArgumentException e) {
}
}
@SuppressWarnings("serial")
static class IntegerList extends ArrayList<Integer> {
}
static class WildcardBounds {
public Collection<?> any;
public Collection<? extends Number> upper;
public Collection<? super Integer> lower;
}
public void testGetBound() throws Exception {
subtestGetBound(Object.class, "any");
subtestGetBound(Number.class, "upper");
subtestGetBound(Integer.class, "lower");
}
public void subtestGetBound(Type expectedBound, String fieldName) throws Exception {
ParameterizedType collectionType =
(ParameterizedType) WildcardBounds.class.getField(fieldName).getGenericType();
WildcardType wildcardType = (WildcardType) collectionType.getActualTypeArguments()[0];
assertEquals(expectedBound, Types.getBound(wildcardType));
}
static class Resolve<X, T extends Number> {
public T t;
public X x;
}
static class IntegerResolve extends Resolve<Boolean, Integer> {
}
static class MedResolve<T extends Number> extends Resolve<Boolean, T> {
}
static class DoubleResolve extends MedResolve<Double> {
}
static class Med2Resolve<T extends Number> extends MedResolve<T> {
}
static class LongResolve extends Med2Resolve<Long> {
}
static class ArrayResolve extends Resolve<Boolean[], Integer> {
}
static class ParameterizedResolve extends Resolve<Collection<Integer>, Integer> {
}
public void testResolveTypeVariable() throws Exception {
// t
TypeVariable<?> tTypeVar = (TypeVariable<?>) Resolve.class.getField("t").getGenericType();
assertNull(resolveTypeVariable(new Object().getClass(), tTypeVar));
assertNull(resolveTypeVariable(new Resolve<Boolean, Double>().getClass(), tTypeVar));
assertEquals(Integer.class, resolveTypeVariable(new IntegerResolve().getClass(), tTypeVar));
assertEquals(Long.class, resolveTypeVariable(new LongResolve().getClass(), tTypeVar));
assertEquals(Double.class, resolveTypeVariable(new DoubleResolve().getClass(), tTypeVar));
// partially resolved
assertEquals(MedResolve.class,
((TypeVariable<?>) resolveTypeVariable(new MedResolve<Double>().getClass(), tTypeVar))
.getGenericDeclaration());
// x
TypeVariable<?> xTypeVar = (TypeVariable<?>) Resolve.class.getField("x").getGenericType();
assertNull(resolveTypeVariable(new Object().getClass(), xTypeVar));
assertEquals(Boolean.class,
Types.getArrayComponentType(resolveTypeVariable(new ArrayResolve().getClass(), xTypeVar)));
assertEquals(Collection.class, Types.getRawClass(
(ParameterizedType) resolveTypeVariable(new ParameterizedResolve().getClass(), xTypeVar)));
}
private static Type resolveTypeVariable(Type context, TypeVariable<?> typeVariable) {
return Types.resolveTypeVariable(Arrays.asList(context), typeVariable);
}
public class A<T> {
public Iterable<String> i;
public ArrayList<String> a;
@SuppressWarnings({"unchecked", "rawtypes"})
public ArrayList aNoType;
public Stack<? extends Number> wild;
public Vector<Integer[]> arr;
public Vector<T[]> tarr;
public LinkedList<ArrayList<Boolean>> list;
public Iterable<T> tv;
public ArrayList<T> atv;
}
public class B extends A<DateTime> {
}
public void testGetIterableParameter() throws Exception {
assertEquals("T",
((TypeVariable<?>) Types.getIterableParameter(A.class.getField("tv").getGenericType()))
.getName());
assertEquals("T",
((TypeVariable<?>) Types.getIterableParameter(A.class.getField("atv").getGenericType()))
.getName());
assertEquals(String.class, Types.getIterableParameter(A.class.getField("i").getGenericType()));
assertEquals(String.class, Types.getIterableParameter(A.class.getField("a").getGenericType()));
assertEquals("E",
((TypeVariable<?>) Types.getIterableParameter(A.class.getField("aNoType").getGenericType()))
.getName());
assertEquals(Integer.class, Types.getArrayComponentType(
Types.getIterableParameter(A.class.getField("arr").getGenericType())));
assertEquals("T",
((GenericArrayType) Types.getIterableParameter(A.class.getField("tarr").getGenericType()))
.getGenericComponentType().toString());
assertEquals(ArrayList.class,
((ParameterizedType) Types.getIterableParameter(A.class.getField("list").getGenericType()))
.getRawType());
assertEquals(Number.class,
((WildcardType) Types.getIterableParameter(A.class.getField("wild").getGenericType()))
.getUpperBounds()[0]);
}
public class C<T> {
public Map<String, String> i;
public ArrayMap<String, String> a;
@SuppressWarnings({"unchecked", "rawtypes"})
public ArrayMap aNoType;
public TreeMap<String, ? extends Number> wild;
public Vector<Integer[]> arr;
public HashMap<String, T[]> tarr;
public ImmutableMap<String, ArrayList<Boolean>> list;
public Map<String, T> tv;
public ArrayMap<String, T> atv;
}
public class D extends C<DateTime> {
}
public void testGetMapParameter() throws Exception {
assertEquals("T",
((TypeVariable<?>) Types.getMapValueParameter(C.class.getField("tv").getGenericType()))
.getName());
assertEquals("T",
((TypeVariable<?>) Types.getMapValueParameter(C.class.getField("atv").getGenericType()))
.getName());
assertEquals(String.class, Types.getMapValueParameter(C.class.getField("i").getGenericType()));
assertEquals(String.class, Types.getMapValueParameter(C.class.getField("a").getGenericType()));
assertEquals("V",
((TypeVariable<?>) Types.getMapValueParameter(C.class.getField("aNoType").getGenericType()))
.getName());
assertEquals(Integer.class, Types.getArrayComponentType(
Types.getIterableParameter(A.class.getField("arr").getGenericType())));
assertEquals("T", ((GenericArrayType) Types.getMapValueParameter(
C.class.getField("tarr").getGenericType())).getGenericComponentType().toString());
assertEquals(ArrayList.class,
((ParameterizedType) Types.getMapValueParameter(C.class.getField("list").getGenericType()))
.getRawType());
assertEquals(Number.class,
((WildcardType) Types.getMapValueParameter(C.class.getField("wild").getGenericType()))
.getUpperBounds()[0]);
}
public void testIterableOf() {
List<String> list = ImmutableList.of("a");
assertEquals(list, Types.iterableOf(list));
assertEquals(list, Types.iterableOf(new String[] {"a"}));
assertTrue(Iterables.elementsEqual(ImmutableList.of(1), Types.iterableOf(new int[] {1})));
}
public void testToArray() {
assertTrue(
Arrays.equals(new String[] {"a", "b"},
(String[]) Types.toArray(ImmutableList.of("a", "b"), String.class)));
assertTrue(Arrays.equals(
new Integer[] {1, 2}, (Integer[]) Types.toArray(ImmutableList.of(1, 2), Integer.class)));
assertTrue(
Arrays.equals(new int[] {1, 2}, (int[]) Types.toArray(ImmutableList.of(1, 2), int.class)));
int[][] arr = (int[][]) Types.toArray(ImmutableList.of(new int[] {1, 2}), int[].class);
assertEquals(1, arr.length);
assertTrue(Arrays.equals(new int[] {1, 2}, arr[0]));
}
}