graphql.schema.validation.NoUnbrokenInputCycles Maven / Gradle / Ivy
The newest version!
package graphql.schema.validation;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import graphql.schema.GraphQLArgument;
import graphql.schema.GraphQLFieldDefinition;
import graphql.schema.GraphQLInputObjectField;
import graphql.schema.GraphQLInputObjectType;
import graphql.schema.GraphQLInputType;
import graphql.schema.GraphQLList;
import graphql.schema.GraphQLModifiedType;
import graphql.schema.GraphQLNonNull;
import graphql.schema.GraphQLType;
/**
* Schema validation rule ensuring no input type forms an unbroken non-nullable recursion,
* as such a type would be impossible to satisfy
*/
public class NoUnbrokenInputCycles implements ValidationRule {
public void check(GraphQLFieldDefinition fieldDef, ValidationErrorCollector validationErrorCollector) {
for (GraphQLArgument argument : fieldDef.getArguments()) {
GraphQLInputType argumentType = argument.getType();
if (argumentType instanceof GraphQLInputObjectType) {
List path = new ArrayList<>();
path.add(argumentType.getName());
check((GraphQLInputObjectType) argumentType, new HashSet<>(), path, validationErrorCollector);
}
}
}
private void check(GraphQLInputObjectType type, Set seen, List path, ValidationErrorCollector validationErrorCollector) {
if (seen.contains(type)) {
validationErrorCollector.addError(new ValidationError(ValidationErrorType.UnbrokenInputCycle, getErrorMessage(path)));
return;
}
seen.add(type);
for (GraphQLInputObjectField field : type.getFieldDefinitions()) {
if (field.getType() instanceof GraphQLNonNull) {
GraphQLType unwrapped = unwrapNonNull((GraphQLNonNull) field.getType());
if (unwrapped instanceof GraphQLInputObjectType) {
path = new ArrayList<>(path);
path.add(field.getName() + "!");
check((GraphQLInputObjectType) unwrapped, new HashSet<>(seen), path, validationErrorCollector);
}
}
}
}
private GraphQLType unwrapNonNull(GraphQLNonNull type) {
if (type.getWrappedType() instanceof GraphQLList) {
//we only care about [type!]! i.e. non-null lists of non-nulls
if (((GraphQLList) type.getWrappedType()).getWrappedType() instanceof GraphQLNonNull) {
return unwrap(((GraphQLList) type.getWrappedType()).getWrappedType());
} else {
return type.getWrappedType();
}
} else {
return unwrap(type.getWrappedType());
}
}
private GraphQLType unwrap(GraphQLType type) {
if (type instanceof GraphQLModifiedType) {
return unwrap(((GraphQLModifiedType) type).getWrappedType());
}
return type;
}
private String getErrorMessage(List path) {
StringBuilder message = new StringBuilder();
message.append("[");
for (int i = 0; i < path.size(); i++) {
if (i != 0) {
message.append(".");
}
message.append(path.get(i));
}
message.append("] forms an unsatisfiable cycle");
return message.toString();
}
}