use of graphql.schema.GraphQLTypeVisitorStub 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();
}
use of graphql.schema.GraphQLTypeVisitorStub in project graphql-java by graphql-java.
the class FieldVisibilitySchemaTransformation method removeUnreferencedTypes.
private GraphQLSchema removeUnreferencedTypes(Set<GraphQLType> markedForRemovalTypes, GraphQLSchema connectedSchema) {
GraphQLSchema withoutAdditionalTypes = connectedSchema.transform(builder -> {
Set<GraphQLType> additionalTypes = new HashSet<>(connectedSchema.getAdditionalTypes());
additionalTypes.removeAll(markedForRemovalTypes);
builder.clearAdditionalTypes();
builder.additionalTypes(additionalTypes);
});
// remove from markedForRemovalTypes any type that might still be referenced by other schema elements
transformSchema(withoutAdditionalTypes, new AdditionalTypeVisibilityVisitor(markedForRemovalTypes));
// finally remove the types on the schema we are certain aren't referenced by any other node.
return transformSchema(connectedSchema, new GraphQLTypeVisitorStub() {
@Override
protected TraversalControl visitGraphQLType(GraphQLSchemaElement node, TraverserContext<GraphQLSchemaElement> context) {
if (node instanceof GraphQLType && markedForRemovalTypes.contains(node)) {
return deleteNode(context);
}
return super.visitGraphQLType(node, context);
}
});
}
Aggregations