package com.fasterxml.jackson.jr.type;

import java.io.Serializable;
import java.util.*;

public class ResolvedType implements java.lang.reflect.Type,
    Serializable
{
    private static final long serialVersionUID = 1L;

    public final static ResolvedType[] NO_TYPES = new ResolvedType[0];

    protected final static int T_ARRAY = 1;
    protected final static int T_INTERFACE = 2;
    protected final static int T_PRIMITIVE = 3;
    protected final static int T_RECURSIVE = 4;
    protected final static int T_REGULAR = 5;
 
    protected final int _kind;

    protected final Class<?> _erasedType;
    protected final TypeBindings _bindings;

    // interfaces implemented
    protected final ResolvedType[] _interfaces;
    // for arrays, type of element contained
    protected final ResolvedType _elemType;
    // for "regular" class types, super-class
    protected final ResolvedType _super;

    // for primitives
    protected ResolvedType(Class<?> cls) {
        this(T_PRIMITIVE, cls, null, null, null, null);
    }

    // for recursive types
    protected ResolvedType(Class<?> cls, TypeBindings bindings) {
        this(T_PRIMITIVE, cls, null, null, null, null);
    }
    
    // for Array type
    protected ResolvedType(Class<?> cls, TypeBindings bindings, ResolvedType elemType) {
        this(T_ARRAY, cls, null, bindings, null, elemType);
    }

    // for Interfaces
    protected ResolvedType(Class<?> cls, TypeBindings bindings, ResolvedType[] ifaces) {
        this(T_INTERFACE, cls, null, bindings, ifaces, null);
    }

    // for "Regular" classes
    protected ResolvedType(Class<?> cls, ResolvedType sup,
            TypeBindings bindings, ResolvedType[] ifaces) {
        this(T_REGULAR, cls, sup, bindings, ifaces, null);
    }
    
    private ResolvedType(int k, Class<?> cls, ResolvedType sup,
            TypeBindings bindings,
            ResolvedType[] ifs, ResolvedType elemType) {
        _kind = k;
        _erasedType = cls;
        _super = sup;
        _bindings = (bindings == null) ? TypeBindings.emptyBindings() : bindings;
        _interfaces = ifs;
        _elemType = elemType;
    }

    public Class<?> erasedType() { return _erasedType; }

    public ResolvedType elementType() { return _elemType; }
    public ResolvedType parentType() { return _super; }

    public boolean isArray() { return _kind == T_ARRAY; }
    
    public final List<ResolvedType> implInterfaces() {
        if (_interfaces == null || _interfaces.length == 0) {
            return Collections.<ResolvedType>emptyList();
        }
        return Arrays.asList(_interfaces);
    }

    public List<ResolvedType> typeParams() { return _bindings.getTypeParameters(); }

    public TypeBindings typeBindings() { return _bindings; }
    
    
Method that will try to find type parameterization this type has for specified super type
Returns:List of type parameters for specified supertype (which may be empty, if supertype is not a parametric type); null if specified type is not a super type of this type
/** * Method that will try to find type parameterization this type * has for specified super type * * @return List of type parameters for specified supertype (which may * be empty, if supertype is not a parametric type); null if specified * type is not a super type of this type */
public List<ResolvedType> typeParametersFor(Class<?> erasedSupertype) { ResolvedType type = findSupertype(erasedSupertype); if (type != null) { return type.typeParams(); } return null; }
Method for finding super type of this type that has specified type erased signature. If supertype is an interface which is implemented using multiple inheritance paths, preference is given to interfaces implemented "highest up the stack" (directly implemented interfaces over interfaces superclass implements).
/** * Method for finding super type of this type that has specified type * erased signature. If supertype is an interface which is implemented * using multiple inheritance paths, preference is given to interfaces * implemented "highest up the stack" (directly implemented interfaces * over interfaces superclass implements). */
public ResolvedType findSupertype(Class<?> erasedSupertype) { if (erasedSupertype == _erasedType) { return this; } // Check super interfaces first: if (erasedSupertype.isInterface()) { for (ResolvedType it : implInterfaces()) { ResolvedType type = it.findSupertype(erasedSupertype); if (type != null) { return type; } } } // and if not found, super class and its supertypes ResolvedType pc = parentType(); if (pc != null) { ResolvedType type = pc.findSupertype(erasedSupertype); if (type != null) { return type; } } // nope; doesn't look like we extend or implement super type in question return null; } public String getDesc() { StringBuilder sb = new StringBuilder(); return appendDesc(sb).toString(); } public StringBuilder appendDesc(StringBuilder sb) { switch (_kind) { case T_PRIMITIVE: return sb.append(_erasedType.getName()); case T_ARRAY: return _elemType.appendDesc(sb).append("[]"); } return _appendClassDesc(sb); } @Override public String toString() { return getDesc(); } @Override public int hashCode() { return _erasedType.getName().hashCode() + _bindings.hashCode(); } @Override public boolean equals(Object o) { if (o == this) return true; // sub-types must be same: if (o == null || o.getClass() != getClass()) return false; // Should be possible to actually implement here... ResolvedType other = (ResolvedType) o; if (other._erasedType != _erasedType) { return false; } // and type bindings must match as well return _bindings.equals(other._bindings); } protected StringBuilder _appendClassDesc(StringBuilder sb) { sb.append(_erasedType.getName()); int count = _bindings.size(); if (count > 0) { sb.append('<'); for (int i = 0; i < count; ++i) { if (i > 0) { sb.append(','); } sb = _bindings.getBoundType(i).appendDesc(sb); } sb.append('>'); } return sb; } }