aoqi@0: /* aoqi@0: * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. aoqi@0: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. aoqi@0: * aoqi@0: * This code is free software; you can redistribute it and/or modify it aoqi@0: * under the terms of the GNU General Public License version 2 only, as aoqi@0: * published by the Free Software Foundation. Oracle designates this aoqi@0: * particular file as subject to the "Classpath" exception as provided aoqi@0: * by Oracle in the LICENSE file that accompanied this code. aoqi@0: * aoqi@0: * This code is distributed in the hope that it will be useful, but WITHOUT aoqi@0: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or aoqi@0: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License aoqi@0: * version 2 for more details (a copy is included in the LICENSE file that aoqi@0: * accompanied this code). aoqi@0: * aoqi@0: * You should have received a copy of the GNU General Public License version aoqi@0: * 2 along with this work; if not, write to the Free Software Foundation, aoqi@0: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. aoqi@0: * aoqi@0: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA aoqi@0: * or visit www.oracle.com if you need additional information or have any aoqi@0: * questions. aoqi@0: */ aoqi@0: aoqi@0: package com.sun.xml.internal.bind.v2.model.nav; aoqi@0: aoqi@0: import java.lang.reflect.Field; aoqi@0: import java.lang.reflect.Method; aoqi@0: import java.lang.reflect.Proxy; aoqi@0: import java.lang.reflect.Type; aoqi@0: import java.util.Collection; aoqi@0: aoqi@0: import com.sun.xml.internal.bind.v2.runtime.Location; aoqi@0: aoqi@0: /** aoqi@0: * Provides unified view of the underlying reflection library, aoqi@0: * such as {@code java.lang.reflect} and/or Annotation Processing. aoqi@0: * aoqi@0: *

aoqi@0: * This interface provides navigation over the reflection model aoqi@0: * to decouple the caller from any particular implementation. aoqi@0: * This allows the JAXB RI to reuse much of the code between aoqi@0: * the compile time (which works on top of Annotation Processing) and the run-time aoqi@0: * (which works on top of {@code java.lang.reflect}) aoqi@0: * aoqi@0: *

aoqi@0: * {@link Navigator} instances are stateless and immutable. aoqi@0: * aoqi@0: * aoqi@0: *

Parameterization

aoqi@0: *

C

aoqi@0: *

aoqi@0: * A Java class declaration (not an interface, a class and an enum.) aoqi@0: * aoqi@0: *

T

aoqi@0: *

aoqi@0: * A Java type. This includs declaration, but also includes such aoqi@0: * things like arrays, primitive types, parameterized types, and etc. aoqi@0: * aoqi@0: * @author Kohsuke Kawaguchi (kk@kohsuke.org) aoqi@0: */ aoqi@0: public interface Navigator { aoqi@0: /** aoqi@0: * Gets the base class of the specified class. aoqi@0: * aoqi@0: * @return aoqi@0: * null if the parameter represents {@link Object}. aoqi@0: */ aoqi@0: C getSuperClass(C clazz); aoqi@0: aoqi@0: /** aoqi@0: * Gets the parameterization of the given base type. aoqi@0: * aoqi@0: *

aoqi@0: * For example, given the following aoqi@0: *


aoqi@0:      * interface Foo<T> extends List<List<T>> {}
aoqi@0:      * interface Bar extends Foo<String> {}
aoqi@0:      * 
aoqi@0: * This method works like this: aoqi@0: *

aoqi@0:      * getBaseClass( Bar, List ) = List<List<String>
aoqi@0:      * getBaseClass( Bar, Foo  ) = Foo<String>
aoqi@0:      * getBaseClass( Foo<? extends Number>, Collection ) = Collection<List<? extends Number>>
aoqi@0:      * getBaseClass( ArrayList<? extends BigInteger>, List ) = List<? extends BigInteger>
aoqi@0:      * 
aoqi@0: * aoqi@0: * @param type aoqi@0: * The type that derives from {@code baseType} aoqi@0: * @param baseType aoqi@0: * The class whose parameterization we are interested in. aoqi@0: * @return aoqi@0: * The use of {@code baseType} in {@code type}. aoqi@0: * or null if the type is not assignable to the base type. aoqi@0: */ aoqi@0: T getBaseClass(T type, C baseType); aoqi@0: aoqi@0: /** aoqi@0: * Gets the fully-qualified name of the class. aoqi@0: * ("java.lang.Object" for {@link Object}) aoqi@0: */ aoqi@0: String getClassName(C clazz); aoqi@0: aoqi@0: /** aoqi@0: * Gets the display name of the type object aoqi@0: * aoqi@0: * @return aoqi@0: * a human-readable name that the type represents. aoqi@0: */ aoqi@0: String getTypeName(T rawType); aoqi@0: aoqi@0: /** aoqi@0: * Gets the short name of the class ("Object" for {@link Object}.) aoqi@0: * aoqi@0: * For nested classes, this method should just return the inner name. aoqi@0: * (for example "Inner" for "com.acme.Outer$Inner". aoqi@0: */ aoqi@0: String getClassShortName(C clazz); aoqi@0: aoqi@0: /** aoqi@0: * Gets all the declared fields of the given class. aoqi@0: */ aoqi@0: Collection getDeclaredFields(C clazz); aoqi@0: aoqi@0: /** aoqi@0: * Gets the named field declared on the given class. aoqi@0: * aoqi@0: * This method doesn't visit ancestors, but does recognize aoqi@0: * non-public fields. aoqi@0: * aoqi@0: * @return aoqi@0: * null if not found aoqi@0: */ aoqi@0: F getDeclaredField(C clazz, String fieldName); aoqi@0: aoqi@0: /** aoqi@0: * Gets all the declared methods of the given class aoqi@0: * (regardless of their access modifiers, regardless aoqi@0: * of whether they override methods of the base classes.) aoqi@0: * aoqi@0: *

aoqi@0: * Note that this method does not list methods declared on base classes. aoqi@0: * aoqi@0: * @return aoqi@0: * can be empty but always non-null. aoqi@0: */ aoqi@0: Collection getDeclaredMethods(C clazz); aoqi@0: aoqi@0: /** aoqi@0: * Gets the class that declares the given field. aoqi@0: */ aoqi@0: C getDeclaringClassForField(F field); aoqi@0: aoqi@0: /** aoqi@0: * Gets the class that declares the given method. aoqi@0: */ aoqi@0: C getDeclaringClassForMethod(M method); aoqi@0: aoqi@0: /** aoqi@0: * Gets the type of the field. aoqi@0: */ aoqi@0: T getFieldType(F f); aoqi@0: aoqi@0: /** aoqi@0: * Gets the name of the field. aoqi@0: */ aoqi@0: String getFieldName(F field); aoqi@0: aoqi@0: /** aoqi@0: * Gets the name of the method, such as "toString" or "equals". aoqi@0: */ aoqi@0: String getMethodName(M m); aoqi@0: aoqi@0: /** aoqi@0: * Gets the return type of a method. aoqi@0: */ aoqi@0: T getReturnType(M m); aoqi@0: aoqi@0: /** aoqi@0: * Returns the list of parameters to the method. aoqi@0: */ aoqi@0: T[] getMethodParameters(M method); aoqi@0: aoqi@0: /** aoqi@0: * Returns true if the method is static. aoqi@0: */ aoqi@0: boolean isStaticMethod(M method); aoqi@0: aoqi@0: /** aoqi@0: * Checks if {@code sub} is a sub-type of {@code sup}. aoqi@0: * aoqi@0: * TODO: should this method take T or C? aoqi@0: */ aoqi@0: boolean isSubClassOf(T sub, T sup); aoqi@0: aoqi@0: /** aoqi@0: * Gets the representation of the given Java type in {@code T}. aoqi@0: * aoqi@0: * @param c aoqi@0: * can be a primitive, array, class, or anything. aoqi@0: * (therefore the return type has to be T, not C) aoqi@0: */ aoqi@0: T ref(Class c); aoqi@0: aoqi@0: /** aoqi@0: * Gets the T for the given C. aoqi@0: */ aoqi@0: T use(C c); aoqi@0: aoqi@0: /** aoqi@0: * If the given type is an use of class declaration, aoqi@0: * returns the type casted as {@code C}. aoqi@0: * Otherwise null. aoqi@0: * aoqi@0: *

aoqi@0: * TODO: define the exact semantics. aoqi@0: */ aoqi@0: C asDecl(T type); aoqi@0: aoqi@0: /** aoqi@0: * Gets the {@code C} representation for the given class. aoqi@0: * aoqi@0: * The behavior is undefined if the class object represents aoqi@0: * primitives, arrays, and other types that are not class declaration. aoqi@0: */ aoqi@0: C asDecl(Class c); aoqi@0: aoqi@0: /** aoqi@0: * Checks if the type is an array type. aoqi@0: */ aoqi@0: boolean isArray(T t); aoqi@0: aoqi@0: /** aoqi@0: * Checks if the type is an array type but not byte[]. aoqi@0: */ aoqi@0: boolean isArrayButNotByteArray(T t); aoqi@0: aoqi@0: /** aoqi@0: * Gets the component type of the array. aoqi@0: * aoqi@0: * @param t aoqi@0: * must be an array. aoqi@0: */ aoqi@0: T getComponentType(T t); aoqi@0: aoqi@0: /** aoqi@0: * Gets the i-th type argument from a parameterized type. aoqi@0: * aoqi@0: * For example, {@code getTypeArgument([Map],0)=Integer} aoqi@0: * aoqi@0: * @throws IllegalArgumentException aoqi@0: * If t is not a parameterized type aoqi@0: * @throws IndexOutOfBoundsException aoqi@0: * If i is out of range. aoqi@0: * aoqi@0: * @see #isParameterizedType(Object) aoqi@0: */ aoqi@0: T getTypeArgument(T t, int i); aoqi@0: aoqi@0: /** aoqi@0: * Returns true if t is a parameterized type. aoqi@0: */ aoqi@0: boolean isParameterizedType(T t); aoqi@0: aoqi@0: /** aoqi@0: * Checks if the given type is a primitive type. aoqi@0: */ aoqi@0: boolean isPrimitive(T t); aoqi@0: aoqi@0: /** aoqi@0: * Returns the representation for the given primitive type. aoqi@0: * aoqi@0: * @param primitiveType aoqi@0: * must be Class objects like {@link Integer#TYPE}. aoqi@0: */ aoqi@0: T getPrimitive(Class primitiveType); aoqi@0: aoqi@0: /** aoqi@0: * Returns a location of the specified class. aoqi@0: */ aoqi@0: Location getClassLocation(C clazz); aoqi@0: aoqi@0: Location getFieldLocation(F field); aoqi@0: aoqi@0: Location getMethodLocation(M getter); aoqi@0: aoqi@0: /** aoqi@0: * Returns true if the given class has a no-arg default constructor. aoqi@0: * The constructor does not need to be public. aoqi@0: */ aoqi@0: boolean hasDefaultConstructor(C clazz); aoqi@0: aoqi@0: /** aoqi@0: * Returns true if the field is static. aoqi@0: */ aoqi@0: boolean isStaticField(F field); aoqi@0: aoqi@0: /** aoqi@0: * Returns true if the method is public. aoqi@0: */ aoqi@0: boolean isPublicMethod(M method); aoqi@0: aoqi@0: /** aoqi@0: * Returns true if the method is final. aoqi@0: */ aoqi@0: boolean isFinalMethod(M method); aoqi@0: aoqi@0: /** aoqi@0: * Returns true if the field is public. aoqi@0: */ aoqi@0: boolean isPublicField(F field); aoqi@0: aoqi@0: /** aoqi@0: * Returns true if this is an enum class. aoqi@0: */ aoqi@0: boolean isEnum(C clazz); aoqi@0: aoqi@0: /** aoqi@0: * Computes the erasure aoqi@0: */ aoqi@0:

T erasure(T contentInMemoryType); aoqi@0: // This unused P is necessary to make ReflectionNavigator.erasure work nicely aoqi@0: aoqi@0: /** aoqi@0: * Returns true if this is an abstract class. aoqi@0: */ aoqi@0: boolean isAbstract(C clazz); aoqi@0: aoqi@0: /** aoqi@0: * Returns true if this is a final class. aoqi@0: */ aoqi@0: boolean isFinal(C clazz); aoqi@0: aoqi@0: /** aoqi@0: * Gets the enumeration constants from an enum class. aoqi@0: * aoqi@0: * @param clazz aoqi@0: * must derive from {@link Enum}. aoqi@0: * aoqi@0: * @return aoqi@0: * can be empty but never null. aoqi@0: */ aoqi@0: F[] getEnumConstants(C clazz); aoqi@0: aoqi@0: /** aoqi@0: * Gets the representation of the primitive "void" type. aoqi@0: */ aoqi@0: T getVoidType(); aoqi@0: aoqi@0: /** aoqi@0: * Gets the package name of the given class. aoqi@0: * aoqi@0: * @return aoqi@0: * i.e. "", "java.lang" but not null. aoqi@0: */ aoqi@0: String getPackageName(C clazz); aoqi@0: aoqi@0: /** aoqi@0: * Finds ObjectFactory for the given referencePoint. aoqi@0: * aoqi@0: * @param referencePoint aoqi@0: * The class that refers to the specified class. aoqi@0: * @return aoqi@0: * null if not found. aoqi@0: */ aoqi@0: C loadObjectFactory(C referencePoint, String packageName); aoqi@0: aoqi@0: /** aoqi@0: * Returns true if this method is a bridge method as defined in JLS. aoqi@0: */ aoqi@0: boolean isBridgeMethod(M method); aoqi@0: aoqi@0: /** aoqi@0: * Returns true if the given method is overriding another one aoqi@0: * defined in the base class 'base' or its ancestors. aoqi@0: */ aoqi@0: boolean isOverriding(M method, C base); aoqi@0: aoqi@0: /** aoqi@0: * Returns true if 'clazz' is an interface. aoqi@0: */ aoqi@0: boolean isInterface(C clazz); aoqi@0: aoqi@0: /** aoqi@0: * Returns true if the field is transient. aoqi@0: */ aoqi@0: boolean isTransient(F f); aoqi@0: aoqi@0: /** aoqi@0: * Returns true if the given class is an inner class. aoqi@0: * aoqi@0: * This is only used to improve the error diagnostics, so aoqi@0: * it's OK to fail to detect some inner classes as such. aoqi@0: * aoqi@0: * Note that this method should return false for nested classes aoqi@0: * (static classes.) aoqi@0: */ aoqi@0: boolean isInnerClass(C clazz); aoqi@0: aoqi@0: /** aoqi@0: * Checks if types are the same aoqi@0: * @param t1 type aoqi@0: * @param t2 type aoqi@0: * @return true if types are the same aoqi@0: */ aoqi@0: boolean isSameType(T t1, T t2); aoqi@0: }