com.softicar.platform.common.code.java.reflection.TypeParameterAnalyzer Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of platform-common Show documentation
Show all versions of platform-common Show documentation
The SoftiCAR Platform is a lightweight, Java-based library to create interactive business web applications.
package com.softicar.platform.common.code.java.reflection;
import com.softicar.platform.common.string.Padding;
import com.softicar.platform.common.string.Substring;
import java.lang.reflect.Field;
import java.lang.reflect.Type;
import java.util.Objects;
import java.util.function.Supplier;
/**
* Analyzes the generic type parameters of a given {@link Type} or
* {@link Field}.
*
* @author Alexander Schmidt
*/
public class TypeParameterAnalyzer {
private final Type type;
/**
* Constructs a {@link TypeParameterAnalyzer}.
*
* @param type
* the {@link Type} to analyze (never null)
*/
public TypeParameterAnalyzer(Type type) {
this.type = Objects.requireNonNull(type);
}
/**
* Constructs a {@link TypeParameterAnalyzer} for the declared generic
* {@link Type} of the given {@link Field}.
*
* @param field
* the {@link Field} to analyze (never null)
*/
public TypeParameterAnalyzer(Field field) {
this(field.getGenericType());
}
/**
* Determines the generic type parameter of the given {@link Type} or
* {@link Field}, as a {@link String} of canonical class names.
*
* Examples:
*
* - For type "{@code Long}" (or any other non-generic type), this method
* returns an empty {@link String}.
* - For type "{@code Optional
}", this method returns
* "{@code java.lang.String}".
* - For type "{@code Optional
>}", this method returns
* "{@code java.util.function.Supplier}".
*
*
* @return the generic type parameter, as a {@link String} (never
* null)
*/
public String getTypeParameterName() {
String genericTypeName = type.getTypeName();
return Substring.between(genericTypeName, "<", ">");
}
/**
* Determines whether the generic type parameter of the given {@link Type}
* or {@link Field} corresponds to the given {@link Class}.
*
* Examples:
*
* - For type "{@code Long}" and given class {@link Long}, this method
* returns false.
* - For type "{@code Optional
}" and given class {@link Long}, this
* method returns true.
*
*
* @param expectedTypeParameter
* the expected type parameter {@link Class} (never null)
* @return true if the given {@link Class} is used as a type
* parameter; false otherwise
*/
public boolean hasExpectedTypeParameter(Class expectedTypeParameter) {
return hasExpectedTypeParameter(expectedTypeParameter, new Class[0]);
}
/**
* Determines whether the generic type parameter of the given {@link Type}
* or {@link Field} corresponds to the given {@link Class}, and further
* nested classes.
*
* Examples:
*
* - For type "{@code Optional
}" and given class {@link Long}, this
* method returns true.
* - For type "{@code Optional
>}" and given class
* {@link Long}, this method returns false.
* - For type "{@code Optional
>}" and given classes
* {@link Supplier} and {@link Long}, this method returns true.
*
*
* @param expectedTypeParameter
* the expected type parameter {@link Class} (never null)
* @param expextedNestedTypeParameters
* further nested type parameter {@link Class}es
* @return true if the given {@link Class}es are used as a type
* parameters; false otherwise
*/
public boolean hasExpectedTypeParameter(Class expectedTypeParameter, Class...expextedNestedTypeParameters) {
return getTypeParameterName().equals(createExpectedTypeName(expectedTypeParameter, expextedNestedTypeParameters));
}
private String createExpectedTypeName(Class expectedTypeParameter, Class[] expextedNestedTypeParameters) {
StringBuilder typeName = new StringBuilder();
typeName.append(expectedTypeParameter.getCanonicalName());
for (Class type: expextedNestedTypeParameters) {
typeName.append("<");
typeName.append(type.getCanonicalName());
}
typeName.append(Padding.generate('>', expextedNestedTypeParameters.length));
return typeName.toString();
}
}