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 com.google.common.collect.Lists;
24  import eu.ehri.extension.errors.ExecutionError;
25  import graphql.ExecutionInput;
26  import graphql.GraphQLError;
27  import graphql.InvalidSyntaxError;
28  import graphql.execution.AsyncExecutionStrategy;
29  import graphql.execution.ExecutionId;
30  import graphql.execution.ValuesResolver;
31  import graphql.execution.instrumentation.NoOpInstrumentation;
32  import graphql.language.Document;
33  import graphql.language.NodeUtil;
34  import graphql.language.OperationDefinition;
35  import graphql.language.SourceLocation;
36  import graphql.language.VariableDefinition;
37  import graphql.parser.Parser;
38  import graphql.schema.GraphQLSchema;
39  import graphql.validation.ValidationError;
40  import graphql.validation.Validator;
41  import org.antlr.v4.runtime.RecognitionException;
42  import org.slf4j.Logger;
43  import org.slf4j.LoggerFactory;
44  
45  import java.io.IOException;
46  import java.util.Collections;
47  import java.util.List;
48  import java.util.Map;
49  
50  import static graphql.Assert.assertNotNull;
51  
52  
53  public class StreamingGraphQL {
54  
55      private static final Logger log = LoggerFactory.getLogger(StreamingGraphQL.class);
56  
57      private final GraphQLSchema graphQLSchema;
58  
59      public StreamingGraphQL(GraphQLSchema schema) {
60          this.graphQLSchema = schema;
61      }
62  
63  
64      public void execute(JsonGenerator generator, String requestString, Document document, String operationName, Object context, Map<String, Object>
65              arguments) throws IOException {
66          assertNotNull(arguments, "arguments can't be null");
67          log.trace("Executing request. operation name: {}. Request: {} ", operationName, document);
68          StreamingExecution execution = new StreamingExecution(new StreamingExecutionStrategy(), new AsyncExecutionStrategy(),
69                  new AsyncExecutionStrategy(), NoOpInstrumentation.INSTANCE);
70          ExecutionInput input = ExecutionInput.newExecutionInput()
71                  .context(context)
72                  .variables(arguments)
73                  .query(requestString)
74                  .operationName(operationName)
75                  .build();
76          execution.execute(generator, graphQLSchema, document, ExecutionId.from("test"), input);
77      }
78  
79      public void execute(JsonGenerator generator, String requestString, String operationName, Object context, Map<String, Object> arguments) throws IOException {
80          assertNotNull(arguments, "arguments can't be null");
81          log.trace("Executing request. operation name: {}. Request: {} ", operationName, requestString);
82          Document document = parseAndValidate(requestString, operationName, arguments);
83          execute(generator, requestString, document, operationName, context, arguments);
84      }
85  
86      public Document parseAndValidate(String query, String operationName, Map<String, Object> variables) {
87          Parser parser = new Parser();
88          Document document;
89          try {
90              document = parser.parseDocument(query);
91          } catch (Exception e) {
92              RecognitionException recognitionException = (RecognitionException) e.getCause();
93              SourceLocation sourceLocation = new SourceLocation(recognitionException.getOffendingToken().getLine(),
94                      recognitionException.getOffendingToken().getCharPositionInLine());
95              InvalidSyntaxError invalidSyntaxError = new InvalidSyntaxError(sourceLocation, "Invalid syntax");
96              throw new ExecutionError(Collections.singletonList(invalidSyntaxError));
97          }
98  
99          Validator validator = new Validator();
100         List<ValidationError> validationErrors = validator.validateDocument(graphQLSchema, document);
101         if (validationErrors.size() > 0) {
102             throw new ExecutionError(validationErrors);
103         }
104 
105         NodeUtil.GetOperationResult operationResult = NodeUtil.getOperation(document, operationName);
106         OperationDefinition operationDefinition = operationResult.operationDefinition;
107 
108         ValuesResolver valuesResolver = new ValuesResolver();
109         List<VariableDefinition> variableDefinitions = operationDefinition.getVariableDefinitions();
110 
111         try {
112             valuesResolver.coerceArgumentValues(graphQLSchema, variableDefinitions, variables);
113         } catch (RuntimeException rte) {
114             if (rte instanceof GraphQLError) {
115                 throw new ExecutionError(Lists.newArrayList((GraphQLError)rte));
116             }
117             throw rte;
118         }
119 
120         return document;
121     }
122 }