Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion src/main/java/graphql/language/AbstractNode.java
Original file line number Diff line number Diff line change
Expand Up @@ -46,5 +46,4 @@ protected <V extends Node> List<V> deepCopy(List<? extends Node> list) {
}
return list.stream().map(Node::deepCopy).map(node -> (V) node).collect(Collectors.toList());
}

}
27 changes: 17 additions & 10 deletions src/main/java/graphql/language/Argument.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,10 @@
@PublicApi
public class Argument extends AbstractNode<Argument> implements NamedNode<Argument> {

private String name;
private Value value;
private final String name;
private final Value value;

private static final String CHILD_VALUE = "value";

@Internal
protected Argument(String name, Value value, SourceLocation sourceLocation, List<Comment> comments) {
Expand Down Expand Up @@ -42,21 +44,26 @@ public Value getValue() {
return value;
}

public void setName(String name) {
this.name = name;
}

public void setValue(Value value) {
this.value = value;
}

@Override
public List<Node> getChildren() {
List<Node> result = new ArrayList<>();
result.add(value);
return result;
}

@Override
public ChildrenContainer getNamedChildren() {
return ChildrenContainer.newChildrenContainer()
.child(CHILD_VALUE, value)
.build();
}

@Override
public Argument withNewChildren(ChildrenContainer newChildren) {
return transform(builder -> builder
.value(newChildren.getSingleValueOrNull(CHILD_VALUE))
);
}

@Override
public boolean isEqualTo(Node o) {
Expand Down
16 changes: 16 additions & 0 deletions src/main/java/graphql/language/ArrayValue.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ public class ArrayValue extends AbstractNode<ArrayValue> implements Value<ArrayV

private final List<Value> values = new ArrayList<>();

private static final String CHILD_VALUES = "values";

@Internal
protected ArrayValue(List<Value> values, SourceLocation sourceLocation, List<Comment> comments) {
super(sourceLocation, comments);
Expand All @@ -40,6 +42,20 @@ public List<Node> getChildren() {
return new ArrayList<>(values);
}

@Override
public ChildrenContainer getNamedChildren() {
return ChildrenContainer.newChildrenContainer()
.children(CHILD_VALUES, values)
.build();
}

@Override
public ArrayValue withNewChildren(ChildrenContainer newChildren) {
return transform(builder -> builder
.values(newChildren.getList(CHILD_VALUES))
);
}

@Override
public boolean isEqualTo(Node o) {
if (this == o) return true;
Expand Down
86 changes: 86 additions & 0 deletions src/main/java/graphql/language/AstZipper.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
package graphql.language;


import graphql.PublicApi;

import java.util.ArrayList;
import java.util.List;
import java.util.function.Function;

@PublicApi
public class AstZipper {

private final Node curNode;
// reverse: the breadCrumbs start from curNode upwards
private final List<AstBreadcrumb> breadcrumbs;


public AstZipper(Node curNode, List<AstBreadcrumb> breadcrumbs) {
this.curNode = curNode;
this.breadcrumbs = breadcrumbs;
}

public static AstZipper rootZipper(Node rootNode) {
return new AstZipper(rootNode, new ArrayList<>());
}

public static class AstBreadcrumb {
private final Node node;
private final Location location;

public AstBreadcrumb(Node node, Location location) {
this.node = node;
this.location = location;
}
}

public static class Location {
private final String childName;
private final int position;

public Location(String childName, int position) {
this.childName = childName;
this.position = position;
}
}


public AstZipper modifyNode(Function<Node, Node> transform) {
return new AstZipper(transform.apply(curNode), breadcrumbs);
}

public AstZipper changeLocation(Location newLocationInParent) {
// validate position
List<AstBreadcrumb> newBreadcrumbs = new ArrayList<>(breadcrumbs);
AstBreadcrumb lastBreadcrumb = newBreadcrumbs.get(newBreadcrumbs.size() - 1);
newBreadcrumbs.set(newBreadcrumbs.size() - 1, new AstBreadcrumb(lastBreadcrumb.node, newLocationInParent));
return new AstZipper(curNode, newBreadcrumbs);
}

public AstZipper changeLocation(Location newLocationInParent, List<AstBreadcrumb> newBreadcrumbs) {
// validate position
return new AstZipper(curNode, newBreadcrumbs);
}

public AstZipper moveUp() {
return null;
}

public Node toRoot() {
Node curNode = this.curNode;
for (AstBreadcrumb breadcrumb : breadcrumbs) {
// just handle replace
ChildrenContainer newChildren = breadcrumb.node.getNamedChildren();
final Node newChild = curNode;
newChildren = newChildren.transform(builder -> {
Location location = breadcrumb.location;
builder.replaceChild(location.childName, location.position, newChild);
});
curNode = breadcrumb.node.withNewChildren(newChildren);
}
return curNode;
}


}

14 changes: 14 additions & 0 deletions src/main/java/graphql/language/BooleanValue.java
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,20 @@ public List<Node> getChildren() {
return new ArrayList<>();
}

@Override
public ChildrenContainer getNamedChildren() {
return ChildrenContainer.newChildrenContainer().build();
}

@Override
public BooleanValue withNewChildren(ChildrenContainer newChildren) {
if (!newChildren.isEmpty()) {
throw new IllegalArgumentException("Cannot pass non-empty newChildren to Node that doesn't hold children");
}

return this;
}

@Override
public boolean isEqualTo(Node o) {
if (this == o) return true;
Expand Down
81 changes: 81 additions & 0 deletions src/main/java/graphql/language/ChildrenContainer.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
package graphql.language;

import graphql.Assert;
import graphql.PublicApi;

import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;

@PublicApi
public class ChildrenContainer {

private final Map<String, List<Node>> children = new LinkedHashMap<>();

private ChildrenContainer(Map<String, List<Node>> children) {
this.children.putAll(Assert.assertNotNull(children));
}

public <T extends Node> List<T> getList(String key) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

getChildrenWithName or just getChildren is a better namer I think. You know its a List from the return type

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

still stand by this comment

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

will change

return (List<T>) children.getOrDefault(key, new ArrayList<>());
}

public <T extends Node> T getSingleValueOrNull(String key) {
List<? extends Node> result = children.getOrDefault(key, new ArrayList<>());
if (result.size() > 1) {
throw new IllegalStateException("children " + key + " is not a single value");
}
return result.size() > 0 ? (T) result.get(0) : null;
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

getChildOrNull might ber a better name

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, will change



public static Builder newChildrenContainer() {
return new Builder();
}

public ChildrenContainer transform(Consumer<Builder> builderConsumer) {
Builder builder = new Builder(this);
builderConsumer.accept(builder);
return builder.build();
}

public boolean isEmpty() {
return this.children.isEmpty();
}

public static class Builder {
private final Map<String, List<Node>> children = new LinkedHashMap<>();

private Builder() {

}

private Builder(ChildrenContainer other) {
this.children.putAll(other.children);
}

public Builder child(String key, Node child) {
children.computeIfAbsent(key, (k) -> new ArrayList<>());
children.get(key).add(child);
return this;
}

public Builder children(String key, List<? extends Node> children) {
this.children.computeIfAbsent(key, (k) -> new ArrayList<>());
this.children.get(key).addAll(children);
return this;
}

public Builder replaceChild(String key, int index, Node newChild) {
this.children.get(key).set(index, newChild);
return this;
}

public ChildrenContainer build() {
return new ChildrenContainer(this.children);

}
}
}
16 changes: 16 additions & 0 deletions src/main/java/graphql/language/Directive.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ public class Directive extends AbstractNode<Directive> implements NamedNode<Dire
private final String name;
private final List<Argument> arguments = new ArrayList<>();

private static final String CHILD_ARGUMENTS = "arguments";

@Internal
protected Directive(String name, List<Argument> arguments, SourceLocation sourceLocation, List<Comment> comments) {
super(sourceLocation, comments);
Expand Down Expand Up @@ -64,6 +66,20 @@ public List<Node> getChildren() {
return new ArrayList<>(arguments);
}

@Override
public ChildrenContainer getNamedChildren() {
return ChildrenContainer.newChildrenContainer()
.children(CHILD_ARGUMENTS, arguments)
.build();
}

@Override
public Directive withNewChildren(ChildrenContainer newChildren) {
return transform(builder -> builder
.arguments(newChildren.getList(CHILD_ARGUMENTS))
);
}

@Override
public boolean isEqualTo(Node o) {
if (this == o) return true;
Expand Down
33 changes: 25 additions & 8 deletions src/main/java/graphql/language/DirectiveDefinition.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,19 +13,24 @@
@PublicApi
public class DirectiveDefinition extends AbstractNode<DirectiveDefinition> implements SDLDefinition<DirectiveDefinition>, NamedNode<DirectiveDefinition> {
private final String name;
private Description description;
private final Description description;
private final List<InputValueDefinition> inputValueDefinitions;
private final List<DirectiveLocation> directiveLocations;

private static final String CHILD_INPUT_VALUE_DEFINITIONS = "inputValueDefinitions";
private static final String CHILD_DIRECTIVE_LOCATION = "directiveLocation";

@Internal
protected DirectiveDefinition(String name,
Description description,
List<InputValueDefinition> inputValueDefinitions,
List<DirectiveLocation> directiveLocations,
SourceLocation sourceLocation,
List<Comment> comments
) {
super(sourceLocation, comments);
this.name = name;
this.description = description;
this.inputValueDefinitions = inputValueDefinitions;
this.directiveLocations = directiveLocations;
}
Expand All @@ -34,7 +39,7 @@ protected DirectiveDefinition(String name,
* alternative to using a Builder for convenience
*/
public DirectiveDefinition(String name) {
this(name, new ArrayList<>(), new ArrayList<>(), null, new ArrayList<>());
this(name, null, new ArrayList<>(), new ArrayList<>(), null, new ArrayList<>());
}

@Override
Expand All @@ -46,10 +51,6 @@ public Description getDescription() {
return description;
}

public void setDescription(Description description) {
this.description = description;
}

public List<InputValueDefinition> getInputValueDefinitions() {
return new ArrayList<>(inputValueDefinitions);
}
Expand All @@ -66,6 +67,22 @@ public List<Node> getChildren() {
return result;
}

@Override
public ChildrenContainer getNamedChildren() {
return ChildrenContainer.newChildrenContainer()
.children(CHILD_INPUT_VALUE_DEFINITIONS, inputValueDefinitions)
.children(CHILD_DIRECTIVE_LOCATION, directiveLocations)
.build();
}

@Override
public DirectiveDefinition withNewChildren(ChildrenContainer newChildren) {
return transform(builder -> builder
.inputValueDefinitions(newChildren.getList(CHILD_INPUT_VALUE_DEFINITIONS))
.directiveLocations(newChildren.getList(CHILD_DIRECTIVE_LOCATION))
);
}

@Override
public boolean isEqualTo(Node o) {
if (this == o) return true;
Expand All @@ -79,6 +96,7 @@ public boolean isEqualTo(Node o) {
@Override
public DirectiveDefinition deepCopy() {
return new DirectiveDefinition(name,
description,
deepCopy(inputValueDefinitions),
deepCopy(directiveLocations),
getSourceLocation(),
Expand Down Expand Up @@ -170,8 +188,7 @@ public Builder directiveLocation(DirectiveLocation directiveLocation) {
}

public DirectiveDefinition build() {
DirectiveDefinition directiveDefinition = new DirectiveDefinition(name, inputValueDefinitions, directiveLocations, sourceLocation, comments);
directiveDefinition.setDescription(description);
DirectiveDefinition directiveDefinition = new DirectiveDefinition(name, description, inputValueDefinitions, directiveLocations, sourceLocation, comments);
return directiveDefinition;
}
}
Expand Down
Loading