View Javadoc

1   /*
2    * Copyright 2015 Data Archiving and Networked Services (an institute of
3    * Koninklijke Nederlandse Akademie Van Wetenschappen), King's College London,
4    * Georg-August-Universitaet Goettingen Stiftung Oeffentlichen Rechts
5    *
6    * Licensed under the EUPL, Version 1.1 or – as soon they will be approved by
7    * the European Commission - subsequent versions of the EUPL (the "Licence");
8    * You may not use this work except in compliance with the Licence.
9    * You may obtain a copy of the Licence at:
10   *
11   * https://joinup.ec.europa.eu/software/page/eupl
12   *
13   * Unless required by applicable law or agreed to in writing, software
14   * distributed under the Licence is distributed on an "AS IS" basis,
15   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16   * See the Licence for the specific language governing
17   * permissions and limitations under the Licence.
18   */
19  
20  package eu.ehri.project.graphql;
21  
22  import com.fasterxml.jackson.core.JsonGenerator;
23  import graphql.ExecutionInput;
24  import graphql.execution.Execution;
25  import graphql.execution.ExecutionContext;
26  import graphql.execution.ExecutionContextBuilder;
27  import graphql.execution.ExecutionId;
28  import graphql.execution.ExecutionPath;
29  import graphql.execution.ExecutionStrategy;
30  import graphql.execution.ExecutionStrategyParameters;
31  import graphql.execution.ExecutionTypeInfo;
32  import graphql.execution.FieldCollector;
33  import graphql.execution.FieldCollectorParameters;
34  import graphql.execution.NonNullableFieldValidator;
35  import graphql.execution.instrumentation.Instrumentation;
36  import graphql.language.Document;
37  import graphql.language.Field;
38  import graphql.language.NodeUtil;
39  import graphql.language.OperationDefinition;
40  import graphql.schema.GraphQLObjectType;
41  import graphql.schema.GraphQLSchema;
42  
43  import java.io.IOException;
44  import java.util.List;
45  import java.util.Map;
46  
47  import static graphql.Assert.assertShouldNeverHappen;
48  import static graphql.execution.ExecutionTypeInfo.newTypeInfo;
49  import static graphql.execution.FieldCollectorParameters.newParameters;
50  import static graphql.language.OperationDefinition.Operation.MUTATION;
51  import static graphql.language.OperationDefinition.Operation.QUERY;
52  import static graphql.language.OperationDefinition.Operation.SUBSCRIPTION;
53  
54  
55  public class StreamingExecution extends Execution {
56  
57      private final FieldCollector fieldCollector = new FieldCollector();
58      private final ExecutionStrategy queryStrategy;
59      private final ExecutionStrategy mutationStrategy;
60      private final ExecutionStrategy subscriptionStrategy;
61      private final Instrumentation instrumentation;
62  
63      public StreamingExecution(ExecutionStrategy queryStrategy, ExecutionStrategy mutationStrategy, ExecutionStrategy subscriptionStrategy, Instrumentation instrumentation) {
64          super(queryStrategy, mutationStrategy, subscriptionStrategy, instrumentation);
65          this.queryStrategy = queryStrategy;
66          this.mutationStrategy = mutationStrategy;
67          this.subscriptionStrategy = subscriptionStrategy;
68          this.instrumentation = instrumentation;
69      }
70  
71      private GraphQLObjectType getOperationRootType(GraphQLSchema graphQLSchema, OperationDefinition.Operation operation) {
72          if (operation == MUTATION) {
73              return graphQLSchema.getMutationType();
74          } else if (operation == QUERY) {
75              return graphQLSchema.getQueryType();
76          } else if (operation == SUBSCRIPTION) {
77              return graphQLSchema.getSubscriptionType();
78          } else {
79              return assertShouldNeverHappen("Unhandled case.  An extra operation enum has been added without code support");
80          }
81      }
82      private void executeOperation(
83              JsonGenerator generator,
84              ExecutionContext executionContext,
85              Object root,
86              OperationDefinition operationDefinition) throws IOException {
87          GraphQLObjectType operationRootType = getOperationRootType(executionContext.getGraphQLSchema(),
88                  operationDefinition.getOperation());
89  
90          FieldCollectorParameters collectorParameters = newParameters()
91                  .schema(executionContext.getGraphQLSchema())
92                  .objectType(operationRootType)
93                  .fragments(executionContext.getFragmentsByName())
94                  .variables(executionContext.getVariables())
95                  .build();
96  
97          Map<String, List<Field>> fields = fieldCollector.collectFields(collectorParameters, operationDefinition.getSelectionSet());
98  
99          ExecutionTypeInfo typeInfo = newTypeInfo().type(operationRootType).build();
100         NonNullableFieldValidator nonNullableFieldValidator = new NonNullableFieldValidator(executionContext, typeInfo);
101 
102         ExecutionStrategyParameters parameters = ExecutionStrategyParameters.newParameters()
103                 .typeInfo(typeInfo)
104                 .source(root)
105                 .fields(fields)
106                 .nonNullFieldValidator(nonNullableFieldValidator)
107                 .path(ExecutionPath.rootPath())
108                 .build();
109 
110         new StreamingExecutionStrategy().execute(generator, executionContext, parameters);
111     }
112 
113     public void execute(JsonGenerator generator, GraphQLSchema graphQLSchema, Document document, ExecutionId executionId, ExecutionInput executionInput) throws IOException {
114         NodeUtil.GetOperationResult operationResult = NodeUtil.getOperation(document, executionInput.getOperationName());
115         ExecutionContext executionContext = new ExecutionContextBuilder()
116                 .instrumentation(instrumentation)
117                 .executionId(executionId)
118                 .graphQLSchema(graphQLSchema)
119                 .queryStrategy(queryStrategy)
120                 .mutationStrategy(mutationStrategy)
121                 .subscriptionStrategy(subscriptionStrategy)
122                 .operationDefinition(operationResult.operationDefinition)
123                 .context(executionInput.getContext())
124                 .fragmentsByName(operationResult.fragmentsByName)
125                 .root(executionInput.getRoot())
126                 .document(document)
127                 .variables(executionInput.getVariables())
128                 .build();
129 
130         executeOperation(generator, executionContext, executionInput.getRoot(), executionContext.getOperationDefinition());
131     }
132 }