de.team33.patterns.reflect.luna.Fields Maven / Gradle / Ivy
Show all versions of reflect-luna Show documentation
package de.team33.patterns.reflect.luna;
import de.team33.patterns.exceptional.dione.Converter;
import de.team33.patterns.exceptional.dione.XConsumer;
import de.team33.patterns.exceptional.dione.XFunction;
import java.lang.reflect.Field;
import java.lang.reflect.Member;
import java.lang.reflect.Modifier;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.function.BiConsumer;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* Represents an aggregate of {@link Field}s of a specific class and allows elementary operations over all these
* {@link Field}s, with any {@link IllegalAccessException}s that may occur being encapsulated in unchecked exceptions.
*/
public class Fields {
private static final int SYNTHETIC = 0x00001000;
private static final int NOT_SIGNIFICANT = Modifier.STATIC | Modifier.TRANSIENT | SYNTHETIC;
private static final Converter CNV = Converter.using(AccessException::new);
private final List fields;
private Fields(final Group group, final Class> subjectClass, final Collection ignorable) {
this.fields = group.streaming.apply(subjectClass)
.filter(Fields::isSignificant)
.filter(field -> !ignorable.contains(field.getName()))
.collect(Collectors.toList());
}
private static boolean isSignificant(final Member field) {
return isSignificant(field.getModifiers());
}
private static boolean isSignificant(final int modifiers) {
return 0 == (modifiers & NOT_SIGNIFICANT);
}
/**
* Returns a new instance that includes all significant* {@link Field}s that exist in the given class
* and belong to the given {@link Group}.
*
* *Significant fields are those fields that are not declared static, transient,
* or synthetic**.
* These are typically the fields that make up the "value" of a data object and as such should be considered when
* implementing {@code equals()}, {@code hashCode()} and {@code toString()}.
*
* **A synthetically declared field, for example, appears in a non-static inner class,
* namely a reference to the instance of the outer class.
*
* @see #of(Class, String...)
*/
public static Fields of(final Group group, final Class> subjectClass, final String... ignorable) {
return new Fields(group, subjectClass, Arrays.asList(ignorable));
}
/**
* Returns a new instance that includes all significant* {@link Field}s declared by the given class.
*
* *Significant fields are those fields that are not declared static, transient,
* or synthetic**.
* These are typically the fields that make up the "value" of a data object and as such should be considered when
* implementing {@code equals()}, {@code hashCode()} and {@code toString()}.
*
* **A synthetically declared field, for example, appears in a non-static inner class,
* namely a reference to the instance of the outer class.
*
* @see #of(Group, Class, String...)
*/
public static Fields of(final Class> subjectClass, final String... ignorable) {
return of(Group.DECLARED, subjectClass, ignorable);
}
private static BiConsumer