
com.diffplug.common.base.FieldsAndGetters Maven / Gradle / Ivy
Show all versions of durian Show documentation
/*
* Copyright 2015 DiffPlug
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.diffplug.common.base;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Arrays;
import java.util.Map;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Stream;
/**
* Utilities for obtaining the fields and getter methods of an object using reflection.
* Useful for first-pass debugging of runtime objects.
*/
public class FieldsAndGetters {
/**
* Returns a {@code Stream} of all public fields and their values for the given object.
*
* @see #fields(Object, Predicate)
*/
public static Stream> fields(Object obj) {
return fields(obj, Predicates.alwaysTrue());
}
/**
* Returns a {@code Stream} of all public fields which match {@code predicate} and their values for the given object.
*
* This method uses reflection to find all of the public instance fields of the given object,
* and if they pass the given predicate, it includes them in a stream of {@code Map.Entry}
* where the entry's value is the value of the field for this object.
*/
public static Stream> fields(Object obj, Predicate predicate) {
Class> clazz = obj == null ? ObjectIsNull.class : obj.getClass();
return Arrays.asList(clazz.getFields()).stream()
// gotta be public
.filter(field -> Modifier.isPublic(field.getModifiers()))
// gotta be an instance field
.filter(field -> !Modifier.isStatic(field.getModifiers()))
// gotta pass the predicate
.filter(predicate)
// get its value
.map(field -> createEntry(field, tryCall(field.getName(), () -> field.get(obj))));
}
/**
* Returns a {@code Stream} of all public getter methods and their return values for the given object.
*
* @see #getters(Object, Predicate)
*/
public static Stream> getters(Object obj) {
return getters(obj, Predicates.alwaysTrue());
}
/**
* Returns a {@code Stream} of all public getter methods which match {@code predicate} and their return values for the given object.
*
* This method uses reflection to find all of the public instance methods which don't take any arguments
* and return a value. If they pass the given predicate, then they are called, and the return value is
* included in a stream of {@code Map.Entry}.
*
* Note that there are some methods which have the signature of a getter, but actually mutate the object
* being inspected, e.g. {@link java.io.InputStream#read()}. These will be called unless you manually
* exclude them using the predicate.
*/
public static Stream> getters(Object obj, Predicate predicate) {
Class> clazz = obj == null ? ObjectIsNull.class : obj.getClass();
return Arrays.asList(clazz.getMethods()).stream()
// we only want methods that don't take parameters
.filter(method -> method.getParameterTypes().length == 0)
// we only want public methods
.filter(method -> Modifier.isPublic(method.getModifiers()))
// we only want instance methods
.filter(method -> !Modifier.isStatic(method.getModifiers()))
// we only want methods that don't return void
.filter(method -> !method.getReturnType().equals(Void.TYPE))
// we only want methods that pass our predicate
.filter(predicate)
// turn it into Map
.map(method -> createEntry(method, tryCall(method.getName(), () -> method.invoke(obj))));
}
/** Sentinel class for null objects. */
public static class ObjectIsNull {}
/** Executes the given function, return any exceptions it might throw as wrapped values. */
private static Object tryCall(String methodName, Throwing.Supplier