/// <summary> /// Dumps one or more matches with a given graph dumper. /// </summary> /// <param name="graph">The graph to be dumped.</param> /// <param name="dumper">The graph dumper to be used.</param> /// <param name="dumpInfo">Specifies how the graph shall be dumped.</param> /// <param name="matches">An IMatches object containing the matches.</param> /// <param name="which">Which match to dump, or AllMatches for dumping all matches /// adding connections between them, or OnlyMatches to dump the matches only</param> public static void DumpMatch(IGraph graph, IDumper dumper, DumpInfo dumpInfo, IMatches matches, DumpMatchSpecial which) { Set <INode> matchedNodes = null; Set <INode> multiMatchedNodes = null; Set <IEdge> matchedEdges = null; Set <IEdge> multiMatchedEdges = null; if (matches != null) { DumpMatchOnly(dumper, dumpInfo, matches, which, ref matchedNodes, ref multiMatchedNodes, ref matchedEdges, ref multiMatchedEdges); } // Dump the graph, but color the matches if any exist DumpContext dc = new DumpContext(dumper, dumpInfo, matchedNodes, multiMatchedNodes, matchedEdges, multiMatchedEdges); foreach (NodeType nodeType in graph.Model.NodeModel.Types) { if (dumpInfo.IsExcludedNodeType(nodeType)) { continue; } dc.Nodes.Add(graph.GetExactNodes(nodeType)); } dc.InitialNodes = new Set <INode>(dc.Nodes); Set <INode> nodes = new Set <INode>(dc.Nodes); DumpGroups(graph, nodes, dc); }
internal static void DumpNodeAndEdges(INode node, DumpContext dc) { GrElemDumpType dumpType = GrElemDumpType.Normal; GrColor color, borderColor, textColor; GrNodeShape shape; if (dc.MatchedNodes != null && dc.MatchedNodes.Contains(node)) { if (dc.MultiMatchedNodes != null && dc.MultiMatchedNodes.Contains(node)) { dumpType = GrElemDumpType.MultiMatched; } else { dumpType = GrElemDumpType.SingleMatched; } color = dc.DumpInfo.GetNodeDumpTypeColor(dumpType); borderColor = dc.DumpInfo.GetNodeDumpTypeBorderColor(dumpType); textColor = dc.DumpInfo.GetNodeDumpTypeTextColor(dumpType); shape = dc.DumpInfo.GetNodeDumpTypeShape(dumpType); } else { color = dc.DumpInfo.GetNodeTypeColor(node.Type); borderColor = dc.DumpInfo.GetNodeTypeBorderColor(node.Type); textColor = dc.DumpInfo.GetNodeTypeTextColor(node.Type); shape = dc.DumpInfo.GetNodeTypeShape(node.Type); } DumpNode(node, textColor, color, borderColor, shape, dc.Dumper, dc.DumpInfo); DumpEdgesFromNode(node, dc); }
private static void DumpEdgesFromNode(INode node, DumpContext dc) { // dumping only outgoing ensures every edge is dumped only once foreach (IEdge edge in node.Outgoing) // TODO: This is probably wrong for group nodes grouped by outgoing edges { if (dc.DumpInfo.IsExcludedEdgeType(edge.Type)) { continue; } if (dc.ExcludedEdges.Contains(edge)) { continue; } if (!dc.InitialNodes.Contains(edge.Target)) { continue; } GrColor color; GrColor textColor; GrLineStyle style; int thickness; if (dc.MatchedEdges != null && dc.MatchedEdges.Contains(edge)) { GrElemDumpType dumpType; if (dc.MultiMatchedEdges != null && dc.MultiMatchedEdges.Contains(edge)) { dumpType = GrElemDumpType.MultiMatched; } else { dumpType = GrElemDumpType.SingleMatched; } color = dc.DumpInfo.GetEdgeDumpTypeColor(dumpType); textColor = dc.DumpInfo.GetEdgeDumpTypeTextColor(dumpType); style = dc.DumpInfo.GetEdgeDumpTypeLineStyle(dumpType); thickness = dc.DumpInfo.GetEdgeDumpTypeThickness(dumpType); } else { color = dc.DumpInfo.GetEdgeTypeColor(edge.Type); textColor = dc.DumpInfo.GetEdgeTypeTextColor(edge.Type); style = dc.DumpInfo.GetEdgeTypeLineStyle(edge.Type); thickness = dc.DumpInfo.GetEdgeTypeThickness(edge.Type); } DumpEdge(edge, textColor, color, style, thickness, dc.Dumper, dc.DumpInfo); } }
private static void DumpGroups(IGraph graph, Set <INode> nodes, DumpContext dc) { // Compute the nesting hierarchy (groups) Dictionary <INode, DumpGroupNode> groupNodes = new Dictionary <INode, DumpGroupNode>(); Dictionary <INode, INode> containedIn = new Dictionary <INode, INode>(); Set <INode> groupedNodes = new Set <INode>(); // (by iterating the group node types in order of dump declaration and removing the iterated nodes from the available nodes, // the conflict resolution priorities of debug enable are taken care of) foreach (GroupNodeType groupNodeType in dc.DumpInfo.GroupNodeTypes) { foreach (INode node in graph.GetCompatibleNodes(groupNodeType.NodeType)) { if (nodes.Contains(node)) { if (!groupNodes.ContainsKey(node)) { groupNodes.Add(node, new DumpGroupNode()); // todo: is the if needed? } nodes.Remove(node); } if (dc.DumpInfo.IsExcludedNodeType(node.Type)) { continue; } foreach (IEdge edge in node.Incoming) { GroupMode grpMode = groupNodeType.GetEdgeGroupMode(edge.Type, edge.Source.Type); if ((grpMode & GroupMode.GroupIncomingNodes) == 0) { continue; } if (!dc.Nodes.Contains(edge.Source)) { continue; } groupNodes[node].groupedNodes.Add(edge.Source); if (!containedIn.ContainsKey(edge.Source)) { containedIn.Add(edge.Source, node); // crashes without if in case of multiple containment due to dump misspecification by user } groupedNodes.Add(edge.Source); if ((grpMode & GroupMode.Hidden) != 0) { dc.ExcludedEdges.Add(edge); } } foreach (IEdge edge in node.Outgoing) { GroupMode grpMode = groupNodeType.GetEdgeGroupMode(edge.Type, edge.Target.Type); if ((grpMode & GroupMode.GroupOutgoingNodes) == 0) { continue; } if (!dc.Nodes.Contains(edge.Target)) { continue; } groupNodes[node].groupedNodes.Add(edge.Target); if (!containedIn.ContainsKey(edge.Target)) { containedIn.Add(edge.Target, node); // crashes without if in case of multiple containment due to dump misspecification by user } groupedNodes.Add(edge.Target); if ((grpMode & GroupMode.Hidden) != 0) { dc.ExcludedEdges.Add(edge); } } } } // Dump the groups (begin at the roots of the group trees) foreach (KeyValuePair <INode, DumpGroupNode> groupNode in groupNodes) { if (!containedIn.ContainsKey(groupNode.Key)) { DumpGroupTree(groupNode.Key, groupNodes, dc); DumpEdgesFromNode(groupNode.Key, dc); } } // Dump the rest, which has not been grouped nodes.Remove(groupedNodes); foreach (INode node in nodes) { DumpNodeAndEdges(node, dc); } }
internal static void DumpGroupTree(INode root, Dictionary <INode, DumpGroupNode> groupNodes, DumpContext dc) { GrElemDumpType dumpType = GrElemDumpType.Normal; if (dc.MatchedNodes != null && dc.MatchedNodes.Contains(root)) { if (dc.MultiMatchedNodes != null && dc.MultiMatchedNodes.Contains(root)) { dumpType = GrElemDumpType.MultiMatched; } else { dumpType = GrElemDumpType.SingleMatched; } } dc.Dumper.StartSubgraph(root, GetElemLabel(root, dc.DumpInfo), DumpAttributes(root), dc.DumpInfo.GetNodeDumpTypeTextColor(dumpType), dc.DumpInfo.GetNodeTypeColor(root.Type)); // TODO: Check coloring... // Dump the elements nested inside this subgraph foreach (INode node in groupNodes[root].groupedNodes) { if (groupNodes.ContainsKey(node)) { DumpGroupTree(node, groupNodes, dc); DumpEdgesFromNode(node, dc); } else { DumpNodeAndEdges(node, dc); } } dc.Dumper.FinishSubgraph(); }
/// <summary> /// Dumps one or more matches with a given graph dumper. /// </summary> /// <param name="graph">The graph to be dumped.</param> /// <param name="dumper">The graph dumper to be used.</param> /// <param name="dumpInfo">Specifies how the graph shall be dumped.</param> /// <param name="matches">An IMatches object containing the matches.</param> /// <param name="which">Which match to dump, or AllMatches for dumping all matches /// adding connections between them, or OnlyMatches to dump the matches only</param> public static void DumpMatch(IGraph graph, IDumper dumper, DumpInfo dumpInfo, IMatches matches, DumpMatchSpecial which) { Set<INode> matchedNodes = null; Set<INode> multiMatchedNodes = null; Set<IEdge> matchedEdges = null; Set<IEdge> multiMatchedEdges = null; if(matches != null) { DumpMatchOnly(dumper, dumpInfo, matches, which, ref matchedNodes, ref multiMatchedNodes, ref matchedEdges, ref multiMatchedEdges); } // Dump the graph, but color the matches if any exist DumpContext dc = new DumpContext(dumper, dumpInfo, matchedNodes, multiMatchedNodes, matchedEdges, multiMatchedEdges); foreach(NodeType nodeType in graph.Model.NodeModel.Types) { if(dumpInfo.IsExcludedNodeType(nodeType)) continue; dc.Nodes.Add(graph.GetExactNodes(nodeType)); } dc.InitialNodes = new Set<INode>(dc.Nodes); Set<INode> nodes = new Set<INode>(dc.Nodes); DumpGroups(graph, nodes, dc); }
private static void DumpGroups(IGraph graph, Set<INode> nodes, DumpContext dc) { // Compute the nesting hierarchy (groups) Dictionary<INode, DumpGroupNode> groupNodes = new Dictionary<INode, DumpGroupNode>(); Dictionary<INode, INode> containedIn = new Dictionary<INode, INode>(); Set<INode> groupedNodes = new Set<INode>(); // (by iterating the group node types in order of dump declaration and removing the iterated nodes from the available nodes, // the conflict resolution priorities of debug enable are taken care of) foreach(GroupNodeType groupNodeType in dc.DumpInfo.GroupNodeTypes) { foreach(INode node in graph.GetCompatibleNodes(groupNodeType.NodeType)) { if(nodes.Contains(node)) { if(!groupNodes.ContainsKey(node)) groupNodes.Add(node, new DumpGroupNode()); // todo: is the if needed? nodes.Remove(node); } if(dc.DumpInfo.IsExcludedNodeType(node.Type)) continue; foreach(IEdge edge in node.Incoming) { GroupMode grpMode = groupNodeType.GetEdgeGroupMode(edge.Type, edge.Source.Type); if((grpMode & GroupMode.GroupIncomingNodes) == 0) continue; if(!dc.Nodes.Contains(edge.Source)) continue; groupNodes[node].groupedNodes.Add(edge.Source); if(!containedIn.ContainsKey(edge.Source)) containedIn.Add(edge.Source, node); // crashes without if in case of multiple containment due to dump misspecification by user groupedNodes.Add(edge.Source); if((grpMode & GroupMode.Hidden) != 0) dc.ExcludedEdges.Add(edge); } foreach(IEdge edge in node.Outgoing) { GroupMode grpMode = groupNodeType.GetEdgeGroupMode(edge.Type, edge.Target.Type); if((grpMode & GroupMode.GroupOutgoingNodes) == 0) continue; if(!dc.Nodes.Contains(edge.Target)) continue; groupNodes[node].groupedNodes.Add(edge.Target); if(!containedIn.ContainsKey(edge.Target)) containedIn.Add(edge.Target, node); // crashes without if in case of multiple containment due to dump misspecification by user groupedNodes.Add(edge.Target); if((grpMode & GroupMode.Hidden) != 0) dc.ExcludedEdges.Add(edge); } } } // Dump the groups (begin at the roots of the group trees) foreach(KeyValuePair<INode, DumpGroupNode> groupNode in groupNodes) { if(!containedIn.ContainsKey(groupNode.Key)) { DumpGroupTree(groupNode.Key, groupNodes, dc); DumpEdgesFromNode(groupNode.Key, dc); } } // Dump the rest, which has not been grouped nodes.Remove(groupedNodes); foreach(INode node in nodes) { DumpNodeAndEdges(node, dc); } }
internal static void DumpGroupTree(INode root, Dictionary<INode, DumpGroupNode> groupNodes, DumpContext dc) { GrElemDumpType dumpType = GrElemDumpType.Normal; if(dc.MatchedNodes != null && dc.MatchedNodes.Contains(root)) { if(dc.MultiMatchedNodes != null && dc.MultiMatchedNodes.Contains(root)) dumpType = GrElemDumpType.MultiMatched; else dumpType = GrElemDumpType.SingleMatched; } dc.Dumper.StartSubgraph(root, GetElemLabel(root, dc.DumpInfo), DumpAttributes(root), dc.DumpInfo.GetNodeDumpTypeTextColor(dumpType), dc.DumpInfo.GetNodeTypeColor(root.Type)); // TODO: Check coloring... // Dump the elements nested inside this subgraph foreach(INode node in groupNodes[root].groupedNodes) { if(groupNodes.ContainsKey(node)) { DumpGroupTree(node, groupNodes, dc); DumpEdgesFromNode(node, dc); } else { DumpNodeAndEdges(node, dc); } } dc.Dumper.FinishSubgraph(); }
internal static void DumpNodeAndEdges(INode node, DumpContext dc) { GrElemDumpType dumpType = GrElemDumpType.Normal; GrColor color, borderColor, textColor; GrNodeShape shape; if(dc.MatchedNodes != null && dc.MatchedNodes.Contains(node)) { if(dc.MultiMatchedNodes != null && dc.MultiMatchedNodes.Contains(node)) dumpType = GrElemDumpType.MultiMatched; else dumpType = GrElemDumpType.SingleMatched; color = dc.DumpInfo.GetNodeDumpTypeColor(dumpType); borderColor = dc.DumpInfo.GetNodeDumpTypeBorderColor(dumpType); textColor = dc.DumpInfo.GetNodeDumpTypeTextColor(dumpType); shape = dc.DumpInfo.GetNodeDumpTypeShape(dumpType); } else { color = dc.DumpInfo.GetNodeTypeColor(node.Type); borderColor = dc.DumpInfo.GetNodeTypeBorderColor(node.Type); textColor = dc.DumpInfo.GetNodeTypeTextColor(node.Type); shape = dc.DumpInfo.GetNodeTypeShape(node.Type); } DumpNode(node, textColor, color, borderColor, shape, dc.Dumper, dc.DumpInfo); DumpEdgesFromNode(node, dc); }
private static void DumpEdgesFromNode(INode node, DumpContext dc) { // dumping only outgoing ensures every edge is dumped only once foreach(IEdge edge in node.Outgoing) // TODO: This is probably wrong for group nodes grouped by outgoing edges { if(dc.DumpInfo.IsExcludedEdgeType(edge.Type)) continue; if(dc.ExcludedEdges.Contains(edge)) continue; if(!dc.InitialNodes.Contains(edge.Target)) continue; GrColor color; GrColor textColor; GrLineStyle style; int thickness; if(dc.MatchedEdges != null && dc.MatchedEdges.Contains(edge)) { GrElemDumpType dumpType; if(dc.MultiMatchedEdges != null && dc.MultiMatchedEdges.Contains(edge)) dumpType = GrElemDumpType.MultiMatched; else dumpType = GrElemDumpType.SingleMatched; color = dc.DumpInfo.GetEdgeDumpTypeColor(dumpType); textColor = dc.DumpInfo.GetEdgeDumpTypeTextColor(dumpType); style = dc.DumpInfo.GetEdgeDumpTypeLineStyle(dumpType); thickness = dc.DumpInfo.GetEdgeDumpTypeThickness(dumpType); } else { color = dc.DumpInfo.GetEdgeTypeColor(edge.Type); textColor = dc.DumpInfo.GetEdgeTypeTextColor(edge.Type); style = dc.DumpInfo.GetEdgeTypeLineStyle(edge.Type); thickness = dc.DumpInfo.GetEdgeTypeThickness(edge.Type); } DumpEdge(edge, textColor, color, style, thickness, dc.Dumper, dc.DumpInfo); } }