/** * */ package agg.ruleappl; import java.util.Enumeration; import java.util.Hashtable; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Vector; import agg.parser.CriticalPairOption; import agg.util.Pair; import agg.util.Triple; import agg.util.XMLHelper; import agg.xt_basis.Arc; import agg.xt_basis.ConcurrentRule; import agg.xt_basis.GraGra; import agg.xt_basis.GraTraEvent; import agg.xt_basis.GraTraEventListener; import agg.xt_basis.Graph; import agg.xt_basis.GraphObject; import agg.xt_basis.Match; import agg.xt_basis.Node; import agg.xt_basis.OrdinaryMorphism; import agg.xt_basis.Rule; import agg.xt_basis.agt.KernelRule; import agg.xt_basis.agt.RuleScheme; /** * This class implements a rule sequence and checking applicability and non-applicability * criteria of this sequence. * * The constructor needs a grammar <code>agg.xt_basis.GraGra</code> and * CPA options <code>agg.parser.CriticalPairOption</code> instances. * * Adding a rule which belongs to the given gragra can be done * by the method <code>add(agg.xt_basis.Rule)</code> * or <code>addRule(String)</code> where a string is a rule name, * but also by using <code>setRules(List<String></code> with list of rule names. * * To set a graph on which the rule sequence should be checked is available by * <code>setGraph(agg.xt_basis.Graph</code>. The given graph must belong to the gragra.<br> * * To check applicability of the rule sequence is possible by * calling the method <code>check</code>. * * There are two results of this check: applicability and non-applicability result. * * Applicability result can be asked by <code>Pair<Boolean, String> getApplicabilityResult()</code>. * The returned pair is (true, ApplicabilityConstants.UNDEFINED) or (false, criterion). * * Non-Applicability result can be asked by <code>Pair<Boolean, String> getNonApplicabilityResult()</code>. * The returned pair is (false, ApplicabilityConstants.UNDEFINED) or (true, criterion).<br> * * @see agg.ruleappl.ApplicabilityConstants * for the possible meaning of applicability and non-applicability criterion.<br> * * Used in <code>agg.xt_basis.RuleSequencesGraTraImpl.setRuleSequence(RuleSequence)</code>. * * @author olga * */ public class RuleSequence implements GraTraEventListener { public static final int OBJECT_FLOW_TRANSITIVE_CLOSURE_FAILED = 0; public static final int OBJECT_FLOW_PERSISTENT_FAILED = 1; public static final String TRAFO_BY_OBJECT_FLOW = "trafoByOF"; public static final String TRAFO_BY_ARS = "trafoByARS"; @SuppressWarnings("unused") private static final String TRAFO_BY_IN_OUT_PARAM = "trafoByIOP"; private String name = "RuleSequence"; private GraGra gragra; private CriticalPairOption cpOption; private Graph graph; private List<Pair<List<Pair<String, String>>, String>> subSequenceList = new Vector<Pair<List<Pair<String, String>>, String>>(); private final Vector<Rule> rules = new Vector<Rule>(); private final Vector<String> ruleNames = new Vector<String>(); // flattened rule sequence private final Pair<Boolean, String> applResult = new Pair<Boolean, String>(new Boolean(false), ApplicabilityConstants.UNDEFINED); private final Pair<Boolean, String> nonapplResult = new Pair<Boolean, String>(new Boolean(false), ApplicabilityConstants.UNDEFINED); private final Hashtable<String, Pair<Boolean, List<String>>> ruleResults = new Hashtable<String, Pair<Boolean, List<String>>>(); final private ApplicabilityChecker checker; protected boolean checked; protected boolean checkAtGraph; private final Map<String, List<List<ConcurrentRule>>> concurrentRules = new Hashtable<String, List<List<ConcurrentRule>>>(); // key String is "rule.hashCode:ruleIndex" protected final Hashtable<String, ObjectFlow> objectFlow; private boolean enabledObjectFlow; private boolean completeNodesOF; private int objectFlowError = -1; private boolean trafoByOF, trafoByARS; private int startIndx; private boolean usePreviousSequenceResults = true; protected MatchSequence matchSequence; public RuleSequence(final GraGra gra, final String name) { this.gragra = gra; this.name = name; this.checker = new ApplicabilityChecker(this, this.gragra); this.enabledObjectFlow = true; this.usePreviousSequenceResults = true; this.checkAtGraph = true; if (this.gragra != null) this.graph = this.gragra.getGraph(); this.subSequenceList = new Vector<Pair<List<Pair<String, String>>, String>>(); this.objectFlow = new Hashtable<String, ObjectFlow>(); this.matchSequence = new MatchSequence(this); this.matchSequence.setObjectFlow(this.objectFlow); this.completeNodesOF = false; } public RuleSequence(final GraGra gra, final String name, final CriticalPairOption option) { this(gra, name); this.cpOption = option; } public RuleSequence( final GraGra gra, final String name, final CriticalPairOption option, final List<Pair<List<Pair<String, String>>, String>> ruleSubSequenceList) { this(gra, name, option); this.makeFlatSequence(); } public RuleSequence( final GraGra gra, final String name, final List<Pair<List<Pair<String, String>>, String>> ruleSubSequenceList) { this(gra, name); this.makeFlatSequence(); } public boolean isObjFlowDefined() { return !this.objectFlow.isEmpty(); } public Hashtable<String, ObjectFlow> getObjectFlow() { return this.objectFlow; } public void setCriticalPairOption(final CriticalPairOption option) { this.cpOption = option; this.checker.setCriticalPairOption(option); } public CriticalPairOption getCriticalPairOption() { return this.cpOption; } public void setName(final String aName) { this.name = aName; } public String getName() { return this.name; } public void refresh() { this.clear(); this.makeFlatSequence(); } public List<Pair<List<Pair<String, String>>, String>> getSubSequenceList() { return this.subSequenceList; } public void setSubsequenceList(final List<Pair<List<Pair<String, String>>, String>> list) { this.subSequenceList = list; } private void copySubsequenceList(final List<Pair<List<Pair<String, String>>, String>> list) { this.subSequenceList.clear(); for (int i=0; i<list.size(); i++) { Pair<List<Pair<String, String>>, String> pseg = list.get(i); List<Pair<String, String>> sublist = new Vector<Pair<String, String>>(); for (int j=0; j<pseg.first.size(); j++) { Pair<String, String> pRule = pseg.first.get(j); sublist.add(new Pair<String, String>(pRule.first, pRule.second)); } this.subSequenceList.add( new Pair<List<Pair<String, String>>, String>(sublist, pseg.second)); } } public void makeFlatSequence() { this.rules.clear(); this.ruleNames.clear(); for (int i=0; i<this.subSequenceList.size(); i++) { Pair<List<Pair<String, String>>, String> pseg = this.subSequenceList.get(i); int seqIters = 2; // when * if (!pseg.second.equals("*")) { seqIters = Integer.valueOf(pseg.second).intValue(); } List<Pair<String, String>> rList = pseg.first; for (int its=0; its<seqIters; its++) { for (int j=0; j<rList.size(); j++) { Pair<String, String> pRule = rList.get(j); int rIters = 2; // statt * if (!pRule.second.equals("*")) { rIters = Integer.valueOf(pRule.second).intValue(); } Rule r = this.gragra.getRuleByQualifiedName(pRule.first); if (r != null) { if (r instanceof RuleScheme) { // this.rules.add(r); r = ((RuleScheme) r).getKernelRule(); } // else if (r instanceof KernelRule) { // this.rules.add(r.getRuleScheme()); // } // else { // this.rules.add(r); // } for (int itr=0; itr<rIters; itr++) { if (r.getRuleScheme() != null && r instanceof KernelRule) { this.rules.add(r.getRuleScheme()); //test this.ruleNames.add(r.getRuleScheme().getName()+"."+r.getName()); } else { this.rules.add(r); // test this.ruleNames.add(r.getName()); } } } } } } } public void dispose() { this.clear(); this.gragra = null; this.cpOption = null; } public ApplicabilityChecker getApplicabilityChecker() { return this.checker; } protected Map<String, List<List<ConcurrentRule>>> getConcurrentRulesContainer() { return this.concurrentRules; } protected List<List<ConcurrentRule>> getListsOfConcurrentRules( final Rule r, final int indx) { String key = String.valueOf(r.hashCode()).concat(":").concat(String.valueOf(indx)); return this.concurrentRules.get(key); } protected void putListsOfConcurrentRules( final Rule r, final int indx, final List<List<ConcurrentRule>> lists) { String key = String.valueOf(r.hashCode()).concat(":").concat(String.valueOf(indx)); this.concurrentRules.put(key, lists); } public List<ConcurrentRule> getApplicableConcurrentRules() { return this.checker.getApplicableConcurrentRules(); } public Iterator<List<List<ConcurrentRule>>> getConcurrentRules() { return this.concurrentRules.values().iterator(); } public void reinit() { this.clearResult(); for (int i=0; i<this.rules.size(); i++) { Rule r = this.rules.get(i); if (r.getMatch() != null) { r.getMatch().dispose(); r.setMatch(null); } } this.matchSequence.reinit(this); this.removeEmptyObjFlow(); } public void clear() { this.matchSequence.clear(); this.objectFlow.clear(); this.rules.clear(); this.ruleNames.clear(); this.clearResult(); } public void clearObjFlow() { this.objectFlow.clear(); } public void clearResult() { this.concurrentRules.clear(); clearApplResult(); clearNonApplResult(); this.ruleResults.clear(); } private void clearApplResult() { this.applResult.first = new Boolean(false); this.applResult.second = ApplicabilityConstants.UNDEFINED; this.checked = false; } private void clearNonApplResult() { this.nonapplResult.first = new Boolean(false); this.nonapplResult.second = ApplicabilityConstants.UNDEFINED; this.checked = false; } public GraGra getGraGra() { return this.gragra; } public void setCheckAtGraph(boolean b) { this.checkAtGraph = b; } public boolean doesCheckAtGraph() { return this.checkAtGraph; } public void setGraph(final Graph g) { this.removeObjFlowOfGraph(); this.clearResult(); this.graph = g; } public Graph getGraph() { return this.graph; } public void setTrafoByObjFlow(boolean b) { this.trafoByOF = b; } public boolean isTrafoByObjFlow() { return this.trafoByOF; } public void setTrafoByARS(boolean b) { this.trafoByARS = b; } public boolean isTrafoByARS() { return this.trafoByARS; } public void setUsePreviousSequenceResults(boolean b) { this.usePreviousSequenceResults = b; } public boolean makeUseOfPreviousSequenceResults() { return this.usePreviousSequenceResults; } public void setStartIndexOfCheck(int indx) { this.startIndx = indx; } public int getStartIndexOfCheck() { return this.startIndx; } public Rule getStartRule() { if (!this.rules.isEmpty()) { if (this.startIndx >= 0 && this.startIndx < this.rules.size()) return this.rules.get(this.startIndx); return this.rules.get(0); } return null; } public void enableObjFlow(boolean b) { this.enabledObjectFlow = b; } /** * Returns true if the object flow of <code>this</code> is enabled, * otherwise false. */ public boolean isObjFlowEnabled() { return this.enabledObjectFlow; } public void enableCompleteObjFlowOfNodes(boolean b) { this.completeNodesOF = b; } public boolean isCompleteObjFlowOfNodesEnabled() { return this.completeNodesOF; } /** * Returns true if its object flow is enabled and not empty, * otherwise false. */ public boolean isObjFlowActive() { return this.enabledObjectFlow && !this.objectFlow.isEmpty(); } public boolean isGraphUsedInObjFlow() { Enumeration<String> keys = this.objectFlow.keys(); while (keys.hasMoreElements()) { String key = keys.nextElement(); String[] keyItems = key.split(":"); if (keyItems[0].equals("0")) return true; } return false; } public boolean containsRuleLoop() { for (int i=0; i<this.subSequenceList.size(); i++) { Pair<List<Pair<String, String>>, String> pseg = this.subSequenceList.get(i); for (int j=0; j<pseg.first.size(); j++) { Pair<String, String> pRule = pseg.first.get(j); if ("*".equals(pRule.second)) return true; } } return false; } public boolean containsOneRuleIterationOnly() { boolean result = !this.isEmpty(); for (int i=0; i<this.subSequenceList.size(); i++) { Pair<List<Pair<String, String>>, String> pseg = this.subSequenceList.get(i); for (int j=0; j<pseg.first.size(); j++) { Pair<String, String> pRule = pseg.first.get(j); if (!"1".equals(pRule.second)) result = false; } } return result; } /* * Returns true if this rule sequence contains only one subsequence, * otherwise false. */ public boolean hasOneSubsequence() { return this.subSequenceList.size() == 1; } public boolean containsRuleScheme() { for (int i=0; i<this.rules.size(); i++) { Rule r = this.rules.get(i); if (r.getRuleScheme() != null) return true; } return false; } public void addRule(final Rule r) { this.rules.add(r); this.ruleNames.add(r.getName()); if (this.subSequenceList.isEmpty()) { List<Pair<String, String>> l = new Vector<Pair<String, String>>(); Pair<List<Pair<String, String>>, String> p = new Pair<List<Pair<String, String>>, String>(l, "1"); this.subSequenceList.add(p); } this.subSequenceList.get(0).first.add(new Pair<String, String>(r.getName(), "1")); } public boolean addRule(final String rname) { if (this.gragra.getRule(rname) != null) { Rule r = this.gragra.getRule(rname); if (this.gragra.isLayered() && !this.rules.isEmpty()) { Rule r0 = this.rules.get(0); if (r0.getLayer() != r.getLayer()) { return false; } } this.addRule(this.gragra.getRule(rname)); return true; } return false; } public void setRules(List<String> sequence) { this.clear(); this.makeRules(sequence); } public void setRules(Iterator<Rule> sequence) { this.clear(); this.makeRules(sequence); } public Rule getRule(final int indx) { if (indx >= 0 && indx < this.rules.size()) { return this.rules.get(indx); } return null; } public Rule getRule(final String rname) { for (int i=0; i<this.rules.size(); i++) { final Rule r = this.rules.get(i); if (r.getName().equals(rname)) return r; } return null; } public int getIndexOf(final Rule r) { return this.rules.indexOf(r); } public List<Rule> getRules() { return this.rules; } public void resetRuleNames(final List<String> rnames) { this.ruleNames.clear(); this.ruleNames.addAll(rnames); this.resetRules(); } private void resetRules() { Vector<Rule> v = new Vector<Rule>(this.rules); this.rules.clear(); for (int i=0; i<this.ruleNames.size(); i++) { String rn = this.ruleNames.get(i); for (int j=0; j<v.size(); j++) { Rule r = v.get(j); if (r.getQualifiedName().equals(rn)) { this.rules.add(r); break; } } } } public List<String> getRuleNames() { return new Vector<String>(this.ruleNames); } public int getSize() { return this.rules.size(); } public boolean isEmpty() { return this.rules.isEmpty(); } public boolean isValid() { boolean ok = true; for (int i=0; i<this.rules.size() && ok; i++) { Rule r = this.rules.get(i); boolean found = false; Enumeration<Rule> en = this.gragra.getRules(); while (en.hasMoreElements() && !found) { Rule ru = en.nextElement(); if (r == ru) { found = true; } else if (ru.getRuleScheme() != null && ((RuleScheme)ru.getRuleScheme()).getKernelRule() == r) { found = true; } } ok = found; } return ok; } public boolean containsRuleWithGACs() { for (int i=0; i<this.rules.size(); i++) { if (this.rules.get(i).hasEnabledACs(true)) return true; } return false; } public String getText() { String text = ""; if (this.graph == null) { text = getRuleNamesString(); } else { text = text.concat(this.graph.getName()); text = text.concat(" <= "); text = text.concat(getRuleNamesString()); } return text; } public String getToolTipText() { String text = ""; for (int i = 0; i < this.subSequenceList.size(); i++) { Pair<List<Pair<String, String>>, String> g = this.subSequenceList.get(i); String grpStr = ""; List<Pair<String, String>> grpRules = g.first; long grpIters = -1; String grpItersStr = g.second; if (grpItersStr.equals("*")) grpStr = grpStr.concat("( "); else { try { grpIters = (new Long(g.second)).longValue(); if (grpRules.size() > 1 || grpIters > 1) grpStr = grpStr.concat("( "); } catch (java.lang.NumberFormatException ex) {} } for (int j = 0; j < grpRules.size(); j++) { Pair<String, String> p = grpRules.get(j); String rulename = p.first; grpStr = grpStr.concat(rulename); long ruleIters = -1; String ruleItersStr = p.second; if (ruleItersStr.equals("*")){ grpStr = grpStr.concat("{"); grpStr = grpStr.concat(ruleItersStr); grpStr = grpStr.concat("}"); } else { ruleIters = (new Long(p.second)).longValue(); if (ruleIters > 1) { grpStr = grpStr.concat("{"); grpStr = grpStr.concat(String.valueOf(ruleIters)); grpStr = grpStr.concat("}"); } } grpStr = grpStr.concat(" "); } if (grpItersStr.equals("*")) grpStr = grpStr.concat(")"); else if (grpRules.size() > 1 || grpIters > 1) grpStr = grpStr.concat(")"); if (grpRules.size() > 0) { if (grpItersStr.equals("*")) { grpStr = grpStr.concat("{"); grpStr = grpStr.concat(grpItersStr); grpStr = grpStr.concat("}"); } else if (grpIters > 1) { grpStr = grpStr + "{" + grpIters + "}"; } } else { grpStr = "()"; } grpStr = grpStr.concat("\n"); text = text.concat(grpStr); } if (this.graph != null) { text = this.graph.getName().concat(" <= ").concat(text); } return text; } public String getRuleNamesString(){ String str = "( "; for (int i=0; i<this.rules.size(); i++) { str = str.concat(this.rules.get(i).getName()); str = str.concat(" "); } str = str.concat(")"); return str; } public Pair<Boolean, String> getApplicabilityResult() { return this.applResult; } public Pair<Boolean, String> getNonApplicabilityResult() { return this.nonapplResult; } private void makeRules(final List<String> sequence) { for (int j=0; j<sequence.size(); j++) { Rule r = this.gragra.getRule(sequence.get(j)); if (r != null){ this.rules.add(r); this.ruleNames.add(r.getName()); } } } private void makeRules(final Iterator<Rule> sequence) { while(sequence.hasNext()) { Rule r = sequence.next(); this.rules.add(r); this.ruleNames.add(r.getName()); } } public void removeRule(final int indx) { if (indx >= 0 && indx < this.rules.size()) { Rule r = this.rules.get(indx); removeObjFlowOfRule(r, indx); this.rules.remove(indx); this.ruleNames.remove(indx); this.clearResult(); } } public void removeRule(final Rule r) { if (this.rules.contains(r)) { int indx = this.rules.indexOf(r); removeObjFlowOfRule(r, indx); this.rules.remove(r); this.ruleNames.remove(indx); this.clearResult(); } } private void removeObjFlowOfRule(final Rule r, int indx) { int ind = indx; if (this.graph != null) ind++; Enumeration<String> keys = this.objectFlow.keys(); while (keys.hasMoreElements()) { String key = keys.nextElement(); String[] keyItems = key.split(":"); if (Integer.valueOf(keyItems[0]).intValue() == ind || Integer.valueOf(keyItems[1]).intValue() == ind) { this.objectFlow.remove(key); keys = this.objectFlow.keys(); break; } } } /** * Creates a new RuleSequence as a copy of the current RuleSequence instance * inclusive its object flow and applicability resp. non-applicability results. * In case when the new copied sequence will be extended the start index of check * should be set to the index of the first added rule: * <code>copiedSeq.setStartIndexOfCheck(indxOfExtention)</code> * */ public RuleSequence getCopy() { final RuleSequence seq = new RuleSequence( this.gragra, this.name.concat("_copy"), this.cpOption); seq.setCriticalPairOption(this.cpOption); seq.setRules(this.getRules().iterator()); seq.setGraph(this.graph); seq.copySubsequenceList(this.subSequenceList); if (!seq.getRuleNames().equals(this.getRuleNames())) { seq.resetRuleNames(this.getRuleNames()); } seq.copyObjFlow(this.getObjectFlow()); seq.enableCompleteObjFlowOfNodes(this.completeNodesOF); seq.tryToApplyResultsOfRuleSequence(this); return seq; } private void copyObjFlow(final Hashtable<String, ObjectFlow> objFlow) { Enumeration<String> keys = objFlow.keys(); while (keys.hasMoreElements()) { final String k = keys.nextElement(); final ObjectFlow flow = objFlow.get(k); final ObjectFlow f = new ObjectFlow( flow.srcOfOutput, flow.srcOfInput, flow.indxOfOutput, flow.indxOfInput, new Hashtable<Object,Object>(flow.outputInputMap)); this.objectFlow.put(k, f); } } public void moveRule(final int from, final int to) { if (from >= 0 && from < this.rules.size() && to >= 0 && to < this.rules.size()) { Rule r = this.rules.get(from); this.clearResult(); move(r, from, to); } } private void move(final Rule r, final int from, final int to) { this.rules.remove(from); this.ruleNames.remove(from); this.rules.add(to, r); this.ruleNames.add(to, r.getName()); } public boolean isChecked() { return this.checked; } public void uncheck() { this.clearResult(); this.checked = false; } /* * Number of direct enabling predecessors */ public void setDepthOfConcurrentRule(final int d) { this.checker.setDepthOfConcurrentRule(d); } public int getDepthOfConcurrentRule() { return this.checker.getDepthOfConcurrentRule(); } /** * If the specified parameter is true, * only maximal intersection of rhs and lhs of base rules * is taken into account for building a concurrent rule, * otherwise all possible intersections are used. */ public void setCompleteConcurrency(boolean b) { this.checker.setCompleteConcurrency(b); } public boolean getCompleteConcurrency() { return this.checker.getCompleteConcurrency(); } public boolean getCompleteCPAOfConcurrency() { return this.checker.getCompleteCPAOfConcurrency(); } /* * Complete recognition of potential conflict free * summarized predecessors */ public void setCompleteCPAOfConcurrency(boolean b) { this.checker.setCompleteCPAOfConcurrency(b); } // public void setConsistentConcurrency(boolean b) { // this.checker.setConsistentConcurrency(b); // } // // public boolean getConsistentConcurrency() { // return this.checker.getConsistentConcurrency(); // } /** * Set the value of the local variable for checking * the dangling edge condition when a rule is node-deleting. */ public void setIgnoreDanglingEdgeOfDelNode(boolean b) { this.checker.setIgnoreDanglingEdgeOfDelNode(b); } /** * Returns the value of the local variable for checking * the dangling edge condition when a rule is node-deleting. */ public boolean getIgnoreDanglingEdgeOfDelNode() { return this.checker.getIgnoreDanglingEdgeOfDelNode(); } /** * Checks the current rule sequence. * Do not forget to call <code>this.setCriticalPairOption(CriticalPairOption)</code> before. * * This method starts with checking of validity of the defined object flow of this sequence. * Use the method <code>int getMessageOfInvalidObjectFlow</code> to get the error message: * <code>RuleSequence.OBJECT_FLOW_TRANSITIVE_CLOSURE_FAILED = 0</code> * <code>RuleSequence.OBJECT_FLOW_PERSISTENT_FAILED = 1</code>, * otherwise (-1). * When the object flow is valid or not defined the applicability criteria will be checked. */ public boolean check() { if (this.checked) { this.reinit(); this.matchSequence.reinit(this); } if (!this.isObjFlowValid()) { return false; } // this.tryCompleteObjFlowTransClosure(); boolean result = this.checker.check(); this.checked = true; return result; } public MatchSequence getMatchSequence() { return this.matchSequence; } protected void saveConcurrentRules() { System.out.println("saveConcurrentRules... (for test only)"); boolean dosave = false; int nn = 0; // add concurrent rules to grammar and save for (int i=0; i<this.rules.size(); i++) { Rule r = this.rules.get(i); String key = String.valueOf(r.hashCode()).concat(":").concat(String.valueOf(i)); List<List<ConcurrentRule>> lists = this.concurrentRules.get(key); if (lists != null) { if (!lists.isEmpty()) { dosave = true; } for (int j=0; j<lists.size(); j++) { List<ConcurrentRule> list = lists.get(j); for (int k=0; k<list.size(); k++) { Rule cr = list.get(k).getRule(); this.gragra.addRule(cr); nn++; } } } } if (dosave) { String aname = "CR_".concat(this.gragra.getName()).concat(".ggx"); XMLHelper xmlh = new XMLHelper(); xmlh.addTopObject(this.gragra); xmlh.save_to_xml(aname); //remove concurrent rules from grammar for (int i=0; i<nn; i++) { int indx = this.gragra.getListOfRules().size()-1; this.gragra.getListOfRules().remove(indx); } } } public Hashtable<String, Pair<Boolean, List<String>>> getRuleResults() { return this.ruleResults; } public Pair<Boolean, List<String>> getRuleResult( final int indx, final String ruleName, final String criterion) { String key = this.makeRuleKey(indx, ruleName, criterion); // System.out.println("\nRuleSequence.getRuleResult "+key+" "+this.ruleResults.get(key)); return this.ruleResults.get(key); } public boolean getRuleApplicabilityResult(final int indx, final String ruleName) { boolean result = false; if (indx==0) { String criterion = ApplicabilityConstants.INITIALIZATION; String key = this.makeRuleKey(indx, ruleName, criterion); Pair<Boolean, List<String>> pair = this.ruleResults.get(key); if (pair != null) { result = pair.first.booleanValue(); // System.out.println(result+" "+pair.second); } } else { // indx > 0 String criterion = ApplicabilityConstants.PURE_ENABLING_PREDECESSOR; String key = this.makeRuleKey(indx, ruleName, criterion); Pair<Boolean, List<String>> pair = this.ruleResults.get(key); if (pair != null) { result = result || pair.first.booleanValue(); // System.out.println(pair.first.booleanValue()+" "+pair.second); } if (pair == null || !result) { criterion = ApplicabilityConstants.DIRECT_ENABLING_PREDECESSOR; key = this.makeRuleKey(indx, ruleName, criterion); pair = this.ruleResults.get(key); if (pair != null) { result = result || pair.first.booleanValue(); // System.out.println(pair.first.booleanValue()+" "+pair.second); } } if (pair == null || !result) { criterion = ApplicabilityConstants.PARTIAL_ENABLING_PREDECESSOR; key = this.makeRuleKey(indx, ruleName, criterion); pair = this.ruleResults.get(key); if (pair != null) { result = result || this.ruleResults.get(key).first.booleanValue(); // System.out.println(pair.first.booleanValue()+" "+pair.second); } } if (pair == null || !result) { criterion = ApplicabilityConstants.PREDECESSOR_NOT_NEEDED; key = this.makeRuleKey(indx, ruleName, criterion); pair = this.ruleResults.get(key); if (pair != null) { result = result || this.ruleResults.get(key).first.booleanValue(); // System.out.println(pair.first.booleanValue()+" "+pair.second); } } } return result; } public boolean getRuleNonApplicabilityResult(final int indx, final String ruleName) { boolean result = false; String criterion = ApplicabilityConstants.INITIALIZATION_ERROR; String key = this.makeRuleKey(indx, ruleName, criterion); Pair<Boolean, List<String>> pair = this.ruleResults.get(key); if (pair != null) { result = pair.first.booleanValue(); // System.out.println(pair.first.booleanValue()+" "+pair.second); if (!result) { criterion = ApplicabilityConstants.NO_ENABLING_PREDECESSOR; key = this.makeRuleKey(indx, ruleName, criterion); pair = this.ruleResults.get(key); if (pair != null) { result = result || pair.first.booleanValue(); // System.out.println(pair.first.booleanValue()+" "+pair.second); } } } return result; } private String makeRuleKey(final int indx, final String rName, final String criterion) { String ruleKey = String.valueOf(indx); ruleKey = ruleKey.concat(rName); ruleKey = ruleKey.concat(criterion); return ruleKey; } public void setRuleResult( final int indx, final String ruleName, final boolean result, final String criterion, final String otherRuleName) { final List<String> v = new Vector<String>(); v.add(criterion); v.add(otherRuleName); final Pair<Boolean, List<String>> pair = new Pair<Boolean, List<String>>(Boolean.valueOf(result), v); String key = makeRuleKey(indx, ruleName, criterion); // System.out.println("RuleSequence.setRuleResult:: "+key+" "+result +" (( "+otherRuleName); this.ruleResults.put(key, pair); } public void setApplicabilityResult(final boolean result, final String criterion) { if (ApplicabilityConstants.UNDEFINED.equals(this.applResult.second) || (this.applResult.first.booleanValue() && !result)) { this.applResult.first = new Boolean(result); this.applResult.second = criterion; } } /* private void setNonApplicabilityResultORIG(final boolean result, final String criterion) { if (ApplicabilityConstants.UNDEFINED.equals(this.nonapplResult.second) || (this.nonapplResult.first.booleanValue() && !result)) { this.nonapplResult.first = new Boolean(result); this.nonapplResult.second = criterion; } } */ public void setNonApplicabilityResult(final boolean result, final String criterion) { if (ApplicabilityConstants.UNDEFINED.equals(this.nonapplResult.second) || (!this.nonapplResult.first.booleanValue() && result)) { this.nonapplResult.first = new Boolean(result); this.nonapplResult.second = criterion; } } /* (non-Javadoc) * @see agg.xt_basis.GraTraEventListener#graTraEventOccurred(agg.xt_basis.GraTraEvent) */ public void graTraEventOccurred(GraTraEvent e) { if ((e.getMessage() == GraTraEvent.STEP_COMPLETED)) { Match match = e.getMatch(); OrdinaryMorphism comatch = match.getCoMorphism(); this.matchSequence.addComatch(match.getRule(), comatch); } } public boolean containsObjFlow(final Hashtable<String, ObjectFlow> objFlow) { List<Object> keys1 = new Vector<Object>(this.objectFlow.keySet()); List<Object> keys2 = new Vector<Object>(objFlow.keySet()); if ((keys1.isEmpty() && !keys2.isEmpty()) || (!keys1.isEmpty() && keys2.isEmpty())) { return false; } if (keys1.containsAll(keys2)) { for (int i=0; i<keys2.size(); i++) { final ObjectFlow flow2 = objFlow.get(keys2.get(i)); final ObjectFlow flow1 = this.objectFlow.get(flow2.getKey()); if (flow1 == null || !flow1.compareTo(flow2)) { return false; } } } else { return false; } return true; } public boolean extendsRuleList(final List<String> ruleList) { if (this.ruleNames.size() < ruleList.size()) return false; for (int i=0; i<ruleList.size(); i++) { if (!ruleList.get(i).equals(this.ruleNames.get(i))) return false; } return true; } /** * Returns true when these three conditions are satisfied : * 1) the graph (name) of this sequence is equal to the graph (name) * of the specified sequence or both graphs are undefined, * 2) the rule list of this sequence extends the rule list of the specified sequence, * 3) this sequence contains the object flow of the specified sequence, * otherwise - false. * */ public boolean extendsRuleSequence(final RuleSequence ruleSeq) { if (((this.graph != null && ruleSeq.getGraph() != null && this.graph.getName().equals(ruleSeq.getGraph().getName())) || (this.graph == null && ruleSeq.getGraph() == null)) && this.extendsRuleList(ruleSeq.getRuleNames()) && this.containsObjFlow(ruleSeq.getObjectFlow())) { return true; } return false; } /** * When results of the specified rule sequence, which is already checked, are applied, * returns the index of the next rule to check, * otherwise - 0; * * The specified rule sequence must be : * - shorter then current sequence, * - all its rules in given order are at beginning of the current sequence, * - using the same host graph, * - using similar object flow, * - already checked. * */ public int tryToApplyResultsOfRuleSequence(final RuleSequence ruleSeq) { int res = 0; if (this.usePreviousSequenceResults && ruleSeq != null && ruleSeq.isChecked() && !this.checked && this.extendsRuleSequence(ruleSeq) && this.getDepthOfConcurrentRule() == ruleSeq.getDepthOfConcurrentRule() && this.getCompleteConcurrency() == ruleSeq.getCompleteConcurrency() && this.getCompleteCPAOfConcurrency() == ruleSeq.getCompleteCPAOfConcurrency()) { final Hashtable<String, Pair<Boolean, List<String>>> table = ruleSeq.getRuleResults(); Enumeration<String> keys = table.keys(); while (keys.hasMoreElements()) { String key = keys.nextElement(); Pair<Boolean, List<String>> p = table.get(key); Pair<Boolean, List<String>> p1 = new Pair<Boolean, List<String>>( Boolean.valueOf(p.first.booleanValue()), new Vector<String>(p.second)); this.getRuleResults().put(key, p1); } final Pair<Boolean, String> applRes = ruleSeq.getApplicabilityResult(); this.applResult.first = applRes.first; this.applResult.second = applRes.second; final Pair<Boolean, String> nonapplRes = ruleSeq.getNonApplicabilityResult(); this.nonapplResult.first = nonapplRes.first; this.nonapplResult.second = nonapplRes.second; tryToApplyDoneMatchesOfRuleSequence(ruleSeq); res = ruleSeq.getRules().size(); } return res; } private void tryToApplyDoneMatchesOfRuleSequence(final RuleSequence ruleSeq) { final List<Rule> otherRules = ruleSeq.matchSequence.rules; for (int i=0; i<otherRules.size(); i++) { final Rule r = otherRules.get(i); final Rule preRule = (i==0)? null : otherRules.get(i-1); final Hashtable<GraphObject, GraphObject> match = new Hashtable<GraphObject, GraphObject>(ruleSeq.matchSequence.matches.get(i)); this.matchSequence.matches.add(match); this.matchSequence.rules.add(r); if (preRule != null) { if (ruleSeq.matchSequence.imgObj2Rule.get(Integer.valueOf(i-1)) != null) { this.matchSequence.imgObj2Rule.put(Integer.valueOf(i-1), preRule); } else { if (ruleSeq.matchSequence.imgObj2ConcurrentRule.get(Integer.valueOf(i)) != null) { this.matchSequence.imgObj2ConcurrentRule.put( Integer.valueOf(i), ruleSeq.matchSequence.imgObj2ConcurrentRule.get(Integer.valueOf(i))); } } } } } public Hashtable<GraphObject, GraphObject> getInput2outputMapIntoGraphAbovePreRule( final Rule targetRule, int targetIndx, final List<ObjectFlow> targetObjFlowList, final Rule rule, int ruleIndx, final Hashtable<GraphObject, GraphObject> input2postInput, final Graph g) { final Hashtable<GraphObject, GraphObject> map = new Hashtable<GraphObject, GraphObject>(); final Rule preRule = this.getRule(ruleIndx-1); if (preRule != null) { final List<ObjectFlow> preObjFlowList = this.getObjFlowForRule(preRule, ruleIndx-1); if (preObjFlowList.isEmpty()) { return map; } boolean alreadyChecked = (rule == targetRule); List<ObjectFlow> objFlowList = this.getObjFlowForRule(rule, ruleIndx); if (objFlowList.isEmpty() && rule != targetRule) { objFlowList = targetObjFlowList; alreadyChecked = true; } boolean done = reflectObjFlow(preObjFlowList, objFlowList, map, input2postInput, g); if (!done && !alreadyChecked) { objFlowList = targetObjFlowList; reflectObjFlow(preObjFlowList, objFlowList, map, input2postInput, g); } } return map; } private boolean reflectObjFlow( final List<ObjectFlow> preObjFlowList, final List<ObjectFlow> objFlowList, final Hashtable<GraphObject, GraphObject> map, final Hashtable<GraphObject, GraphObject> input2postInput, final Graph g) { boolean result = false; if (!objFlowList.isEmpty()) { if (!preObjFlowList.isEmpty()) { for (int i=0; i<objFlowList.size(); i++) { ObjectFlow objFlow = objFlowList.get(i); List<Object> inputObjs = objFlow.getInputs(); for (int k=0; k<inputObjs.size(); k++) { GraphObject inObj = (GraphObject) inputObjs.get(k); for (int j=0; j<preObjFlowList.size(); j++) { ObjectFlow preObjFlow = preObjFlowList.get(j); GraphObject connectedInObj = (GraphObject) objFlow.getConnectedInput(preObjFlow, inObj); GraphObject connectedOutObj = (GraphObject) objFlow.getConnectedOutput(preObjFlow, inObj); if (connectedOutObj != null) { if (g.isElement(connectedOutObj)) { if (input2postInput.isEmpty()) { map.put(inObj, connectedOutObj); result = true; } else if (connectedInObj != null && input2postInput.get(connectedInObj) != null) { map.put(input2postInput.get(connectedInObj), connectedOutObj); input2postInput.remove(connectedInObj); result = true; } } else if (connectedInObj != null) { input2postInput.put(connectedInObj, inObj); result = true; } } } } } } } return result; } //TODO: to optimize public Hashtable<GraphObject, GraphObject> getReflectedObjectFlowOfGraphAndPreRule( final ConcurrentRule cr, final List<ObjectFlow> targetObjFlowList, final Rule rule, int ruleIndx, final Hashtable<GraphObject, GraphObject> input2postInput, final Graph g) { final Hashtable<GraphObject, GraphObject> map = new Hashtable<GraphObject, GraphObject>(); final Rule preRule = this.getRule(ruleIndx-1); if (preRule != null) { final List<ObjectFlow> preObjFlowList = this.getObjFlowForRule(preRule, ruleIndx-1); if (preObjFlowList.isEmpty()) { return map; } boolean alreadyChecked = false; List<ObjectFlow> objFlowList = this.getObjFlowForRule(rule, ruleIndx); if (objFlowList.isEmpty()) { objFlowList = targetObjFlowList; alreadyChecked = true; } boolean done = reflectObjFlow(cr, preRule, preObjFlowList, objFlowList, map, input2postInput, g); if (!done && !alreadyChecked) { objFlowList = targetObjFlowList; reflectObjFlow(cr, preRule, preObjFlowList, objFlowList, map, input2postInput, g); } } return map; } public void removeEmptyObjFlow() { Enumeration<String> keys = this.objectFlow.keys(); while (keys.hasMoreElements()) { String key = keys.nextElement(); ObjectFlow objFlow = this.objectFlow.get(key); if (objFlow.isEmpty()) { this.objectFlow.remove(key); keys = this.objectFlow.keys(); } } } private boolean reflectObjFlow( final ConcurrentRule cr, final Rule preRule, final List<ObjectFlow> preObjFlowList, final List<ObjectFlow> objFlowList, final Hashtable<GraphObject, GraphObject> map, final Hashtable<GraphObject, GraphObject> input2postInput, final Graph g) { boolean result = false; if (!objFlowList.isEmpty() && !preObjFlowList.isEmpty()) { for (int i=0; i<objFlowList.size(); i++) { ObjectFlow objFlow = objFlowList.get(i); Hashtable<Object, Object> outInMap = objFlow.getMapping(); Enumeration<Object> outs = outInMap.keys(); while (outs.hasMoreElements()) { Object out = outs.nextElement(); if (out instanceof GraphObject && preRule.getRight().isElement((GraphObject) out)) { Enumeration<GraphObject> inverse = preRule.getInverseImage((GraphObject) out); while (inverse.hasMoreElements()) { GraphObject prein = inverse.nextElement(); for (int j=0; j<preObjFlowList.size(); j++) { ObjectFlow preObjFlow = preObjFlowList.get(j); Hashtable<Object, Object> preOutInMap = preObjFlow.getMapping(); Enumeration<Object> preOuts = preOutInMap.keys(); while (preOuts.hasMoreElements()) { Object preOut = preOuts.nextElement(); if (preOut instanceof GraphObject && (prein == preObjFlow.getMapping().get(preOut))) { GraphObject inObj = (GraphObject)objFlow.getMapping().get(out); GraphObject crInObj = cr.getLeftEmbedding(inObj); if (crInObj != null) { if (g.isElement((GraphObject) preOut)) { if (input2postInput.isEmpty()) { map.put(crInObj, (GraphObject)preOut); result = true; } else if (input2postInput.get(prein) != null) { map.put(input2postInput.get(prein), (GraphObject)preOut); input2postInput.remove(prein); result = true; } } else if (preRule.getRight().isElement((GraphObject) preOut)) { input2postInput.put(prein, crInObj); result = true; } } } } } } } } } } return result; } public void addObjFlow(final ObjectFlow objFlow) { if (objFlow != null) { int indx1 = objFlow.getIndexOfOutput(); int indx2 = objFlow.getIndexOfInput(); if (indx1 >= 0 && indx2 > indx1) { String keyStr = objFlow.getKey(); this.objectFlow.put(keyStr, objFlow); // System.out.println("Rulesequence.addObjectFlow:: "+keyStr+" "+objFlow); } } } public void removeObjFlow(final ObjectFlow objFlow) { if (objFlow != null) { int indx1 = objFlow.getIndexOfOutput(); int indx2 = objFlow.getIndexOfInput(); if (indx1 >= 0 && indx2 > indx1) { String keyStr = objFlow.getKey(); this.objectFlow.remove(keyStr); // System.out.println("Rulesequence.removeObjectFlow:: "+keyStr+" "+objFlow); } } } public void removeObjFlowOfGraph() { // remove graph outputs from object flow if (this.graph != null) { Enumeration<String> keys = this.objectFlow.keys(); while (keys.hasMoreElements()) { String key = keys.nextElement(); String[] keyItems = key.split(":"); if (keyItems[0].equals("0")) { this.objectFlow.remove(key); keys = this.objectFlow.keys(); } } } } public void removeObjFlow() { this.objectFlow.clear(); } /** * Returns an object flow which is defined for the given rule r1 as output and * the rule r2 as input. * * @param r1 output of an object flow * @param indx_r1 index in the rule sequence * @param r2 input of an object flow * @param indx_r2 index in the rule sequence */ public ObjectFlow getObjFlowForRules(final Rule r1, int indx_r1, final Rule r2, int indx_r2) { int i1 = indx_r1; int i2 = indx_r2; if (this.graph != null) { i1++; i2++; } Enumeration<String> keys = this.objectFlow.keys(); while (keys.hasMoreElements()) { String key = keys.nextElement(); ObjectFlow objFlow = this.objectFlow.get(key); if (objFlow.getSourceOfOutput() == r1 && objFlow.getIndexOfOutput() == i1 && objFlow.getSourceOfInput() == r2 && objFlow.indxOfInput == i2) { return objFlow; } } return null; } public ObjectFlow getObjFlowForGraphAndRule(final Rule r, int indx_r) { int i = indx_r; if (this.graph == null) return null; i++; Enumeration<String> keys = this.objectFlow.keys(); while (keys.hasMoreElements()) { String key = keys.nextElement(); // System.out.println(key); ObjectFlow objFlow = this.objectFlow.get(key); if (objFlow.getSourceOfOutput() == this.graph && objFlow.getSourceOfInput() == r && objFlow.indxOfInput == i) { return objFlow; } } return null; } /** * Returns a list with all defined object flows of the given rule. * * @param r rule * @param indx rule index in the rule sequence */ public List<ObjectFlow> getObjFlowForRule(final Rule r, int indx) { final List<ObjectFlow> list = new Vector<ObjectFlow>(); if (indx < 0) { return list; } int i = indx; if (this.graph != null) i++; Enumeration<String> keys = this.objectFlow.keys(); while (keys.hasMoreElements()) { String key = keys.nextElement(); String[] keyItems = key.split(":"); if (Integer.valueOf(keyItems[1]).intValue() == i) { list.add(this.objectFlow.get(key)); } } return list; } public List<ObjectFlow> getObjFlowFromGraph() { final List<ObjectFlow> list = new Vector<ObjectFlow>(); if (this.graph != null) { Enumeration<String> keys = this.objectFlow.keys(); while (keys.hasMoreElements()) { String key = keys.nextElement(); String[] keyItems = key.split(":"); if (Integer.valueOf(keyItems[0]).intValue() == 0) { list.add(this.objectFlow.get(key)); } } } return list; } public List<ObjectFlow> getObjFlowFromRule(final Rule r, int indx) { final List<ObjectFlow> list = new Vector<ObjectFlow>(); if (indx < 0) { return list; } int i = indx; if (this.graph != null) i++; Enumeration<String> keys = this.objectFlow.keys(); while (keys.hasMoreElements()) { String key = keys.nextElement(); String[] keyItems = key.split(":"); if (Integer.valueOf(keyItems[0]).intValue() == i) { list.add(this.objectFlow.get(key)); } } return list; } public int getSizeOfObjFlowForRule(final Rule r, int indx) { if (indx < 0) { return 0; } int i = indx; if (this.graph != null) i++; int size = 0; Enumeration<String> keys = this.objectFlow.keys(); while (keys.hasMoreElements()) { String key = keys.nextElement(); String[] keyItems = key.split(":"); if (Integer.valueOf(keyItems[1]).intValue() == i) { size = size + this.objectFlow.get(key).getSizeOfInput(); } } return size; } /* * When an object flow defined for this rule sequence * returns all rules of an input object which is connected to * an output object of the given Object which can be Rule or Graph, * otherwise - empty list. * * @param output is Rule or Graph * @param itsIndx * @return */ /* private List<Rule> getConnectedInputOfOutput(final Object outputSource, int itsIndx) { final List<Rule> list = new Vector<Rule>(); if (itsIndx < 0) { return list; } Enumeration<String> keys = this.objectFlow.keys(); while (keys.hasMoreElements()) { String key = keys.nextElement(); String[] keyItems = key.split(":"); if (Integer.valueOf(keyItems[0]).intValue() == itsIndx && this.objectFlow.get(key).getSourceOfOutput() == outputSource) { int rindx = Integer.valueOf(keyItems[1]).intValue(); if (this.graph != null) rindx--; final Rule inRule = this.getRule(rindx); if (inRule != null) list.add(inRule); } } return list; } */ private List<Pair<Rule, Integer>> getNextRuleOfObjFlow(final Object outputSource, int itsIndx) { final List<Pair<Rule, Integer>> list = new Vector<Pair<Rule, Integer>>(); if (itsIndx < 0) { return list; } Enumeration<String> keys = this.objectFlow.keys(); while (keys.hasMoreElements()) { String key = keys.nextElement(); String[] keyItems = key.split(":"); if (Integer.valueOf(keyItems[0]).intValue() == itsIndx && this.objectFlow.get(key).getSourceOfOutput() == outputSource) { final Rule r2 = (Rule) this.objectFlow.get(key).getSourceOfInput(); list.add(new Pair<Rule, Integer>(r2, Integer.valueOf(keyItems[1]))); } } return list; } private GraphObject getConnectedInputForOutput( final Object ouputSource, int itsIndx, final GraphObject out, final Rule r2) { if (itsIndx < 0) { return null; } Enumeration<String> keys = this.objectFlow.keys(); while (keys.hasMoreElements()) { String key = keys.nextElement(); String[] keyItems = key.split(":"); if (Integer.valueOf(keyItems[0]).intValue() == itsIndx && this.objectFlow.get(key).getSourceOfOutput() == ouputSource && this.objectFlow.get(key).getSourceOfInput() == r2) { return (GraphObject) this.objectFlow.get(key).getMapping().get(out); } } return null; } private List<GraphObject> getOutputObjsOfOutput( final Object output, int itsIndx) { final List<GraphObject> list = new Vector<GraphObject>(); if (itsIndx < 0) { return list; } final Enumeration<String> keys = this.objectFlow.keys(); while (keys.hasMoreElements()) { String key = keys.nextElement(); String[] keyItems = key.split(":"); if (Integer.valueOf(keyItems[0]).intValue() == itsIndx && this.objectFlow.get(key).getSourceOfOutput() == output) { final ObjectFlow objFlow = this.objectFlow.get(key); if (objFlow.getSourceOfOutput() == output) { final Enumeration<Object> outputs = objFlow.getMapping().keys(); while (outputs.hasMoreElements()) { final Object obj = outputs.nextElement(); if (!list.contains(obj)) list.add((GraphObject) obj); } } } } return list; } private void getClosuresOfObjFlow( final Object outputSource, int itsIndx, final GraphObject outObj, final List<Triple<GraphObject, Rule, Integer>> closures) { if (itsIndx < 0) { return; } final List<Pair<Rule, Integer>> nextRule = this.getNextRuleOfObjFlow(outputSource, itsIndx); for (int r=0; r<nextRule.size(); r++) { final Pair<Rule, Integer> pair = nextRule.get(r); final Rule rule = pair.first; final GraphObject inputObj = getConnectedInputForOutput( outputSource, itsIndx, outObj, rule); if (inputObj != null) { closures.add(new Triple<GraphObject, Rule, Integer>(inputObj, rule, pair.second)); final GraphObject rhsObj = rule.getImage(inputObj); if (rhsObj != null) { getClosuresOfObjFlow(rule, pair.second.intValue(), rhsObj, closures); } } } } public int getMessageOfInvalidObjectFlow() { return this.objectFlowError; } /** * Returns <code>true</code> if the transitive closure of the object flow * for this rule sequence exists and the object flow is persistent, * otherwise <code>false</code>. * * @see #getMessageOfInvalidObjectFlow() for error kind like: * <code> RuleSequence.OBJECT_FLOW_TRANSITIVE_CLOSURE_FAILED</code> or * <code> RuleSequence.OBJECT_FLOW_PERSISTENT_FAILED</code>. */ public boolean isObjFlowValid() { this.objectFlowError = -1; if (this.objectFlow != null && !this.objectFlow.isEmpty()) { final List<Object> tmp = new Vector<Object> (this.rules); if (this.graph != null) tmp.add(0, this.graph); boolean closureOK = true; for (int i=0; i<tmp.size() && closureOK; i++) { final Object outputSource = tmp.get(i); final List<GraphObject> rOutputs = getOutputObjsOfOutput(outputSource, i); if (rOutputs.isEmpty()) continue; for (int j=0; j<rOutputs.size() && closureOK; j++) { final GraphObject outObj = rOutputs.get(j); // System.out.println("\n out object: "+outObj); final List<Triple<GraphObject, Rule, Integer>> closures = new Vector<Triple<GraphObject, Rule, Integer>>(); // collect recursively closure input objects of an output object // outputSource - Graph or Rule // i - index of this rule sequence // outObj - GraphObject as output // closures - container to fill getClosuresOfObjFlow(outputSource, i, outObj, closures); if (!this.isObjFlowTransitive(closures)) { this.objectFlowError = RuleSequence.OBJECT_FLOW_TRANSITIVE_CLOSURE_FAILED; closureOK = false; } else if (!this.isObjFlowPersistent(closures)) { this.objectFlowError = RuleSequence.OBJECT_FLOW_PERSISTENT_FAILED; closureOK = false; } } } return closureOK; } return true; } /** * Checks whether the transitive closure of the object flow * for this rule sequence exists. */ private boolean isObjFlowTransitive( final List<Triple<GraphObject, Rule, Integer>> closures) { // no different input objects for an output inside the same graph for (int k=0; k<closures.size()-1; k++) { Triple<GraphObject, Rule, Integer> triple = closures.get(k); GraphObject go1 = triple.first; for (int l=1; l<closures.size(); l++) { // l=k+1??? Triple<GraphObject, Rule, Integer> triple2 = closures.get(l); GraphObject go2 = triple2.first; if (go1.getContext() == go2.getContext() && go1 != go2) { return false; } } } return true; } public void tryCompleteObjFlowTransClosure() { tryCompleteArcsOF(); final Vector<Object> tmp = new Vector<Object> (this.rules); boolean withGraph = false; if (this.graph != null) { if (tmp.get(0) != this.graph) tmp.add(0, this.graph); withGraph = true; } completeNodeTC(tmp, withGraph); completeNodeTC1(tmp, withGraph); } private void completeNodeTC(final Vector<Object> tmp, boolean withGraph) { for (int i=0; i<tmp.size()-1; i++) { final Object outSrc = tmp.get(i); if (outSrc instanceof Rule) { for (int j=i+1; j<tmp.size()-1; j++) { final Object inSrc1 = tmp.get(j); final Object inSrc2 = tmp.get(j+1); if (inSrc1 instanceof Rule && inSrc2 instanceof Rule) { Iterator<Node> elems = ((Rule)outSrc).getRight().getNodesSet().iterator(); while (elems.hasNext()) { GraphObject go_out = elems.next(); this.tryCompleteNodeTC(go_out, (Rule)outSrc, i, (Rule)inSrc1, j, (Rule)inSrc2, j+1, withGraph); } } } } } } private void completeNodeTC1( final Vector<Object> tmp, boolean withGraph) { int c= withGraph? -1: 0; for (int i=0; i<tmp.size()-1; i++) { final Object outSrc = tmp.get(i); int j = i+1; final Object inSrc = tmp.get(j); ObjectFlow of = null; if (outSrc instanceof Rule) of = this.getObjFlowForRules((Rule)outSrc, i+c, (Rule)inSrc, j+c); else if (outSrc instanceof Graph) of = this.getObjFlowForGraphAndRule((Rule)inSrc, j+c); if (of != null && i >= 1 && tmp.get(i-1) instanceof Rule) { Enumeration<GraphObject> elems = ((Rule)inSrc).getLeft().getElements(); while (elems.hasMoreElements()) { GraphObject go_in = elems.nextElement(); if (of.isInputObject(go_in)) { if (i-1 >= 0) { GraphObject go_out = (GraphObject)of.getOutput(go_in); Triple<GraphObject, Rule, Integer> result = tryCompleteTransClosure( go_out, (Rule) tmp.get(i-1), i-1, (Rule) tmp.get(j-1), j-1, withGraph); int l = i-1; int k = j-1; while (result != null) { ObjectFlow of1 = this.getObjFlowForRules( result.second, result.third.intValue()+c, (Rule)inSrc, j+c); if (of1 == null) { of1 = new ObjectFlow(result.second, inSrc, result.third.intValue(), j); of1.addMapping(result.first, go_in); this.addObjFlow(of1); } else if (!of1.isInputObject(go_in)) { of1.addMapping(result.first, go_in); } l--; k--; if (l >= 0 && k >= 0 && tmp.get(l) instanceof Rule && tmp.get(k) instanceof Rule) { result = tryCompleteTransClosure(result.first, (Rule)tmp.get(l), l, (Rule)tmp.get(k), k, withGraph); } else break; } } } } } } } @SuppressWarnings("unused") private void tryCompleteNodeOF( final GraphObject go_in, final Object inSrc, int inIndx, final List<Object> tmp) { ObjectFlow of = null; int c=0; if (this.graph != null && tmp.get(0) == this.graph) c--; for (int i=tmp.size()-1; i>=0; i--) { final Object outSrc = tmp.get(i); if (outSrc instanceof Rule) of = this.getObjFlowForRules((Rule)outSrc, i+c, (Rule)inSrc, inIndx+c); else if (outSrc instanceof Graph) of = this.getObjFlowForGraphAndRule((Rule)inSrc, inIndx+c); GraphObject go_out = null; if (outSrc instanceof Rule) { List<GraphObject> objs = ((Rule)outSrc).getElementsToCreate(); for (int l=0; l<objs.size(); l++) { go_out = objs.get(l); if (go_out.compareTo(go_in)) { // TODO: check if can map? break; } else go_out = null; } if (go_out == null) { objs = ((Rule)outSrc).getCodomainObjects(); for (int l=0; l<objs.size(); l++) { go_out = objs.get(l); if (go_out.compareTo(go_in)) { // TODO: check if can map? break; } else go_out = null; } } if (go_out != null) { if (of == null) { of = new ObjectFlow((Rule)outSrc, inSrc, i, inIndx); this.addObjFlow(of); } this.addObjFlow(of); of.addMapping(go_out, go_in); break; } } } } private Triple<GraphObject, Rule, Integer> tryCompleteTransClosure( final GraphObject go_out, Rule r_out, int j, Rule r_in, int i, boolean withGraph) { int c = withGraph? -1: 0; Enumeration<GraphObject> en = r_in.getInverseImage(go_out); if (en.hasMoreElements()) { GraphObject go = en.nextElement(); ObjectFlow of = this.getObjFlowForRules(r_out, j+c, r_in, i+c); if (of != null && of.isInputObject(go)) { GraphObject go_out_j = (GraphObject)of.getOutput(go); return new Triple<GraphObject, Rule, Integer>(go_out_j, r_out, Integer.valueOf(j)); } } return null; } private void tryCompleteNodeTC( final GraphObject go_out, final Rule r_out, int j, final Rule r_in1, int i1, final Rule r_in2, int i2, boolean withGraph) { int c = withGraph? -1: 0; if (i2 > i1) { ObjectFlow of1 = this.getObjFlowForRules(r_out, j+c, r_in1, i1+c); if (of1 != null) { ObjectFlow of2 = this.getObjFlowForRules(r_out, j+c, r_in2, i2+c); Object go_in1 = of1.getInput(go_out); if (go_in1 != null) { GraphObject go_out3 = r_in1.getImage((GraphObject) go_in1); if (go_out3 != null) { if (of2 != null) { ObjectFlow of3 = this.getObjFlowForRules(r_in1, i1+c, r_in2, i2+c); Object go_in2 = of2.getInput(go_out); if (go_in2 != null) { if (of3 == null) { of3 = new ObjectFlow(r_in1, r_in2, i1, i2); this.addObjFlow(of3); } if (of3.getInput(go_out3) == null) { of3.addMapping(go_out3, (GraphObject)go_in2); } } else { if (of3 != null) { Object go_in3 = of3.getInput(go_out3); if (go_in3 != null) { of2.addMapping(go_out, (GraphObject)go_in3); } } } } else { ObjectFlow of3 = this.getObjFlowForRules(r_in1, i1+c, r_in2, i2+c); if (of3 != null) { Object go_in3 = of3.getInput(go_out3); if (go_in3 != null) { of2 = new ObjectFlow(r_out, r_in2, j, i2); this.addObjFlow(of2); of2.addMapping(go_out, (GraphObject)go_in3); } } } } } } else { ObjectFlow of2 = this.getObjFlowForRules(r_out, j+c, r_in2, i2+c); if (of2 != null) { Object go_in2 = of2.getInput(go_out); if (go_in2 != null) { ObjectFlow of3 = this.getObjFlowForRules(r_in1, i1+c, r_in2, i2+c); if (of3 != null) { Object go_out3 = of3.getOutput(go_in2); if (go_out3 != null) { Enumeration<GraphObject> en = r_in1.getInverseImage((GraphObject)go_out3); if (en.hasMoreElements()) { of1 = new ObjectFlow(r_out, r_in1, j, i1); this.addObjFlow(of1); of1.addMapping(go_out, en.nextElement()); } } } } } } } } private void tryCompleteArcsOF() { Enumeration<String> keys = this.objectFlow.keys(); while (keys.hasMoreElements()) { ObjectFlow of = this.objectFlow.get(keys.nextElement()); int indxR1 = of.getIndexOfOutput(); if (this.graph != null) indxR1--; Rule r1 = this.getRule(indxR1); if ( r1 != null) { Object outSrc = of.getSourceOfOutput(); Object inSrc = of.getSourceOfInput(); Graph inG = ((Rule)inSrc).getLeft(); Graph outG = ((Rule)outSrc).getRight(); Iterator<Arc> arcs = outG.getArcsCollection().iterator(); while (arcs.hasNext()) { Arc a = arcs.next(); if (this.completeNodesOF) { // source of arc is connected by OF if (of.isOutputObject(a.getSource()) && !of.isOutputObject(a.getTarget())) { Node inNode = (Node) of.getInput(a.getSource()); Iterator<Arc> outgoings = inNode.getOutgoingArcs(); while (outgoings.hasNext()) { Arc outgoing = outgoings.next(); if (outgoing.getTarget().getType().isParentOf(a.getTarget().getType())) { Node goL1 = null; // get left go of r1 Enumeration<GraphObject> gosL1 = r1.getInverseImage(a.getTarget()); if (gosL1.hasMoreElements()) { goL1 = (Node) gosL1.nextElement(); } if (goL1 == null) { if (!outgoing.getTarget().isAttrMemConstantValDifferent(a.getTarget())) { // connect target of.addMapping(a.getTarget(), outgoing.getTarget()); // System.out.println(of.getKey()+" new (target) node mapping of ObjectFlow added"); break; } } else if (!outgoing.getTarget().isAttrMemConstantValDifferent(a.getTarget(), goL1)) { // connect target of.addMapping(a.getTarget(), outgoing.getTarget()); // System.out.println(of.getKey()+" new (target) node mapping of ObjectFlow added"); break; } } } } // target of arc is connected by OF else if (!of.isOutputObject(a.getSource()) && of.isOutputObject(a.getTarget())) { Node inNode = (Node) of.getInput(a.getTarget()); Iterator<Arc> incomings = inNode.getIncomingArcs(); while (incomings.hasNext()) { Arc incoming = incomings.next(); if (incoming.getSource().getType().isParentOf(a.getSource().getType())) { Node goL1 = null; // get left go of r1 // get left go of r1 Enumeration<GraphObject> gosL1 = r1.getInverseImage(a.getSource()); if (gosL1.hasMoreElements()) { goL1 = (Node) gosL1.nextElement(); } if (goL1 == null) { if (!incoming.getSource().isAttrMemConstantValDifferent(a.getSource())) { // connect source of.addMapping(a.getSource(), incoming.getSource()); // System.out.println(of.getKey()+" new (source) node mapping of ObjectFlow added"); break; } } else if (!incoming.getSource().isAttrMemConstantValDifferent(a.getSource(), goL1)) { // connect target of.addMapping(a.getSource(), incoming.getSource()); // System.out.println(of.getKey()+" new (source) node mapping of ObjectFlow added"); break; } } } } } // source and target of arc are connected by OF if (of.isOutputObject(a.getSource()) && of.isOutputObject(a.getTarget()) && !of.isOutputObject(a)) { Node src = (Node)of.getInput(a.getSource()); Node tar = (Node)of.getInput(a.getTarget()); List<Arc> list = inG.getArcs(a.getType(), src, tar); if (list != null && !list.isEmpty()) { // connect arc for (int i=0; i<list.size(); i++) { Arc a1 = list.get(0); if (a1.getType().isParentOf(a.getType())) { Arc goL1 = null; // get left go of r1 Enumeration<GraphObject> gosL1 = r1.getInverseImage(a); if (gosL1.hasMoreElements()) { goL1 = (Arc) gosL1.nextElement(); } if (goL1 == null) { if (!a1.isAttrMemConstantValDifferent(a)) { of.addMapping(a,a1); // System.out.println(of.getKey()+" new arc mapping of ObjectFlow added"); break; } } else if (!a1.isAttrMemConstantValDifferent(a, goL1)) { // connect target of.addMapping(a, a1); // System.out.println(of.getKey()+" new arc mapping of ObjectFlow added"); break; } } } } } } } } } private boolean isObjFlowPersistent( final List<Triple<GraphObject, Rule, Integer>> closures) { for (int k=0; k<closures.size()-1; k++) { Triple<GraphObject, Rule, Integer> triple = closures.get(k); GraphObject go1 = triple.first; Rule r1 = triple.second; int indx1 = triple.third.intValue(); // System.out.println("1) "+r1.getName()+" "+indx1); for (int l=1; l<closures.size(); l++) { Triple<GraphObject, Rule, Integer> triple2 = closures.get(l); GraphObject go2 = triple2.first; Rule r2 = triple2.second; int indx2 = triple2.third.intValue(); // System.out.println("2) "+r2.getName()+" "+indx2); if (go1 != go2) { if (indx1 < indx2 && (r1.getImage(go1) == null)) { // System.out.println("persistent object of the object flow failed : " // +go1+" , "+go2); return false; } else if (indx2 < indx1 && (r2.getImage(go2) == null)) { // System.out.println("persistent object of the object flow failed : " // +go1+" , "+go2); return false; } } } } return true; } public static void printObjFlow(final RuleSequence currentSequence) { System.out.println(); final Hashtable<String, ObjectFlow> objectFlows=currentSequence.getObjectFlow(); for(int i=0;i<=currentSequence.getRules().size()-1;i++){ for(int j=i+1;j<=currentSequence.getRules().size();j++){ ObjectFlow of=objectFlows.get(i+":"+j); if(of!=null){ System.out.println("Object flow: "+i+":"+j +" from "+of.getNameOfOutput()+" to " +of.getNameOfInput()); for(Object oneKey:of.getMapping().keySet()){ GraphObject value=(GraphObject) of.getMapping().get(oneKey); GraphObject key=(GraphObject) oneKey; System.out.println("Map: from "+key.getObjectName() +":"+key.getType().getName() + " to "+value.getObjectName()+":"+value.getType().getName()); } } } } } /** * Trims the capacity of used vectors to be the vector's current * size. */ public void trimToSize() { this.rules.trimToSize(); this.ruleNames.trimToSize(); ((Vector<Pair<List<Pair<String, String>>, String>>)this.subSequenceList).trimToSize(); } }