graphql.schema.PropertyDataFetcher Maven / Gradle / Ivy
package graphql.schema;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.Map;
import static graphql.Scalars.GraphQLBoolean;
public class PropertyDataFetcher implements DataFetcher {
private final String propertyName;
public PropertyDataFetcher(String propertyName) {
this.propertyName = propertyName;
}
@SuppressWarnings("unchecked")
@Override
public T get(DataFetchingEnvironment environment) {
Object source = environment.getSource();
if (source == null) return null;
if (source instanceof Map) {
return (T) ((Map, ?>) source).get(propertyName);
}
return (T) getPropertyViaGetter(source, environment.getFieldType());
}
/**
* Invoking public methods on package-protected classes via reflection
* causes exceptions. This method searches a class's hierarchy for
* public visibility parent classes with the desired getter. This
* particular case is required to support AutoValue style data classes,
* which have abstract public interfaces implemented by package-protected
* (generated) subclasses.
*/
private Method findAccessibleMethod(Class root, String methodName) throws NoSuchMethodException {
Class cur = root;
while(cur != null) {
if(Modifier.isPublic(cur.getModifiers())){
Method m = cur.getMethod(methodName);
if (Modifier.isPublic(m.getModifiers())) {
return m;
}
}
cur = cur.getSuperclass();
}
return root.getMethod(methodName);
}
private Object getPropertyViaGetter(Object object, GraphQLOutputType outputType) {
try {
if (isBooleanProperty(outputType)) {
try {
return getPropertyViaGetterUsingPrefix(object, "is");
} catch (NoSuchMethodException e) {
return getPropertyViaGetterUsingPrefix(object, "get");
}
} else {
return getPropertyViaGetterUsingPrefix(object, "get");
}
} catch (NoSuchMethodException e1) {
return getPropertyViaFieldAccess(object);
}
}
private Object getPropertyViaGetterUsingPrefix(Object object, String prefix) throws NoSuchMethodException {
String getterName = prefix + propertyName.substring(0, 1).toUpperCase() + propertyName.substring(1);
try {
Method method = findAccessibleMethod(object.getClass(), getterName);
return method.invoke(object);
} catch (IllegalAccessException | InvocationTargetException e) {
throw new RuntimeException(e);
}
}
private boolean isBooleanProperty(GraphQLOutputType outputType) {
if (outputType == GraphQLBoolean) return true;
if (outputType instanceof GraphQLNonNull) {
return ((GraphQLNonNull) outputType).getWrappedType() == GraphQLBoolean;
}
return false;
}
private Object getPropertyViaFieldAccess(Object object) {
try {
Field field = object.getClass().getField(propertyName);
return field.get(object);
} catch (NoSuchFieldException e) {
return null;
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy