ru.vyarus.java.generics.resolver.context.GenericsContext Maven / Gradle / Ivy
Show all versions of generics-resolver Show documentation
package ru.vyarus.java.generics.resolver.context;
import ru.vyarus.java.generics.resolver.util.GenericsUtils;
import ru.vyarus.java.generics.resolver.util.NoGenericException;
import ru.vyarus.java.generics.resolver.util.TypeToStringUtils;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.*;
/**
* Context object wraps root type hierarchy generics information descriptor and provides utility methods for
* actual types resolution.
* Usage: navigate to required type {@code context.type(MyClass.class)} and use utility methods to
* get type's own generics or as helper for methods/fields introspection.
* Every context object is immutable. Context doesn't hold actual types hierarchy (use reflection api in parallel
* if you need hierarchy info). Navigation is allowed to any class (within original root class hierarchy) from any
* child context. For convenience root class is also allowed (no matter the fact that it doesn't contain resolved
* generics).
* API operated mainly on types, because it's the only way to resolve recursive generics: e.g. when you have
* {@code List} then generic could be represented as {@code Integer} class, but if
* {@code List>} we can't represent generic as class ({@code Collection}),
* because this makes actual collection generic not accessible)
* Complete example: suppose we have {@code class A extends B}.
* {@code GenericsResolver.resolve(A.class).type(B.class).generic(0) == Integer.class}
*
* @author Vyacheslav Rusakov
* @since 17.11.2014
*/
// huge class size is OK, because it should be the only entry point for api
@SuppressWarnings("PMD.ExcessiveClassLength")
public class GenericsContext {
private final GenericsInfo genericsInfo;
private final Class> currentType;
private final Map typeGenerics;
public GenericsContext(final GenericsInfo genericsInfo, final Class> type) {
this.genericsInfo = genericsInfo;
this.currentType = type;
// collection resolved for fail fast on wrong type
typeGenerics = type == genericsInfo.getRootClass() ? Collections.emptyMap()
: genericsInfo.getTypeGenerics(type);
}
/**
* @return current context class
*/
public Class> currentClass() {
return currentType;
}
/**
* {@code class A extends B