use of graphql.schema.GraphQLTypeVisitor in project graphql-java by graphql-java.
the class SchemaUtil method visitPartiallySchema.
/**
* Called to visit a partially build schema (during {@link GraphQLSchema} build phases) with a set of visitors
*
* Each visitor is expected to hold its own side effects that might be last used to construct a full schema
*
* @param partiallyBuiltSchema the partially built schema
* @param visitors the visitors to call
*/
public static void visitPartiallySchema(final GraphQLSchema partiallyBuiltSchema, GraphQLTypeVisitor... visitors) {
List<GraphQLSchemaElement> roots = new ArrayList<>();
roots.add(partiallyBuiltSchema.getQueryType());
if (partiallyBuiltSchema.isSupportingMutations()) {
roots.add(partiallyBuiltSchema.getMutationType());
}
if (partiallyBuiltSchema.isSupportingSubscriptions()) {
roots.add(partiallyBuiltSchema.getSubscriptionType());
}
if (partiallyBuiltSchema.getAdditionalTypes() != null) {
roots.addAll(partiallyBuiltSchema.getAdditionalTypes());
}
if (partiallyBuiltSchema.getDirectives() != null) {
roots.addAll(partiallyBuiltSchema.getDirectives());
}
roots.add(partiallyBuiltSchema.getIntrospectionSchemaType());
GraphQLTypeVisitor visitor = new MultiReadOnlyGraphQLTypeVisitor(Arrays.asList(visitors));
SchemaTraverser traverser;
traverser = new SchemaTraverser(schemaElement -> schemaElement.getChildrenWithTypeReferences().getChildrenAsList());
traverser.depthFirst(visitor, roots);
}
use of graphql.schema.GraphQLTypeVisitor in project spring-graphql by spring-projects.
the class DefaultGraphQlSourceBuilder method applyTypeVisitors.
private GraphQLSchema applyTypeVisitors(GraphQLSchema schema) {
List<GraphQLTypeVisitor> visitors = new ArrayList<>(this.typeVisitors);
visitors.add(ContextDataFetcherDecorator.TYPE_VISITOR);
GraphQLCodeRegistry.Builder codeRegistry = GraphQLCodeRegistry.newCodeRegistry(schema.getCodeRegistry());
Map<Class<?>, Object> vars = Collections.singletonMap(GraphQLCodeRegistry.Builder.class, codeRegistry);
SchemaTraverser traverser = new SchemaTraverser();
traverser.depthFirstFullSchema(visitors, schema, vars);
return schema.transformWithoutTypes(builder -> builder.codeRegistry(codeRegistry));
}
use of graphql.schema.GraphQLTypeVisitor in project graphql-java by graphql-java.
the class Anonymizer method recordNewNamesForSchema.
public static Map<GraphQLNamedSchemaElement, String> recordNewNamesForSchema(GraphQLSchema schema) {
AtomicInteger objectCounter = new AtomicInteger(1);
AtomicInteger inputObjectCounter = new AtomicInteger(1);
AtomicInteger inputObjectFieldCounter = new AtomicInteger(1);
AtomicInteger fieldCounter = new AtomicInteger(1);
AtomicInteger scalarCounter = new AtomicInteger(1);
AtomicInteger directiveCounter = new AtomicInteger(1);
AtomicInteger argumentCounter = new AtomicInteger(1);
AtomicInteger interfaceCounter = new AtomicInteger(1);
AtomicInteger unionCounter = new AtomicInteger(1);
AtomicInteger enumCounter = new AtomicInteger(1);
AtomicInteger enumValueCounter = new AtomicInteger(1);
Map<GraphQLNamedSchemaElement, String> newNameMap = new LinkedHashMap<>();
Map<String, String> directivesOriginalToNewNameMap = new HashMap<>();
// DirectiveName.argumentName -> newArgumentName
Map<String, String> seenArgumentsOnDirectivesMap = new HashMap<>();
Map<String, List<GraphQLImplementingType>> interfaceToImplementations = new SchemaUtil().groupImplementationsForInterfacesAndObjects(schema);
Consumer<GraphQLNamedSchemaElement> recordDirectiveName = (graphQLDirective) -> {
String directiveName = graphQLDirective.getName();
if (directivesOriginalToNewNameMap.containsKey(directiveName)) {
newNameMap.put(graphQLDirective, directivesOriginalToNewNameMap.get(directiveName));
return;
}
String newName = "Directive" + directiveCounter.getAndIncrement();
newNameMap.put(graphQLDirective, newName);
directivesOriginalToNewNameMap.put(directiveName, newName);
};
BiConsumer<GraphQLNamedSchemaElement, String> recordDirectiveArgumentName = (graphQLArgument, directiveArgumentKey) -> {
if (seenArgumentsOnDirectivesMap.containsKey(directiveArgumentKey)) {
newNameMap.put(graphQLArgument, seenArgumentsOnDirectivesMap.get(directiveArgumentKey));
return;
}
String newName = "argument" + argumentCounter.getAndIncrement();
newNameMap.put(graphQLArgument, newName);
seenArgumentsOnDirectivesMap.put(directiveArgumentKey, newName);
};
GraphQLTypeVisitor visitor = new GraphQLTypeVisitorStub() {
@Override
public TraversalControl visitGraphQLArgument(GraphQLArgument graphQLArgument, TraverserContext<GraphQLSchemaElement> context) {
String curName = graphQLArgument.getName();
GraphQLSchemaElement parentNode = context.getParentNode();
if (parentNode instanceof GraphQLDirective) {
// if we already went over the argument for this directive name, no need to add new names
String directiveArgumentKey = ((GraphQLDirective) parentNode).getName() + graphQLArgument.getName();
recordDirectiveArgumentName.accept(graphQLArgument, directiveArgumentKey);
return CONTINUE;
}
if (!(parentNode instanceof GraphQLFieldDefinition)) {
String newName = "argument" + argumentCounter.getAndIncrement();
newNameMap.put(graphQLArgument, newName);
return CONTINUE;
}
GraphQLFieldDefinition fieldDefinition = (GraphQLFieldDefinition) parentNode;
String fieldName = fieldDefinition.getName();
GraphQLImplementingType implementingType = (GraphQLImplementingType) context.getParentContext().getParentNode();
Set<GraphQLFieldDefinition> matchingInterfaceFieldDefinitions = getSameFields(fieldName, implementingType.getName(), interfaceToImplementations, schema);
String newName;
if (matchingInterfaceFieldDefinitions.size() == 0) {
newName = "argument" + argumentCounter.getAndIncrement();
} else {
List<GraphQLArgument> matchingArgumentDefinitions = getMatchingArgumentDefinitions(curName, matchingInterfaceFieldDefinitions);
if (matchingArgumentDefinitions.size() == 0) {
newName = "argument" + argumentCounter.getAndIncrement();
} else {
if (newNameMap.containsKey(matchingArgumentDefinitions.get(0))) {
newName = newNameMap.get(matchingArgumentDefinitions.get(0));
} else {
newName = "argument" + argumentCounter.getAndIncrement();
for (GraphQLArgument argument : matchingArgumentDefinitions) {
newNameMap.put(argument, newName);
}
}
}
}
newNameMap.put(graphQLArgument, newName);
return CONTINUE;
}
@Override
public TraversalControl visitGraphQLAppliedDirectiveArgument(GraphQLAppliedDirectiveArgument graphQLArgument, TraverserContext<GraphQLSchemaElement> context) {
GraphQLSchemaElement parentNode = context.getParentNode();
if (parentNode instanceof GraphQLAppliedDirective) {
// if we already went over the argument for this directive name, no need to add new names
String directiveArgumentKey = ((GraphQLAppliedDirective) parentNode).getName() + graphQLArgument.getName();
recordDirectiveArgumentName.accept(graphQLArgument, directiveArgumentKey);
}
return CONTINUE;
}
@Override
public TraversalControl visitGraphQLDirective(GraphQLDirective graphQLDirective, TraverserContext<GraphQLSchemaElement> context) {
if (DirectiveInfo.isGraphqlSpecifiedDirective(graphQLDirective)) {
return TraversalControl.ABORT;
}
recordDirectiveName.accept(graphQLDirective);
return CONTINUE;
}
@Override
public TraversalControl visitGraphQLAppliedDirective(GraphQLAppliedDirective graphQLAppliedDirective, TraverserContext<GraphQLSchemaElement> context) {
if (DirectiveInfo.isGraphqlSpecifiedDirective(graphQLAppliedDirective.getName())) {
return TraversalControl.ABORT;
}
recordDirectiveName.accept(graphQLAppliedDirective);
return CONTINUE;
}
@Override
public TraversalControl visitGraphQLInterfaceType(GraphQLInterfaceType graphQLInterfaceType, TraverserContext<GraphQLSchemaElement> context) {
if (Introspection.isIntrospectionTypes(graphQLInterfaceType)) {
return TraversalControl.ABORT;
}
String newName = "Interface" + interfaceCounter.getAndIncrement();
newNameMap.put(graphQLInterfaceType, newName);
return CONTINUE;
}
@Override
public TraversalControl visitGraphQLEnumType(GraphQLEnumType graphQLEnumType, TraverserContext<GraphQLSchemaElement> context) {
if (Introspection.isIntrospectionTypes(graphQLEnumType)) {
return TraversalControl.ABORT;
}
String newName = "Enum" + enumCounter.getAndIncrement();
newNameMap.put(graphQLEnumType, newName);
return CONTINUE;
}
@Override
public TraversalControl visitGraphQLEnumValueDefinition(GraphQLEnumValueDefinition enumValueDefinition, TraverserContext<GraphQLSchemaElement> context) {
String newName = "EnumValue" + enumValueCounter.getAndIncrement();
newNameMap.put(enumValueDefinition, newName);
return CONTINUE;
}
@Override
public TraversalControl visitGraphQLFieldDefinition(GraphQLFieldDefinition graphQLFieldDefinition, TraverserContext<GraphQLSchemaElement> context) {
String fieldName = graphQLFieldDefinition.getName();
GraphQLImplementingType parentNode = (GraphQLImplementingType) context.getParentNode();
Set<GraphQLFieldDefinition> sameFields = getSameFields(fieldName, parentNode.getName(), interfaceToImplementations, schema);
String newName;
if (sameFields.size() == 0) {
newName = "field" + fieldCounter.getAndIncrement();
} else {
if (newNameMap.containsKey(sameFields.iterator().next())) {
newName = newNameMap.get(sameFields.iterator().next());
} else {
newName = "field" + fieldCounter.getAndIncrement();
for (GraphQLFieldDefinition fieldDefinition : sameFields) {
newNameMap.put(fieldDefinition, newName);
}
}
}
newNameMap.put(graphQLFieldDefinition, newName);
return CONTINUE;
}
@Override
public TraversalControl visitGraphQLInputObjectField(GraphQLInputObjectField graphQLInputObjectField, TraverserContext<GraphQLSchemaElement> context) {
String newName = "inputField" + inputObjectFieldCounter.getAndIncrement();
newNameMap.put(graphQLInputObjectField, newName);
return CONTINUE;
}
@Override
public TraversalControl visitGraphQLInputObjectType(GraphQLInputObjectType graphQLInputObjectType, TraverserContext<GraphQLSchemaElement> context) {
if (Introspection.isIntrospectionTypes(graphQLInputObjectType)) {
return TraversalControl.ABORT;
}
String newName = "InputObject" + inputObjectCounter.getAndIncrement();
newNameMap.put(graphQLInputObjectType, newName);
return CONTINUE;
}
@Override
public TraversalControl visitGraphQLObjectType(GraphQLObjectType graphQLObjectType, TraverserContext<GraphQLSchemaElement> context) {
if (Introspection.isIntrospectionTypes(graphQLObjectType)) {
return TraversalControl.ABORT;
}
String newName = "Object" + objectCounter.getAndIncrement();
newNameMap.put(graphQLObjectType, newName);
return CONTINUE;
}
@Override
public TraversalControl visitGraphQLScalarType(GraphQLScalarType graphQLScalarType, TraverserContext<GraphQLSchemaElement> context) {
if (ScalarInfo.isGraphqlSpecifiedScalar(graphQLScalarType)) {
return TraversalControl.ABORT;
}
String newName = "Scalar" + scalarCounter.getAndIncrement();
newNameMap.put(graphQLScalarType, newName);
return CONTINUE;
}
@Override
public TraversalControl visitGraphQLUnionType(GraphQLUnionType graphQLUnionType, TraverserContext<GraphQLSchemaElement> context) {
if (Introspection.isIntrospectionTypes(graphQLUnionType)) {
return TraversalControl.ABORT;
}
String newName = "Union" + unionCounter.getAndIncrement();
newNameMap.put(graphQLUnionType, newName);
return CONTINUE;
}
};
SchemaTransformer.transformSchema(schema, visitor);
return newNameMap;
}
use of graphql.schema.GraphQLTypeVisitor in project graphql-java by graphql-java.
the class SchemaUsageSupport method getSchemaUsage.
/**
* This builds out {@link SchemaUsage} statistics about the usage of types and directives within a schema
*
* @param schema the schema to check
*
* @return usage stats
*/
public static SchemaUsage getSchemaUsage(GraphQLSchema schema) {
assertNotNull(schema);
SchemaUsage.Builder builder = new SchemaUsage.Builder();
GraphQLTypeVisitor visitor = new GraphQLTypeVisitorStub() {
private BiFunction<String, Integer, Integer> incCount() {
return (k, v) -> v == null ? 1 : v + 1;
}
private void recordBackReference(GraphQLNamedSchemaElement referencedElement, GraphQLSchemaElement referencingElement) {
String referencedElementName = referencedElement.getName();
if (referencingElement instanceof GraphQLType) {
String typeName = (GraphQLTypeUtil.unwrapAll((GraphQLType) referencingElement)).getName();
builder.elementBackReferences.computeIfAbsent(referencedElementName, k -> new HashSet<>()).add(typeName);
}
if (referencingElement instanceof GraphQLDirective) {
String typeName = ((GraphQLDirective) referencingElement).getName();
builder.elementBackReferences.computeIfAbsent(referencedElementName, k -> new HashSet<>()).add(typeName);
}
}
private void memberInterfaces(GraphQLNamedType containingType, List<GraphQLNamedOutputType> members) {
for (GraphQLNamedOutputType member : members) {
builder.interfaceReferenceCount.compute(member.getName(), incCount());
builder.interfaceImplementors.computeIfAbsent(member.getName(), k -> new HashSet<>()).add(containingType.getName());
recordBackReference(containingType, member);
}
}
@Override
public TraversalControl visitGraphQLArgument(GraphQLArgument node, TraverserContext<GraphQLSchemaElement> context) {
GraphQLNamedType inputType = GraphQLTypeUtil.unwrapAll(node.getType());
builder.argReferenceCount.compute(inputType.getName(), incCount());
GraphQLSchemaElement parentElement = context.getParentNode();
if (parentElement instanceof GraphQLFieldDefinition) {
parentElement = context.getParentContext().getParentNode();
}
recordBackReference(inputType, parentElement);
return CONTINUE;
}
@Override
public TraversalControl visitGraphQLFieldDefinition(GraphQLFieldDefinition node, TraverserContext<GraphQLSchemaElement> context) {
GraphQLNamedType fieldType = GraphQLTypeUtil.unwrapAll(node.getType());
builder.fieldReferenceCounts.compute(fieldType.getName(), incCount());
builder.outputFieldReferenceCounts.compute(fieldType.getName(), incCount());
recordBackReference(fieldType, context.getParentNode());
return CONTINUE;
}
@Override
public TraversalControl visitGraphQLInputObjectField(GraphQLInputObjectField node, TraverserContext<GraphQLSchemaElement> context) {
GraphQLNamedType fieldType = GraphQLTypeUtil.unwrapAll(node.getType());
builder.fieldReferenceCounts.compute(fieldType.getName(), incCount());
builder.inputFieldReferenceCounts.compute(fieldType.getName(), incCount());
recordBackReference(fieldType, context.getParentNode());
return CONTINUE;
}
@Override
public TraversalControl visitGraphQLDirective(GraphQLDirective directive, TraverserContext<GraphQLSchemaElement> context) {
GraphQLSchemaElement parentElement = context.getParentNode();
if (parentElement != null) {
// a null parent is a directive definition
// we record a count if the directive is applied to something - not just defined
builder.directiveReferenceCount.compute(directive.getName(), incCount());
}
if (parentElement instanceof GraphQLArgument) {
context = context.getParentContext();
parentElement = context.getParentNode();
}
if (parentElement instanceof GraphQLFieldDefinition) {
context = context.getParentContext();
parentElement = context.getParentNode();
}
if (parentElement instanceof GraphQLInputObjectField) {
context = context.getParentContext();
parentElement = context.getParentNode();
}
recordBackReference(directive, parentElement);
return CONTINUE;
}
@Override
public TraversalControl visitGraphQLUnionType(GraphQLUnionType unionType, TraverserContext<GraphQLSchemaElement> context) {
List<GraphQLNamedOutputType> members = unionType.getTypes();
for (GraphQLNamedOutputType member : members) {
builder.unionReferenceCount.compute(member.getName(), incCount());
recordBackReference(unionType, member);
}
return CONTINUE;
}
@Override
public TraversalControl visitGraphQLInterfaceType(GraphQLInterfaceType interfaceType, TraverserContext<GraphQLSchemaElement> context) {
memberInterfaces(interfaceType, interfaceType.getInterfaces());
return CONTINUE;
}
@Override
public TraversalControl visitGraphQLObjectType(GraphQLObjectType objectType, TraverserContext<GraphQLSchemaElement> context) {
memberInterfaces(objectType, objectType.getInterfaces());
return CONTINUE;
}
};
new SchemaTraverser().depthFirstFullSchema(visitor, schema);
return builder.build();
}
Aggregations