/// <summary> /// Add a new child in this vertex /// </summary> /// <param name="child">Child to add</param> public void AddChild(EntityItem <T> child) { if (child != null) { this.children.Add(child); } }
/// <summary> /// Add a new parent in this vertex /// </summary> /// <param name="parent">Parent to add</param> public void AddParent(EntityItem <T> parent) { // if is Root parent is null if (parent != null) { this.parents.Add(parent); } }
private void PopulateEntityItem(EntityItem <T> entityItem, EntityItem <T> parent, EntityItem <T> previous, int index, int indexAtLevel, int levelAtExpression, int level) { entityItem.Index = index; entityItem.Parent = parent; entityItem.Previous = previous; entityItem.IndexAtLevel = indexAtLevel; entityItem.LevelAtExpression = levelAtExpression; entityItem.Level = level; }
/// <summary> /// Method used to create new graph information. Must be used during expression creation. /// </summary> /// <param name="entityItem">EntityItem to generate a new graph info</param> public void SetGraphInfo(EntityItem <T> entityItem) { Vertex <T> vertex = FindVertexFirstOccurrence(entityItem.Entity); if (vertex == null) { VertexContainer <T> .EntityId globalEntity = null; if (entityItem.Entity != null) { globalEntity = VertexContainer <T> .GetEntityId(entityItem.Entity); } if (globalEntity == null) { globalEntity = VertexContainer <T> .Add(entityItem.Entity); } vertex = new Vertex <T>(entityItem.Entity, globalEntity.Id); vertexes.Add(vertex); } vertex.CountVisited++; vertex.AddParent(entityItem.Parent); // Indegrees entityItem.Parent?.Vertex.AddChild(entityItem); // Outdegrees entityItem.Vertex = vertex; entityItem.Edge = new Edge <T>(entityItem.Parent, entityItem, 0); entityItem.Path = new Path <T>(entityItem); edges.Add(entityItem.Edge); //var edge = edges.LastOrDefault(f => f.Source?.AreEquals(vertexParent) == true && f.Target?.AreEquals(vertex) == true); //if (edge == null) //{ // edge = new Edge<T> // { // Source = vertexParent, // Target = vertex // }; // //if (graph.Configuration.AssignEdgeWeightCallback != null) // // graph.Configuration.AssignEdgeWeightCallback(entity, entityParent); // edges.Add(edge); //} // create path item //this.AddInCurrentPath(entityItem);; }
private bool HasAncestorEqualsTo(EntityItem <T> entityItem) { var ancestor = entityItem.Parent; while (ancestor != null) { if (entityItem.Entity?.Equals(ancestor.Entity) == true) { return(true); } ancestor = ancestor.Parent; } return(false); }
/// <summary> /// Creates a path for a given entity /// </summary> /// <param name="entityItem">Entity that will be part of the path</param> public Path(EntityItem <T> entityItem) { this.entityItem = entityItem; var parent = this.entityItem.Parent; if (parent != null) { this.Items = new List <EntityItem <T> >(parent.Path.Items) { entityItem }; } else { this.Items = new EntityItem <T>[] { entityItem }; } }
private bool HasAncestorEqualsTo(EntityItem <T> parentRef, T entity) { bool exists = parentRef != null && parentRef.Entity != null && parentRef.Entity.Equals(entity); if (!exists && parentRef != null) { var ancestor = parentRef.Parent; while (ancestor != null) { if (entity?.Equals(ancestor.Entity) == true) { return(true); } ancestor = ancestor.Parent; } } return(exists); }
/// <summary> /// Creates an instance that represents an expression of graphs that will be mounted automatically /// </summary> /// <param name="root">Represents the root entity that will start every expression.</param> /// <param name="childrenCallback">Function to retriave the children of the current entity</param> /// <param name="deep">Determines whether the search will be deep (TRUE)</param> public Expression(T root, Func <T, IEnumerable <T> > childrenCallback, bool deep = false) { this.Deep = deep; this.getChildrenCallback = (expr, e) => { return(CreateEntityItems(childrenCallback(e.Entity))); }; if (root != null) { var itemRoot = new EntityItem <T>(this) { Entity = root }; if (EnableNonRecursiveAlgorithm) { BuildNonRecursive(itemRoot); } else { Build(itemRoot, getChildrenCallback(this, itemRoot)); } } }
private bool IsEntityDeclared(EntityItem <T> entityItem) { return(this.Any(e => e != entityItem && e.Entity?.Equals(entityItem.Entity) == true)); }
private void BuildNonRecursive(EntityItem <T> root) { var rootEnumerator = new EntityItem <T>[] { root }.Cast <EntityItem <T> >().GetEnumerator(); var iteration = new Iteration <T>() { Enumerator = rootEnumerator, Level = 1, IndexAtLevel = 0 }; var iterations = new List <Iteration <T> > { iteration }; while (true) { while (iteration.Enumerator.MoveNext()) { var current = iteration.Enumerator.Current; var parent = iteration.IterationParent?.Enumerator.Current; var previous = this.LastOrDefault(); if (previous != null) { previous.Next = current; } // Populate EntityItem PopulateEntityItem(current, parent, previous, Count, iteration.IndexAtLevel++, 0, iteration.Level); Add(current); // Create GraphInfo if enabled if (EnableGraphInfo) { this.Graph = this.Graph ?? new Graph <T>(); //current.ParentIterationRef = iteration; this.Graph.SetGraphInfo(current); } bool continueBuild; if (Deep) { continueBuild = !HasAncestorEqualsTo(parent, current.Entity); } else { continueBuild = !IsEntityDeclared(current); } IEnumerable <EntityItem <T> > children = null; if (continueBuild) { children = getChildrenCallback(this, current); continueBuild = children.Any(); } if (continueBuild) { current.LevelAtExpression = iteration.Level; iteration = new Iteration <T>() { Enumerator = children.GetEnumerator(), Level = iteration.Level + 1, EntityRootOfTheIterationForDebug = iteration.Enumerator.Current, IterationParent = iteration, IndexAtLevel = 0 }; iterations.Add(iteration); } else { current.LevelAtExpression = iteration.Level - 1; if (EnableGraphInfo) { this.Graph.EndPath(current.Path); } } } // Remove iteration because is empty iterations.Remove(iteration); if (iterations.Count == 0) { break; } iteration = iterations.LastOrDefault(); } }
private void Build(EntityItem <T> parent, IEnumerable <EntityItem <T> > children, int level = 1) { // only when is root entity if (Count == 0) { PopulateEntityItem(parent, null, null, 0, 0, level, level); Add(parent); // Create GraphInfo if enabled if (EnableGraphInfo) { this.Graph = this.Graph ?? new Graph <T>(); //parent.ParentIterationRef = null; this.Graph.SetGraphInfo(parent); if (!children.Any()) { this.Graph.EndPath(parent.Path); } } } var indexLevel = 0; var parentItem = this.Last(); level++; foreach (var child in children) { var previous = this.Last(); previous.Next = child; PopulateEntityItem(child, parent, previous, Count, indexLevel++, 0, level); Add(child); // Create GraphInfo if enabled if (EnableGraphInfo) { //child.ParentIterationRef = children; this.Graph.SetGraphInfo(child); } // if: IS 'deep' and the entity already declareted in expression, don't build the children of item. // else: if current entity exists in ancestors (to INFINITE LOOP), don't build the children of item. bool continueBuild; if (Deep) { continueBuild = !HasAncestorEqualsTo(child); } else { continueBuild = !IsEntityDeclared(child); } IEnumerable <EntityItem <T> > grandchildren = null; if (continueBuild) { grandchildren = getChildrenCallback(this, child); continueBuild = grandchildren.Any(); } if (continueBuild) { child.LevelAtExpression = level; Build(child, grandchildren, level); } else { child.LevelAtExpression = level - 1; if (EnableGraphInfo) { this.Graph.EndPath(child.Path); } } } }
private IEnumerable <EntityItem <object> > GetChildren(Expression <object> expression, EntityItem <object> parent) { var entityParent = parent?.Entity; if (entityParent == null) { yield break; } // Find the reader, the last "reader" is the most important var instanceReader = Readers .Where(f => f.CanRead(this, entityParent)) .LastOrDefault(); if (instanceReader != null) { foreach (var item in instanceReader.GetChildren(this, expression, entityParent)) { yield return(item); } } }
/// <summary> /// Find a EntityItem in expression that contain a specify EntityItem /// </summary> /// <typeparam name="T">Type of real entity</typeparam> /// <param name="expression">Expression to find</param> /// <param name="item">EntityItem to search</param> /// <returns>Return all EntityItem from the EntityItem</returns> public static IEnumerable <EntityItem <T> > Find <T>(this Expression <T> expression, EntityItem <T> item) { return(expression.Where(f => f == item)); }