001 package fj; 002 003 import fj.data.List; 004 import static fj.data.List.unfold; 005 import fj.data.Option; 006 import static fj.data.Option.none; 007 import static fj.data.Option.some; 008 import fj.data.Tree; 009 010 import java.lang.reflect.ParameterizedType; 011 import java.lang.reflect.Type; 012 013 /** 014 * A wrapper for a {@link java.lang.Class} that provides additional methods. 015 * 016 * @version %build.number%<br> 017 * <ul> 018 * <li>$LastChangedRevision: 122 $</li> 019 * <li>$LastChangedDate: 2009-04-25 08:24:38 +1000 (Sat, 25 Apr 2009) $</li> 020 * </ul> 021 */ 022 public final class Class<T> { 023 private final java.lang.Class<T> c; 024 025 private Class(final java.lang.Class<T> c) { 026 this.c = c; 027 } 028 029 /** 030 * Returns the inheritance hierarchy of this class. 031 * 032 * @return The inheritance hierarchy of this class. 033 */ 034 public List<Class<? super T>> inheritance() { 035 return unfold( 036 new F<java.lang.Class<? super T>, Option<P2<java.lang.Class<? super T>, java.lang.Class<? super T>>>>() { 037 public Option<P2<java.lang.Class<? super T>, java.lang.Class<? super T>>> f( 038 final java.lang.Class<? super T> c) { 039 if (c == null) 040 return none(); 041 else { 042 final P2<java.lang.Class<? super T>, java.lang.Class<? super T>> p = 043 new P2<java.lang.Class<? super T>, java.lang.Class<? super T>>() { 044 public java.lang.Class<? super T> _1() { 045 return c; 046 } 047 048 @SuppressWarnings({"unchecked"}) 049 public java.lang.Class<? super T> _2() { 050 return c.getSuperclass(); 051 } 052 }; 053 return some(p); 054 } 055 } 056 }, c).map(new F<java.lang.Class<? super T>, Class<? super T>>() { 057 public Class<? super T> f(final java.lang.Class<? super T> c) { 058 return clas(c); 059 } 060 }); 061 } 062 063 /** 064 * Provides this class's type parameter information as a Tree of the type expression. 065 * Only descends into Parameterized classes. Non-abstract classes, or classes that don't implement an interface, 066 * are treated as raw types. Arrays, Type Variables, and Wildcards are treated as opaque Types. 067 * 068 * @return The rose tree representing the type expression for this class. 069 */ 070 public Tree<Type> classParameters() { 071 return typeParameterTree(c); 072 } 073 074 /** 075 * Provides this class's superclass type parameter information as a Tree of the type expression. 076 * Only descends into Parameterized classes. Non-abstract classes, or classes that don't implement an interface, 077 * are treated as raw types. Arrays, Type Variables, and Wildcards are treated as opaque Types. 078 * 079 * @return The Tree representing the type expression for this class's superclass. 080 */ 081 public Tree<Type> superclassParameters() { 082 return typeParameterTree(c.getGenericSuperclass()); 083 } 084 085 /** 086 * Provides this class's interface type parameter information as a list of trees. 087 * 088 * @return A list of trees representing the type expressions for this class's interfaces. 089 */ 090 public List<Tree<Type>> interfaceParameters() { 091 List<Tree<Type>> ts = List.nil(); 092 for (final Type t : c.getInterfaces()) { 093 ts = ts.snoc(typeParameterTree(t)); 094 } 095 return ts; 096 } 097 098 /** 099 * Provides type parameter information as a Tree of the type expression. 100 * Only descends into Parameterized classes. Non-abstract classes, or classes that don't implement an interface, 101 * are treated as raw types. Arrays, Type Variables, and Wildcards are treated as opaque Types. 102 * 103 * @param t The type (class) for which to get the generic type information. 104 * @return Type parameter information as a rose tree of the type expression. 105 */ 106 public static Tree<Type> typeParameterTree(final Type t) { 107 List<Tree<Type>> typeArgs = List.nil(); 108 final Tree<Type> types; 109 if (t instanceof ParameterizedType) { 110 final ParameterizedType pt = (ParameterizedType) t; 111 for (final Type arg : pt.getActualTypeArguments()) { 112 typeArgs = typeArgs.snoc(typeParameterTree(arg)); 113 } 114 types = Tree.node(pt.getRawType(), typeArgs); 115 } else { 116 types = Tree.node(t, List.<Tree<Type>>nil()); 117 } 118 return types; 119 } 120 121 /** 122 * Returns the underlying class. 123 * 124 * @return The underlying class. 125 */ 126 public java.lang.Class<T> clas() { 127 return c; 128 } 129 130 /** 131 * Constructs a class from the given argument. 132 * 133 * @param c The argument to construct this class with. 134 * @return A class from the given argument. 135 */ 136 public static <T> Class<T> clas(final java.lang.Class<T> c) { 137 return new Class<T>(c); 138 } 139 }