Package org.jquantlib.lang.reflect

Source Code of org.jquantlib.lang.reflect.TypeTokenTree

package org.jquantlib.lang.reflect;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;

import org.jquantlib.QL;

/**
* TypeTokenTree is a helper class intended to return a {@link TypeNode} root.
* <p>
* A typical usage consists on obtain a {@link TypeNode} root which can be used to traverse a hierarchy of generic parameters.
* Each {@link TypeNode} holds a Class information and contains a list of children nodes. A typical usage is in the context of
* retrieving actual generic parameters. The example below shows how a generic class can verify at instantiation time
* which actual generic parameters where passed by the caller.
* <code>
* public class TimeSeries<T> {
*
*     public TimeSeries() {
*         this.klass = new TypeTokenTree(this.getClass()).getRoot().get(0).getElement();
*         if (Double.class.isAssignableFrom(klass)) {
*             this.delegate = new SeriesDouble<T>();
*         } else if (IntervalPrice.class.isAssignableFrom(klass)) {
*             this.delegate = new SeriesIntervalPrice<T>();
*         } else {
*             throw new UnsupportedOperationException("only Double and IntervalPrice are supported");
*         }
*     }
* }
* </code>
* Below you can see how the caller code looks like:
* <code>
* TimeSeries<Double> ts = new TimeSeries<Double>() { }
* </code>
* Notice that <code>ts</code> is an anonymous class, denoted by <code>{  }</code>.
*
* @note It's important to remember to instantiate an anonymous class in order to avoid <i>type erasure</i>.
* Doing so, type information will be kept and can be retrieved at runtime.
*
* @see TypeToken
* @see TypeReference
* @see TypeNode
*
* @see <a href="http://gafter.blogspot.com/2006/12/super-type-tokens.html">Super Type Tokens</a>
* @see <a href="http://gafter.blogspot.com/2007/05/limitation-of-super-type-tokens.html">A Limitation of Super Type Tokens</a>
* @see <a href="http://java.sun.com/j2se/1.5/pdf/generics-tutorial.pdf">Generics Tutorial</a>
* @see <a href="http://www.jquantlib.org/index.php/Using_TypeTokens_to_retrieve_generic_parameters">Using TypeTokens to retrieve generic parameters</a>
*
* @author Richard Gomes
*/
public class TypeTokenTree {

    //
    // private fields
    //

    private final TypeNode root;


    //
    // public constructors
    //

    public TypeTokenTree() {
        this.root = retrieve(getClass());
    }

    public TypeTokenTree(final Class<?> klass) {
        this.root = retrieve(klass);
    }

    /**
     * Returns the Class of a generic parameter
     *
     * @param pos represents the position of parameter, first is zero
     * @return the Class of a generic parameter
     */
    public Class<?> getElement(final int pos) {
        if (root==null) {
            return null;
        }
        final TypeNode typeNode = root.get(pos);
        if (typeNode==null) {
            return null;
        }
        return typeNode.getElement();
    }

    //
    // public methods
    //

    public TypeNode getRoot() {
        return root;
    }


    //
    // private methods
    //

    private TypeNode retrieve(final Class<?> klass) {
        final Type superclass = klass.getGenericSuperclass();
        QL.require(!(superclass instanceof Class) , ReflectConstants.SHOULD_BE_ANONYMOUS_OR_EXTENDED); // QA:[RG]::verified
        final TypeNode node = new TypeNode(klass);
        for (final Type t : ((ParameterizedType) superclass).getActualTypeArguments() ) {
            node.add(retrieve(t));
        }
        return node;
    }

    private TypeNode retrieve(final Type type) {
        final TypeNode node;
        if (type instanceof Class<?>) {
            node = new TypeNode((Class<?>)type);
        } else if (type instanceof ParameterizedType) {
            final Type rawType = ((ParameterizedType) type).getRawType();
            node = retrieve(rawType);
            for (final Type arg : ((ParameterizedType) type).getActualTypeArguments()) {
                node.add(retrieve(arg));
                //
                //TODO: code review
                //
                // More test cases need to be done, specially related to Monte Carlo needs on generic parameters
                //
                //        } else if (type instanceof TypeVariable) {
                //            GenericDeclaration declaration = ((TypeVariable) type).getGenericDeclaration();
                //            node = new TypeNode(declaration);
                //            for (Type arg : ((TypeVariable) type).getBounds()) {
                //                node.add(retrieve(arg));
                //            }
                //
            }
        } else {
            throw new IllegalArgumentException(ReflectConstants.ILLEGAL_TYPE_PARAMETER);
        }
        return node;
    }

}
TOP

Related Classes of org.jquantlib.lang.reflect.TypeTokenTree

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.