package agg.parser; import java.util.Hashtable; import java.util.Enumeration; import java.util.Iterator; import java.util.List; import java.util.Vector; import agg.parser.ExcludePairContainer; import agg.xt_basis.BaseFactory; import agg.xt_basis.GraGra; import agg.xt_basis.Graph; import agg.xt_basis.OrdinaryMorphism; import agg.xt_basis.TypeSet; import agg.xt_basis.Rule; import agg.xt_basis.Type; import agg.xt_basis.TypeException; import agg.xt_basis.Node; import agg.xt_basis.Arc; import agg.xt_basis.agt.RuleScheme; import agg.attribute.facade.impl.DefaultInformationFacade; import agg.attribute.facade.InformationFacade; import agg.attribute.impl.ValueTuple; import agg.attribute.AttrType; import agg.attribute.handler.AttrHandler; import agg.util.Pair; public class ConflictsDependenciesBasisGraph { ExcludePairContainer conflictCont; ExcludePairContainer dependCont; GraGra grammar; Hashtable<Rule, Hashtable<Rule, Pair<Boolean, Vector<Pair<Pair<OrdinaryMorphism, OrdinaryMorphism>, Pair<OrdinaryMorphism, OrdinaryMorphism>>>>>> conflicts; Hashtable<Rule, Hashtable<Rule, Pair<Boolean, Vector<Pair<Pair<OrdinaryMorphism, OrdinaryMorphism>, Pair<OrdinaryMorphism, OrdinaryMorphism>>>>>> dependencies; Graph conflictGraph, dependGraph, combiGraph; Hashtable<Node, Rule> node2rule; public ConflictsDependenciesBasisGraph( ExcludePairContainer conflictsContainer, ExcludePairContainer dependenciesContainer) { this.conflictCont = conflictsContainer; this.dependCont = dependenciesContainer; initTables(); createGraphs(); if (this.combiGraph != null) optimizeLayout(this.combiGraph); else if (this.conflictGraph != null) optimizeLayout(this.conflictGraph); else if (this.dependGraph != null) optimizeLayout(this.dependGraph); } public ConflictsDependenciesBasisGraph(ExcludePairContainer conflictsContainer, ExcludePairContainer dependenciesContainer, Graph combiCPAgraph) { this.conflictCont = conflictsContainer; this.dependCont = dependenciesContainer; initTables(); if (combiCPAgraph != null && !combiCPAgraph.isEmpty()) { this.combiGraph = combiCPAgraph; createGraphs(this.combiGraph); } else createGraphs(); if (this.combiGraph != null) optimizeLayout(this.combiGraph); else if (this.conflictGraph != null) optimizeLayout(this.conflictGraph); else if (this.dependGraph != null) optimizeLayout(this.dependGraph); } /** * Returns conflict graph. * The nodes represent the rules and the edges - conflict relations. */ public Graph getConflictsGraph() { return this.conflictGraph; } /** * Returns dependency graph. * The nodes represent the rules and the edges - dependency relations. */ public Graph getDependenciesGraph() { return this.dependGraph; } /** * Returns conflict-dependency graph. * The nodes represent the rules and the edges - conflict and dependency relations. */ public Graph getConflictsDependenciesGraph() { return this.combiGraph; } /** * Replace the nodes representing a rule scheme by only one node. * The name of the new node is the name of the rule scheme. * The edges of replaced nodes will be redirected to/from the new node. * This method should be used before <code>get...Graph()</code> methods. * * @param g * a graph which combines conflict and dependency between rule nodes */ @SuppressWarnings("unused") private void collapseRuleSchemes(Graph g) { if (g != null) { collapseRuleSchemes(g, "c"); collapseRuleSchemes(g, "d"); } } /** * Replace the nodes representing a rule scheme by only one node. * The name of the new node is the name of the rule scheme. * The edges of replaced nodes will be redirected to/from the new node. * This method should be used before <code>get...Graph()</code> methods. * * @param g * a graph which contains conflict or dependency edges between rule nodes * @param tname * the name of the arc type */ public void collapseRuleSchemes(Graph g, String tname) { if (this.node2rule == null) return; Hashtable<RuleScheme, List<Node>> map = new Hashtable<RuleScheme, List<Node>>(); Iterator<Node> iter = g.getNodesSet().iterator(); while (iter.hasNext()) { Node n = iter.next(); Rule r = this.node2rule.get(n); if (r != null && r.getRuleScheme() != null) { List<Node> l = map.get(r.getRuleScheme()); if (l == null) { l = new Vector<Node>(5); map.put(r.getRuleScheme(), l); } if (!l.contains(n)) l.add(n); } } Type nt = g.getTypeSet().getTypeByName("RuleScheme"); if (nt == null) { nt = g.getTypeSet().createNodeType(true); nt.setStringRepr("RuleScheme"); nt.setAdditionalRepr("[NODE]"); nt.getAttrType().addMember( DefaultInformationFacade.self().getJavaHandler(), "String", "name"); } List<Arc> ll = new Vector<Arc>(); Iterator<RuleScheme> rsIter = map.keySet().iterator(); while (rsIter.hasNext()) { RuleScheme rs = rsIter.next(); List<Node> l = map.get(rs); try { Node rsn = g.createNode(nt); ValueTuple vt = (ValueTuple) rsn.getAttribute(); vt.getValueMemberAt("name").setExprAsObject(rs.getName()); for (Node n : l) { Iterator<Arc> arcsIn = n.getIncomingArcsSet().iterator(); while (arcsIn.hasNext()) { Arc a = arcsIn.next(); if (!ll.contains(a)) ll.add(a); if (a.getType().getName().equals(tname)) { if (!a.isDirected()) { if (g.getArcs(a.getSource(), rsn) == null) g.createArc(a.getType(), (Node)a.getSource(), rsn); if (g.getArcs(rsn, a.getSource()) == null) g.createArc(a.getType(), rsn, (Node)a.getSource()); } else if (a.isVisible() && a.isDirected()) { if (g.getArcs(a.getSource(), rsn) == null) g.createArc(a.getType(), (Node)a.getSource(), rsn); } } } Iterator<Arc> arcsOut = n.getOutgoingArcsSet().iterator(); while (arcsOut.hasNext()) { Arc a = arcsOut.next(); if (a.isLoop()) { continue; } if (!ll.contains(a)) ll.add(a); if (a.getType().getName().equals(tname)) { if (!a.isDirected()) { if (g.getArcs(rsn, a.getTarget()) == null) g.createArc(a.getType(), rsn, (Node)a.getTarget()); if (g.getArcs(a.getTarget(), rsn) == null) g.createArc(a.getType(), (Node)a.getTarget(), rsn); } else if (a.isVisible() && a.isDirected()) { if (g.getArcs(rsn, a.getTarget()) == null) g.createArc(a.getType(), rsn, (Node)a.getTarget()); } } } } } catch (TypeException e) {} } for (Arc a : ll) { try { g.destroyArc(a, false); } catch (TypeException e) {} } ll.clear(); List<Arc> la = new Vector<Arc>(); List<Arc> arcs = new Vector<Arc>(g.getArcsSet()); for (Arc a : arcs) { if (!a.getType().getName().equals(tname)) { if (!la.contains(a)) la.add(a); } else { if (!a.isVisible()) { if (!la.contains(a)) la.add(a); } if (!a.isDirected()) { try { g.createArc(a.getType(), (Node)a.getSource(), (Node)a.getTarget()); g.createArc(a.getType(), (Node)a.getTarget(), (Node)a.getSource()); if (!la.contains(a)) la.add(a); } catch (TypeException e) {} } } } for (Arc a : la) { try { g.destroyArc(a, false); } catch (TypeException e) {} } la.clear(); Iterator<List<Node>> ln = map.values().iterator(); while (ln.hasNext()) { List<Node> l = ln.next(); for (Node n : l) { try { g.destroyNode(n, false); } catch (TypeException e) {} } } } private void initTables() { if (this.conflictCont != null) { this.conflicts = this.conflictCont.getExcludeContainer(); this.grammar = this.conflictCont.getGrammar(); } if (this.dependCont != null) { this.dependencies = this.dependCont.getExcludeContainer(); if (this.grammar == null) this.grammar = this.dependCont.getGrammar(); } } private void createGraphs() { if ((this.conflicts == null) && (this.dependencies == null)) return; Hashtable<String, Node> common = new Hashtable<String, Node>(); Hashtable<String, Node> local = new Hashtable<String, Node>(); node2rule = new Hashtable<Node, Rule>(); TypeSet types = null; if (this.conflicts != null) { this.conflictGraph = BaseFactory.theFactory().createGraph(); this.conflictGraph.setName("Conflicts of Rules"); types = this.conflictGraph.getTypeSet(); } if (this.dependencies != null) { if (types != null) this.dependGraph = BaseFactory.theFactory().createGraph(types); else { this.dependGraph = BaseFactory.theFactory().createGraph(); types = this.dependGraph.getTypeSet(); } this.dependGraph.setName("Dependencies of Rules"); } if (this.conflictGraph != null && this.dependGraph != null) { this.combiGraph = BaseFactory.theFactory().createGraph(types); this.combiGraph.setName("CPA Graph: Conflicts (red) - Dependencies (blue) of Rules"); } if (types != null) { Type nodeType = types.createNodeType(true); Type arcTypeConflict = types.createArcType(false); Type arcTypeDepend = types.createArcType(false); nodeType.setStringRepr("Rule"); nodeType.setAdditionalRepr("[NODE]"); arcTypeConflict.setStringRepr("c"); arcTypeConflict .setAdditionalRepr(":SOLID_LINE:java.awt.Color[r=255,g=0,b=0]::[EDGE]:"); arcTypeDepend.setStringRepr("d"); arcTypeDepend .setAdditionalRepr(":DOT_LINE:java.awt.Color[r=0,g=0,b=255]::[EDGE]:"); InformationFacade info = DefaultInformationFacade.self(); AttrHandler javaHandler = info.getJavaHandler(); AttrType attrType = nodeType.getAttrType(); attrType.addMember(javaHandler, "String", "name"); if (this.conflicts != null) { for (Enumeration<Rule> keys1 = this.conflicts.keys(); keys1.hasMoreElements();) { Rule r1 = keys1.nextElement(); if (r1.isEnabled()) { Hashtable<Rule, Pair<Boolean, Vector<Pair<Pair<OrdinaryMorphism, OrdinaryMorphism>, Pair<OrdinaryMorphism, OrdinaryMorphism>>>>> table = this.conflicts.get(r1); for (Enumeration<Rule> keys2 = table.keys(); keys2 .hasMoreElements();) { Rule r2 = keys2.nextElement(); if (r2.isEnabled()) { ExcludePairContainer.Entry entry = this.conflictCont.getEntry(r1, r2); Node nr1 = local.get(r1.getQualifiedName()); if (nr1 == null) { nr1 = createNode(this.conflictGraph, nodeType, r1); local.put(r1.getQualifiedName(), nr1); node2rule.put(nr1, r1); if (r1 == r2) nr1.setVisible(entry.isRuleVisible()); } if (this.combiGraph != null) { Node nr = common.get(r1.getQualifiedName()); if (nr == null) { nr = createNode(this.combiGraph, nodeType, r1); common.put(r1.getQualifiedName(), nr); node2rule.put(nr, r1); if (r1 == r2) nr.setVisible(entry.isRuleVisible()); } } Node nr2 = local.get(r2.getQualifiedName()); if (nr2 == null) { nr2 = createNode(this.conflictGraph, nodeType, r2); local.put(r2.getQualifiedName(), nr2); node2rule.put(nr2, r2); } if (this.combiGraph != null) { Node nr = common.get(r2.getQualifiedName()); if (nr == null) { nr = createNode(this.combiGraph, nodeType, r2); common.put(r2.getQualifiedName(), nr); node2rule.put(nr, r2); } } Pair<Boolean, Vector<Pair<Pair<OrdinaryMorphism, OrdinaryMorphism>, Pair<OrdinaryMorphism, OrdinaryMorphism>>>> p = table.get(r2); boolean rel = p.first.booleanValue(); if (rel) { // create edge if rule relation createEdge(this.conflictGraph, arcTypeConflict, nr1, nr2); if (this.combiGraph != null) { createEdge(this.combiGraph, arcTypeConflict, common.get(r1.getQualifiedName()), common.get(r2.getQualifiedName())); } } } } } } } if (this.dependencies != null) { local.clear(); for (Enumeration<Rule> keys1 = this.dependencies.keys(); keys1 .hasMoreElements();) { Rule r1 = keys1.nextElement(); if (r1.isEnabled()) { Hashtable<Rule, Pair<Boolean, Vector<Pair<Pair<OrdinaryMorphism, OrdinaryMorphism>, Pair<OrdinaryMorphism, OrdinaryMorphism>>>>> table = this.dependencies.get(r1); for (Enumeration<Rule> keys2 = table.keys(); keys2 .hasMoreElements();) { Rule r2 = keys2.nextElement(); if (r2.isEnabled()) { ExcludePairContainer.Entry entry = this.dependCont .getEntry(r1, r2); Node nr1 = local.get(r1.getQualifiedName()); if (nr1 == null) { nr1 = createNode(this.dependGraph, nodeType, r1); local.put(r1.getQualifiedName(), nr1); node2rule.put(nr1, r1); if (r1 == r2) nr1.setVisible(entry.isRuleVisible()); } if (this.combiGraph != null) { Node nr = common.get(r1.getQualifiedName()); if (nr == null) { nr = createNode(this.combiGraph, nodeType, r1); common.put(r1.getQualifiedName(), nr); node2rule.put(nr, r1); if (r1 == r2) nr.setVisible(entry.isRuleVisible()); } } Node nr2 = local.get(r2.getQualifiedName()); if (nr2 == null) { nr2 = createNode(this.dependGraph, nodeType, r2); local.put(r2.getQualifiedName(), nr2); node2rule.put(nr2, r2); } if (this.combiGraph != null) { Node nr = common.get(r2.getQualifiedName()); if (nr == null) { nr = createNode(this.combiGraph, nodeType, r2); common.put(r2.getQualifiedName(), nr); node2rule.put(nr, r2); } } Pair<Boolean, Vector<Pair<Pair<OrdinaryMorphism, OrdinaryMorphism>, Pair<OrdinaryMorphism, OrdinaryMorphism>>>> p = table.get(r2); boolean rel = p.first.booleanValue(); if (rel) { createEdge(this.dependGraph, arcTypeDepend, nr1, nr2); if (this.combiGraph != null) { createEdge(this.combiGraph, arcTypeDepend, common.get(r1.getQualifiedName()), common.get(r2.getQualifiedName())); } } } } } } } common.clear(); common = null; local.clear(); local = null; } } private void createGraphs(Graph combiCPAGraph) { if ((this.conflicts == null) && (this.dependencies == null)) return; List<Rule> rlist = this.grammar.getRulesWithIntegratedRulesOfRuleScheme(); Hashtable<String, Rule> name2rule = new Hashtable<String, Rule>(); for (Rule r : rlist) { name2rule.put(r.getQualifiedName(), r); } node2rule = new Hashtable<Node, Rule>(); TypeSet types = combiCPAGraph.getTypeSet(); Type arcTypeConflict = types.getTypeByName("c"); Type arcTypeDepend = types.getTypeByName("d"); if (this.conflicts != null) { // copy combiGraph and delete dependency edges this.conflictGraph = combiCPAGraph.copy(); this.conflictGraph.setName("Conflicts of Rules"); Vector<Arc> list = this.conflictGraph.getArcs(arcTypeDepend); if (list != null) { for (Arc a : list) { try { this.conflictGraph.destroyArc(a); } catch (TypeException ex) {} } } } if (this.dependencies != null) { // copy combiGraph and delete conflict edges this.dependGraph = combiCPAGraph.copy(); this.dependGraph.setName("Dependencies of Rules"); Vector<Arc> list = this.dependGraph.getArcs(arcTypeConflict); if (list != null) { for (Arc a : list) { try { this.dependGraph.destroyArc(a); } catch (TypeException ex) {} } } } // fill node2rule hashtable Iterator<Node> iter = this.dependGraph.getNodesSet().iterator(); while (iter.hasNext()) { Node n = iter.next(); String name = n.getAttribute().getValueAsString(0).replace("\"", ""); Rule r = name2rule.get(name); if (r != null) { node2rule.put(n, r); } } iter = this.conflictGraph.getNodesSet().iterator(); while (iter.hasNext()) { Node n = iter.next(); String name = n.getAttribute().getValueAsString(0).replace("\"", ""); Rule r = name2rule.get(name); if (r != null) { node2rule.put(n, r); } } } private void optimizeLayout(Graph g) { // replace two edges between the same nodes through one not directed edge Iterator<Arc> e = g.getArcsSet().iterator(); while (e.hasNext()) { Arc a = e.next(); if (a.getSource() == a.getTarget()) continue; if (!a.isDirected()) continue; Iterator<Arc> e1 = g.getArcsSet().iterator(); while (e1.hasNext()) { Arc a1 = e1.next(); if (a1.getSource() == a1.getTarget()) continue; if (!a1.isDirected()) continue; if (a != a1) { if (a.getType().getName().equals(a1.getType().getName()) && (a.getSource() == a1.getTarget()) && (a.getTarget() == a1.getSource())) { a.setVisible(false); a1.setDirected(false); break; } } } } } private Node createNode(Graph g, Type t, Rule r) { Node n = getNode(g, r); if (n == null) { try { n = g.createNode(t); ValueTuple vt = (ValueTuple) n.getAttribute(); String rname = r.getQualifiedName(); vt.getValueMemberAt("name").setExprAsObject(rname); } catch (TypeException e) { } } return n; } private Node getNode(Graph g, Rule r) { Iterator<Node> e = g.getNodesSet().iterator(); while (e.hasNext()) { Node n = e.next(); if (((String) n.getAttribute().getValueAt("name")).equals(r .getQualifiedName())) return n; } return null; } private Arc createEdge(Graph g, Type t, Node n1, Node n2) { if (t == null || n1 == null || n2 == null) return null; Arc a = getEdge(g, t, n1, n2); if (a == null) { try { a = g.createArc(t, n1, n2); if (n1 != n2) { Arc a1 = getEdge(g, t, n2, n1); if (a1 != null) { a.setDirected(false); a1.setVisible(false); } } } catch (TypeException e) { } } return a; } @SuppressWarnings("unused") private Arc createEdge(Graph g, Type t, Rule r1, Rule r2) { if (t == null || r1 == null || r2 == null) return null; Node n1 = getNode(g, r1); Node n2 = getNode(g, r2); return createEdge(g, t, n1, n2); } private Arc getEdge(Graph g, Type t, Node n1, Node n2) { if (t == null || n1 == null || n2 == null) return null; Iterator<Arc> e = g.getArcsSet().iterator(); while (e.hasNext()) { Arc a = e.next(); if (!a.getType().getName().equals(t.getName())) continue; Object src = a.getSource().getAttribute().getValueAt("name"); Object tar = a.getTarget().getAttribute().getValueAt("name"); Object name1 = n1.getAttribute().getValueAt("name"); Object name2 = n2.getAttribute().getValueAt("name"); if ((src != null && ((String) src).equals(name1)) && (tar != null && ((String) tar).equals(name2))) return a; } return null; } }