graphql.normalized.ExecutableNormalizedOperationToAstCompiler Maven / Gradle / Ivy
package graphql.normalized;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import graphql.Internal;
import graphql.language.Argument;
import graphql.language.ArrayValue;
import graphql.language.Document;
import graphql.language.Field;
import graphql.language.InlineFragment;
import graphql.language.NullValue;
import graphql.language.ObjectField;
import graphql.language.ObjectValue;
import graphql.language.OperationDefinition;
import graphql.language.Selection;
import graphql.language.SelectionSet;
import graphql.language.TypeName;
import graphql.language.Value;
import graphql.schema.GraphQLSchema;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import static graphql.collect.ImmutableKit.map;
import static graphql.language.Argument.newArgument;
import static graphql.language.Field.newField;
import static graphql.language.InlineFragment.newInlineFragment;
import static graphql.language.SelectionSet.newSelectionSet;
import static graphql.language.TypeName.newTypeName;
@Internal
public class ExecutableNormalizedOperationToAstCompiler {
public static Document compileToDocument(GraphQLSchema schema,
OperationDefinition.Operation operationKind,
String operationName,
List topLevelFields) {
List> selections = selectionsForNormalizedFields(schema, topLevelFields);
SelectionSet selectionSet = new SelectionSet(selections);
return Document.newDocument()
.definition(OperationDefinition.newOperationDefinition()
.name(operationName)
.operation(operationKind)
.selectionSet(selectionSet)
.build())
.build();
}
private static List> selectionsForNormalizedFields(GraphQLSchema schema,
List executableNormalizedFields) {
ImmutableList.Builder> selections = ImmutableList.builder();
// All conditional fields go here instead of directly to selections so they can be grouped together
// in the same inline fragement in the output
Map> conditionalFieldsByObjectTypeName = new LinkedHashMap<>();
for (ExecutableNormalizedField nf : executableNormalizedFields) {
Map> groupFieldsForChild = selectionForNormalizedField(schema, nf);
if (nf.isConditional(schema)) {
groupFieldsForChild.forEach((objectTypeName, fields) -> {
List fieldList = conditionalFieldsByObjectTypeName.computeIfAbsent(objectTypeName, ignored -> new ArrayList<>());
fieldList.addAll(fields);
});
} else {
List fields = groupFieldsForChild.values().iterator().next();
selections.addAll(fields);
}
}
conditionalFieldsByObjectTypeName.forEach((objectTypeName, fields) -> {
TypeName typeName = newTypeName(objectTypeName).build();
InlineFragment inlineFragment = newInlineFragment().
typeCondition(typeName)
.selectionSet(selectionSet(fields))
.build();
selections.add(inlineFragment);
});
return selections.build();
}
private static Map> selectionForNormalizedField(GraphQLSchema schema,
ExecutableNormalizedField executableNormalizedField) {
Map> groupedFields = new LinkedHashMap<>();
for (String objectTypeName : executableNormalizedField.getObjectTypeNames()) {
List> subSelections = selectionsForNormalizedFields(schema, executableNormalizedField.getChildren());
SelectionSet selectionSet = null;
if (subSelections.size() > 0) {
selectionSet = newSelectionSet()
.selections(subSelections)
.build();
}
List arguments = createArguments(executableNormalizedField);
Field field = newField()
.name(executableNormalizedField.getFieldName())
.alias(executableNormalizedField.getAlias())
.selectionSet(selectionSet)
.arguments(arguments)
.build();
groupedFields.computeIfAbsent(objectTypeName, ignored -> new ArrayList<>()).add(field);
}
return groupedFields;
}
private static SelectionSet selectionSet(List fields) {
return newSelectionSet().selections(fields).build();
}
private static List createArguments(ExecutableNormalizedField executableNormalizedField) {
ImmutableList.Builder result = ImmutableList.builder();
ImmutableMap normalizedArguments = executableNormalizedField.getNormalizedArguments();
for (String argName : normalizedArguments.keySet()) {
Argument argument = newArgument()
.name(argName)
.value(argValue(normalizedArguments.get(argName).getValue()))
.build();
result.add(argument);
}
return result.build();
}
private static Value> argValue(Object value) {
if (value instanceof List) {
ArrayValue.Builder arrayValue = ArrayValue.newArrayValue();
arrayValue.values(map((List