QueryGeneratorPrinter.java
package graphql.util.querygenerator;
import graphql.language.AstPrinter;
import graphql.parser.Parser;
import org.jspecify.annotations.Nullable;
import java.util.List;
import java.util.stream.Collectors;
class QueryGeneratorPrinter {
String print(
String operationFieldPath,
@Nullable String operationName,
@Nullable String arguments,
QueryGeneratorFieldSelection.FieldSelection rootFieldSelection
) {
String[] fieldPathParts = operationFieldPath.split("\\.");
String fields = printFieldsForTopLevelType(rootFieldSelection);
String start = printOperationStart(fieldPathParts, operationName, arguments);
String end = printOperationEnd(fieldPathParts);
String raw = start + fields + end;
return AstPrinter.printAst(Parser.parse(raw));
}
private String printFieldsForTopLevelType(QueryGeneratorFieldSelection.FieldSelection rootFieldSelection) {
return rootFieldSelection.fieldsByContainer.values().iterator().next().stream()
.map(this::printFieldSelection)
.collect(Collectors.joining(
"",
"... on " + rootFieldSelection.name + " {\n",
"}\n"
));
}
private String printOperationStart(
String[] fieldPathParts,
@Nullable String operationName,
@Nullable String arguments
) {
String operation = fieldPathParts[0].toLowerCase();
StringBuilder sb = new StringBuilder();
sb.append(operation);
if (operationName != null) {
sb.append(" ").append(operationName).append(" ");
}
sb.append(" {\n");
for (int i = 1; i < fieldPathParts.length; i++) {
sb.append(fieldPathParts[i]);
boolean isLastField = i == fieldPathParts.length - 1;
if (isLastField) {
if (arguments != null) {
sb.append(arguments);
}
}
sb.append(" {\n");
}
return sb.toString();
}
private String printOperationEnd(String[] fieldPathParts) {
return "}\n".repeat(fieldPathParts.length);
}
private String printFieldSelectionForContainer(
String containerName,
List<QueryGeneratorFieldSelection.FieldSelection> fieldSelections,
boolean needsTypeClassifier
) {
String fieldStr = fieldSelections.stream()
.map(subField ->
printFieldSelection(subField, needsTypeClassifier ? containerName + "_" : null))
.collect(Collectors.joining());
if (fieldStr.isEmpty()) {
return "";
}
StringBuilder fieldSelectionSb = new StringBuilder();
if (needsTypeClassifier) {
fieldSelectionSb.append("... on ").append(containerName).append(" {\n");
}
fieldSelectionSb.append(fieldStr);
if (needsTypeClassifier) {
fieldSelectionSb.append(" }\n");
}
return fieldSelectionSb.toString();
}
private String printFieldSelection(QueryGeneratorFieldSelection.FieldSelection fieldSelection, @Nullable String aliasPrefix) {
StringBuilder sb = new StringBuilder();
if (fieldSelection.fieldsByContainer != null) {
String fieldSelectionString = fieldSelection.fieldsByContainer.entrySet().stream()
.map((entry) ->
printFieldSelectionForContainer(entry.getKey(), entry.getValue(), fieldSelection.needsTypeClassifier))
.collect(Collectors.joining());
// It is possible that some container fields ended up with empty fields (due to filtering etc). We shouldn't print those
if (!fieldSelectionString.isEmpty()) {
if (aliasPrefix != null) {
sb.append(aliasPrefix).append(fieldSelection.name).append(": ");
}
sb.append(fieldSelection.name)
.append(" {\n")
.append(fieldSelectionString)
.append("}\n");
}
} else {
if (aliasPrefix != null) {
sb.append(aliasPrefix).append(fieldSelection.name).append(": ");
}
sb.append(fieldSelection.name).append("\n");
}
return sb.toString();
}
private String printFieldSelection(QueryGeneratorFieldSelection.FieldSelection fieldSelection) {
return printFieldSelection(fieldSelection, null);
}
}