2525
2626public class Execution {
2727
28- private FieldCollector fieldCollector ;
29- private ValuesResolver valuesResolver ;
30- private ExecutorService executorService ;
28+ private FieldCollector fieldCollector = new FieldCollector ();
29+ private ExecutionStrategy strategy ;
3130
31+ public Execution (ExecutionStrategy strategy ) {
32+ this .strategy = strategy ;
3233
33- private static final Logger log = LoggerFactory .getLogger (Execution .class );
34-
35- public Execution (ExecutorService executorService ) {
36- fieldCollector = new FieldCollector ();
37- valuesResolver = new ValuesResolver ();
38- this .executorService = executorService ;
34+ if (this .strategy == null ) {
35+ this .strategy = new SimpleExecutionStrategy ();
36+ }
3937 }
4038
4139 public ExecutionResult execute (GraphQLSchema graphQLSchema , Object root , Document document , String operationName , Map <String , Object > args ) {
4240 ExecutionContextBuilder executionContextBuilder = new ExecutionContextBuilder (new ValuesResolver ());
43- ExecutionContext executionContext = executionContextBuilder .build (graphQLSchema , root , document , operationName , args );
41+ ExecutionContext executionContext = executionContextBuilder .build (graphQLSchema , strategy , root , document , operationName , args );
4442 return executeOperation (executionContext , root , executionContext .getOperationDefinition ());
4543 }
4644
@@ -65,162 +63,10 @@ private ExecutionResult executeOperation(
6563 Map <String , List <Field >> fields = new LinkedHashMap <>();
6664 fieldCollector .collectFields (executionContext , operationRootType , operationDefinition .getSelectionSet (), new ArrayList <String >(), fields );
6765
68- Map <String , Object > result ;
6966 if (operationDefinition .getOperation () == OperationDefinition .Operation .MUTATION ) {
70- result = executeFieldsSerially (executionContext , operationRootType , root , fields );
67+ return new SimpleExecutionStrategy (). execute (executionContext , operationRootType , root , fields );
7168 } else {
72- result = executeFieldsParallel (executionContext , operationRootType , root , fields );
69+ return strategy . execute (executionContext , operationRootType , root , fields );
7370 }
74- return new ExecutionResultImpl (result , executionContext .getErrors ());
75- }
76-
77- private Map <String , Object > executeFieldsSerially (ExecutionContext executionContext , GraphQLObjectType parentType , Object source , Map <String , List <Field >> fields ) {
78- Map <String , Object > results = new LinkedHashMap <>();
79- for (String fieldName : fields .keySet ()) {
80- List <Field > fieldList = fields .get (fieldName );
81- Object resolvedResult = resolveField (executionContext , parentType , source , fieldList );
82- results .put (fieldName , resolvedResult );
83- }
84- return results ;
85- }
86-
87-
88- private Map <String , Object > executeFieldsParallel (final ExecutionContext executionContext , final GraphQLObjectType parentType , final Object source , Map <String , List <Field >> fields ) {
89- if (executorService == null ) return executeFieldsSerially (executionContext , parentType , source , fields );
90-
91- Map <String , Future <Object >> futures = new LinkedHashMap <>();
92- for (String fieldName : fields .keySet ()) {
93- final List <Field > fieldList = fields .get (fieldName );
94- Callable <Object > resolveField = new Callable <Object >() {
95- @ Override
96- public Object call () throws Exception {
97- return resolveField (executionContext , parentType , source , fieldList );
98-
99- }
100- };
101- futures .put (fieldName , executorService .submit (resolveField ));
102- }
103- try {
104- Map <String , Object > results = new LinkedHashMap <>();
105- for (String fieldName : futures .keySet ()) {
106- results .put (fieldName , futures .get (fieldName ).get ());
107- }
108- return results ;
109- } catch (InterruptedException | ExecutionException e ) {
110- throw new GraphQLException (e );
111- }
112-
11371 }
114-
115- private Object resolveField (ExecutionContext executionContext , GraphQLObjectType parentType , Object source , List <Field > fields ) {
116- GraphQLFieldDefinition fieldDef = getFieldDef (executionContext .getGraphQLSchema (), parentType , fields .get (0 ));
117- if (fieldDef == null ) return null ;
118-
119- Map <String , Object > argumentValues = valuesResolver .getArgumentValues (fieldDef .getArguments (), fields .get (0 ).getArguments (), executionContext .getVariables ());
120- DataFetchingEnvironment environment = new DataFetchingEnvironment (
121- source ,
122- argumentValues ,
123- executionContext .getRoot (),
124- fields ,
125- fieldDef .getType (),
126- parentType ,
127- executionContext .getGraphQLSchema ()
128- );
129-
130- Object resolvedValue = null ;
131- try {
132- resolvedValue = fieldDef .getDataFetcher ().get (environment );
133- } catch (Exception e ) {
134- log .info ("Exception while fetching data" , e );
135- executionContext .addError (new ExceptionWhileDataFetching (e ));
136- }
137-
138-
139- return completeValue (executionContext , fieldDef .getType (), fields , resolvedValue );
140- }
141-
142- private Object completeValue (ExecutionContext executionContext , GraphQLType fieldType , List <Field > fields , Object result ) {
143- if (fieldType instanceof GraphQLNonNull ) {
144- GraphQLNonNull graphQLNonNull = (GraphQLNonNull ) fieldType ;
145- Object completed = completeValue (executionContext , graphQLNonNull .getWrappedType (), fields , result );
146- if (completed == null ) throw new GraphQLException ("Cannot return null for non-nullable type: " + fields );
147- return completed ;
148-
149- } else if (result == null ) {
150- return null ;
151- } else if (fieldType instanceof GraphQLList ) {
152- return completeValueForList (executionContext , (GraphQLList ) fieldType , fields , (List <Object >) result );
153- } else if (fieldType instanceof GraphQLScalarType ) {
154- return completeValueForScalar ((GraphQLScalarType ) fieldType , result );
155- } else if (fieldType instanceof GraphQLEnumType ) {
156- return completeValueForEnum ((GraphQLEnumType ) fieldType , result );
157- }
158-
159-
160- GraphQLObjectType resolvedType ;
161- if (fieldType instanceof GraphQLInterfaceType ) {
162- resolvedType = resolveType ((GraphQLInterfaceType ) fieldType , result );
163- } else if (fieldType instanceof GraphQLUnionType ) {
164- resolvedType = resolveType ((GraphQLUnionType ) fieldType , result );
165- } else {
166- resolvedType = (GraphQLObjectType ) fieldType ;
167- }
168-
169- Map <String , List <Field >> subFields = new LinkedHashMap <>();
170- List <String > visitedFragments = new ArrayList <>();
171- for (Field field : fields ) {
172- if (field .getSelectionSet () == null ) continue ;
173- fieldCollector .collectFields (executionContext , resolvedType , field .getSelectionSet (), visitedFragments , subFields );
174- }
175- return executeFieldsParallel (executionContext , resolvedType , result , subFields );
176- }
177-
178- private GraphQLObjectType resolveType (GraphQLInterfaceType graphQLInterfaceType , Object value ) {
179- GraphQLObjectType result = graphQLInterfaceType .getTypeResolver ().getType (value );
180- if (result == null ) throw new GraphQLException ("could not determine type" );
181- return result ;
182- }
183-
184- private GraphQLObjectType resolveType (GraphQLUnionType graphQLUnionType , Object value ) {
185- GraphQLObjectType result = graphQLUnionType .getTypeResolver ().getType (value );
186- if (result == null ) throw new GraphQLException ("could not determine type" );
187- return result ;
188- }
189-
190-
191- private Object completeValueForEnum (GraphQLEnumType enumType , Object result ) {
192- return enumType .getCoercing ().coerce (result );
193- }
194-
195- private Object completeValueForScalar (GraphQLScalarType scalarType , Object result ) {
196- return scalarType .getCoercing ().coerce (result );
197- }
198-
199- private Object completeValueForList (ExecutionContext executionContext , GraphQLList fieldType , List <Field > fields , List <Object > result ) {
200- List <Object > completedResults = new ArrayList <>();
201- for (Object item : result ) {
202- completedResults .add (completeValue (executionContext , fieldType .getWrappedType (), fields , item ));
203- }
204- return completedResults ;
205- }
206-
207- private GraphQLFieldDefinition getFieldDef (GraphQLSchema schema , GraphQLObjectType parentType , Field field ) {
208- if (schema .getQueryType () == parentType ) {
209- if (field .getName ().equals (SchemaMetaFieldDef .getName ())) {
210- return SchemaMetaFieldDef ;
211- }
212- if (field .getName ().equals (TypeMetaFieldDef .getName ())) {
213- return TypeMetaFieldDef ;
214- }
215- }
216- if (field .getName ().equals (TypeNameMetaFieldDef .getName ())) {
217- return TypeNameMetaFieldDef ;
218- }
219-
220- GraphQLFieldDefinition fieldDefinition = parentType .getFieldDefinition (field .getName ());
221- if (fieldDefinition == null ) throw new GraphQLException ("unknown field " + field .getName ());
222- return fieldDefinition ;
223- }
224-
225-
22672}
0 commit comments