graphql.schema.diffing.SchemaGraph Maven / Gradle / Ivy
package graphql.schema.diffing;
import com.google.common.collect.HashBasedTable;
import com.google.common.collect.Iterables;
import com.google.common.collect.LinkedHashMultimap;
import com.google.common.collect.Multimap;
import com.google.common.collect.Table;
import graphql.ExperimentalApi;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.function.Predicate;
import static graphql.Assert.assertTrue;
import static java.lang.String.format;
@ExperimentalApi
public class SchemaGraph {
public static final String SCHEMA = "Schema";
public static final String OBJECT = "Object";
public static final String INTERFACE = "Interface";
public static final String UNION = "Union";
public static final String FIELD = "Field";
public static final String ARGUMENT = "Argument";
public static final String SCALAR = "Scalar";
public static final String ENUM = "Enum";
public static final String ENUM_VALUE = "EnumValue";
public static final String INPUT_OBJECT = "InputObject";
public static final String INPUT_FIELD = "InputField";
public static final String DIRECTIVE = "Directive";
public static final String APPLIED_DIRECTIVE = "AppliedDirective";
public static final String APPLIED_ARGUMENT = "AppliedArgument";
public static final String ISOLATED = "__ISOLATED";
private List vertices = new ArrayList<>();
private List edges = new ArrayList<>();
private Map typesByName = new LinkedHashMap<>();
private Map directivesByName = new LinkedHashMap<>();
private Table edgesByDirection = HashBasedTable.create();
private Table edgesByInverseDirection = HashBasedTable.create();
private Multimap typeToVertices = LinkedHashMultimap.create();
public SchemaGraph() {
}
public SchemaGraph(List vertices, List edges, Table edgeByVertexPair) {
this.vertices = vertices;
this.edges = edges;
this.edgesByDirection = edgeByVertexPair;
}
public void addVertex(Vertex vertex) {
vertices.add(vertex);
typeToVertices.put(vertex.getType(), vertex);
}
public void addVertices(Collection vertices) {
for (Vertex vertex : vertices) {
this.vertices.add(vertex);
typeToVertices.put(vertex.getType(), vertex);
}
}
public Collection getVerticesByType(String type) {
return typeToVertices.get(type);
}
public Multimap getVerticesByType() {
return typeToVertices;
}
public void addEdge(Edge edge) {
edges.add(edge);
edgesByDirection.put(edge.getFrom(), edge.getTo(), edge);
edgesByInverseDirection.put(edge.getTo(), edge.getFrom(), edge);
}
//
// public List getAdjacentEdges(Vertex from) {
// return new ArrayList<>(edgesByDirection.row(from).values());
// }
public Collection getAdjacentEdgesNonCopy(Vertex from) {
return edgesByDirection.row(from).values();
}
public Iterable getAdjacentEdgesAndInverseNonCopy(Vertex fromAndTo) {
Collection edges = edgesByInverseDirection.row(fromAndTo).values();
Collection edgesInverse = edgesByDirection.row(fromAndTo).values();
return Iterables.concat(edges, edgesInverse);
}
public int adjacentEdgesAndInverseCount(Vertex fromAndTo) {
return edgesByInverseDirection.row(fromAndTo).size() + edgesByDirection.row(fromAndTo).size();
}
public List getAdjacentVertices(Vertex from) {
return getAdjacentVertices(from, x -> true);
}
public List getAdjacentVertices(Vertex from, Predicate predicate) {
List result = new ArrayList<>();
for (Edge edge : edgesByDirection.row(from).values()) {
Vertex v = edge.getTo();
if (predicate.test(v)) {
result.add(v);
}
}
return result;
}
public List getAdjacentVerticesInverse(Vertex to) {
return getAdjacentVerticesInverse(to, x -> true);
}
public List getAdjacentVerticesInverse(Vertex to, Predicate predicate) {
List result = new ArrayList<>();
for (Edge edge : edgesByInverseDirection.row(to).values()) {
Vertex v = edge.getFrom();
if (predicate.test(v)) {
result.add(v);
}
}
return result;
}
public List getAdjacentEdges(Vertex from) {
return getAdjacentEdges(from, x -> true);
}
public List getAdjacentEdges(Vertex from, Predicate predicate) {
List result = new ArrayList<>();
for (Edge edge : edgesByDirection.row(from).values()) {
Vertex v = edge.getTo();
if (predicate.test(v)) {
result.add(edge);
}
}
return result;
}
public List getAdjacentEdgesInverseCopied(Vertex to) {
return new ArrayList<>(edgesByInverseDirection.row(to).values());
}
public Collection getAdjacentEdgesInverseNonCopy(Vertex to) {
return edgesByInverseDirection.row(to).values();
}
public List getAdjacentEdgesInverse(Vertex to, Predicate predicate) {
List result = new ArrayList<>();
for (Edge edge : edgesByInverseDirection.row(to).values()) {
Vertex v = edge.getFrom();
if (predicate.test(v)) {
result.add(edge);
}
}
return result;
}
public Edge getSingleAdjacentEdge(Vertex from, Predicate predicate) {
for (Edge edge : edgesByDirection.row(from).values()) {
if (predicate.test(edge)) {
return edge;
}
}
return null;
}
public List getEdges() {
return edges;
}
// null if the edge doesn't exist
public @Nullable Edge getEdge(Vertex from, Vertex to) {
return edgesByDirection.get(from, to);
}
public @Nullable Edge getEdgeOrInverse(Vertex from, Vertex to) {
Edge result = edgesByDirection.get(from, to);
return result != null ? result : edgesByInverseDirection.get(from, to);
}
public List getVertices() {
return vertices;
}
public void setVertices(List vertices) {
this.vertices = vertices;
}
public void addType(String name, Vertex vertex) {
typesByName.put(name, vertex);
}
public void addDirective(String name, Vertex vertex) {
directivesByName.put(name, vertex);
}
public Vertex getType(String name) {
return typesByName.get(name);
}
public Vertex getDirective(String name) {
return directivesByName.get(name);
}
public Optional findTargetVertex(Vertex from, Predicate vertexPredicate) {
return edgesByDirection.row(from).values().stream().map(Edge::getTo).filter(vertexPredicate).findFirst();
}
public int size() {
return vertices.size();
}
public List addIsolatedVertices(int count, String debugPrefix) {
List result = new ArrayList<>();
for (int i = 0; i < count; i++) {
Vertex isolatedVertex = Vertex.newIsolatedNode(debugPrefix + i);
vertices.add(isolatedVertex);
result.add(isolatedVertex);
}
return result;
}
public Vertex getFieldOrDirectiveForArgument(Vertex argument) {
List adjacentVertices = getAdjacentVerticesInverse(argument);
assertTrue(adjacentVertices.size() == 1, "No field or directive found for %s", argument);
return adjacentVertices.get(0);
}
public Vertex getFieldsContainerForField(Vertex field) {
List adjacentVertices = getAdjacentVerticesInverse(field);
assertTrue(adjacentVertices.size() == 1, "No fields container found for %s", field);
return adjacentVertices.get(0);
}
public Vertex getInputObjectForInputField(Vertex inputField) {
List adjacentVertices = this.getAdjacentVerticesInverse(inputField);
assertTrue(adjacentVertices.size() == 1, "No input object found for %s", inputField);
return adjacentVertices.get(0);
}
public Vertex getAppliedDirectiveForAppliedArgument(Vertex appliedArgument) {
List adjacentVertices = this.getAdjacentVerticesInverse(appliedArgument);
assertTrue(adjacentVertices.size() == 1, "No applied directive found for %s", appliedArgument);
return adjacentVertices.get(0);
}
public Vertex getAppliedDirectiveContainerForAppliedDirective(Vertex appliedDirective) {
List adjacentVertices = this.getAdjacentVerticesInverse(appliedDirective);
assertTrue(adjacentVertices.size() == 1, "No applied directive container found for %s", appliedDirective);
return adjacentVertices.get(0);
}
/**
* Gets the one inverse adjacent edge to the input and gets the other vertex.
*
* @param input the vertex input
* @return a vertex
*/
public Vertex getSingleAdjacentInverseVertex(Vertex input) {
Collection adjacentVertices = this.getAdjacentEdgesInverseNonCopy(input);
assertTrue(adjacentVertices.size() == 1, "No parent found for %s", input);
return adjacentVertices.iterator().next().getFrom();
}
public int getAppliedDirectiveIndex(Vertex appliedDirective) {
List adjacentEdges = this.getAdjacentEdgesInverseCopied(appliedDirective);
assertTrue(adjacentEdges.size() == 1, "No applied directive container found for %s", appliedDirective);
return Integer.parseInt(adjacentEdges.get(0).getLabel());
}
public Vertex getEnumForEnumValue(Vertex enumValue) {
List adjacentVertices = this.getAdjacentVerticesInverse(enumValue);
assertTrue(adjacentVertices.size() == 1, "No enum found for %s", enumValue);
return adjacentVertices.get(0);
}
public List getAllAdjacentEdges(List fromList, Vertex to) {
List result = new ArrayList<>();
for (Vertex from : fromList) {
Edge edge = getEdge(from, to);
if (edge == null) {
continue;
}
result.add(edge);
}
return result;
}
public boolean containsEdge(Vertex from, Vertex to) {
return this.edges.stream().anyMatch(edge -> edge.getFrom().equals(from) && edge.getTo().equals(to));
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy