internal static IEnumerable <SchemaPath> ExpandPropertyToEdgeList(QueueItem expandItem, GraphSchema graph) { var traverse = new TraverseExpandQueueItem(graph, ignored => { }, ignored => { }); var result = traverse.Traverse(graph.VertexContainingType(typeof(TRootQueryType)), expandItem).ToList(); return(result); }
internal IEnumerable <SchemaPath> ExpandPropertyToEdgeList(QueueItem expandItem) { var traverse = new TraverseExpandQueueItem(Graph, _SelectAdd.AddToClause, _FilterAdd.AddToClause); var result = traverse.Traverse(Graph.VertexContainingType(typeof(TRootQueryType)), expandItem).ToList(); return(result); }
IEnumerable <SchemaPath> TraverseChildren(SchemaVertex from, QueueItem tree, IEnumerable <SchemaEdge> currentPath) { foreach (var path in tree.Children.SelectMany(x => Traverse(from, x.Item2, currentPath))) { yield return(path); } }
IEnumerable <SchemaPath> ExpandProperty(SchemaVertex from, QueueItem tree, IEnumerable <SchemaEdge> currentPath) { // get the edge in the graph where it is connected from the same type as the from vertex, and the property name matches. var edge = graph.Edges.FirstOrDefault(e => e.From.Value.TypeId == from.Value.TypeId && e.Value.Name == tree.Root.Value.Text); if (edge == null) { yield break; } if (tree.IsDirectPropertyAccess()) { var childEdgePath = new List <SchemaEdge>(currentPath); childEdgePath.Add(edge); yield return(new SchemaPath(childEdgePath)); } var cPath = new List <SchemaEdge>(currentPath); cPath.Add(edge); yield return(new SchemaPath(cPath)); foreach (var child in tree.Children) { foreach (var path in Traverse(edge.To, child.Item2, cPath).Distinct()) { yield return(path); } } }
public IEnumerable <SchemaPath> Traverse(SchemaVertex from, QueueItem tree, IEnumerable <SchemaEdge> currentPath = null) { if (currentPath == null) { currentPath = new List <SchemaEdge>(); } if (tree.Representation == TextRepresentation.ExpandProperty) { return(ExpandProperty(from, tree, currentPath)); } bool IsPassThrough(string rep) { return(rep == TextRepresentation.ListOfExpands || rep == TextRepresentation.ListOfClause || rep == TextRepresentation.ExpandExpression); } if (IsPassThrough(tree.Representation)) { return(TraverseChildren(from, tree, currentPath).Distinct()); } if (tree.Representation == TextRepresentation.SelectExpression) { SelectAddFunc(AppendPathToQueueItem(currentPath, tree.Children.First().Item2)); return(new List <SchemaPath>()); } if (tree.Representation == TextRepresentation.FilterExpression) { FilterAddFunc(AppendPathToQueueItem(currentPath, tree.Children.First().Item2)); return(new List <SchemaPath>()); } throw new NotImplementedException("Unknown tree type: " + tree.Representation); }
public void AddToClause(QueueItem clause) { if (clause is null || (clause.Representation != TextRepresentation.ListOfExpands && clause.Representation != TextRepresentation.ExpandProperty)) { throw new ArgumentException("invalid query"); } if (clause.Representation == TextRepresentation.ListOfExpands) { foreach (var expand in clause.Children.Select(x => x.Item2)) { AddToClause(expand); } return; } ResultList.Add(PathAndPropertyFromExpandItem(clause, Graph, RootQueryType)); }
public static PathToProperty PathAndPropertyFromExpandItem(QueueItem addition, GraphSchema graph, Type RootQueryType) { // add to path list. var edges = new List <Edge>(); Property propertyName = null; void traverseExpandTree(Vertex from, QueueItem parsedSelection) { if (parsedSelection?.Root?.Value.Representation != TextRepresentation.ExpandProperty) { return; } if (!parsedSelection.Children.Any()) { propertyName = from.Value.Properties.Single(x => x.Name == parsedSelection.Root.Value.Text); return; } // get the edge in the graph where it is connected from the same type as the from vertex, and the property name matches. var edge = graph.Edges.FirstOrDefault(e => e.From.Value.TypeId == from.Value.TypeId && e.Value.Name == parsedSelection.Root.Value.Text); if (edge is null) { return; } edges.Add(edge); foreach (var child in parsedSelection.Children) { traverseExpandTree(edge.To, child.Item2); } } var rootQueryVertex = graph.VertexContainingType(RootQueryType); traverseExpandTree(rootQueryVertex, addition); return(new PathToProperty(edges, propertyName)); }
// note: this mehtod is immutable - it does not change the current state of the "source" argument. private QueueItem AppendPathToQueueItem(IEnumerable <SchemaEdge> prependEdges, QueueItem source) { if (!prependEdges.Any()) { return(source); } if (source.Representation == TextRepresentation.ExpandProperty) { var text = prependEdges.First().Value.Name; var root = new ParserVertex(new TInfo(text, TextRepresentation.ExpandProperty)); var child = AppendPathToQueueItem(prependEdges.Skip(1), source); return(new QueueItem(root, new[] { ITuple.Create(new ParserEdge(root, child.Root), child) })); } var children = source.Children.Select(x => AppendPathToQueueItem(prependEdges, x.Item2)); var childrenWithEdges = children.Select(child => ITuple.Create(new ParserEdge(source.Root, child.Root), child)); return(new QueueItem(source.Root, childrenWithEdges)); }