graphql.validation.RulesVisitor Maven / Gradle / Ivy
The newest version!
package graphql.validation;
import graphql.language.*;
import java.util.*;
public class RulesVisitor implements QueryLanguageVisitor {
private final List rules = new ArrayList<>();
private ValidationContext validationContext;
private boolean subVisitor;
private List rulesVisitingFragmentSpreads = new ArrayList<>();
private Map> rulesToSkipByUntilNode = new IdentityHashMap<>();
private Set rulesToSkip = new LinkedHashSet<>();
public RulesVisitor(ValidationContext validationContext, List rules) {
this(validationContext, rules, false);
}
public RulesVisitor(ValidationContext validationContext, List rules, boolean subVisitor) {
this.validationContext = validationContext;
this.subVisitor = subVisitor;
this.rules.addAll(rules);
this.subVisitor = subVisitor;
findRulesVisitingFragmentSpreads();
}
private void findRulesVisitingFragmentSpreads() {
for (AbstractRule rule : rules) {
if (rule.isVisitFragmentSpreads()) {
rulesVisitingFragmentSpreads.add(rule);
}
}
}
@Override
public void enter(Node node, List ancestors) {
// System.out.println("enter: " + node);
validationContext.getTraversalContext().enter(node, ancestors);
Set tmpRulesSet = new LinkedHashSet<>(this.rules);
tmpRulesSet.removeAll(rulesToSkip);
List rulesToConsider = new ArrayList<>(tmpRulesSet);
if (node instanceof Argument) {
checkArgument((Argument) node, rulesToConsider);
} else if (node instanceof TypeName) {
checkTypeName((TypeName) node, rulesToConsider);
} else if (node instanceof VariableDefinition) {
checkVariableDefinition((VariableDefinition) node, rulesToConsider);
} else if (node instanceof Field) {
checkField((Field) node, rulesToConsider);
} else if (node instanceof InlineFragment) {
checkInlineFragment((InlineFragment) node, rulesToConsider);
} else if (node instanceof Directive) {
checkDirective((Directive) node, ancestors, rulesToConsider);
} else if (node instanceof FragmentSpread) {
checkFragmentSpread((FragmentSpread) node, rulesToConsider, ancestors);
} else if (node instanceof FragmentDefinition) {
checkFragmentDefinition((FragmentDefinition) node, rulesToConsider);
} else if (node instanceof OperationDefinition) {
checkOperationDefinition((OperationDefinition) node, rulesToConsider);
} else if (node instanceof VariableReference) {
checkVariable((VariableReference) node, rulesToConsider);
} else if (node instanceof SelectionSet) {
checkSelectionSet((SelectionSet) node, rulesToConsider);
}
}
private void checkArgument(Argument node, List rules) {
for (AbstractRule rule : rules) {
rule.checkArgument(node);
}
}
private void checkTypeName(TypeName node, List rules) {
for (AbstractRule rule : rules) {
rule.checkTypeName(node);
}
}
private void checkVariableDefinition(VariableDefinition variableDefinition, List rules) {
for (AbstractRule rule : rules) {
rule.checkVariableDefinition(variableDefinition);
}
}
private void checkField(Field field, List rules) {
for (AbstractRule rule : rules) {
rule.checkField(field);
}
}
private void checkInlineFragment(InlineFragment inlineFragment, List rules) {
for (AbstractRule rule : rules) {
rule.checkInlineFragment(inlineFragment);
}
}
private void checkDirective(Directive directive, List ancestors, List rules) {
for (AbstractRule rule : rules) {
rule.checkDirective(directive, ancestors);
}
}
private void checkFragmentSpread(FragmentSpread fragmentSpread, List rules, List ancestors) {
for (AbstractRule rule : rules) {
rule.checkFragmentSpread(fragmentSpread);
}
List rulesVisitingFragmentSpreads = getRulesVisitingFragmentSpreads(rules);
if (rulesVisitingFragmentSpreads.size() > 0) {
FragmentDefinition fragment = validationContext.getFragment(fragmentSpread.getName());
if (fragment != null && !ancestors.contains(fragment)) {
new LanguageTraversal(ancestors).traverse(fragment, new RulesVisitor(validationContext, rulesVisitingFragmentSpreads, true));
}
}
}
private List getRulesVisitingFragmentSpreads(List rules) {
List result = new ArrayList<>();
for (AbstractRule rule : rules) {
if (rule.isVisitFragmentSpreads()) result.add(rule);
}
return result;
}
private void checkFragmentDefinition(FragmentDefinition fragmentDefinition, List rules) {
if (!subVisitor) {
rulesToSkipByUntilNode.put(fragmentDefinition, new ArrayList<>(rulesVisitingFragmentSpreads));
rulesToSkip.addAll(rulesVisitingFragmentSpreads);
}
for (AbstractRule rule : rules) {
if (!subVisitor && (rule.isVisitFragmentSpreads())) continue;
rule.checkFragmentDefinition(fragmentDefinition);
}
}
private void checkOperationDefinition(OperationDefinition operationDefinition, List rules) {
for (AbstractRule rule : rules) {
rule.checkOperationDefinition(operationDefinition);
}
}
private void checkSelectionSet(SelectionSet selectionSet, List rules) {
for (AbstractRule rule : rules) {
rule.checkSelectionSet(selectionSet);
}
}
private void checkVariable(VariableReference variableReference, List rules) {
for (AbstractRule rule : rules) {
rule.checkVariable(variableReference);
}
}
@Override
public void leave(Node node, List ancestors) {
validationContext.getTraversalContext().leave(node, ancestors);
if (node instanceof Document) {
documentFinished((Document) node);
} else if (node instanceof OperationDefinition) {
leaveOperationDefinition((OperationDefinition) node);
} else if (node instanceof SelectionSet) {
leaveSelectionSet((SelectionSet) node);
}
if (rulesToSkipByUntilNode.containsKey(node)) {
rulesToSkip.removeAll(rulesToSkipByUntilNode.get(node));
rulesToSkipByUntilNode.remove(node);
}
}
private void leaveSelectionSet(SelectionSet selectionSet) {
for (AbstractRule rule : rules) {
rule.leaveSelectionSet(selectionSet);
}
}
private void leaveOperationDefinition(OperationDefinition operationDefinition) {
for (AbstractRule rule : rules) {
rule.leaveOperationDefinition(operationDefinition);
}
}
private void documentFinished(Document document) {
for (AbstractRule rule : rules) {
rule.documentFinished(document);
}
}
}