package agg.xt_basis; import java.util.Hashtable; import java.util.List; import java.util.Vector; import java.util.Date; import java.io.FileOutputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.File; import agg.attribute.AttrException; import agg.attribute.impl.VarTuple; import agg.cons.AtomConstraint; import agg.ruleappl.RuleSequence; import agg.util.Pair; import agg.xt_basis.agt.RuleScheme; public class RuleSequencesGraTraImpl extends GraTra { protected boolean appliedOnce, eachRuleToApply; protected boolean trafoSequenceBroken; protected boolean allRulesEnabled = false; protected int indx=-1; protected RuleSequence ruleSequence; protected List<Pair<List<Pair<Rule, String>>, String>> ruleSubsequences; protected List<String> ruleNameSequences; protected File f; protected FileOutputStream os; protected String protocolFileName = ""; protected boolean grammarChecked; protected long time; public RuleSequencesGraTraImpl() {} public void dispose() { this.clearRuleSequence(); super.dispose(); } public boolean setGraGra(GraGra gg) { boolean res = super.setGraGra(gg); if (this.grammar.getRuleSequenceList() != null) { setRuleSequence(this.grammar.getRuleSequenceList()); } return res; } public void setEachRuleToApply(boolean b) { this.eachRuleToApply = b; } public boolean isEachRuleToApply() { return this.eachRuleToApply; } public boolean apply() { if (this.ruleSequence != null) { this.addGraTraListener(this.ruleSequence); } Pair<List<Pair<Rule, String>>, String> p; for (int i = 0; i < this.ruleSubsequences.size() && !this.stopping; i++) { String rs = (i + 1) + ". subsequence: " + this.ruleNameSequences.get(i); if (this.ruleSubsequences.size() > 1) System.out.println(rs); if (this.os != null) { writeTransformProtocol(rs); } p = this.ruleSubsequences.get(i); apply(p.first, p.second); // System.out.println((i + 1) + ". subsequence applied"); // System.out.println(); if (this.os != null) { writeTransformProtocol(rs + "\t applied"); } } if (this.ruleSequence != null) { this.removeGraTraListener(this.ruleSequence); } return this.appliedOnce; } public void setRuleSequence(final RuleSequence ruleSeq) { this.ruleSequence = ruleSeq; this.setRuleSequence(ruleSeq.getSubSequenceList()); } protected void setRuleSequence( final List<Pair<List<Pair<String, String>>, String>> sequence) { this.ruleSubsequences = new Vector<Pair<List<Pair<Rule, String>>, String>>( sequence.size()); for (int i = 0; i < sequence.size(); i++) { Pair<List<Pair<String, String>>, String> pi = sequence.get(i); List<Pair<String, String>> v = pi.first; List<Pair<Rule, String>> vec = new Vector<Pair<Rule, String>>(v .size()); for (int j = 0; j < v.size(); j++) { Pair<String, String> pj = v.get(j); Rule r = this.grammar.getRuleByQualifiedName(pj.first); Pair<Rule, String> p = new Pair<Rule, String>(r, pj.second); vec.add(p); } this.ruleSubsequences.add( new Pair<List<Pair<Rule, String>>, String>(vec, pi.second)); } } protected void clearRuleSequence() { for (int i = 0; i < this.ruleSubsequences.size(); i++) { Pair<List<Pair<Rule, String>>, String> pi = this.ruleSubsequences.get(i); List<Pair<Rule, String>> v = pi.first; for (int j = 0; j < v.size(); j++) { v.get(j).first = null; } v.clear(); } this.ruleSubsequences.clear(); } protected void apply(Rule r, String iters) { boolean ruleapplied = true; if (iters.equals("*")) { // System.out.println("\nrule: " + r.getName()+ "\t* times"); int i=0; while (ruleapplied && !this.stopping) { if (this.options.hasOption(GraTraOptions.WAIT_AFTER_STEP)) { fireGraTra(new GraTraEvent(this, GraTraEvent.RULE, r)); } if (this.ruleSequence.isTrafoByObjFlow() && !this.ruleSequence.getObjectFlow().isEmpty()) { if (this.ruleSequence.getRule(this.indx) != r || this.ruleSequence.getRule(this.indx-1) != r) { this.indx++; this.ruleSequence.getMatchSequence().setTrafoIndex(this.indx); } propagateObjFlowOfRule(this.indx, r); } if (this.currentRule.getRuleScheme() != null) { ruleapplied = apply((RuleScheme) this.currentRule); } else { ruleapplied = apply(r); } if (ruleapplied) { i++; this.appliedOnce = true; } System.out.println(r.getName() + " \t applied: " + ruleapplied); if (this.os != null) writeTransformProtocol(r.getName() + " \t applied: " + ruleapplied); if ((i==0 && !ruleapplied && this.eachRuleToApply) || !isGraphConsistent()) { this.stopping = true; this.trafoSequenceBroken = true; } } } else { long N = (new Long(iters)).longValue(); for (long i = 0; i < N && !this.stopping; i++) { if (this.options.hasOption(GraTraOptions.WAIT_AFTER_STEP)) { fireGraTra(new GraTraEvent(this, GraTraEvent.RULE, r)); } if (this.ruleSequence.isTrafoByObjFlow() && !this.ruleSequence.getObjectFlow().isEmpty()) { this.indx++; // if (this.ruleSequence.getRule(this.indx) != r // || this.ruleSequence.getRule(this.indx-1) != r) { //// this.indx++; // this.ruleSequence.getMatchSequence().setTrafoIndex(this.indx); // } this.ruleSequence.getMatchSequence().setTrafoIndex(this.indx); propagateObjFlowOfRule(this.indx, r); } if (!this.stopping) { if (this.currentRule.getRuleScheme() != null) { ruleapplied = apply((RuleScheme) this.currentRule); } else { ruleapplied = apply(r); } if (ruleapplied) { this.appliedOnce = true; } System.out.println(r.getName() + " \t applied: " + ruleapplied); if (this.os != null) writeTransformProtocol(r.getName() + " \t applied: " + ruleapplied); if ((i==0 && !ruleapplied && this.eachRuleToApply) || !isGraphConsistent()) { this.stopping = true; this.trafoSequenceBroken = true; } } } } } private void propagateObjFlowOfRule( int ind, final Rule r) { Hashtable<GraphObject, GraphObject> matchMap = (r.getRuleScheme() == null)? this.ruleSequence.getMatchSequence().getMatch(ind, r): this.ruleSequence.getMatchSequence().getMatch(ind, r.getRuleScheme().getKernelRule()); if (r.getMatch() == null) { this.currentMatch = (r.getRuleScheme() == null)? this.grammar.createMatch(r): r.getRuleScheme().getKernelMatch(this.grammar.getGraph()); this.currentMatch.setCompletionStrategy( (MorphCompletionStrategy) this.strategy.clone(), true); } else { this.currentMatch = (r.getRuleScheme() == null)? r.getMatch(): r.getRuleScheme().getKernelMatch(this.grammar.getGraph()); } if (matchMap != null && !matchMap.isEmpty()) { try { this.currentMatch.addMapping(matchMap); this.currentMatch.setPartialMorphismCompletion(true); this.currentMatch.adaptAttrContextValues(this.currentMatch.getRule().getAttrContext()); this.currentMatch.adaptAttrContextValuesFromExistingObjMapping(); } catch (BadMappingException ex) { fireGraTra(new GraTraEvent(this, GraTraEvent.NO_COMPLETION, this.currentMatch, ex.getMessage())); this.currentMatch.clear(); this.stopping = true; this.trafoSequenceBroken = true; } } } protected boolean apply(final List<Pair<Rule, String>> group, final String iters) { if (iters.equals("*")) { // System.out.println("\n apply * times"); this.appliedOnce = true; while (this.appliedOnce && !this.stopping) { this.appliedOnce = false; long time0 = System.currentTimeMillis(); for (int j = 0; j < group.size() && !this.stopping; j++) { Pair<Rule, String> p = group.get(j); if (p.first == null) continue; this.currentRule = p.first; if (this.currentRule.isEnabled()) { apply(this.currentRule, p.second); } } this.time = this.time + (System.currentTimeMillis()-time0); System.out.println("used time: "+time+"ms"); if (this.os != null) writeUsedTimeToProtocol("used time: ", time); } } else { long N = (new Long(iters)).longValue(); // if (N > 1) // System.out.println("\n apply " + N + " time(s)"); for (long i = 0; i < N && !this.stopping; i++) { long time0 = System.currentTimeMillis(); for (int j = 0; j < group.size() && !this.stopping; j++) { Pair<Rule, String> p = group.get(j); if (p.first == null) continue; this.currentRule = p.first; if (this.currentRule.isEnabled()) { apply(this.currentRule, p.second); } } this.time = this.time + (System.currentTimeMillis()-time0); System.out.println("used time: "+time+"ms"); //+" ### "+this.hostgraph.getNodesCount()); if (this.os != null) writeUsedTimeToProtocol("used time: ", time); } } if (this.options.hasOption(GraTraOptions.CONSISTENCY_CHECK_AFTER_GRAPH_TRAFO)) { this.checkGraphConsistency(); } return this.appliedOnce; } public boolean apply(Rule r) { // System.out.println("RuleSequenceGraTra.apply(Rule) : "+r.getName()+" "+updateTypeObjectsMapAfterStep); this.stoppingRule = false; boolean result = false; boolean valid = false; this.currentMatch = r.getMatch(); if (this.currentMatch == null) { this.currentMatch = this.grammar.createMatch(r); this.currentMatch.setCompletionStrategy( (MorphCompletionStrategy) this.strategy.clone(), true); // this.strategy.showProperties(); } else if (this.updateTypeObjectsMapAfterStep) { this.currentMatch.setTypeObjectsMapChanged(true); } boolean parallelApply = true; boolean is_applied = false; // int matchCompletions = 0; // long time0 = System.currentTimeMillis(); while (parallelApply) { if (!isInputParameterSet(r.getLeft(), true, this.currentMatch)) { fireGraTra( new GraTraEvent(this, GraTraEvent.INPUT_PARAMETER_NOT_SET, this.currentMatch)); } if(this.stopping || this.stoppingRule) { this.currentMatch.clear(); return false; } if(this.pauseRule) return false; valid = false; while (!valid) { if (this.ruleSequence.isTrafoByObjFlow()) { if (this.currentMatch.isTotal() && this.currentMatch.isAttrConditionSatisfied() && this.currentMatch.arePACsSatisfied() && this.currentMatch.areNACsSatisfied() && this.currentMatch.getRule().evalFormula() && this.currentMatch.isValid()) { valid = true; // matchCompletions++; break; } } if (this.currentMatch.nextCompletion()) { if (this.currentMatch.isValid()) { valid = true; // matchCompletions++; if (r.isParallelApplyEnabled() && this.currentMatch.typeObjectsMapChanged) { this.currentMatch.typeObjectsMapChanged = false; this.updateTypeObjectsMapAfterStep = false; // das hat Auswirkung auf den naechsten Aufruf // von nextCompletion(): // die Graphaenderungen nach dem Step werden // NICHT BEACHTET!!! } break; } else { this.errorMsg = this.currentMatch.getErrorMsg(); this.currentMatch.clear(); } } else { this.errorMsg = this.currentMatch.getErrorMsg(); break; } } if (valid) { fireGraTra(new GraTraEvent(this, GraTraEvent.MATCH_VALID, this.currentMatch)); if (!isInputParameterSet(r.getRight(), false, this.currentMatch)) { fireGraTra(new GraTraEvent(this, GraTraEvent.INPUT_PARAMETER_NOT_SET, this.currentMatch)); } try { // check attr context: variables only boolean checkVarsOnly = true; this.currentMatch.getAttrContext().getVariables() .getAttrManager().checkIfReadyToTransform( this.currentMatch.getAttrContext(), checkVarsOnly); } catch (AttrException ex) { fireGraTra(new GraTraEvent(this, GraTraEvent.NOT_READY_TO_TRANSFORM, r.getName())); return false; } Morphism coMatch = apply(this.currentMatch); if (coMatch != null) { result = true; this.errorMsg = ""; is_applied = true; this.currentMatch.clear(); coMatch.dispose(); coMatch = null; } else { result = false; valid = false; fireGraTra(new GraTraEvent(this, GraTraEvent.NO_COMPLETION, this.currentMatch, this.errorMsg)); this.currentMatch.clear(); } } else { result = false; fireGraTra(new GraTraEvent(this, GraTraEvent.NO_COMPLETION, this.currentMatch, this.currentMatch.getErrorMsg())); this.currentMatch.clear(); } // if (r.isParallelApplyEnabled()) { if (!valid) { parallelApply = false; this.currentMatch.typeObjectsMapChanged = true; this.updateTypeObjectsMapAfterStep = true; } if (is_applied) result = true; } else { parallelApply = false; break; } // } return result; } public void transform(List<Rule> rules) { if (this.grammar == null ||this.ruleSubsequences == null || this.ruleSubsequences.isEmpty()) { return; } apply(); } public void transform() { System.out.println("GraTra by "+this.getClass().getName()+" running"); this.stopping = false; if(!this.grammar.getListOfRules().isEmpty() && this.currentRuleSet.isEmpty()) setRuleSet(); String ruleSequencesAsText = getRuleSequenceAsText(); String s2 = "rule sequence: " + ruleSequencesAsText; System.out.println(s2); if (this.writeLogFile) { String dirName = this.grammar.getDirName(); String fileName = this.grammar.getFileName(); if ((fileName == null) || fileName.equals("")) fileName = this.grammar.getName(); openTransformProtocol(dirName, fileName); String version = "Version: AGG " + Version.getID() + "\n"; writeTransformProtocol(version); String s0 = "Graph transformation by rule sequence of : " + this.grammar.getName(); String s1 = "on graph : " + this.grammar.getGraph().getName(); writeTransformProtocol(s0); writeTransformProtocol(s1); writeTransformProtocol(s2); } // first check the rules, the graph if (!this.grammarChecked) { Pair<Object, String> checkpair = this.grammar.isReadyToTransform(true); if (checkpair != null) { Object test = checkpair.first; if (test != null) { String s = checkpair.second + "\nTransformation is stopped."; if (test instanceof Type) ((GraTra) this).fireGraTra(new GraTraEvent(this, GraTraEvent.ATTR_TYPE_FAILED, s)); else if (test instanceof Rule) ((GraTra) this).fireGraTra(new GraTraEvent(this, GraTraEvent.RULE_FAILED, s)); else if (test instanceof AtomConstraint) ((GraTra) this).fireGraTra(new GraTraEvent(this, GraTraEvent.ATOMIC_GC_FAILED, s)); transformFailed(s); return; } } // now check the host graph else if (!this.grammar.isGraphReadyForTransform()) { String s = "Graph of the grammar isn't fine." + "\nPlease check attribute settings of the objects." + "\nTransformation is stopped."; ((GraTra) this).fireGraTra(new GraTraEvent(this, GraTraEvent.GRAPH_FAILED, s)); transformFailed(s); return; } else if (!this.checkGraphConsistency()) { String s = "Graph consistency failed." + "\nPlease check the host graph against the graph constraints." + "\nTransformation is stopped."; ((GraTra) this).fireGraTra(new GraTraEvent(this, GraTraEvent.GRAPH_FAILED, s)); transformFailed(s); return; } this.grammarChecked = true; } // stop start time long startTime = System.currentTimeMillis(); transform(this.grammar.getListOfRules()); if (this.options.hasOption(GraTraOptions.CONSISTENCY_CHECK_AFTER_GRAPH_TRAFO)) { this.checkGraphConsistency(); } if (this.writeLogFile) { writeUsedTimeToProtocol("Used time for graph transformation: ", startTime); writeTransformProtocol("Graph transformation finished"); closeTransformProtocol(); } fireGraTra(new GraTraEvent(this, GraTraEvent.TRANSFORM_FINISHED, this.errorMsg)); } public boolean isTrafoSequenceBroken() { return this.trafoSequenceBroken; } protected Vector<Rule> getEnabledRules(Vector<Rule> ruleSet) { Vector<Rule> vec = new Vector<Rule>(ruleSet.size()); for (int j = 0; j < ruleSet.size(); j++) { if (ruleSet.elementAt(j).isEnabled()) vec.add(ruleSet.elementAt(j)); } return vec; } protected void transformFailed(String text) { System.out.println(text); writeTransformProtocol(text); writeTransformProtocol("\nGraph transformation failed"); // fireGraTra(new GraTraEvent(this,GraTraEvent.TRANSFORM_FAILED, // errorMsg)); fireGraTra(new GraTraEvent(this, GraTraEvent.TRANSFORM_FINISHED, this.errorMsg)); closeTransformProtocol(); } public boolean transformationDone() { return this.appliedOnce; } public String getProtocolName() { return this.protocolFileName; } protected String getRuleNames(Vector<Rule> rules) { String names = "[ "; for (int j = 0; j < rules.size(); j++) { Rule r = rules.elementAt(j); names = names + r.getName() + " "; } names = names + "]"; return names; } protected String getRuleNamesOfSubsequence(Vector<Pair<Rule, String>> rules) { String names = "Rule subsequence: ( "; for (int j = 0; j < rules.size(); j++) { Pair<Rule, String> p = rules.get(j); String rname = p.first.getName(); names = names + rname; String iters = p.second; if (!iters.equals("1")) names = names + "{" + iters + "}"; names = names + " "; } names = names + ")"; return names; } protected void openTransformProtocol(String dirName, String fileName) { // System.out.println(RuleSequencesGraTra.openTransformProtocol..."); String dName = dirName; String fName = "RuleSequencesGraTra.log"; if ((fileName != null) && !fileName.equals("")) { if (fileName.endsWith(".ggx")) fName = fileName.substring(0, fileName.length() - 4) + "_GraTra.log"; else fName = fileName + "_GraTra.log"; } // System.out.println(fName); if ((dName != null) && !dName.equals("")) { this.f = new File(dirName); if (this.f.exists()) { if (this.f.isFile()) { if (this.f.getParent() != null) dName = this.f.getParent() + File.separator; else dName = "." + File.separator; } else if (this.f.isDirectory()) dName = this.f.getPath() + File.separator; else dName = "." + File.separator; } else dName = "." + File.separator; this.f = new File(dirName + fName); } else this.f = new File(fName); try { this.os = new FileOutputStream(this.f); this.protocolFileName = this.f.getName(); } catch (FileNotFoundException ex) { ex.printStackTrace(); } writeTransformProtocol((new Date()).toString()); } protected void writeTransformProtocol(String s) { if (this.os == null) return; if (!this.os.getChannel().isOpen()) return; try { if (!s.equals("\n")) this.os.write(s.getBytes()); this.os.write('\n'); } catch (IOException ex) { ex.printStackTrace(); } } protected void writeUsedTimeToProtocol(String text, long beginTime) { writeTransformProtocol(text + (System.currentTimeMillis()-beginTime) + "ms\n"); } protected void closeTransformProtocol() { if (this.os == null) return; try { this.os.close(); } catch (IOException ex) { ex.printStackTrace(); } } public Pair<Morphism, Morphism> derivation(Match m) /** not implemented yet! * */ { return (null); } public String getRuleSequenceAsText() { this.ruleNameSequences = new Vector<String>(this.ruleSubsequences.size()); String s = ""; for (int i = 0; i < this.ruleSubsequences.size(); i++) { Pair<List<Pair<Rule, String>>, String> grp = this.ruleSubsequences.get(i); String grpStr = ""; List<Pair<Rule, String>> grpRules = grp.first; long grpIters = -1; String grpItersStr = grp.second; if (grpItersStr.equals("*")) grpStr = grpStr + "( "; else { grpIters = (new Long(grp.second)).longValue(); if (grpRules.size() > 1 || grpIters > 1) grpStr = grpStr + "( "; } for (int j = 0; j < grpRules.size(); j++) { Pair<Rule, String> p = grpRules.get(j); if (p.first == null) continue; String rulename = p.first.getName(); grpStr = grpStr + rulename; long ruleIters = -1; String ruleItersStr = p.second; if (ruleItersStr.equals("*")) grpStr = grpStr + "{" + ruleItersStr + "}"; else { ruleIters = (new Long(p.second)).longValue(); if (ruleIters > 1) grpStr = grpStr + "{" + ruleIters + "}"; } grpStr = grpStr + " "; } if (grpItersStr.equals("*")) grpStr = grpStr + ")"; else if (grpRules.size() > 1 || grpIters > 1) grpStr = grpStr + ")"; if (grpRules.size() > 0) { if (grpItersStr.equals("*")) grpStr = grpStr + "{" + grpItersStr + "}"; else if (grpIters > 1) grpStr = grpStr + "{" + grpIters + "}"; } else grpStr = "()"; this.ruleNameSequences.add(grpStr); grpStr = grpStr + "\n"; s = s + grpStr; } return s; } protected boolean isInputParameterSet( final Graph g, boolean left, final Match match) { // ((VarTuple)match.getAttrContext().getVariables()).showVariables(); if (match != null && left && this.ruleSequence != null && !this.ruleSequence.getObjectFlow().isEmpty() && ((VarTuple)match.getAttrContext().getVariables()).areInputParametersSet()) { return true; } return super.isInputParameterSet(g, left, match); } }