graphql.validation.TraversalContext Maven / Gradle / Ivy
package graphql.validation;
import graphql.ShouldNotHappenException;
import graphql.execution.TypeFromAST;
import graphql.language.*;
import graphql.schema.*;
import java.util.ArrayList;
import java.util.List;
import static graphql.introspection.Introspection.*;
public class TraversalContext implements QueryLanguageVisitor {
GraphQLSchema schema;
List outputTypeStack = new ArrayList();
List parentTypeStack = new ArrayList();
List inputTypeStack = new ArrayList();
List fieldDefStack = new ArrayList();
GraphQLDirective directive;
GraphQLArgument argument;
SchemaUtil schemaUtil = new SchemaUtil();
public TraversalContext(GraphQLSchema graphQLSchema) {
this.schema = graphQLSchema;
}
@Override
public void enter(Node node, List path) {
if (node instanceof OperationDefinition) {
enterImpl((OperationDefinition) node);
} else if (node instanceof SelectionSet) {
enterImpl((SelectionSet) node);
} else if (node instanceof Field) {
enterImpl((Field) node);
} else if (node instanceof Directive) {
enterImpl((Directive) node);
} else if (node instanceof InlineFragment) {
enterImpl((InlineFragment) node);
} else if (node instanceof FragmentDefinition) {
enterImpl((FragmentDefinition) node);
} else if (node instanceof VariableDefinition) {
enterImpl((VariableDefinition) node);
} else if (node instanceof Argument) {
enterImpl((Argument) node);
} else if (node instanceof ArrayValue) {
enterImpl((ArrayValue) node);
} else if (node instanceof ObjectField) {
enterImpl((ObjectField) node);
}
}
private void enterImpl(SelectionSet selectionSet) {
GraphQLUnmodifiedType rawType = new SchemaUtil().getUnmodifiedType(getOutputType());
GraphQLCompositeType parentType = null;
if (rawType instanceof GraphQLCompositeType) {
parentType = (GraphQLCompositeType) rawType;
}
addParentType(parentType);
}
private void enterImpl(Field field) {
GraphQLCompositeType parentType = getParentType();
GraphQLFieldDefinition fieldDefinition = null;
if (parentType != null) {
fieldDefinition = getFieldDef(schema, parentType, field);
}
addFieldDef(fieldDefinition);
addType(fieldDefinition != null ? fieldDefinition.getType() : null);
}
private void enterImpl(Directive directive) {
this.directive = schema.getDirective(directive.getName());
}
private void enterImpl(OperationDefinition operationDefinition) {
if (operationDefinition.getOperation() == OperationDefinition.Operation.MUTATION) {
addType(schema.getMutationType());
} else if (operationDefinition.getOperation() == OperationDefinition.Operation.QUERY) {
addType(schema.getQueryType());
} else {
throw new ShouldNotHappenException();
}
}
private void enterImpl(InlineFragment inlineFragment) {
GraphQLType type = schema.getType(inlineFragment.getTypeCondition().getName());
addType((GraphQLOutputType) type);
}
private void enterImpl(FragmentDefinition fragmentDefinition) {
GraphQLType type = schema.getType(fragmentDefinition.getTypeCondition().getName());
addType((GraphQLOutputType) type);
}
private void enterImpl(VariableDefinition variableDefinition) {
GraphQLType type = TypeFromAST.getTypeFromAST(schema, variableDefinition.getType());
addInputType((GraphQLInputType) type);
}
private void enterImpl(Argument argument) {
GraphQLArgument argumentType = null;
if (getDirective() != null) {
argumentType = find(getDirective().getArguments(), argument.getName());
} else if (getFieldDef() != null) {
argumentType = find(getFieldDef().getArguments(), argument.getName());
}
addInputType(argumentType != null ? argumentType.getType() : null);
this.argument = argumentType;
}
private void enterImpl(ArrayValue arrayValue) {
GraphQLNullableType nullableType = getNullableType(getInputType());
GraphQLInputType inputType = null;
if (nullableType instanceof GraphQLList) {
inputType = (GraphQLInputType) ((GraphQLList) nullableType).getWrappedType();
}
addInputType(inputType);
}
private void enterImpl(ObjectField objectField) {
GraphQLUnmodifiedType objectType = schemaUtil.getUnmodifiedType(getInputType());
GraphQLInputType inputType = null;
if (objectType instanceof GraphQLInputObjectType) {
GraphQLInputObjectField inputField = ((GraphQLInputObjectType) objectType).getField(objectField.getName());
if (inputField != null)
inputType = inputField.getType();
}
addInputType(inputType);
}
private GraphQLArgument find(List arguments, String name) {
for (GraphQLArgument argument : arguments) {
if (argument.getName().equals(name)) return argument;
}
return null;
}
@Override
public void leave(Node node, List ancestors) {
if (node instanceof OperationDefinition) {
outputTypeStack.remove(outputTypeStack.size() - 1);
} else if (node instanceof SelectionSet) {
parentTypeStack.remove(parentTypeStack.size() - 1);
} else if (node instanceof Field) {
fieldDefStack.remove(fieldDefStack.size() - 1);
outputTypeStack.remove(outputTypeStack.size() - 1);
} else if (node instanceof Directive) {
directive = null;
} else if (node instanceof InlineFragment) {
outputTypeStack.remove(outputTypeStack.size() - 1);
} else if (node instanceof FragmentDefinition) {
outputTypeStack.remove(outputTypeStack.size() - 1);
} else if (node instanceof VariableDefinition) {
inputTypeStack.remove(inputTypeStack.size() - 1);
} else if (node instanceof Argument) {
argument = null;
inputTypeStack.remove(inputTypeStack.size() - 1);
} else if (node instanceof ArrayValue) {
inputTypeStack.remove(inputTypeStack.size() - 1);
} else if (node instanceof ObjectField) {
inputTypeStack.remove(inputTypeStack.size() - 1);
}
}
private GraphQLNullableType getNullableType(GraphQLType type) {
return (GraphQLNullableType) (type instanceof GraphQLNonNull ? ((GraphQLNonNull) type).getWrappedType() : type);
}
public GraphQLOutputType getOutputType() {
return lastElement(outputTypeStack);
}
private void addType(GraphQLOutputType type) {
outputTypeStack.add(type);
}
private T lastElement(List list) {
if (list.size() == 0) return null;
return list.get(list.size() - 1);
}
public GraphQLCompositeType getParentType() {
return lastElement(parentTypeStack);
}
private void addParentType(GraphQLCompositeType compositeType) {
parentTypeStack.add(compositeType);
}
public GraphQLInputType getInputType() {
return lastElement(inputTypeStack);
}
private void addInputType(GraphQLInputType graphQLInputType) {
inputTypeStack.add(graphQLInputType);
}
public GraphQLFieldDefinition getFieldDef() {
return lastElement(fieldDefStack);
}
private void addFieldDef(GraphQLFieldDefinition fieldDefinition) {
fieldDefStack.add(fieldDefinition);
}
public GraphQLDirective getDirective() {
return directive;
}
public GraphQLArgument getArgument() {
return argument;
}
private GraphQLFieldDefinition getFieldDef(GraphQLSchema schema, GraphQLType parentType, Field field) {
if (schema.getQueryType().equals(parentType)) {
if (field.getName().equals(SchemaMetaFieldDef.getName())) {
return SchemaMetaFieldDef;
}
if (field.getName().equals(TypeMetaFieldDef.getName())) {
return TypeMetaFieldDef;
}
}
if (field.getName().equals(TypeNameMetaFieldDef.getName())
&& (parentType instanceof GraphQLObjectType ||
parentType instanceof GraphQLInterfaceType ||
parentType instanceof GraphQLUnionType)) {
return TypeNameMetaFieldDef;
}
if (parentType instanceof GraphQLFieldsContainer) {
return ((GraphQLFieldsContainer) parentType).getFieldDefinition(field.getName());
}
return null;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy