blob: 327dac06d413d8d689a757e34c3518dfa9a149cb [file] [log] [blame]
/*
* Copyright (c) 2007 Mockito contributors
* This program is made available under the terms of the MIT License.
*/
package org.mockito.internal.util.reflection;
import org.mockito.internal.util.Checks;
import org.mockito.internal.util.collections.ListUtil;
import org.mockito.internal.util.collections.ListUtil.Filter;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
/**
* Small fluent reflection tools to work with fields.
*
* Code is very new and might need rework.
*/
public abstract class Fields {
/**
* Instance fields declared in the class and superclasses of the given instance.
*
* @param instance Instance from which declared fields will be retrieved.
* @return InstanceFields of this object instance.
*/
public static InstanceFields allDeclaredFieldsOf(Object instance) {
List<InstanceField> instanceFields = new ArrayList<InstanceField>();
for (Class<?> clazz = instance.getClass(); clazz != Object.class; clazz = clazz.getSuperclass()) {
instanceFields.addAll(instanceFieldsIn(instance, clazz.getDeclaredFields()));
}
return new InstanceFields(instance, instanceFields);
}
/**
* Instance fields declared in the class of the given instance.
*
* @param instance Instance from which declared fields will be retrieved.
* @return InstanceFields of this object instance.
*/
public static InstanceFields declaredFieldsOf(Object instance) {
List<InstanceField> instanceFields = new ArrayList<InstanceField>();
instanceFields.addAll(instanceFieldsIn(instance, instance.getClass().getDeclaredFields()));
return new InstanceFields(instance, instanceFields);
}
private static List<InstanceField> instanceFieldsIn(Object instance, Field[] fields) {
List<InstanceField> instanceDeclaredFields = new ArrayList<InstanceField>();
for (Field field : fields) {
InstanceField instanceField = new InstanceField(field, instance);
instanceDeclaredFields.add(instanceField);
}
return instanceDeclaredFields;
}
/**
* Accept fields annotated by the given annotations.
*
* @param annotations Annotation types to check.
* @return The filter.
*/
public static Filter<InstanceField> annotatedBy(final Class<? extends Annotation>... annotations) {
return new Filter<InstanceField>() {
public boolean isOut(InstanceField instanceField) {
Checks.checkNotNull(annotations, "Provide at least one annotation class");
for (Class<? extends Annotation> annotation : annotations) {
if(instanceField.isAnnotatedBy(annotation)) {
return false;
}
}
return true;
}
};
}
/**
* Accept fields with non null value.
*
* @return The filter.
*/
private static Filter<InstanceField> nullField() {
return new Filter<InstanceField>() {
public boolean isOut(InstanceField instanceField) {
return instanceField.isNull();
}
};
}
public static class InstanceFields {
private final Object instance;
private final List<InstanceField> instanceFields;
public InstanceFields(Object instance, List<InstanceField> instanceFields) {
this.instance = instance;
this.instanceFields = instanceFields;
}
public InstanceFields filter(Filter<InstanceField> withFilter) {
return new InstanceFields(instance, ListUtil.filter(instanceFields, withFilter));
}
public InstanceFields notNull() {
return filter(nullField());
}
public List<InstanceField> instanceFields() {
return new ArrayList<InstanceField>(instanceFields);
}
public List<Object> assignedValues() {
List<Object> values = new ArrayList<Object>(instanceFields.size());
for (InstanceField instanceField : instanceFields) {
values.add(instanceField.read());
}
return values;
}
public List<String> names() {
List<String> fieldNames = new ArrayList<String>(instanceFields.size());
for (InstanceField instanceField : instanceFields) {
fieldNames.add(instanceField.name());
}
return fieldNames;
}
}
}