All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.scijava.util.GenericUtils Maven / Gradle / Ivy

Go to download

SciJava Common is a shared library for SciJava software. It provides a plugin framework, with an extensible mechanism for service discovery, backed by its own annotation processor, so that plugins can be loaded dynamically. It is used by downstream projects in the SciJava ecosystem, such as ImageJ and SCIFIO.

There is a newer version: 2.99.0
Show newest version
/*
 * #%L
 * SciJava Common shared library for SciJava software.
 * %%
 * Copyright (C) 2009 - 2017 Board of Regents of the University of
 * Wisconsin-Madison, Broad Institute of MIT and Harvard, and Max Planck
 * Institute of Molecular Cell Biology and Genetics.
 * %%
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 * 
 * 1. Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 * #L%
 */

package org.scijava.util;

import com.googlecode.gentyref.GenericTypeReflector;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.List;

/**
 * Useful methods for working with {@link Type} objects, particularly generic
 * types.
 * 

* This class leans heavily on the excellent gentyref library, and exists * mainly to keep the gentyref dependency encapsulated within SciJava Common. *

* * @author Curtis Rueden * @see ClassUtils For utility methods specific to {@link Class} objects. * @see ConversionUtils For utility methods that convert between {@link Type}s. */ public final class GenericUtils { private GenericUtils() { // prevent instantiation of utility class } /** * Gets the sole raw class corresponding to the given type, or null if none. */ public static Class getClass(final Type type) { if (type == null) return null; if (type instanceof Class) return (Class) type; final List> c = getClasses(type); if (c == null || c.size() != 1) return null; return c.get(0); } /** * Gets all raw classes corresponding to the given type. *

* For example, a type parameter {@code A extends Number & Iterable} will * return both {@link Number} and {@link Iterable} as its raw classes. *

*/ public static List> getClasses(final Type type) { if (type == null) return null; return GenericTypeReflector.getUpperBoundClassAndInterfaces(type); } /** * Gets the component type of the given array type, or null if not an array. */ public static Type getComponentType(final Type type) { return GenericTypeReflector.getArrayComponentType(type); } /** * Gets the sole component class of the given array type, or null if none. */ public static Class getComponentClass(final Type type) { return getClass(getComponentType(type)); } /** * Returns the "safe" generic type of the given field, as viewed from the * given type. This may be narrower than what {@link Field#getGenericType()} * returns, if the field is declared in a superclass, or {@code type} has a * type parameter that is used in the type of the field. *

* For example, suppose we have the following three classes: *

* *
	 * public class Thing<T> {
	 * 	public T thing;
	 * }
	 * 
	 * public class NumberThing<N extends Number> extends Thing<N> { }
	 * 
	 * public class IntegerThing extends NumberThing<Integer> { }
	 * 
* * Then this method operates as follows: * *
	 * field = ClassUtils.getField(Thing.class, "thing");
	 * 
	 * field.getType(); // Object
	 * field.getGenericType(); // T
	 * 
	 * GenericUtils.getFieldType(field, Thing.class); // T
	 * GenericUtils.getFieldType(field, NumberThing.class); // N extends Number
	 * GenericUtils.getFieldType(field, IntegerThing.class); // Integer
	 * 
*/ public static Type getFieldType(final Field field, final Class type) { final Type wildType = GenericTypeReflector.addWildcardParameters(type); return GenericTypeReflector.getExactFieldType(field, wildType); } /** * Returns the "safe" class(es) of the given field, as viewed from the * specified type. This may be narrower than what {@link Field#getType()} * returns, if the field is declared in a superclass, or {@code type} has a * type parameter that is used in the type of the field. *

* For example, suppose we have the following three classes: *

* *
	 * 
	 * public class Thing<T> {
	 * 
	 * 	public T thing;
	 * }
	 * 
	 * public class NumberThing<N extends Number> extends Thing<N> {}
	 * 
	 * public class IntegerThing extends NumberThing<Integer> {}
	 * 
* * Then this method operates as follows: * *
	 * field = ClassUtils.getField(Thing.class, "thing");
	 * 
	 * field.getType(); // Object
	 * 
	 * ClassUtils.getTypes(field, Thing.class).get(0); // Object
	 * ClassUtils.getTypes(field, NumberThing.class).get(0); // Number
	 * ClassUtils.getTypes(field, IntegerThing.class).get(0); // Integer
	 * 
*

* In cases of complex generics which take the intersection of multiple types * using the {@code &} operator, there may be multiple types returned by this * method. For example: *

* *
	 * public class ComplexThing<T extends Serializable & Cloneable> extends Thing<T> {}
	 * 
	 * ClassUtils.getTypes(field, ComplexThing.class); // Serializable, Cloneable
	 * 
* * @see #getFieldType(Field, Class) * @see #getClasses(Type) */ public static List> getFieldClasses(final Field field, final Class type) { final Type genericType = getFieldType(field, type); return getClasses(genericType); } /** * As {@link #getFieldType(Field, Class)}, but with respect to the return * type of the given {@link Method} rather than a {@link Field}. */ public static Type getMethodReturnType(final Method method, final Class type) { final Type wildType = GenericTypeReflector.addWildcardParameters(type); return GenericTypeReflector.getExactReturnType(method, wildType); } /** * As {@link #getFieldClasses(Field, Class)}, but with respect to the return * type of the given {@link Method} rather than a {@link Field}. * * @see #getMethodReturnType(Method, Class) * @see #getClasses(Type) */ public static List> getMethodReturnClasses(final Method method, final Class type) { final Type genericType = getMethodReturnType(method, type); return getClasses(genericType); } /** * Gets the given type's {@code n}th type parameter of the specified class. *

* For example, with class {@code StringList implements List}, * {@code getTypeParameter(StringList.class, Collection.class, 0)} returns * {@code String}. *

*/ public static Type getTypeParameter(final Type type, final Class c, final int paramNo) { return GenericTypeReflector.getTypeParameter(type, c.getTypeParameters()[paramNo]); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy