Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
package graphql.execution;
import graphql.ExecutionResult;
import graphql.ExecutionResultImpl;
import graphql.GraphQLException;
import graphql.PublicSpi;
import graphql.SerializationError;
import graphql.TypeResolutionEnvironment;
import graphql.execution.instrumentation.Instrumentation;
import graphql.execution.instrumentation.InstrumentationContext;
import graphql.execution.instrumentation.parameters.InstrumentationFieldFetchParameters;
import graphql.execution.instrumentation.parameters.InstrumentationFieldParameters;
import graphql.language.Field;
import graphql.schema.CoercingSerializeException;
import graphql.schema.DataFetcher;
import graphql.schema.DataFetchingEnvironment;
import graphql.schema.DataFetchingFieldSelectionSet;
import graphql.schema.DataFetchingFieldSelectionSetImpl;
import graphql.schema.GraphQLEnumType;
import graphql.schema.GraphQLFieldDefinition;
import graphql.schema.GraphQLInterfaceType;
import graphql.schema.GraphQLList;
import graphql.schema.GraphQLObjectType;
import graphql.schema.GraphQLOutputType;
import graphql.schema.GraphQLScalarType;
import graphql.schema.GraphQLSchema;
import graphql.schema.GraphQLType;
import graphql.schema.GraphQLUnionType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionException;
import java.util.concurrent.CompletionStage;
import static graphql.execution.ExecutionTypeInfo.newTypeInfo;
import static graphql.execution.FieldCollectorParameters.newParameters;
import static graphql.introspection.Introspection.SchemaMetaFieldDef;
import static graphql.introspection.Introspection.TypeMetaFieldDef;
import static graphql.introspection.Introspection.TypeNameMetaFieldDef;
import static graphql.schema.DataFetchingEnvironmentBuilder.newDataFetchingEnvironment;
import static java.util.concurrent.CompletableFuture.completedFuture;
/**
* An execution strategy is give a list of fields from the graphql query to execute and find values for using a recursive strategy.
*
* query {
* friends {
* id
* name
* friends {
* id
* name
* }
* }
* enemies {
* id
* name
* allies {
* id
* name
* }
* }
* }
*
*
*
* Given the graphql query above, an execution strategy will be called for the top level fields 'friends' and 'enemies' and it will be asked to find an object
* to describe them. Because they are both complex object types, it needs to descend down that query and start fetching and completing
* fields such as 'id','name' and other complex fields such as 'friends' and 'allies', by recursively calling to itself to execute these lower
* field layers
*
* The execution of a field has two phases, first a raw object must be fetched for a field via a {@link DataFetcher} which
* is defined on the {@link GraphQLFieldDefinition}. This object must then be 'completed' into a suitable value, either as a scalar/enum type via
* coercion or if its a complex object type by recursively calling the execution strategy for the lower level fields.
*
* The first phase (data fetching) is handled by the method {@link #fetchField(ExecutionContext, ExecutionStrategyParameters)}
*
* The second phase (value completion) is handled by the methods {@link #completeField(ExecutionContext, ExecutionStrategyParameters, Object)}
* and the other "completeXXX" methods.
*
* Normally the executor can execute the entries in a grouped field set in whatever order it chooses (often in parallel). Because
* the resolution of fields other than top-level mutation fields must always be side effect-free and idempotent, the
* execution order must not affect the result, and hence the server has the freedom to execute the
* field entries in whatever order it deems optimal.
*
*
* So in the case above you could execute the fields depth first ('friends' and its sub fields then do 'enemies' and its sub fields or it
* could do breadth first ('fiends' and 'enemies' data fetch first and then all the sub fields) or in parallel via asynchronous
* facilities like {@link CompletableFuture}s.
*
* {@link #execute(ExecutionContext, ExecutionStrategyParameters)} is the entry point of the execution strategy.
*/
@PublicSpi
public abstract class ExecutionStrategy {
private static final Logger log = LoggerFactory.getLogger(ExecutionStrategy.class);
protected final ValuesResolver valuesResolver = new ValuesResolver();
protected final FieldCollector fieldCollector = new FieldCollector();
protected final DataFetcherExceptionHandler dataFetcherExceptionHandler;
/**
* The default execution strategy constructor uses the {@link SimpleDataFetcherExceptionHandler}
* for data fetching errors.
*/
protected ExecutionStrategy() {
dataFetcherExceptionHandler = new SimpleDataFetcherExceptionHandler();
}
/**
* The consumers of the execution strategy can pass in a {@link DataFetcherExceptionHandler} to better
* decide what do when a data fetching error happens
*
* @param dataFetcherExceptionHandler the callback invoked if an exception happens during data fetching
*/
protected ExecutionStrategy(DataFetcherExceptionHandler dataFetcherExceptionHandler) {
this.dataFetcherExceptionHandler = dataFetcherExceptionHandler;
}
/**
* This is the entry point to an execution strategy. It will be passed the fields to execute and get values for.
*
* @param executionContext contains the top level execution parameters
* @param parameters contains the parameters holding the fields to be executed and source object
*
* @return an {@link ExecutionResult}
*
* @throws NonNullableFieldWasNullException if a non null field resolves to a null value
*/
public abstract CompletableFuture execute(ExecutionContext executionContext, ExecutionStrategyParameters parameters) throws NonNullableFieldWasNullException;
/**
* Called to fetch a value for a field and resolve it further in terms of the graphql query. This will call
* #fetchField followed by #completeField and the completed {@link ExecutionResult} is returned.
*
* An execution strategy can iterate the fields to be executed and call this method for each one
*
* Graphql fragments mean that for any give logical field can have one or more {@link Field} values associated with it
* in the query, hence the fieldList. However the first entry is representative of the field for most purposes.
*
* @param executionContext contains the top level execution parameters
* @param parameters contains the parameters holding the fields to be executed and source object
*
* @return an {@link ExecutionResult}
*
* @throws NonNullableFieldWasNullException if a non null field resolves to a null value
*/
protected CompletableFuture resolveField(ExecutionContext executionContext, ExecutionStrategyParameters parameters) {
GraphQLFieldDefinition fieldDef = getFieldDef(executionContext, parameters, parameters.field().get(0));
Instrumentation instrumentation = executionContext.getInstrumentation();
InstrumentationContext fieldCtx = instrumentation.beginField(
new InstrumentationFieldParameters(executionContext, fieldDef, fieldTypeInfo(parameters, fieldDef))
);
CompletableFuture result = fetchField(executionContext, parameters)
.thenCompose((fetchedValue) ->
completeField(executionContext, parameters, fetchedValue));
result.whenComplete(fieldCtx::onEnd);
return result;
}
/**
* Called to fetch a value for a field from the {@link DataFetcher} associated with the field
* {@link GraphQLFieldDefinition}.
*
* Graphql fragments mean that for any give logical field can have one or more {@link Field} values associated with it
* in the query, hence the fieldList. However the first entry is representative of the field for most purposes.
*
* @param executionContext contains the top level execution parameters
* @param parameters contains the parameters holding the fields to be executed and source object
*
* @return a fetched object
*
* @throws NonNullableFieldWasNullException if a non null field resolves to a null value
*/
protected CompletableFuture