/// <summary> /// Create a new graph based on a filter. Only edges based on "GraphDependsOnEdge" of TEdge /// will be included. /// </summary> /// <typeparam name="TResult">result graph</typeparam> /// <param name="filter">filter to create new graph by</param> /// <param name="factory">factory to create new graph, if null will use reflection to create</param> /// <returns>new graph based on filter</returns> public TResult Create <TResult>(IGraphFilter <TKey> filter, Func <TResult> factory = null) where TResult : GraphMap <TKey, TNode, TEdge> { filter.Verify(nameof(filter)).IsNotNull(); factory.Verify(nameof(factory)).IsNotNull(); // Create new graph TResult newGraph = factory?.Invoke() ?? (TResult)Create(); // Get connected nodes IReadOnlyList <TNode> childrenNodes = GetLinkedNodes(filter); // Add include nodes to the list var focusedNodes = filter.IncludeNodeKeys .Join(Nodes.Values, x => x, x => x.Key, (o, i) => i, KeyCompare) .Concat(childrenNodes) .GroupBy(x => x.Key, KeyCompare) .Select(x => x.First()); // Set nodes focusedNodes.ForEach(x => newGraph.Add(x)); // Get edges for nodes var focusedEdges = Edges.Values .Where(x => newGraph.Nodes.ContainsKey(x.FromNodeKey) && newGraph.Nodes.ContainsKey(x.ToNodeKey)); focusedEdges.ForEach(x => newGraph.Add(x)); return(newGraph); }
/// <summary> /// Get all the connected nodes for a node(s), including all relationships nodes /// </summary> /// <param name="filter">filter to apply</param> /// <returns>list of leaf children nodes</returns> public IReadOnlyList <TNode> GetLinkedNodes(IGraphFilter <TKey> filter) { filter.Verify(nameof(filter)).IsNotNull(); filter.IncludeNodeKeys.Count.Verify(nameof(filter.IncludeNodeKeys)).Assert(x => x > 0, "must be at lease 1"); HashSet <TKey> excludeKeys = null; // If there are exclude node keys, need to get this list first to exclude if (filter.ExcludeNodeKeys?.Count > 0) { var filterKeys = filter.ExcludeNodeKeys .ToHashSet(KeyCompare); IReadOnlyList <TNode> excludeNodes = GetLinkedNodes(filterKeys, filter.IncludeLinkedNodes, null, false, true); excludeKeys = excludeNodes .Select(x => x.Key) .Concat(filter.ExcludeNodeKeys) .ToHashSet(KeyCompare); } var focusedKeys = filter.IncludeNodeKeys .ToHashSet(KeyCompare); IReadOnlyList <TNode> result = GetLinkedNodes(focusedKeys, filter.IncludeLinkedNodes, excludeKeys, true, false); if (filter.IncludeDependentNodes) { IReadOnlyList <TNode> dependentLinks = GetLinkedNodes(focusedKeys, filter.IncludeLinkedNodes, excludeKeys, false, true); result = result .Concat(dependentLinks) .GroupBy(x => x.Key, KeyCompare) .Select(x => x.First()) .ToList(); } return(result); }