Skip to content

Commit 52119bb

Browse files
committed
Merge branch 'master' into add-directive-creation
# Conflicts: # gradle.properties
2 parents ec7ba9b + b677fcc commit 52119bb

File tree

10 files changed

+253
-49
lines changed

10 files changed

+253
-49
lines changed

README.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ syntax for GraphQL schema definition.
1212

1313
```groovy
1414
dependencies {
15-
compile "io.github.graphql-java:graphql-java-annotations:5.3"
15+
compile "io.github.graphql-java:graphql-java-annotations:5.4"
1616
}
1717
```
1818

@@ -22,7 +22,7 @@ dependencies {
2222
<dependency>
2323
<groupId>io.github.graphql-java</groupId>
2424
<artifactId>graphql-java-annotations</artifactId>
25-
<version>5.3</version>
25+
<version>5.4</version>
2626
</dependency>
2727
```
2828

gradle.properties

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,4 @@ org.gradle.jvmargs=-Dfile.encoding=UTF-8
77

88
bintray.user=DUMMY_USER
99
bintray.key=DUMMY_KEY
10-
version = 5.3.1
10+
version = 5.3.1

src/main/java/graphql/annotations/dataFetchers/MethodDataFetcher.java

+59-18
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,35 @@
2323

2424
import java.lang.reflect.*;
2525
import java.util.ArrayList;
26+
import java.util.Arrays;
2627
import java.util.List;
2728
import java.util.Map;
2829

2930
import static graphql.annotations.processor.util.NamingKit.toGraphqlName;
3031
import static graphql.annotations.processor.util.PrefixesUtil.addPrefixToPropertyName;
32+
import static graphql.annotations.processor.util.PrefixesUtil.extractPrefixedName;
3133
import static graphql.annotations.processor.util.ReflectionKit.constructNewInstance;
3234
import static graphql.annotations.processor.util.ReflectionKit.newInstance;
3335

36+
37+
/**
38+
* This class is determining how to return value of a method from an api entity
39+
* The order of the mapping:
40+
* 1. If no source is provided to map between - invoking the method implementation
41+
* 2. If annotated with @GraphQLInvokeDetached - invoking the method implementation
42+
* 3. else If source is provided, and method name is matching a method name in the source object - execute source implementation
43+
* i.e method name is: `name` ; existing method in the source object with name: `name`
44+
* 4. else If source is provided, and method name is matching a method name with a `get` prefix in the source object - execute source implementation
45+
* i.e method name is: `name` ; existing method in the source object with name: `getName`
46+
* 5. else If source is provided, and method name is matching a method name with a `is` prefix in the source object - execute source implementation
47+
* i.e method name is: `name` ; existing method in the source object with name: isName
48+
* 6. else If source is provided, and method name is matching a field name in the source object - return field value from the source object
49+
* i.e method name is: `name` ; field name in source object is: `name`
50+
* 7. else If source is provided, and method name is prefixed with `get` or `is` - and it matches to a field name (without the prefix) in the source object - return field value from the source object
51+
* i.e method name is: `getName` ; field name in source object is: `name`
52+
*
53+
* @param <T> type of the returned value
54+
*/
3455
public class MethodDataFetcher<T> implements DataFetcher<T> {
3556
private final Method method;
3657
private final ProcessingElementsContainer container;
@@ -47,7 +68,10 @@ public MethodDataFetcher(Method method, TypeFunction typeFunction, ProcessingEle
4768
public T get(DataFetchingEnvironment environment) {
4869
try {
4970
T obj;
50-
if (method.isAnnotationPresent(GraphQLBatched.class) || method.isAnnotationPresent(GraphQLInvokeDetached.class)) {
71+
if (Modifier.isStatic(method.getModifiers())){
72+
return (T) method.invoke(null, invocationArgs(environment, container));
73+
}
74+
else if (method.isAnnotationPresent(GraphQLBatched.class) || method.isAnnotationPresent(GraphQLInvokeDetached.class)) {
5175
obj = newInstance((Class<T>) method.getDeclaringClass());
5276
} else if (!method.getDeclaringClass().isInstance(environment.getSource())) {
5377
obj = newInstance((Class<T>) method.getDeclaringClass(), environment.getSource());
@@ -59,7 +83,7 @@ public T get(DataFetchingEnvironment environment) {
5983
}
6084

6185
if (obj == null && environment.getSource() != null) {
62-
Object value = getGraphQLFieldValue(environment.getSource(), environment.getField().getName());
86+
Object value = getGraphQLFieldValue(environment.getSource(), method.getName());
6387
return (T) value;
6488
}
6589

@@ -140,20 +164,43 @@ private Object getGraphQLFieldValue(Object source, String fieldName) throws Ille
140164
Object methodValue = getValueFromMethod(source, fieldName);
141165
if (methodValue != null) return methodValue;
142166

143-
Field field = getField(source.getClass(), fieldName);
144-
if (getValueFromField(field)) return field.get(source);
167+
Object fieldValue = getValueFromField(source, fieldName);
168+
if (fieldValue != null) return fieldValue;
145169

146170
throw new NoSuchFieldException("No GraphQL field found");
147171
}
148172

149-
private boolean getValueFromField(Field field) throws IllegalAccessException {
173+
private Object getValueFromField(Object source, String fieldName) throws IllegalAccessException {
174+
List<String> namesToSearchFor = Arrays.asList(fieldName, extractPrefixedName(fieldName));
175+
for (String name : namesToSearchFor) {
176+
Field field = getField(source.getClass(), name);
177+
if (isFieldContainsValue(field)) {
178+
return field.get(source);
179+
}
180+
}
181+
return null;
182+
}
183+
184+
private boolean isFieldContainsValue(Field field) throws IllegalAccessException {
150185
if (field != null) {
151186
field.setAccessible(true);
152187
return true;
153188
}
154189
return false;
155190
}
156191

192+
private Field getField(Class<?> clazz, String name) {
193+
Field field = null;
194+
while (clazz != null && field == null) {
195+
try {
196+
field = clazz.getDeclaredField(name);
197+
} catch (Exception ignored) {
198+
}
199+
clazz = clazz.getSuperclass();
200+
}
201+
return field;
202+
}
203+
157204
private Object getValueFromMethod(Object source, String fieldName) throws IllegalAccessException, InvocationTargetException {
158205
String[] orderedPrefixes = new String[]{"", "get", "is"};
159206
for (String orderedPrefix : orderedPrefixes) {
@@ -166,7 +213,13 @@ private Object getValueFromMethod(Object source, String fieldName) throws Illega
166213
}
167214

168215
private Method getMethod(Class<?> clazz, String name, String prefix) {
169-
String prefixedName = addPrefixToPropertyName(prefix, name);
216+
String prefixedName;
217+
if (prefix.isEmpty()) {
218+
prefixedName = name;
219+
} else {
220+
prefixedName = addPrefixToPropertyName(prefix, name);
221+
}
222+
170223
Method method = null;
171224
while (clazz != null && method == null) {
172225
try {
@@ -179,16 +232,4 @@ private Method getMethod(Class<?> clazz, String name, String prefix) {
179232
return method;
180233
}
181234

182-
private Field getField(Class<?> clazz, String name) {
183-
Field field = null;
184-
while (clazz != null && field == null) {
185-
try {
186-
field = clazz.getDeclaredField(name);
187-
} catch (Exception ignored) {
188-
}
189-
clazz = clazz.getSuperclass();
190-
}
191-
return field;
192-
}
193-
194235
}

src/main/java/graphql/annotations/processor/retrievers/GraphQLFieldRetriever.java

+10-4
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,8 @@ public class GraphQLFieldRetriever {
5858

5959
private DataFetcherConstructor dataFetcherConstructor;
6060

61+
private boolean alwaysPrettify = false;
62+
6163
public GraphQLFieldRetriever(DataFetcherConstructor dataFetcherConstructor) {
6264
this.dataFetcherConstructor = dataFetcherConstructor;
6365
}
@@ -69,7 +71,7 @@ public GraphQLFieldRetriever() {
6971
public GraphQLFieldDefinition getField(Method method, ProcessingElementsContainer container) throws GraphQLAnnotationsException {
7072
GraphQLFieldDefinition.Builder builder = newFieldDefinition();
7173
TypeFunction typeFunction = getTypeFunction(method, container);
72-
builder.name(new MethodNameBuilder(method).build());
74+
builder.name(new MethodNameBuilder(method).alwaysPrettify(alwaysPrettify).build());
7375
GraphQLOutputType outputType = (GraphQLOutputType) new MethodTypeBuilder(method, typeFunction, container, false).build();
7476

7577
boolean isConnection = ConnectionUtil.isConnection(method, outputType);
@@ -91,7 +93,7 @@ public GraphQLFieldDefinition getField(Method method, ProcessingElementsContaine
9193

9294
public GraphQLFieldDefinition getField(Field field, ProcessingElementsContainer container) throws GraphQLAnnotationsException {
9395
GraphQLFieldDefinition.Builder builder = newFieldDefinition();
94-
builder.name(new FieldNameBuilder(field).build());
96+
builder.name(new FieldNameBuilder(field).alwaysPrettify(alwaysPrettify).build());
9597
TypeFunction typeFunction = getTypeFunction(field, container);
9698

9799
GraphQLType outputType = typeFunction.buildType(field.getType(), field.getAnnotatedType(), container);
@@ -113,15 +115,15 @@ public GraphQLFieldDefinition getField(Field field, ProcessingElementsContainer
113115

114116
public GraphQLInputObjectField getInputField(Method method, ProcessingElementsContainer container) throws GraphQLAnnotationsException {
115117
GraphQLInputObjectField.Builder builder = newInputObjectField();
116-
builder.name(new MethodNameBuilder(method).build());
118+
builder.name(new MethodNameBuilder(method).alwaysPrettify(alwaysPrettify).build());
117119
TypeFunction typeFunction = getTypeFunction(method, container);
118120
GraphQLInputType inputType = (GraphQLInputType) new MethodTypeBuilder(method, typeFunction, container, true).build();
119121
return builder.type(inputType).description(new DescriptionBuilder(method).build()).build();
120122
}
121123

122124
public GraphQLInputObjectField getInputField(Field field, ProcessingElementsContainer container) throws GraphQLAnnotationsException {
123125
GraphQLInputObjectField.Builder builder = newInputObjectField();
124-
builder.name(new FieldNameBuilder(field).build());
126+
builder.name(new FieldNameBuilder(field).alwaysPrettify(alwaysPrettify).build());
125127
TypeFunction typeFunction = getTypeFunction(field, container);
126128
GraphQLType graphQLType = typeFunction.buildType(true, field.getType(), field.getAnnotatedType(), container);
127129
return builder.type((GraphQLInputType) graphQLType).description(new DescriptionBuilder(field).build()).build();
@@ -204,6 +206,10 @@ private GraphQLObjectType getActualType(GraphQLObjectType type, Map<String, grap
204206
return type;
205207
}
206208

209+
public void setAlwaysPrettify(boolean alwaysPrettify) {
210+
this.alwaysPrettify = alwaysPrettify;
211+
}
212+
207213
@Reference(policy = ReferencePolicy.DYNAMIC, policyOption = ReferencePolicyOption.GREEDY)
208214
public void setDataFetcherConstructor(DataFetcherConstructor dataFetcherConstructor) {
209215
this.dataFetcherConstructor = dataFetcherConstructor;

src/main/java/graphql/annotations/processor/retrievers/fieldBuilders/field/FieldNameBuilder.java

+8-1
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,20 @@
2525
public class FieldNameBuilder implements Builder<String> {
2626
private Field field;
2727

28+
private boolean alwaysPrettify = false;
29+
2830
public FieldNameBuilder(Field field) {
2931
this.field = field;
3032
}
3133

34+
public FieldNameBuilder alwaysPrettify(boolean alwaysPrettify) {
35+
this.alwaysPrettify = alwaysPrettify;
36+
return this;
37+
}
38+
3239
@Override
3340
public String build() {
34-
if (field.isAnnotationPresent(GraphQLPrettify.class) && !field.isAnnotationPresent(GraphQLName.class)) {
41+
if ((alwaysPrettify || field.isAnnotationPresent(GraphQLPrettify.class)) && !field.isAnnotationPresent(GraphQLName.class)) {
3542
return toGraphqlName(prettifyName(field.getName()));
3643
}
3744
GraphQLName name = field.getAnnotation(GraphQLName.class);

src/main/java/graphql/annotations/processor/retrievers/fieldBuilders/method/MethodNameBuilder.java

+9-1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import graphql.annotations.annotationTypes.GraphQLName;
1818
import graphql.annotations.annotationTypes.GraphQLPrettify;
1919
import graphql.annotations.processor.retrievers.fieldBuilders.Builder;
20+
import graphql.annotations.processor.retrievers.fieldBuilders.field.FieldNameBuilder;
2021

2122
import java.lang.reflect.Method;
2223

@@ -25,13 +26,20 @@
2526
public class MethodNameBuilder implements Builder<String> {
2627
private Method method;
2728

29+
private boolean alwaysPrettify = false;
30+
2831
public MethodNameBuilder(Method method) {
2932
this.method = method;
3033
}
3134

35+
public MethodNameBuilder alwaysPrettify(boolean alwaysPrettify) {
36+
this.alwaysPrettify = alwaysPrettify;
37+
return this;
38+
}
39+
3240
@Override
3341
public String build() {
34-
if (method.isAnnotationPresent(GraphQLPrettify.class) && !method.isAnnotationPresent(GraphQLName.class)) {
42+
if ((alwaysPrettify || method.isAnnotationPresent(GraphQLPrettify.class)) && !method.isAnnotationPresent(GraphQLName.class)) {
3543
return toGraphqlName(prettifyName(method.getName()));
3644
}
3745
GraphQLName name = method.getAnnotation(GraphQLName.class);

src/main/java/graphql/annotations/processor/util/PrefixesUtil.java

+9
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,13 @@ public class PrefixesUtil {
1818
public static String addPrefixToPropertyName(String prefix, String propertyName) {
1919
return prefix + propertyName.substring(0, 1).toUpperCase() + propertyName.substring(1);
2020
}
21+
22+
public static String extractPrefixedName(String name) {
23+
if (name.startsWith("is")) {
24+
return name.replaceFirst("^is", "").toLowerCase();
25+
} else if (name.startsWith("get")) {
26+
return name.replaceFirst("^get", "").toLowerCase();
27+
}
28+
return name;
29+
}
2130
}

0 commit comments

Comments
 (0)