Skip to content

Commit 364f650

Browse files
phillip-krugerjmartisk
authored andcommitted
Allow adaptTo and adaptWith on class level and make FieldDataFetcher plugable
Signed-off-by: Phillip Kruger <phillip.kruger@gmail.com>
1 parent 88971ee commit 364f650

File tree

12 files changed

+130
-92
lines changed

12 files changed

+130
-92
lines changed

common/schema-builder/src/main/java/io/smallrye/graphql/schema/helper/AdaptToHelper.java

Lines changed: 50 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -49,63 +49,66 @@ public static Optional<AdaptTo> getAdaptTo(Field field, Annotations annotations)
4949
* @return Potentially a AdaptTo model
5050
*/
5151
public static Optional<AdaptTo> getAdaptTo(Reference r, Annotations annotations) {
52-
Type type = getAdaptTo(annotations);
53-
if (type != null) {
54-
String scalarName = getScalarName(type);
55-
Reference reference = Scalars.getScalar(scalarName);
56-
AdaptTo adaptTo = new AdaptTo(reference);
57-
// Check the way to create this (deserializeMethod)
58-
// First check if the user supplied a way
59-
String deserializeMethod = getDeserializeMethod(annotations);
60-
if (deserializeMethod != null) {
61-
adaptTo.setDeserializeMethod(deserializeMethod);
62-
} else {
63-
// Auto detect this.
64-
String className = r.getClassName();
65-
if (!r.getType().equals(ReferenceType.SCALAR)) { // mapping to scalar stays on default NONE
66-
ClassInfo classInfo = ScanningContext.getIndex().getClassByName(DotName.createSimple(className));
67-
if (classInfo != null) {
68-
// Get Parameter type
69-
Type parameter = Type.create(DotName.createSimple(reference.getClassName()), Type.Kind.CLASS);
70-
71-
// Check if we can use a constructor
72-
MethodInfo constructor = classInfo.method(CONTRUCTOR_METHOD_NAME, parameter);
73-
if (constructor != null) {
74-
adaptTo.setDeserializeMethod(CONTRUCTOR_METHOD_NAME); // Create new instance with a contructor
75-
} else {
76-
// Check if we can use setValue
77-
MethodInfo setValueMethod = classInfo.method(SET_VALUE_METHOD_NAME, parameter);
78-
if (setValueMethod != null) {
79-
adaptTo.setDeserializeMethod(SET_VALUE_METHOD_NAME);
52+
53+
if (r.isAdaptingTo()) {
54+
return Optional.of(r.getAdaptTo());
55+
} else {
56+
Type type = getAdaptTo(annotations);
57+
if (type != null) {
58+
String scalarName = getScalarName(type);
59+
Reference reference = Scalars.getScalar(scalarName);
60+
AdaptTo adaptTo = new AdaptTo(reference);
61+
// Check the way to create this (deserializeMethod)
62+
// First check if the user supplied a way
63+
String deserializeMethod = getDeserializeMethod(annotations);
64+
if (deserializeMethod != null) {
65+
adaptTo.setDeserializeMethod(deserializeMethod);
66+
} else {
67+
// Auto detect this.
68+
String className = r.getClassName();
69+
if (!r.getType().equals(ReferenceType.SCALAR)) { // mapping to scalar stays on default NONE
70+
ClassInfo classInfo = ScanningContext.getIndex().getClassByName(DotName.createSimple(className));
71+
if (classInfo != null) {
72+
// Get Parameter type
73+
Type parameter = Type.create(DotName.createSimple(reference.getClassName()), Type.Kind.CLASS);
74+
75+
// Check if we can use a constructor
76+
MethodInfo constructor = classInfo.method(CONTRUCTOR_METHOD_NAME, parameter);
77+
if (constructor != null) {
78+
adaptTo.setDeserializeMethod(CONTRUCTOR_METHOD_NAME); // Create new instance with a contructor
8079
} else {
81-
// Check if we can use static fromXXXXX
82-
String staticFromMethodName = FROM + scalarName;
83-
MethodInfo staticFromMethod = classInfo.method(staticFromMethodName, parameter);
84-
if (staticFromMethod != null) {
85-
adaptTo.setDeserializeMethod(staticFromMethodName);
80+
// Check if we can use setValue
81+
MethodInfo setValueMethod = classInfo.method(SET_VALUE_METHOD_NAME, parameter);
82+
if (setValueMethod != null) {
83+
adaptTo.setDeserializeMethod(SET_VALUE_METHOD_NAME);
8684
} else {
87-
// Check if we can use static getInstance
88-
MethodInfo staticGetInstance = classInfo.method(GET_INSTANCE_METHOD_NAME, parameter);
89-
if (staticGetInstance != null) {
90-
adaptTo.setDeserializeMethod(GET_INSTANCE_METHOD_NAME);
85+
// Check if we can use static fromXXXXX
86+
String staticFromMethodName = FROM + scalarName;
87+
MethodInfo staticFromMethod = classInfo.method(staticFromMethodName, parameter);
88+
if (staticFromMethod != null) {
89+
adaptTo.setDeserializeMethod(staticFromMethodName);
90+
} else {
91+
// Check if we can use static getInstance
92+
MethodInfo staticGetInstance = classInfo.method(GET_INSTANCE_METHOD_NAME, parameter);
93+
if (staticGetInstance != null) {
94+
adaptTo.setDeserializeMethod(GET_INSTANCE_METHOD_NAME);
95+
}
9196
}
9297
}
9398
}
94-
}
9599

100+
}
96101
}
97102
}
98-
}
99103

100-
// Get serializeMethod (default to toString)
101-
String serializeMethod = getSerializeMethod(annotations);
102-
if (serializeMethod != null) {
103-
adaptTo.setSerializeMethod(serializeMethod);
104-
}
104+
// Get serializeMethod (default to toString)
105+
String serializeMethod = getSerializeMethod(annotations);
106+
if (serializeMethod != null) {
107+
adaptTo.setSerializeMethod(serializeMethod);
108+
}
105109

106-
return Optional.of(adaptTo);
107-
} else {
108-
// TODO: Support other than Scalar mapping
110+
return Optional.of(adaptTo);
111+
}
109112
}
110113
return Optional.empty();
111114
}

common/schema-builder/src/main/java/io/smallrye/graphql/schema/helper/AdaptWithHelper.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,9 @@ public static Optional<AdaptWith> getAdaptWith(Direction direction, ReferenceCre
5959
*/
6060
public static Optional<AdaptWith> getAdaptWith(Direction direction, ReferenceCreator referenceCreator, Reference r,
6161
Annotations annotations, AdapterType adapterType) {
62-
63-
if (adapterType != null) {
62+
if (r.isAdaptingWith()) {
63+
return Optional.of(r.getAdaptWith());
64+
} else if (adapterType != null) {
6465
Type type = adapterType.type;
6566
AdaptWith adaptWith = adapterType.adaptWith;
6667
if (type.kind().equals(Type.Kind.CLASS)) {

server/implementation/src/main/java/io/smallrye/graphql/bootstrap/Bootstrap.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@
5050
import io.smallrye.graphql.execution.Classes;
5151
import io.smallrye.graphql.execution.datafetcher.BatchDataFetcher;
5252
import io.smallrye.graphql.execution.datafetcher.CollectionCreator;
53-
import io.smallrye.graphql.execution.datafetcher.FieldDataFetcher;
53+
import io.smallrye.graphql.execution.datafetcher.PlugableDataFetcher;
5454
import io.smallrye.graphql.execution.error.ErrorInfoMap;
5555
import io.smallrye.graphql.execution.event.EventEmitter;
5656
import io.smallrye.graphql.execution.resolver.InterfaceOutputRegistry;
@@ -642,7 +642,7 @@ private GraphQLFieldDefinition createGraphQLFieldDefinitionFromField(Reference o
642642
GraphQLFieldDefinition graphQLFieldDefinition = fieldBuilder.build();
643643

644644
// DataFetcher
645-
FieldDataFetcher<?> datafetcher = new FieldDataFetcher<>(field, getTypeForField(field), owner);
645+
PlugableDataFetcher<?> datafetcher = dataFetcherFactory.getFieldDataFetcher(field, getTypeForField(field), owner);
646646
this.codeRegistryBuilder.dataFetcher(FieldCoordinates.coordinates(owner.getName(), graphQLFieldDefinition.getName()),
647647
datafetcher);
648648

server/implementation/src/main/java/io/smallrye/graphql/bootstrap/DataFetcherFactory.java

Lines changed: 27 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,15 @@
1414
import graphql.schema.DataFetcher;
1515
import io.smallrye.graphql.execution.datafetcher.CompletionStageDataFetcher;
1616
import io.smallrye.graphql.execution.datafetcher.DefaultDataFetcher;
17+
import io.smallrye.graphql.execution.datafetcher.FieldDataFetcher;
1718
import io.smallrye.graphql.execution.datafetcher.MultiDataFetcher;
19+
import io.smallrye.graphql.execution.datafetcher.PlugableBatchableDataFetcher;
1820
import io.smallrye.graphql.execution.datafetcher.PlugableDataFetcher;
1921
import io.smallrye.graphql.execution.datafetcher.PublisherDataFetcher;
2022
import io.smallrye.graphql.execution.datafetcher.UniDataFetcher;
2123
import io.smallrye.graphql.schema.model.Field;
2224
import io.smallrye.graphql.schema.model.Operation;
25+
import io.smallrye.graphql.schema.model.Reference;
2326
import io.smallrye.graphql.schema.model.Type;
2427
import io.smallrye.graphql.schema.model.Wrapper;
2528
import io.smallrye.graphql.spi.DataFetcherService;
@@ -51,6 +54,16 @@ public <T> DataFetcher<T> getDataFetcher(Operation operation, Type type) {
5154
return (DataFetcher<T>) get(operation, type);
5255
}
5356

57+
public <T> PlugableDataFetcher<T> getFieldDataFetcher(Field field, Type type, Reference owner) {
58+
for (DataFetcherService dfe : dataFetcherServices) {
59+
PlugableDataFetcher df = dfe.getFieldDataFetcher(field, type, owner);
60+
if (df != null) {
61+
return (PlugableDataFetcher) df;
62+
}
63+
}
64+
return new FieldDataFetcher<>(field, type, owner);
65+
}
66+
5467
public <K, T> BatchLoaderWithContext<K, T> getSourceBatchLoader(Operation operation, Type type) {
5568
return (BatchLoaderWithContext<K, T>) get(operation, type);
5669
}
@@ -85,10 +98,10 @@ private <V> V get(Operation operation, Type type) {
8598
return (V) getOtherFieldDataFetcher(operation, type);
8699
}
87100

88-
public PlugableDataFetcher getCompletionStageDataFetcher(Operation operation, Type type) {
101+
private PlugableBatchableDataFetcher getCompletionStageDataFetcher(Operation operation, Type type) {
89102

90103
for (DataFetcherService dfe : dataFetcherServices) {
91-
PlugableDataFetcher df = dfe.getCompletionStageDataFetcher(operation, type);
104+
PlugableBatchableDataFetcher df = dfe.getCompletionStageDataFetcher(operation, type);
92105
if (df != null) {
93106
return df;
94107
}
@@ -97,10 +110,10 @@ public PlugableDataFetcher getCompletionStageDataFetcher(Operation operation, Ty
97110
return new CompletionStageDataFetcher(operation, type);
98111
}
99112

100-
public PlugableDataFetcher getUniDataFetcher(Operation operation, Type type) {
113+
private PlugableBatchableDataFetcher getUniDataFetcher(Operation operation, Type type) {
101114

102115
for (DataFetcherService dfe : dataFetcherServices) {
103-
PlugableDataFetcher df = dfe.getUniDataFetcher(operation, type);
116+
PlugableBatchableDataFetcher df = dfe.getUniDataFetcher(operation, type);
104117
if (df != null) {
105118
return df;
106119
}
@@ -109,10 +122,10 @@ public PlugableDataFetcher getUniDataFetcher(Operation operation, Type type) {
109122
return new UniDataFetcher(operation, type);
110123
}
111124

112-
public PlugableDataFetcher getPublisherDataFetcher(Operation operation, Type type) {
125+
private PlugableBatchableDataFetcher getPublisherDataFetcher(Operation operation, Type type) {
113126

114127
for (DataFetcherService dfe : dataFetcherServices) {
115-
PlugableDataFetcher df = dfe.getPublisherDataFetcher(operation, type);
128+
PlugableBatchableDataFetcher df = dfe.getPublisherDataFetcher(operation, type);
116129
if (df != null) {
117130
return df;
118131
}
@@ -121,10 +134,10 @@ public PlugableDataFetcher getPublisherDataFetcher(Operation operation, Type typ
121134
return new PublisherDataFetcher(operation, type);
122135
}
123136

124-
public PlugableDataFetcher getMultiDataFetcher(Operation operation, Type type) {
137+
private PlugableBatchableDataFetcher getMultiDataFetcher(Operation operation, Type type) {
125138

126139
for (DataFetcherService dfe : dataFetcherServices) {
127-
PlugableDataFetcher df = dfe.getMultiDataFetcher(operation, type);
140+
PlugableBatchableDataFetcher df = dfe.getMultiDataFetcher(operation, type);
128141
if (df != null) {
129142
return df;
130143
}
@@ -133,10 +146,10 @@ public PlugableDataFetcher getMultiDataFetcher(Operation operation, Type type) {
133146
return new MultiDataFetcher(operation, type);
134147
}
135148

136-
public PlugableDataFetcher getOtherWrappedDataFetcher(Operation operation, Type type) {
149+
private PlugableBatchableDataFetcher getOtherWrappedDataFetcher(Operation operation, Type type) {
137150

138151
for (DataFetcherService dfe : dataFetcherServices) {
139-
PlugableDataFetcher df = dfe.getOtherWrappedDataFetcher(operation, type);
152+
PlugableBatchableDataFetcher df = dfe.getOtherWrappedDataFetcher(operation, type);
140153
if (df != null) {
141154
return df;
142155
}
@@ -145,17 +158,17 @@ public PlugableDataFetcher getOtherWrappedDataFetcher(Operation operation, Type
145158
return getDefaultDataFetcher(operation, type);
146159
}
147160

148-
public PlugableDataFetcher getOtherFieldDataFetcher(Operation operation, Type type) {
161+
private PlugableBatchableDataFetcher getOtherFieldDataFetcher(Operation operation, Type type) {
149162

150163
for (DataFetcherService dfe : dataFetcherServices) {
151-
PlugableDataFetcher df = dfe.getOtherFieldDataFetcher(operation, type);
164+
PlugableBatchableDataFetcher df = dfe.getOtherFieldDataFetcher(operation, type);
152165
if (df != null) {
153166
return df;
154167
}
155168
}
156169

157170
for (DataFetcherService dfe : dataFetcherServices) {
158-
PlugableDataFetcher df = dfe.getDefaultDataFetcher(operation, type);
171+
PlugableBatchableDataFetcher df = dfe.getDefaultDataFetcher(operation, type);
159172
if (df != null) {
160173
return df;
161174
}
@@ -164,7 +177,7 @@ public PlugableDataFetcher getOtherFieldDataFetcher(Operation operation, Type ty
164177
return new DefaultDataFetcher(operation, type);
165178
}
166179

167-
public PlugableDataFetcher getDefaultDataFetcher(Operation operation, Type type) {
180+
private PlugableBatchableDataFetcher getDefaultDataFetcher(Operation operation, Type type) {
168181
return getOtherFieldDataFetcher(operation, type);
169182
}
170183

server/implementation/src/main/java/io/smallrye/graphql/execution/datafetcher/AbstractDataFetcher.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
* @param <K>
2929
* @param <T>
3030
*/
31-
public abstract class AbstractDataFetcher<K, T> implements PlugableDataFetcher<K, T> {
31+
public abstract class AbstractDataFetcher<K, T> implements PlugableBatchableDataFetcher<K, T> {
3232

3333
protected Operation operation;
3434
protected Type type;

server/implementation/src/main/java/io/smallrye/graphql/execution/datafetcher/FieldDataFetcher.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66

77
import graphql.GraphQLException;
88
import graphql.TrivialDataFetcher;
9-
import graphql.schema.DataFetcher;
109
import graphql.schema.DataFetchingEnvironment;
1110
import io.smallrye.graphql.execution.context.SmallRyeContextManager;
1211
import io.smallrye.graphql.execution.datafetcher.helper.FieldHelper;
@@ -29,7 +28,7 @@
2928
* different
3029
* subtype of the owner class for each call).
3130
*/
32-
public class FieldDataFetcher<T> implements DataFetcher<T>, TrivialDataFetcher<T> {
31+
public class FieldDataFetcher<T> implements PlugableDataFetcher<T>, TrivialDataFetcher<T> {
3332

3433
private final FieldHelper fieldHelper;
3534
private final Field field;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package io.smallrye.graphql.execution.datafetcher;
2+
3+
import org.dataloader.BatchLoaderWithContext;
4+
5+
/**
6+
* Allows DataFetchers to be plugged
7+
*
8+
* @author Phillip Kruger (phillip.kruger@redhat.com)
9+
*/
10+
public interface PlugableBatchableDataFetcher<K, T> extends PlugableDataFetcher<T>, BatchLoaderWithContext<K, T> {
11+
12+
}
Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,12 @@
11
package io.smallrye.graphql.execution.datafetcher;
22

3-
import org.dataloader.BatchLoaderWithContext;
4-
53
import graphql.schema.DataFetcher;
64

75
/**
86
* Allows DataFetchers to be plugged
97
*
108
* @author Phillip Kruger (phillip.kruger@redhat.com)
119
*/
12-
public interface PlugableDataFetcher<K, T> extends DataFetcher<T>, BatchLoaderWithContext<K, T> {
10+
public interface PlugableDataFetcher<T> extends DataFetcher<T> {
1311

1412
}

server/implementation/src/main/java/io/smallrye/graphql/execution/datafetcher/helper/AbstractHelper.java

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,23 @@ protected boolean shouldTransform(Field field) {
5959
* @return if adaption is needed
6060
*/
6161
protected boolean shouldAdapt(Field field) {
62-
return field.getReference().isAdaptingWith() || field.isAdaptingWith()
63-
|| (field.hasWrapper() && field.getWrapper().isMap());
62+
return shouldAdaptWith(field) || shouldAutoAdaptWithMap(field) || shouldAdaptTo(field);
63+
}
64+
65+
protected boolean shouldAutoAdaptWithMap(Field field) {
66+
return field.hasWrapper() && field.getWrapper().isMap();
67+
}
68+
69+
protected boolean shouldAdaptWith(Field field) {
70+
return field.getReference().isAdaptingWith() || field.isAdaptingWith();
71+
}
72+
73+
protected boolean shouldAdaptTo(Field field) {
74+
return field.getReference().isAdaptingTo()
75+
&& field.getReference().getAdaptTo().getDeserializeMethod() != null
76+
||
77+
field.isAdaptingTo()
78+
&& field.getAdaptTo().getDeserializeMethod() != null;
6479
}
6580

6681
public Object transformOrAdapt(Object val, Field field, DataFetchingEnvironment dfe)

server/implementation/src/main/java/io/smallrye/graphql/execution/datafetcher/helper/ArgumentHelper.java

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -243,18 +243,6 @@ private Object transformInput(Field field, Object object) throws AbstractDataFet
243243
}
244244
}
245245

246-
private boolean shouldAdaptTo(Field field) {
247-
return field.getReference().isAdaptingTo()
248-
&& field.getReference().getAdaptTo().getDeserializeMethod() != null
249-
||
250-
field.isAdaptingTo()
251-
&& field.getAdaptTo().getDeserializeMethod() != null;
252-
}
253-
254-
private boolean shouldAdaptWith(Field field) {
255-
return field.getReference().isAdaptingWith() || field.isAdaptingWith();
256-
}
257-
258246
private String getCreateMethodName(Field field) {
259247
if (field.getReference().isAdaptingTo()) {
260248
return field.getReference().getAdaptTo().getDeserializeMethod();

server/implementation/src/main/java/io/smallrye/graphql/execution/datafetcher/helper/FieldHelper.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,8 @@ Object singleAdapting(Object argumentValue, Field field, DataFetchingEnvironment
7979
log.transformError(ex);
8080
throw new TransformException(ex, field, argumentValue);
8181
}
82+
} else if (field.isAdaptingTo()) {
83+
return argumentValue.toString();
8284
} else if (field.hasWrapper() && field.getWrapper().isMap()) {
8385
Object key = null;
8486
Map<String, Object> arguments = dfe.getArguments();

0 commit comments

Comments
 (0)