Reflect.java
package no.motif;
import static no.motif.Base.first;
import java.lang.annotation.Annotation;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Member;
import no.motif.f.Fn;
import no.motif.f.Predicate;
/**
* Operations for doing reflection.
*/
public final class Reflect {
/**
* Evaluates if objects are of a certain type (class or interface).
*
* @param type The type that will satisfy the predicate.
*/
public static Predicate<Object> isA(final Class<?> type) { return new Predicate<Object>() {
@Override public boolean $(Object object) { return type.isInstance(object); }}; }
/**
* Gets the class of an object. This is the functional equivalent of
* the {@link Object#getClass()} method, which returns an untyped
* {@link Class Class<?>}.
*/
public static final Fn<Object, Class<?>> getClass = type();
/**
* This is the same as {@link #getClass}, with the additional
* possible typing of the yielded {@link Class}es.
*/
public static <T> Fn<T, Class<? extends T>> type() { return new Fn<T, Class<? extends T>>() {
@SuppressWarnings("unchecked") @Override public Class<? extends T> $(T object) {
return (Class<? extends T>) object.getClass(); }}; }
/**
* Get the name of a {@link java.lang.reflect.Member}, e.g.
* method or field name.
*/
public static final Fn<Member, String> name = new Fn<Member, String>() {
@Override public String $(Member member) { return member.getName(); }};
/**
* Get the {@link Class#getName() name} of a <code>Class</code>.
*/
public static final Fn<Class<?>, String> className = new Fn<Class<?>, String>() {
@Override public String $(Class<?> cls) { return cls.getName(); }};
/**
* Get the {@link Class#getSimpleName() simple name} of a <code>Class</code>.
*/
public static final Fn<Class<?>, String> simpleName = new Fn<Class<?>, String>() {
@Override public String $(Class<?> cls) { return cls.getSimpleName(); }};
/**
* Get the {@link Class#getPackage() package} of a <code>Class</code>.
*/
public static final Fn<Class<?>, Package> getPackage = new Fn<Class<?>, Package>() {
@Override public Package $(Class<?> cls) { return cls.getPackage(); }};
/**
* Get the {@link Package#getName() package name} of a <code>Class</code>.
*/
public static final Fn<Class<?>, String> packageName = first(getPackage).then(new Fn<Package, String>() {
@Override public String $(Package pkg) { return pkg.getName(); }});
/**
* Check if an element (class, method, field, etc) is annotated with a given annotation.
*
* @param annotation the annotation to check for.
*/
public static Predicate<AnnotatedElement> annotatedWith(final Class<? extends Annotation> annotation) {
return new Predicate<AnnotatedElement>() {
@Override public boolean $(AnnotatedElement element) { return element.isAnnotationPresent(annotation); }}; }
/**
* Create instances of classes using the no-arg constructor.
* Any checked {@link InstantiationException} or {@link IllegalAccessException}
* will be rethrown as <code>RuntimeException</code>.
*/
public static <T> Fn<Class<? extends T>, T> newInstance() {
return new Fn<Class<? extends T>, T>() {
@Override public T $(Class<? extends T> clazz) {
try { return clazz.newInstance(); }
catch (InstantiationException | IllegalAccessException e) {
throw new RuntimeException("Not able to instantiate " + clazz.getName() +
" because of " + e.getClass().getSimpleName() + ": " + e.getMessage(), e);
}
}};
}
private Reflect() {}
}