/******************************************************************************* * Copyright (c) 2009, 2010 SAP AG and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * SAP AG - initial API and implementation ******************************************************************************/ package org.eclipse.ocl.examples.impactanalyzer.debug; import java.awt.Color; import java.util.ArrayList; import java.util.HashMap; import java.util.Map; import org.eclipse.ocl.examples.impactanalyzer.instanceScope.AbstractNavigationStep; import org.eclipse.ocl.examples.impactanalyzer.instanceScope.NavigationStep; import y.base.Edge; import y.base.Graph; import y.base.Node; import y.base.NodeList; import y.base.NodeMap; import y.view.Arrow; import y.view.Graph2D; import y.view.LineType; import y.view.NodeLabel; import y.view.NodeRealizer; import y.view.hierarchy.HierarchyManager; /** * The GraphContext is a context within the process of building the graph structure. Therefore it holds the graph object of * the yFiles API which is needed to create nodes and edges of the graph. * By traversing the NavigationStep object tree the GraphContext is e.g. used to create new nodes only if the * NavigationStep was not visited before. Therefore the context holds a list of visited steps and the according nodes. * * @author Manuel Holzleitner (d049667) */ public class GraphContext { private Graph graph = new Graph2D(); private Map<NavigationStep, Node> visitedNodes = new HashMap<NavigationStep, Node>(); private Map<Node, NavigationStep> reverseVisitedNodes = new HashMap<Node, NavigationStep>(); private Map<NavigationStep, Node> visitedEndNodes = new HashMap<NavigationStep, Node>(); private Map<Node, NavigationStep> reverseVisitedEndNodes = new HashMap<Node, NavigationStep>(); private ArrayList<Node> groupNodeLog = new ArrayList<Node>(); private NodeMap nodeDescription = graph.createNodeMap(); private HierarchyManager hierarchyManager = new HierarchyManager(graph); private boolean nestingActive = true; public void setHierarchyManager(HierarchyManager hierachyManager) { this.hierarchyManager = hierachyManager; } public HierarchyManager getHierarchyManager() { return hierarchyManager; } public void setVisitedNodes(Map<NavigationStep, Node> vistedNodes) { this.visitedNodes = vistedNodes; } public Map<NavigationStep, Node> getVistedNodes() { return visitedNodes; } public void setGraph(Graph graph) { this.graph = graph; } public Graph getGraph() { return graph; } public Graph2D getGraph2D() { return (Graph2D)graph; } public Map<Node, NavigationStep> getReverseVisitedNodes() { return reverseVisitedNodes; } public void setReverseVisitedNodes(Map<Node, NavigationStep> reverseVisitedNodes) { this.reverseVisitedNodes = reverseVisitedNodes; } public boolean stepIsVisited(NavigationStep step) { return visitedNodes.containsKey(step); } public Node createGroupNode(NavigationStep navStep, Node parent, NodeList parentNodeList) { Node newNode = hierarchyManager.createGroupNode(parent); this.groupNodeLog.add(newNode); return newNode; } public Node createRootNode() { Node node = hierarchyManager.createGroupNode(graph); groupNodeLog.add(node); return node; } public Node createNode(NavigationStep navStep) { Node newNode; if (!visitedNodes.containsKey(navStep)) { newNode = graph.createNode(); visitedNodes.put(navStep, newNode); reverseVisitedNodes.put(newNode, navStep); if (visitedNodes.size() != reverseVisitedNodes.size()) { throw new RuntimeException( "Invariant broken: A node must not have multiple steps and a step must not have multiple nodes."); } setIdToNode(newNode, ((AbstractNavigationStep)navStep).getId()); setDebugInfoToNode(newNode, navStep.getDebugInfo().toString()); refreshNodeStyle(newNode); } else { newNode = visitedNodes.get(navStep); } return newNode; } /** * Adjusts width of node according to label text width * * @param node */ public void refreshNodeStyle(Node node) { ((Graph2D) graph).getRealizer(node).setWidth(((Graph2D) graph).getRealizer(node).getLabel().getWidth() + 20); } public void setIdToNode(Node node, int id){ NodeLabel idLabel = ((Graph2D)graph).getRealizer(node).createNodeLabel(); idLabel.setModel(NodeLabel.EIGHT_POS); idLabel.setPosition(NodeLabel.W); idLabel.setText(String.valueOf(id)); idLabel.setFontSize(10); ((Graph2D)graph).getRealizer(node).addLabel(idLabel); } private void setDebugInfoToNode(Node newNode, String debugInfo) { getNodeDescription().set(newNode, debugInfo); } public Node createEndNode(NavigationStep navStep) { Node newNode; if (!getVisitedEndNodes().containsKey(navStep)) { newNode = graph.createNode(); getVisitedEndNodes().put(navStep, newNode); getReverseVisitedEndNodes().put(newNode, navStep); if (getVisitedEndNodes().size() != getReverseVisitedEndNodes().size()) { throw new RuntimeException( "Invariant broken: A node must not have multiple steps and a step must not have multiple nodes."); } setIdToNode(newNode, ((AbstractNavigationStep)navStep).getId()); refreshNodeStyle(newNode); } else { newNode = getVisitedEndNodes().get(navStep); } return newNode; } public void addSideLabelToNode(Node node, String text){ NodeLabel nodeLabel = ((Graph2D)graph).getRealizer(node).createNodeLabel(); nodeLabel.setModel(NodeLabel.EIGHT_POS); nodeLabel.setPosition(NodeLabel.W); nodeLabel.setText(text); ((Graph2D)graph).getRealizer(node).addLabel(nodeLabel); } public void changeNodeStyle(Node node, NodeRealizer nodeRealizer){ NodeRealizer oldRealizer = ((Graph2D)graph).getRealizer(node); for(int i=0; i<oldRealizer.labelCount(); i++){ nodeRealizer.addLabel(oldRealizer.getLabel(i)); } ((Graph2D)graph).setRealizer(node, nodeRealizer); } public void setLabelTextForNode(String steptype, String text, Node node) { if(steptype.equals("")){ ((Graph2D) graph).getRealizer(node).setLabelText(text); }else{ ((Graph2D) graph).getRealizer(node).setLabelText("<html><b><"+steptype+"></b><br><center><font size=\"4\">" + text + "</font></center></html>"); } refreshNodeStyle(node); } public void setLabelTextForGroupNode(String text, Node node) { ((Graph2D) graph).getRealizer(node).setLabelText(text); } public Edge connectNodes(Node source, Node target) { for (Edge e : graph.getEdgeArray()) { if (e.target().equals(target) && e.source().equals(source)) { return e; } } return createEdge(source, target); } public void applyDashedEdge(Edge edge) { ((Graph2D) graph).getRealizer(edge).setLineType(LineType.DASHED_1); } public void applyEmptyNodeColor(Node node) { ((Graph2D) graph).getRealizer(node).setFillColor(Color.LIGHT_GRAY); } private Edge createEdge(Node source, Node target) { Edge edge = graph.createEdge(source, target); ((Graph2D) graph).getRealizer(edge).setTargetArrow(Arrow.STANDARD); return edge; } public void setNestingActive(boolean nestingActive) { this.nestingActive = nestingActive; } public boolean isNestingActive() { return nestingActive; } public void setVisitedEndNodes(Map<NavigationStep, Node> visitedEndNodes) { this.visitedEndNodes = visitedEndNodes; } public Map<NavigationStep, Node> getVisitedEndNodes() { return visitedEndNodes; } public void setReverseVisitedEndNodes(Map<Node, NavigationStep> reverseVisitedEndNodes) { this.reverseVisitedEndNodes = reverseVisitedEndNodes; } public Map<Node, NavigationStep> getReverseVisitedEndNodes() { return reverseVisitedEndNodes; } public NodeMap getNodeDescription() { return nodeDescription; } public ArrayList<Node> getGroupNodeLog() { return groupNodeLog; } }