-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Adds a predicate mechanism to compile a document into all variables or just some #2731
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,128 @@ | ||
| package graphql.normalized; | ||
|
|
||
| import graphql.AssertException; | ||
| import graphql.Internal; | ||
| import graphql.language.ArrayValue; | ||
| import graphql.language.BooleanValue; | ||
| import graphql.language.FloatValue; | ||
| import graphql.language.IntValue; | ||
| import graphql.language.NullValue; | ||
| import graphql.language.ObjectField; | ||
| import graphql.language.ObjectValue; | ||
| import graphql.language.StringValue; | ||
| import graphql.language.TypeName; | ||
| import graphql.language.Value; | ||
| import graphql.language.VariableDefinition; | ||
| import graphql.language.VariableReference; | ||
| import org.jetbrains.annotations.NotNull; | ||
| import org.jetbrains.annotations.Nullable; | ||
|
|
||
| import java.util.LinkedHashMap; | ||
| import java.util.List; | ||
| import java.util.Map; | ||
|
|
||
| import static graphql.collect.ImmutableKit.map; | ||
| import static java.util.stream.Collectors.toList; | ||
|
|
||
| @Internal | ||
| public class ValueToVariableValueCompiler { | ||
|
|
||
| static VariableValueWithDefinition normalizedInputValueToVariable(NormalizedInputValue normalizedInputValue, int queryVariableCount) { | ||
| Object variableValue = normalisedValueToVariableValue(normalizedInputValue); | ||
| String varName = getVarName(queryVariableCount); | ||
| return new VariableValueWithDefinition( | ||
| variableValue, | ||
| VariableDefinition.newVariableDefinition() | ||
| .name(varName) | ||
| .type(TypeName.newTypeName(normalizedInputValue.getTypeName()).build()) | ||
| .build(), | ||
| VariableReference.newVariableReference().name(varName).build()); | ||
| } | ||
|
|
||
| @SuppressWarnings("unchecked") | ||
| @Nullable | ||
| private static Object normalisedValueToVariableValue(Object maybeValue) { | ||
| Object variableValue; | ||
| if (maybeValue instanceof NormalizedInputValue) { | ||
| NormalizedInputValue normalizedInputValue = (NormalizedInputValue) maybeValue; | ||
| Object inputValue = normalizedInputValue.getValue(); | ||
| if (inputValue instanceof Value) { | ||
| variableValue = toVariableValue((Value<?>) inputValue); | ||
| } else if (inputValue instanceof List) { | ||
| variableValue = normalisedValueToVariableValues((List<Object>) inputValue); | ||
| } else if (inputValue instanceof Map) { | ||
| variableValue = normalisedValueToVariableValues((Map<String, Object>) inputValue); | ||
| } else { | ||
| throw new AssertException("Should never happen. Did not expect NormalizedInputValue.getValue() of type: " + inputValue.getClass()); | ||
| } | ||
| } else if (maybeValue instanceof Value) { | ||
| Value<?> value = (Value<?>) maybeValue; | ||
| variableValue = toVariableValue(value); | ||
| } else if (maybeValue instanceof List) { | ||
| variableValue = normalisedValueToVariableValues((List<Object>) maybeValue); | ||
| } else if (maybeValue instanceof Map) { | ||
| variableValue = normalisedValueToVariableValues((Map<String, Object>) maybeValue); | ||
| } else { | ||
| throw new AssertException("Should never happen. Did not expect type: " + maybeValue.getClass()); | ||
| } | ||
| return variableValue; | ||
| } | ||
|
|
||
| private static List<Object> normalisedValueToVariableValues(List<Object> arrayValues) { | ||
| return map(arrayValues, ValueToVariableValueCompiler::normalisedValueToVariableValue); | ||
| } | ||
|
|
||
| @NotNull | ||
| private static Map<String, Object> normalisedValueToVariableValues(Map<String, Object> objectMap) { | ||
| Map<String, Object> output = new LinkedHashMap<>(); | ||
| objectMap.forEach((k, v) -> { | ||
| Object value = normalisedValueToVariableValue(v); | ||
| output.put(k, value); | ||
| }); | ||
| return output; | ||
| } | ||
|
|
||
| private static Map<String, Object> toVariableValue(ObjectValue objectValue) { | ||
| Map<String, Object> map = new LinkedHashMap<>(); | ||
| List<ObjectField> objectFields = objectValue.getObjectFields(); | ||
| for (ObjectField objectField : objectFields) { | ||
| String objectFieldName = objectField.getName(); | ||
| Value<?> objectFieldValue = objectField.getValue(); | ||
| map.put(objectFieldName, toVariableValue(objectFieldValue)); | ||
| } | ||
| return map; | ||
| } | ||
|
|
||
| @NotNull | ||
| private static List<Object> toVariableValues(List<Value> arrayValues) { | ||
| // some values can be null (NullValue) and hence we can use Immutable Lists | ||
| return arrayValues.stream() | ||
| .map(ValueToVariableValueCompiler::toVariableValue) | ||
| .collect(toList()); | ||
| } | ||
|
|
||
| @Nullable | ||
| private static Object toVariableValue(Value<?> value) { | ||
| if (value instanceof ObjectValue) { | ||
| return toVariableValue((ObjectValue) value); | ||
| } else if (value instanceof ArrayValue) { | ||
| return toVariableValues(((ArrayValue) value).getValues()); | ||
| } else if (value instanceof StringValue) { | ||
| return ((StringValue) value).getValue(); | ||
| } else if (value instanceof FloatValue) { | ||
| return ((FloatValue) value).getValue(); | ||
| } else if (value instanceof IntValue) { | ||
| return ((IntValue) value).getValue(); | ||
| } else if (value instanceof BooleanValue) { | ||
| return ((BooleanValue) value).isValue(); | ||
| } else if (value instanceof NullValue) { | ||
| return null; | ||
| } | ||
| throw new AssertException("Should never happen. Cannot handle node of type: " + value.getClass()); | ||
| } | ||
|
|
||
| private static String getVarName(int variableOrdinal) { | ||
| return "v" + variableOrdinal; | ||
| } | ||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I shortened the original work that Artyom put in as |
||
|
|
||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,59 @@ | ||
| package graphql.normalized; | ||
|
|
||
| import graphql.Internal; | ||
| import graphql.language.VariableDefinition; | ||
|
|
||
| import java.util.ArrayList; | ||
| import java.util.List; | ||
| import java.util.Map; | ||
| import java.util.stream.Collectors; | ||
|
|
||
| import static graphql.normalized.ValueToVariableValueCompiler.normalizedInputValueToVariable; | ||
|
|
||
| /** | ||
| * This accumulator class decides on whether to create a variable for a query argument and if so it tracks what variables were made. | ||
| * The {@link ExecutableNormalizedOperationToAstCompiler} then uses all the variables when it compiles the final document. | ||
| */ | ||
| @Internal | ||
| public class VariableAccumulator { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nice |
||
|
|
||
| private final List<VariableValueWithDefinition> valueWithDefinitions; | ||
| private final VariablePredicate variablePredicate; | ||
|
|
||
| public VariableAccumulator(VariablePredicate variablePredicate) { | ||
| this.variablePredicate = variablePredicate; | ||
| valueWithDefinitions = new ArrayList<>(); | ||
| } | ||
|
|
||
| public boolean shouldMakeVariable(ExecutableNormalizedField executableNormalizedField, String argName, NormalizedInputValue normalizedInputValue) { | ||
| return variablePredicate.shouldMakeVariable(executableNormalizedField, argName, normalizedInputValue); | ||
| } | ||
|
|
||
| public VariableValueWithDefinition accumulateVariable(NormalizedInputValue normalizedInputValue) { | ||
| VariableValueWithDefinition variableWithDefinition = normalizedInputValueToVariable(normalizedInputValue, getAccumulatedSize()); | ||
| valueWithDefinitions.add(variableWithDefinition); | ||
| return variableWithDefinition; | ||
| } | ||
|
|
||
| public int getAccumulatedSize() { | ||
| return valueWithDefinitions.size(); | ||
| } | ||
|
|
||
| /** | ||
| * @return the variable definitions that would go on the operation declaration | ||
| */ | ||
| public List<VariableDefinition> getVariableDefinitions() { | ||
| return valueWithDefinitions.stream().map(VariableValueWithDefinition::getDefinition).collect(Collectors.toList()); | ||
| } | ||
|
|
||
| /** | ||
| * @return the map of variable names to variable values | ||
| */ | ||
| public Map<String, Object> getVariablesMap() { | ||
| return valueWithDefinitions.stream() | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No immutable collections stuff? |
||
| .collect(Collectors.toMap( | ||
| variableWithDefinition -> variableWithDefinition.getDefinition().getName(), | ||
| VariableValueWithDefinition::getValue | ||
| )); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| package graphql.normalized; | ||
|
|
||
| import graphql.Internal; | ||
|
|
||
| /** | ||
| * This predicate indicates whether a variable should be made for this field argument | ||
| */ | ||
| @Internal | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Internal? |
||
| public interface VariablePredicate { | ||
| /** | ||
| * Return true if a variable should be made for this field argument | ||
| * | ||
| * @param executableNormalizedField the field in question | ||
| * @param argName the argument on the field | ||
| * @param normalizedInputValue the input value for that argument | ||
| * @return true if a variable should be made | ||
| */ | ||
| boolean shouldMakeVariable(ExecutableNormalizedField executableNormalizedField, String argName, NormalizedInputValue normalizedInputValue); | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should you use FpKit?