package com.moparisthebest.jdbc; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.util.Arrays; /** * This generic abstract class is used for obtaining full generics type information * by sub-classing. *

* Class is based on ideas from * http://gafter.blogspot.com/2006/12/super-type-tokens.html, * Additional idea (from a suggestion made in comments of the article) * is to require bogus implementation of Comparable * (any such generic interface would do, as long as it forces a method * with generic type to be implemented). * to ensure that a Type argument is indeed given. *

* Usage is by sub-classing: here is one way to instantiate reference * to generic type List<Integer>: *

 *  TypeReference ref = new TypeReference<List<Integer>>() { };
 * 
* which can be passed to methods that accept TypeReference *

* Pulled from jackson here: * https://raw.githubusercontent.com/FasterXML/jackson-core/3dcedd2b6838ef29abb179557b6e42479e93834b/src/main/java/com/fasterxml/jackson/core/type/TypeReference.java * Thankfully jackson has an identical Apache 2.0 license so no issues there */ public abstract class TypeReference implements Comparable> { private final ParameterizedType type; private final Class rawType; protected TypeReference() { final Type superClass = getClass().getGenericSuperclass(); if (superClass instanceof Class) { // sanity check, should never happen throw new IllegalArgumentException("Internal error: TypeReference constructed without actual type information"); } /* 22-Dec-2008, tatu: Not sure if this case is safe -- I suspect * it is possible to make it fail? * But let's deal with specific * case when we know an actual use case, and thereby suitable * workarounds for valid case(s) and/or error to throw * on invalid one(s). */ final Type type = ((ParameterizedType) superClass).getActualTypeArguments()[0]; if (type instanceof Class) { this.type = null; this.rawType = (Class) type; } else if (type instanceof ParameterizedType) { this.type = (ParameterizedType) type; this.rawType = (Class) this.type.getRawType(); } else { throw new IllegalArgumentException("Internal error: TypeReference constructed with unknown type: '" + type + "' class: '" + type.getClass() + "'"); } } public final ParameterizedType getType() { return type; } public final Class getRawType() { return rawType; } /** * The only reason we define this method (and require implementation * of Comparable) is to prevent constructing a * reference without type information. */ @Override public final int compareTo(TypeReference o) { return 0; } // just need an implementation, not a good one... hence ^^^ }