org.deephacks.tools4j.config.internal.core.runtime.ClassIntrospector Maven / Gradle / Ivy
package org.deephacks.tools4j.config.internal.core.runtime;
import com.google.common.base.Optional;
import org.deephacks.tools4j.config.Config;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static org.deephacks.tools4j.config.internal.core.Reflections.*;
public class ClassIntrospector {
private Class clazz;
private Map fields;
public ClassIntrospector(Class clazz) {
this.clazz = clazz;
if(Modifier.isFinal(clazz.getModifiers())){
throw new UnsupportedOperationException(
"Class ["+clazz+"] is final. Configurable classes are not allowed to be final since it " +
"breaks the API of proxies that extends configurable classes.");
}
fields = findFields(clazz);
}
/**
* Get the class name of the class.
* @return
*/
public String getName() {
return clazz.getName();
}
public Class getTarget() {
return clazz;
}
/**
* Get class level annotation for class.
*
* @param annotation
* @return
*/
public T getAnnotation(Class annotation) {
return clazz.getAnnotation(annotation);
}
public List getFieldList(Class clazz) {
ArrayList wrap = new ArrayList<>();
for (Field f : fields.values()) {
if (f.isAnnotationPresent(clazz)) {
wrap.add(new FieldWrap(f, f.getAnnotation(clazz)));
}
}
return wrap;
}
public Collection getFieldList() {
ArrayList wrap = new ArrayList<>();
for (Field f : fields.values()) {
wrap.add(new FieldWrap(f));
}
return wrap;
}
public Map getFieldMap(Class clazz) {
HashMap wrap = new HashMap<>();
for (Field f : fields.values()) {
if (f.isAnnotationPresent(clazz)) {
wrap.put(f.getName(), new FieldWrap(f, f.getAnnotation(clazz)));
}
}
return wrap;
}
public static class FieldWrap {
private Optional annotation;
private Field field;
private boolean isCollection = false;
private boolean isMap = false;
private Object defaultDeclaringInstance;
public FieldWrap(Field f, Annotation annotation) {
this.field = f;
this.annotation = Optional.of(annotation);
this.isCollection = Collection.class.isAssignableFrom(f.getType());
this.isMap = Map.class.isAssignableFrom(f.getType());
}
public FieldWrap(Field f) {
this.field = f;
Annotation config = f.getAnnotation(Config.class);
if (config == null) {
this.annotation = Optional.absent();
} else {
this.annotation = Optional.of(config);
}
this.isCollection = Collection.class.isAssignableFrom(f.getType());
this.isMap = Map.class.isAssignableFrom(f.getType());
}
public Optional getAnnotation() {
return annotation;
}
public String getFieldName() {
return field.getName();
}
public Class getType() {
if (!isCollection) {
return field.getType();
}
List> p = getParameterizedType(field);
if (p.size() == 0) {
throw new UnsupportedOperationException("Collection of field [" + field
+ "] does not have parameterized arguments, which is not allowed.");
}
return p.get(0);
}
public List> getMapParamTypes() {
if (!isMap) {
throw new UnsupportedOperationException("Field [" + field + "] is not a map.");
}
List> p = getParameterizedType(field);
if (p.size() == 0) {
throw new UnsupportedOperationException("Map of field [" + field
+ "] does not have parameterized arguments, which is not allowed.");
}
return p;
}
public boolean isCollection() {
return isCollection;
}
public boolean isMap() {
return isMap;
}
public boolean isFinal() {
return Modifier.isFinal(field.getModifiers());
}
public boolean isStatic() {
return Modifier.isStatic(field.getModifiers());
}
public boolean isTransient() {
return Modifier.isTransient(field.getModifiers());
}
public boolean isAnnotationPresent(Class cls) {
return field.isAnnotationPresent(cls);
}
public List getEnums() {
if (!isCollection) {
if (field.getType().isEnum()) {
List s = new ArrayList<>();
for (Object o : field.getType().getEnumConstants()) {
s.add(o.toString());
}
return s;
} else {
return new ArrayList<>();
}
}
List> p = getParameterizedType(field);
if (p.size() == 0) {
throw new UnsupportedOperationException("Collection of field [" + field
+ "] does not have parameterized arguments, which is not allowed.");
}
if (p.get(0).isEnum()) {
List s = new ArrayList<>();
for (Object o : p.get(0).getEnumConstants()) {
s.add(o.toString());
}
return s;
}
return new ArrayList<>();
}
/**
* Return the raw collection type
* @return
*/
public Class getCollRawType() {
if (!isCollection) {
throw new UnsupportedOperationException("This field is not a collection.");
}
return field.getType();
}
/**
* Return the raw map type
* @return
*/
public Class getMapRawType() {
if (!isMap) {
throw new UnsupportedOperationException("This field is not a map.");
}
return field.getType();
}
public Object getDefaultValue() {
if (defaultDeclaringInstance == null) {
try {
defaultDeclaringInstance = newInstance(field.getDeclaringClass());
} catch (InstantiationException e) {
throw new UnsupportedOperationException("Cannot access default values "
+ "from fields of class which cannot be constructed.", e);
} catch (IllegalAccessException e) {
throw new UnsupportedOperationException("Cannot access default values "
+ "from fields of class which cannot be constructed.", e);
} catch (InvocationTargetException e) {
throw new UnsupportedOperationException("Cannot access default values "
+ "from fields of class which cannot be constructed.", e);
} catch (NoSuchMethodException e) {
throw new UnsupportedOperationException("Cannot access default values "
+ "from fields of class which cannot be constructed.", e);
}
}
try {
return field.get(defaultDeclaringInstance);
} catch (IllegalArgumentException e) {
throw new UnsupportedOperationException("Cannot access default values "
+ "from fields of instances which cannot be accessed.", e);
} catch (IllegalAccessException e) {
throw new UnsupportedOperationException("Cannot access default values "
+ "from fields of class which cannot be accessed.", e);
}
}
public Object getStaticValue() {
try {
return field.get(null);
} catch (Exception e) {
throw new IllegalArgumentException(
"Cannot access values from fields that arent static.");
}
}
@SuppressWarnings("unchecked")
public Collection