package com.google.gson.internal;
import java.io.Serializable;
import java.lang.reflect.Array;
import java.lang.reflect.GenericArrayType;
import java.lang.reflect.GenericDeclaration;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.lang.reflect.WildcardType;
import java.util.Arrays;
import java.util.Collection;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Properties;
public final class $Gson$Types
{
static final Type[] EMPTY_TYPE_ARRAY = new Type[0];
public static ParameterizedType newParameterizedTypeWithOwner(Type ownerType, Type rawType, Type[] typeArguments)
{
return new ParameterizedTypeImpl(ownerType, rawType, typeArguments);
}
public static GenericArrayType arrayOf(Type componentType)
{
return new GenericArrayTypeImpl(componentType);
}
public static WildcardType subtypeOf(Type bound)
{
return new WildcardTypeImpl(new Type[] { bound }, EMPTY_TYPE_ARRAY);
}
public static WildcardType supertypeOf(Type bound)
{
return new WildcardTypeImpl(new Type[] { Object.class }, new Type[] { bound });
}
public static Type canonicalize(Type type)
{
if ((type instanceof Class)) {
Class c = (Class)type;
return c.isArray() ? new GenericArrayTypeImpl(canonicalize(c.getComponentType())) : c;
}
if ((type instanceof ParameterizedType)) {
ParameterizedType p = (ParameterizedType)type;
return new ParameterizedTypeImpl(p.getOwnerType(), p.getRawType(), p.getActualTypeArguments());
}
if ((type instanceof GenericArrayType)) {
GenericArrayType g = (GenericArrayType)type;
return new GenericArrayTypeImpl(g.getGenericComponentType());
}
if ((type instanceof WildcardType)) {
WildcardType w = (WildcardType)type;
return new WildcardTypeImpl(w.getUpperBounds(), w.getLowerBounds());
}
return type;
}
public static Class<?> getRawType(Type type)
{
if ((type instanceof Class))
{
return (Class)type;
}
if ((type instanceof ParameterizedType)) {
ParameterizedType parameterizedType = (ParameterizedType)type;
Type rawType = parameterizedType.getRawType();
.Gson.Preconditions.checkArgument(rawType instanceof Class);
return (Class)rawType;
}
if ((type instanceof GenericArrayType)) {
Type componentType = ((GenericArrayType)type).getGenericComponentType();
return Array.newInstance(getRawType(componentType), 0).getClass();
}
if ((type instanceof TypeVariable))
{
return Object.class;
}
if ((type instanceof WildcardType)) {
return getRawType(((WildcardType)type).getUpperBounds()[0]);
}
String className = type == null ? "null" : type.getClass().getName();
throw new IllegalArgumentException("Expected a Class, ParameterizedType, or GenericArrayType, but <" + type + "> is of type " + className);
}
static boolean equal(Object a, Object b)
{
return (a == b) || ((a != null) && (a.equals(b)));
}
public static boolean equals(Type a, Type b)
{
if (a == b)
{
return true;
}
if ((a instanceof Class))
{
return a.equals(b);
}
if ((a instanceof ParameterizedType)) {
if (!(b instanceof ParameterizedType)) {
return false;
}
ParameterizedType pa = (ParameterizedType)a;
ParameterizedType pb = (ParameterizedType)b;
return (equal(pa.getOwnerType(), pb.getOwnerType())) && (pa.getRawType().equals(pb.getRawType())) && (Arrays.equals(pa.getActualTypeArguments(), pb.getActualTypeArguments()));
}
if ((a instanceof GenericArrayType)) {
if (!(b instanceof GenericArrayType)) {
return false;
}
GenericArrayType ga = (GenericArrayType)a;
GenericArrayType gb = (GenericArrayType)b;
return equals(ga.getGenericComponentType(), gb.getGenericComponentType());
}
if ((a instanceof WildcardType)) {
if (!(b instanceof WildcardType)) {
return false;
}
WildcardType wa = (WildcardType)a;
WildcardType wb = (WildcardType)b;
return (Arrays.equals(wa.getUpperBounds(), wb.getUpperBounds())) && (Arrays.equals(wa.getLowerBounds(), wb.getLowerBounds()));
}
if ((a instanceof TypeVariable)) {
if (!(b instanceof TypeVariable)) {
return false;
}
TypeVariable va = (TypeVariable)a;
TypeVariable vb = (TypeVariable)b;
return (va.getGenericDeclaration() == vb.getGenericDeclaration()) && (va.getName().equals(vb.getName()));
}
return false;
}
private static int hashCodeOrZero(Object o)
{
return o != null ? o.hashCode() : 0;
}
public static String typeToString(Type type) {
return (type instanceof Class) ? ((Class)type).getName() : type.toString();
}
static Type getGenericSupertype(Type context, Class<?> rawType, Class<?> toResolve)
{
if (toResolve == rawType) {
return context;
}
if (toResolve.isInterface()) {
Class[] interfaces = rawType.getInterfaces();
int i = 0; for (int length = interfaces.length; i < length; i++) {
if (interfaces[i] == toResolve)
return rawType.getGenericInterfaces()[i];
if (toResolve.isAssignableFrom(interfaces[i])) {
return getGenericSupertype(rawType.getGenericInterfaces()[i], interfaces[i], toResolve);
}
}
}
if (!rawType.isInterface()) {
while (rawType != Object.class) {
Class rawSupertype = rawType.getSuperclass();
if (rawSupertype == toResolve)
return rawType.getGenericSuperclass();
if (toResolve.isAssignableFrom(rawSupertype)) {
return getGenericSupertype(rawType.getGenericSuperclass(), rawSupertype, toResolve);
}
rawType = rawSupertype;
}
}
return toResolve;
}
static Type getSupertype(Type context, Class<?> contextRawType, Class<?> supertype)
{
.Gson.Preconditions.checkArgument(supertype.isAssignableFrom(contextRawType));
return resolve(context, contextRawType, getGenericSupertype(context, contextRawType, supertype));
}
public static Type getArrayComponentType(Type array)
{
return (array instanceof GenericArrayType) ? ((GenericArrayType)array).getGenericComponentType() : ((Class)array).getComponentType();
}
public static Type getCollectionElementType(Type context, Class<?> contextRawType)
{
Type collectionType = getSupertype(context, contextRawType, Collection.class);
if ((collectionType instanceof WildcardType)) {
collectionType = ((WildcardType)collectionType).getUpperBounds()[0];
}
if ((collectionType instanceof ParameterizedType)) {
return ((ParameterizedType)collectionType).getActualTypeArguments()[0];
}
return Object.class;
}
public static Type[] getMapKeyAndValueTypes(Type context, Class<?> contextRawType)
{
if (context == Properties.class) {
return new Type[] { String.class, String.class };
}
Type mapType = getSupertype(context, contextRawType, Map.class);
if ((mapType instanceof ParameterizedType)) {
ParameterizedType mapParameterizedType = (ParameterizedType)mapType;
return mapParameterizedType.getActualTypeArguments();
}
return new Type[] { Object.class, Object.class };
}
public static Type resolve(Type context, Class<?> contextRawType, Type toResolve)
{
while ((toResolve instanceof TypeVariable)) {
TypeVariable typeVariable = (TypeVariable)toResolve;
toResolve = resolveTypeVariable(context, contextRawType, typeVariable);
if (toResolve == typeVariable) {
return toResolve;
}
}
if (((toResolve instanceof Class)) && (((Class)toResolve).isArray())) {
Class original = (Class)toResolve;
Type componentType = original.getComponentType();
Type newComponentType = resolve(context, contextRawType, componentType);
return componentType == newComponentType ? original : arrayOf(newComponentType);
}
if ((toResolve instanceof GenericArrayType)) {
GenericArrayType original = (GenericArrayType)toResolve;
Type componentType = original.getGenericComponentType();
Type newComponentType = resolve(context, contextRawType, componentType);
return componentType == newComponentType ? original : arrayOf(newComponentType);
}
if ((toResolve instanceof ParameterizedType)) {
ParameterizedType original = (ParameterizedType)toResolve;
Type ownerType = original.getOwnerType();
Type newOwnerType = resolve(context, contextRawType, ownerType);
boolean changed = newOwnerType != ownerType;
Type[] args = original.getActualTypeArguments();
int t = 0; for (int length = args.length; t < length; t++) {
Type resolvedTypeArgument = resolve(context, contextRawType, args[t]);
if (resolvedTypeArgument != args[t]) {
if (!changed) {
args = (Type[])args.clone();
changed = true;
}
args[t] = resolvedTypeArgument;
}
}
return changed ? newParameterizedTypeWithOwner(newOwnerType, original.getRawType(), args) : original;
}
if ((toResolve instanceof WildcardType)) {
WildcardType original = (WildcardType)toResolve;
Type[] originalLowerBound = original.getLowerBounds();
Type[] originalUpperBound = original.getUpperBounds();
if (originalLowerBound.length == 1) {
Type lowerBound = resolve(context, contextRawType, originalLowerBound[0]);
if (lowerBound != originalLowerBound[0])
return supertypeOf(lowerBound);
}
else if (originalUpperBound.length == 1) {
Type upperBound = resolve(context, contextRawType, originalUpperBound[0]);
if (upperBound != originalUpperBound[0]) {
return subtypeOf(upperBound);
}
}
return original;
}
return toResolve;
}
static Type resolveTypeVariable(Type context, Class<?> contextRawType, TypeVariable<?> unknown)
{
Class declaredByRaw = declaringClassOf(unknown);
if (declaredByRaw == null) {
return unknown;
}
Type declaredBy = getGenericSupertype(context, contextRawType, declaredByRaw);
if ((declaredBy instanceof ParameterizedType)) {
int index = indexOf(declaredByRaw.getTypeParameters(), unknown);
return ((ParameterizedType)declaredBy).getActualTypeArguments()[index];
}
return unknown;
}
private static int indexOf(Object[] array, Object toFind) {
for (int i = 0; i < array.length; i++) {
if (toFind.equals(array[i])) {
return i;
}
}
throw new NoSuchElementException();
}
private static Class<?> declaringClassOf(TypeVariable<?> typeVariable)
{
GenericDeclaration genericDeclaration = typeVariable.getGenericDeclaration();
return (genericDeclaration instanceof Class) ? (Class)genericDeclaration : null;
}
private static void checkNotPrimitive(Type type)
{
.Gson.Preconditions.checkArgument((!(type instanceof Class)) || (!((Class)type).isPrimitive()));
}
private static final class GenericArrayTypeImpl
implements Serializable, GenericArrayType
{
private final Type componentType;
public GenericArrayTypeImpl(Type componentType)
{
this.componentType = .Gson.Types.canonicalize(componentType);
}
public Type getGenericComponentType() {
return this.componentType;
}
public boolean equals(Object o) {
return ((o instanceof GenericArrayType)) && (.Gson.Types.equals(this, (GenericArrayType)o));
}
public int hashCode()
{
return this.componentType.hashCode();
}
public String toString() {
return .Gson.Types.typeToString(this.componentType) + "[]";
}
}
private static final class ParameterizedTypeImpl
implements Serializable, ParameterizedType
{
private final Type ownerType;
private final Type rawType;
private final Type[] typeArguments;
public ParameterizedTypeImpl(Type ownerType, Type rawType, Type[] typeArguments)
{
if ((rawType instanceof Class)) {
Class rawTypeAsClass = (Class)rawType;
.Gson.Preconditions.checkArgument((ownerType != null) || (rawTypeAsClass.getEnclosingClass() == null));
.Gson.Preconditions.checkArgument((ownerType == null) || (rawTypeAsClass.getEnclosingClass() != null));
}
this.ownerType = (ownerType == null ? null : .Gson.Types.canonicalize(ownerType));
this.rawType = .Gson.Types.canonicalize(rawType);
this.typeArguments = ((Type[])typeArguments.clone());
for (int t = 0; t < this.typeArguments.length; t++) {
.Gson.Preconditions.checkNotNull(this.typeArguments[t]);
.Gson.Types.checkNotPrimitive(this.typeArguments[t]);
this.typeArguments[t] = .Gson.Types.canonicalize(this.typeArguments[t]);
}
}
public Type[] getActualTypeArguments() {
return (Type[])this.typeArguments.clone();
}
public Type getRawType() {
return this.rawType;
}
public Type getOwnerType() {
return this.ownerType;
}
public boolean equals(Object other) {
return ((other instanceof ParameterizedType)) && (.Gson.Types.equals(this, (ParameterizedType)other));
}
public int hashCode()
{
return Arrays.hashCode(this.typeArguments) ^ this.rawType.hashCode() ^ .Gson.Types.hashCodeOrZero(this.ownerType);
}
public String toString()
{
StringBuilder stringBuilder = new StringBuilder(30 * (this.typeArguments.length + 1));
stringBuilder.append(.Gson.Types.typeToString(this.rawType));
if (this.typeArguments.length == 0) {
return stringBuilder.toString();
}
stringBuilder.append("<").append(.Gson.Types.typeToString(this.typeArguments[0]));
for (int i = 1; i < this.typeArguments.length; i++) {
stringBuilder.append(", ").append(.Gson.Types.typeToString(this.typeArguments[i]));
}
return ">";
}
}
private static final class WildcardTypeImpl
implements Serializable, WildcardType
{
private final Type upperBound;
private final Type lowerBound;
public WildcardTypeImpl(Type[] upperBounds, Type[] lowerBounds)
{
.Gson.Preconditions.checkArgument(lowerBounds.length <= 1);
.Gson.Preconditions.checkArgument(upperBounds.length == 1);
if (lowerBounds.length == 1) {
.Gson.Preconditions.checkNotNull(lowerBounds[0]);
.Gson.Types.checkNotPrimitive(lowerBounds[0]);
.Gson.Preconditions.checkArgument(upperBounds[0] == Object.class);
this.lowerBound = .Gson.Types.canonicalize(lowerBounds[0]);
this.upperBound = Object.class;
}
else {
.Gson.Preconditions.checkNotNull(upperBounds[0]);
.Gson.Types.checkNotPrimitive(upperBounds[0]);
this.lowerBound = null;
this.upperBound = .Gson.Types.canonicalize(upperBounds[0]);
}
}
public Type[] getUpperBounds() {
return new Type[] { this.upperBound };
}
public Type[] getLowerBounds() {
return this.lowerBound != null ? new Type[] { this.lowerBound } : .Gson.Types.EMPTY_TYPE_ARRAY;
}
public boolean equals(Object other) {
return ((other instanceof WildcardType)) && (.Gson.Types.equals(this, (WildcardType)other));
}
public int hashCode()
{
return (this.lowerBound != null ? 31 + this.lowerBound.hashCode() : 1) ^ 31 + this.upperBound.hashCode();
}
public String toString()
{
if (this.lowerBound != null)
return "? super " + .Gson.Types.typeToString(this.lowerBound);
if (this.upperBound == Object.class) {
return "?";
}
return "? extends " + .Gson.Types.typeToString(this.upperBound);
}
}
}