using System.Collections.Generic; using QuickGraph; using System.Linq; using System.Diagnostics.Contracts; namespace GraphSharp { public class CompoundGraph : BidirectionalGraph, IMutableCompoundGraph where TEdge : IEdge { public CompoundGraph() { } public CompoundGraph(bool allowParallelEdges) : base(allowParallelEdges) { } public CompoundGraph(bool allowParallelEdges, int vertexCapacity) : base(allowParallelEdges, vertexCapacity) { } public CompoundGraph(IBidirectionalGraph graph) : base(graph.AllowParallelEdges, graph.VertexCount) { //copy the vertices AddVertexRange(graph.Vertices); //copy the edges AddEdgeRange(graph.Edges); } public CompoundGraph(ICompoundGraph graph) : base(graph.AllowParallelEdges, graph.VertexCount) { //copy the vertices AddVertexRange(graph.Vertices); //copy the containment information foreach (var vertex in graph.Vertices) { if (!graph.IsChildVertex(vertex)) continue; var parent = graph.GetParent(vertex); AddChildVertex(parent, vertex); } //copy the edges AddEdgeRange(graph.Edges); } private readonly IDictionary _parentRegistry = new Dictionary(); private readonly IDictionary> _childrenRegistry = new Dictionary>(); public IEnumerable CompoundVertices { get { return _childrenRegistry.Keys; } } public IEnumerable SimpleVertices { get { return Vertices.Where(v => !_childrenRegistry.ContainsKey(v)); } } private IList GetChildrenList(TVertex vertex, bool createIfNotExists) { IList childrenList; if (_childrenRegistry.TryGetValue(vertex, out childrenList) || !createIfNotExists) return childrenList; childrenList = new List(); _childrenRegistry[vertex] = childrenList; return childrenList; } #region ICompoundGraph Members public bool AddChildVertex(TVertex parent, TVertex child) { if (!ContainsVertex(child)) AddVertex(child); _parentRegistry[child] = parent; GetChildrenList(parent, true).Add(child); return true; } public int AddChildVertexRange(TVertex parent, IEnumerable children) { int ret = AddVertexRange(children); IList childrenList = GetChildrenList(parent, true); foreach (var v in children) { _parentRegistry[v] = parent; childrenList.Add(v); } return ret; } public TVertex GetParent(TVertex vertex) { TVertex parent; if (_parentRegistry.TryGetValue(vertex, out parent)) return parent; return default(TVertex); } public bool IsChildVertex(TVertex vertex) { return _parentRegistry.ContainsKey(vertex); } public IEnumerable GetChildrenVertices(TVertex vertex) { return GetChildrenList(vertex, false); } public int GetChildrenCount(TVertex vertex) { IList childrenList = GetChildrenList(vertex, false); if (childrenList == null) return 0; return childrenList.Count; } public bool IsCompoundVertex(TVertex vertex) { return GetChildrenList(vertex, false) != null; } #endregion public override bool RemoveVertex(TVertex v) { bool removed = base.RemoveVertex(v); if (removed) { _parentRegistry.Remove(v); _childrenRegistry.Remove(v); } return removed; } } }