/** * */ package agg.ruleappl; import java.util.Enumeration; import java.util.Hashtable; import java.util.Iterator; import java.util.List; import java.util.Vector; import agg.xt_basis.Arc; import agg.xt_basis.BadMappingException; import agg.xt_basis.BaseFactory; import agg.xt_basis.ConcurrentRule; import agg.xt_basis.Graph; import agg.xt_basis.GraphObject; import agg.xt_basis.Match; import agg.xt_basis.Morphism; import agg.xt_basis.Node; import agg.xt_basis.OrdinaryMorphism; import agg.xt_basis.Rule; import agg.xt_basis.agt.AmalgamatedRule; import agg.xt_basis.agt.RuleScheme; /** * This class is used inside of the <code>RuleSequence</code> class to save information * about matches computed during applicability check of rule sequences. * The class <code>ApplRuleSequencesGraTraImpl</code> makes use of * this information to compute transformation matches of the rules of * an applicable rule sequences. * * @author olga * */ public class MatchSequence { RuleSequence ruleSequence; Graph graph; final List<Rule> rules; final Vector<Hashtable<GraphObject, GraphObject>> matches; final Vector<Hashtable<GraphObject, GraphObject>> comatches; Hashtable<String, ObjectFlow> objectFlow; final Hashtable<Integer, Rule> imgObj2Rule; final Hashtable<Integer, ConcurrentRule> imgObj2ConcurrentRule; int trafoIndx = -1; /** * Initiates new instance and all needed containers. * * @param ruleSeq corresponding rule sequence */ public MatchSequence(final RuleSequence ruleSeq) { this.ruleSequence = ruleSeq; this.graph = this.ruleSequence.getGraph(); this.rules = new Vector<Rule>(); this.matches = new Vector<Hashtable<GraphObject, GraphObject>>(); this.comatches = new Vector<Hashtable<GraphObject, GraphObject>>(); this.imgObj2Rule = new Hashtable<Integer, Rule>(); this.imgObj2ConcurrentRule = new Hashtable<Integer, ConcurrentRule> (); } public boolean objectFlowDefined() { return this.ruleSequence.isObjFlowDefined(); } /** * Initiates newly this instance and all used containers. * * @param ruleSeq */ public void reinit(final RuleSequence ruleSeq) { clear(); this.ruleSequence = ruleSeq; this.graph = this.ruleSequence.getGraph(); this.objectFlow = ruleSeq.getObjectFlow(); } public void dispose() { this.clear(); } public void clear() { this.rules.clear(); this.matches.clear(); this.comatches.clear(); this.imgObj2Rule.clear(); this.imgObj2ConcurrentRule.clear(); this.trafoIndx = -1; } public void clearComatches() { this.comatches.clear(); this.trafoIndx = -1; } public void setObjectFlow(final Hashtable<String, ObjectFlow> objectFlow) { this.objectFlow = objectFlow; } /** * Saves information about current rule and match on which this rule * is applicable at a host graph. * * @param currentRule an applicable rule * @param m a valid match */ public void addDirectMatch(final Rule currentRule, final OrdinaryMorphism m) { final Hashtable<GraphObject, GraphObject> match = new Hashtable<GraphObject, GraphObject>(); final Enumeration<GraphObject> objs = m.getDomain(); while (objs.hasMoreElements()) { GraphObject obj = objs.nextElement(); GraphObject img = m.getImage(obj); match.put(obj, img); } this.matches.add(match); this.rules.add(currentRule); } /** * Saves information about current rule and its pure enabling predecessor rule. * * @param currentRule the current rule * @param totalPureRule a pure enabling predecessor rule * @param m embedding of the LHS of the current rule into the RHS of the * pure enabling predecessor rule * @param indx_currentRule * @param indx_totalPureRule */ public void addTotalPureEnablingSourceMatch( final Rule currentRule, final Rule totalPureRule, final OrdinaryMorphism m, int indx_currentRule, int indx_totalPureRule) { final Hashtable<GraphObject, GraphObject> match = new Hashtable<GraphObject, GraphObject>(); final Enumeration<GraphObject> objs = m.getDomain(); while (objs.hasMoreElements()) { GraphObject obj = objs.nextElement(); GraphObject img = m.getImage(obj); match.put(obj, img); } this.matches.add(match); this.rules.add(currentRule); this.imgObj2Rule.put(Integer.valueOf(indx_totalPureRule), totalPureRule); } /** * Saves information about current rule and corresponding concurrent rule and match which * are computed during applicability check of rule sequence. * * @param currentRule a rule * @param concurrentRule computed concurrent rule * @param m a valid match of the concurrent rule */ public void addConcurrentSourceMatch( final Rule currentRule, final ConcurrentRule concurrentRule, final OrdinaryMorphism m) { Hashtable<GraphObject, GraphObject> match = new Hashtable<GraphObject, GraphObject>(); final Enumeration<GraphObject> objs = m.getDomain(); while (objs.hasMoreElements()) { GraphObject obj = objs.nextElement(); GraphObject img = m.getImage(obj); match.put(obj, img); } this.matches.add(match); this.rules.add(currentRule); int indx = this.matches.size()-1; this.imgObj2ConcurrentRule.put(Integer.valueOf(indx), concurrentRule); } /** * Saves information about the comatch after the given applicable rule was applied * at a host graph. * * @param r * @param com */ public void addComatch(final Rule r, final Morphism com) { final Hashtable<GraphObject, GraphObject> comatch = new Hashtable<GraphObject, GraphObject>(); final Enumeration<GraphObject> objs = com.getDomain(); while (objs.hasMoreElements()) { GraphObject obj = objs.nextElement(); GraphObject img = com.getImage(obj); if (r instanceof AmalgamatedRule) { RuleScheme rs = r.getRuleScheme(); GraphObject kernelRObj = rs.getRHSKernelOfAmalgamRuleObject(obj); if (kernelRObj != null) { comatch.put(kernelRObj, img); } } else { comatch.put(obj, img); } } if (this.trafoIndx < 0) { this.comatches.add(comatch); } else { while (this.trafoIndx > (this.comatches.size())) { this.comatches.add(null); } this.comatches.add(this.trafoIndx, comatch); } } public Hashtable<GraphObject, GraphObject> getDirectMatch( int indx, final Rule rule) { // predefined matches exist if (indx >= 0 && indx < this.matches.size()) { return this.matches.get(indx); } return null; } /** * Returns GraphObject pairs of partial match of the specified rule * at the specified index in the rule sequence * if and only if an object flow is defined. * * @param indx * @param rule * @return table with GraphObject pairs */ public Hashtable<GraphObject, GraphObject> getMatch( int indx, final Rule rule) { // no predefined matches exist if (this.matches.size() == 0) { final Hashtable<GraphObject, GraphObject> match = makeMatchMapByObjectFlow(rule, indx); return match; } return null; } /** * Returns GraphObject pairs of partial match of the specified rule * at the specified index in the rule sequence. * * @param indx index of the current rule * @param rule pure enabling predecessor rule * @param preRuleIndx index of the predecessor rule * @param preRule the predecessor rule * @param g a host graph * * @return a table with pairs of match objects */ public Hashtable<GraphObject, GraphObject> getMatch( int indx, final Rule rule, final int preRuleIndx, final Rule preRule, final Graph g) { // no predefined matches exist if (this.matches.size() == 0) { final Hashtable<GraphObject, GraphObject> match = makeMatchMapByObjectFlow(rule, indx); return match; } else if (indx >= 0 && indx < this.matches.size() && preRuleIndx < indx) { final Hashtable<GraphObject, GraphObject> srcMatch = this.matches.get(indx); // rule is the first rule if (preRule == null) { if (this.ruleSequence.getGraph() != null && this.objectFlow.get("0:1") != null && this.objectFlow.get("0:1").isSourceOfOutput(this.ruleSequence.getGraph()) && this.objectFlow.get("0:1").isSourceOfInput(rule)) { final Hashtable<GraphObject, GraphObject> match = makeMatchMapByObjectFlow( rule, indx, this.objectFlow.get("0:1")); return match; } // initial match of the first rule return srcMatch; } Hashtable<GraphObject, GraphObject> match = makeMatchMapByObjectFlow( rule, indx); if (!match.isEmpty()) { return match; } if (this.imgObj2Rule.get(Integer.valueOf(indx)) != null) { match = makeMatchMapByTotalPureRule( indx, preRule, this.comatches.get(preRuleIndx)); return match; } else if (this.imgObj2ConcurrentRule.get(Integer.valueOf(indx)) != null && this.imgObj2ConcurrentRule.get(Integer.valueOf(indx)).getSecondSourceRule() == rule) { match = makeMatchMapByConcurrentRuleBackward( indx, rule, g); return match; } else { // direct match return srcMatch; } } return null; } public ObjectFlow getObjectFlowForRules(final Rule r1, int indx_r1, final Rule r2, int indx_r2) { return this.ruleSequence.getObjFlowForRules(r1, indx_r1, r2, indx_r2); } public List<ObjectFlow> getObjectFlowForRule(final Rule r, int indx) { return this.ruleSequence.getObjFlowForRule(r, indx); } private Hashtable<GraphObject, GraphObject> makeMatchMapByTotalPureRule( int indx, final Rule preRule, final Hashtable<GraphObject, GraphObject> preRuleComatch) { // System.out.println("## MatchSequence.makeMatchByTotalPureRule :: "); final Hashtable<GraphObject, GraphObject> match = new Hashtable<GraphObject, GraphObject>(); final Hashtable<GraphObject, GraphObject> srcMatch = this.matches.get(indx); final Rule totalPureRule = this.imgObj2Rule.get(Integer.valueOf(indx)); final Enumeration<GraphObject> objs = srcMatch.keys(); while (objs.hasMoreElements()) { GraphObject obj = objs.nextElement(); GraphObject img = srcMatch.get(obj); if (totalPureRule == preRule) { GraphObject img2 = preRuleComatch.get(img); if (img2 != null && img2.getContext() != null) match.put(obj, img2); } else { final Hashtable<GraphObject, GraphObject> srcComatch = this.comatches.get(this.ruleSequence.getIndexOf(totalPureRule)); if (srcComatch != null) { GraphObject img2 = srcComatch.get(img); if (img2 != null && img2.getContext() != null) match.put(obj, img2); } } } return match; } public void fillMatchMapByObjectFlow( final Rule rule, final ObjectFlow objFlow, final Object srcOfOutput, final Hashtable<GraphObject, GraphObject> matchmap) { if (srcOfOutput instanceof Rule) { final Rule preRule = (Rule) srcOfOutput; int indx_preRule = objFlow.getIndexOfOutput(); if (this.ruleSequence.getGraph() != null) indx_preRule--; if (indx_preRule >= 0 && indx_preRule < this.comatches.size()) { final Hashtable<GraphObject, GraphObject> srcComatch = this.comatches.get(indx_preRule); if (srcComatch != null) { Iterator<?> lhs = rule.getLeft().getNodesSet().iterator(); while (lhs.hasNext()) { GraphObject lhs_obj = (GraphObject) lhs.next(); GraphObject rhs_obj = (GraphObject) objFlow.getOutput(lhs_obj); if (rhs_obj != null) { GraphObject g_obj = srcComatch.get(rhs_obj); if (g_obj != null && g_obj.getContext() != null) { matchmap.put(lhs_obj, g_obj); } } } lhs = rule.getLeft().getArcsSet().iterator(); while (lhs.hasNext()) { GraphObject lhs_obj = (GraphObject) lhs.next(); GraphObject rhs_obj = (GraphObject) objFlow.getOutput(lhs_obj); if (rhs_obj != null) { GraphObject g_obj = srcComatch.get(rhs_obj); if (g_obj != null && g_obj.getContext() != null) { matchmap.put(lhs_obj, g_obj); } } } } } else if (indx_preRule >= 0 && indx_preRule < this.matches.size()) { final Hashtable<GraphObject, GraphObject> preMatch = this.matches.get(indx_preRule); Iterator<?> lhs = rule.getLeft().getNodesSet().iterator(); while (lhs.hasNext()) { GraphObject lhs_obj = (GraphObject) lhs.next(); GraphObject rhs_obj = (GraphObject) objFlow.getOutput(lhs_obj); if (rhs_obj != null) { if (preRule.getInverseImage(rhs_obj).hasMoreElements()) { GraphObject pre_lhs_obj = preRule.getInverseImage(rhs_obj).nextElement(); GraphObject g_obj = preMatch.get(pre_lhs_obj); if (g_obj != null) { matchmap.put(lhs_obj, g_obj); } } } } lhs = rule.getLeft().getArcsSet().iterator(); while (lhs.hasNext()) { GraphObject lhs_obj = (GraphObject) lhs.next(); GraphObject rhs_obj = (GraphObject) objFlow.getOutput(lhs_obj); if (rhs_obj != null) { if (preRule.getInverseImage(rhs_obj).hasMoreElements()) { GraphObject pre_lhs_obj = preRule.getInverseImage(rhs_obj).nextElement(); GraphObject g_obj = preMatch.get(pre_lhs_obj); if (g_obj != null) { matchmap.put(lhs_obj, g_obj); } } } } } } else if (srcOfOutput instanceof Graph) { Iterator<?> lhs = rule.getLeft().getNodesSet().iterator(); while (lhs.hasNext()) { GraphObject lhs_obj = (GraphObject) lhs.next(); GraphObject g_obj = (GraphObject) objFlow.getOutput(lhs_obj); if (g_obj != null && g_obj.getContext() != null) { matchmap.put(lhs_obj, g_obj); } } lhs = rule.getLeft().getArcsSet().iterator(); while (lhs.hasNext()) { GraphObject lhs_obj = (GraphObject) lhs.next(); GraphObject g_obj = (GraphObject) objFlow.getOutput(lhs_obj); if (g_obj != null && g_obj.getContext() != null) { matchmap.put(lhs_obj, g_obj); } } } } private Hashtable<GraphObject, GraphObject> makeMatchMapByObjectFlow( final Rule rule, int indx, final ObjectFlow objFlow) { // System.out.println("### MatchSequence.makeMatchByObjectFlow of rule: "+rule.getName()); final Hashtable<GraphObject, GraphObject> matchmap = new Hashtable<GraphObject, GraphObject>(); final Object srcOfOutput = objFlow.getSourceOfOutput(); fillMatchMapByObjectFlow(rule, objFlow, srcOfOutput, matchmap); return matchmap; } public Hashtable<GraphObject, GraphObject> makeMatchMapByObjectFlow( final Rule rule, int indx) { // System.out.println("## MatchSequence.makeMatchByObjectFlow of rule: "+rule.getName()); final Hashtable<GraphObject, GraphObject> matchmap = new Hashtable<GraphObject, GraphObject>(); if (indx == -1) return matchmap; int index = indx; if (this.ruleSequence.getGraph() != null) index++; Enumeration<String> keys = this.objectFlow.keys(); while (keys.hasMoreElements()) { String key = keys.nextElement(); String[] keyItems = key.split(":"); ObjectFlow objFlow = this.objectFlow.get(key); if (Integer.valueOf(keyItems[1]).intValue() == index && rule.getName().equals(((Rule)objFlow.getSourceOfInput()).getName())) { Object srcOfOutput = objFlow.getSourceOfOutput(); fillMatchMapByObjectFlow(rule, objFlow, srcOfOutput, matchmap); } } return matchmap; } public Hashtable<GraphObject, GraphObject> makeMatchMapByObjectFlow( final Rule rule, final List<ObjectFlow> objFlowList) { // System.out.println("##### MatchSequence.makeMatchByObjectFlow of rule: "+rule.getName()); final Hashtable<GraphObject, GraphObject> matchmap = new Hashtable<GraphObject, GraphObject>(); for (int i=0; i<objFlowList.size(); i++) { ObjectFlow objFlow = objFlowList.get(i); Object srcOfOutput = objFlow.getSourceOfOutput(); fillMatchMapByObjectFlow(rule, objFlow, srcOfOutput, matchmap); } return matchmap; } private Hashtable<GraphObject, GraphObject> makeMatchMapByConcurrentRuleBackward( int indx, final Rule ruleAtIndx, final Graph g) { final Hashtable<GraphObject, GraphObject> match = new Hashtable<GraphObject, GraphObject>(); // final Hashtable<GraphObject, GraphObject> srcMatch = this.matches.get(indx); final ConcurrentRule concurRule = this.imgObj2ConcurrentRule.get(Integer.valueOf(indx)); boolean secondRuleIsRuleAtIndx = false; ConcurrentRule testCR = concurRule; while (!secondRuleIsRuleAtIndx) { if (testCR.getSecondSourceRule() == ruleAtIndx) { secondRuleIsRuleAtIndx = true; } else if (testCR.getSecondSourceConcurrentRule() != null) { testCR = testCR.getSecondSourceConcurrentRule(); } else { break; } } if (secondRuleIsRuleAtIndx) { if (concurRule.getSecondSourceConcurrentRule() != null) { final Vector<GraphObject> domList = new Vector<GraphObject>(); ConcurrentRule tmpCR = concurRule; ConcurrentRule tmpPreCR = tmpCR.getSecondSourceConcurrentRule(); // find recursively all done comatches of rule before while (tmpPreCR != null) { int i = tmpPreCR.getIndexOfFirstSourceRule(); if (i >= 0 && i < this.comatches.size() && this.comatches.get(i) != null) { final Enumeration<GraphObject> elems = this.comatches.get(i).elements(); while (elems.hasMoreElements()) { final GraphObject obj = elems.nextElement(); if (obj.getContext() != null && !domList.contains(obj)) { domList.add(obj); } } } tmpCR = tmpPreCR; tmpPreCR = tmpCR.getSecondSourceConcurrentRule(); } int i = tmpCR.getIndexOfFirstSourceRule(); if (i >= 0 && i < this.comatches.size() && this.comatches.get(i) != null) { final Enumeration<GraphObject> elems = this.comatches.get(i).elements(); while (elems.hasMoreElements()) { final GraphObject obj = elems.nextElement(); if (obj.getContext() != null && !domList.contains(obj)) { domList.add(obj); } } } makeGraphObjectMap(ruleAtIndx, domList, match, g); } } return match; } /* private Hashtable<GraphObject, GraphObject> makeMatchMapByConcurrentRuleForward( int indx, final Rule ruleAtIndx, final Graph g) { final Hashtable<GraphObject, GraphObject> match = new Hashtable<GraphObject, GraphObject>(); final Hashtable<GraphObject, GraphObject> srcMatch = this.matches.get(indx); final ConcurrentRule concurRule = this.imgObj2ConcurrentRule.get(Integer.valueOf(indx)); if (concurRule.getSecondSourceRule() == ruleAtIndx) { if (concurRule.getFirstSourceConcurrentRule() != null) { final Vector<GraphObject> domList = new Vector<GraphObject>(); ConcurrentRule tmpCR = concurRule; ConcurrentRule tmpPreCR = tmpCR.getFirstSourceConcurrentRule(); // find recursively all done comatches of rule before while (tmpPreCR != null) { int i = this.rules.indexOf(tmpPreCR.getSecondSourceRule()); if (i >= 0 && i < this.comatches.size()) { final Enumeration<GraphObject> elems = this.comatches.get(i).elements(); while (elems.hasMoreElements()) { final GraphObject obj = elems.nextElement(); if (obj.getContext() != null && !domList.contains(obj)) { domList.add(obj); } } } tmpCR = tmpPreCR; tmpPreCR = tmpCR.getFirstSourceConcurrentRule(); } int i = this.rules.indexOf(tmpCR.getFirstSourceRule()); if (i >= 0 && i < this.comatches.size()) { final Enumeration<GraphObject> elems = this.comatches.get(i).elements(); while (elems.hasMoreElements()) { final GraphObject obj = elems.nextElement(); if (obj.getContext() != null && !domList.contains(obj)) { domList.add(obj); } } } makeGraphObjectMap(ruleAtIndx, domList, match, g); } } return match; } */ private void makeGraphObjectMap( final Rule r, final Vector<GraphObject> goSet, final Hashtable<GraphObject, GraphObject> map, final Graph g) { if (!goSet.isEmpty()) { // create test match Match m = BaseFactory.theFactory().createMatch(r, g); // first try to map edges final Iterator<Arc> arcs = m.getSource().getArcsSet().iterator(); while (arcs.hasNext()) { final Arc a = arcs.next(); for (int i=0; i<goSet.size(); i++) { final GraphObject obj = goSet.get(i); if (obj.getContext() != null && obj.isArc() && a.getType().compareTo(obj.getType())) { boolean srcOK = false; if (m.getImage(a.getSource()) == null) { try { m.addMapping(a.getSource(), ((Arc)obj).getSource()); map.put(a.getSource(), ((Arc)obj).getSource()); srcOK = true; } catch (BadMappingException ex) { System.out.println("MatchSequence.makeGraphObjectMap (Node) of match based on concurrent rule: "+ex.getLocalizedMessage()); } } else { srcOK = true; } boolean tarOK = false; if (m.getImage(a.getTarget()) == null) { try { m.addMapping(a.getTarget(), ((Arc)obj).getTarget()); map.put(a.getTarget(), ((Arc)obj).getTarget()); tarOK = true; } catch (BadMappingException ex) { System.out.println("MatchSequence.makeGraphObjectMap (Node) of match based on concurrent rule: "+ex.getLocalizedMessage()); } } else { tarOK = true; } if (srcOK && tarOK) { try { m.addMapping(a, obj); map.put(a, obj); goSet.remove(obj); goSet.remove(((Arc)obj).getSource()); goSet.remove(((Arc)obj).getTarget()); break; } catch (BadMappingException ex) { System.out.println("MatchSequence.makeGraphObjectMap (Arc) of match based on concurrent rule: "+ex.getLocalizedMessage()); } } } } } // now try to map single nodes final Iterator<Node> nodes = m.getSource().getNodesSet().iterator(); while (nodes.hasNext()) { final Node n = nodes.next(); if (m.getImage(n) == null) { for (int i=0; i<goSet.size(); i++) { final GraphObject obj = goSet.get(i); if (obj.isNode() && n.getType().isParentOf(obj.getType())) { if (!m.getInverseImage(obj).hasMoreElements()) { try { m.addMapping(n, obj); goSet.remove(obj); map.put(n, obj); break; } catch (BadMappingException ex) { System.out.println("MatchSequence.makeGraphObjectMap (Node) of match based on concurrent rule: "+ex.getLocalizedMessage()); } } } } } } // dispose test match m.dispose(); r.setMatch(null); m=null; } } public void setTrafoIndex(int i) { this.trafoIndx = i; } }