package agg.xt_basis; import java.util.Enumeration; import java.util.HashSet; import java.util.Hashtable; import java.util.Iterator; import java.util.List; import java.util.Random; 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.cons.AtomConstraint; import agg.util.IntComparator; import agg.util.OrderedSet; import agg.util.Pair; import agg.xt_basis.agt.RuleScheme; public class LayeredGraTraImpl extends GraTra { Random ran = new Random(); private boolean appliedOnce; private boolean stopLayerAndWait; private int layerToStop; // private boolean stopLayerOpt, stopLayer; private boolean breakLayerOpt, breakLayer; private boolean breakAllLayerOpt, breakAllLayer; private boolean applyContinue; private boolean nextLayerExists; private boolean waitAfterLayer; private boolean waitingAfterLayer; private boolean layeredLoop, resetGraphBeforeLoop; private Integer startLayer; private RuleLayer layer; private Hashtable<Integer, HashSet<Rule>> invertedRuleLayer; private OrderedSet<Integer> ruleLayer; private Integer currentLayer; private boolean startTransform; private boolean grammarChecked; private long time0; //, time=0; File f; FileOutputStream os; String protocolFileName = ""; public LayeredGraTraImpl() { this.nextLayerExists = true; } public void dispose() { if (this.layer != null) this.layer.dispose(); if (this.invertedRuleLayer != null) this.invertedRuleLayer.clear(); if (this.ruleLayer != null) this.ruleLayer.clear(); super.dispose(); } public void setGraTraOptions(Vector<String> newOptions) { super.setGraTraOptions(newOptions); if (newOptions.contains(GraTraOptions.BREAK_ALL_LAYER)) this.breakAllLayerOpt = true; else if (newOptions.contains(GraTraOptions.BREAK_LAYER)) this.breakLayerOpt = true; if (newOptions.contains(GraTraOptions.LOOP_OVER_LAYER)) this.layeredLoop = true; if (newOptions.contains(GraTraOptions.RESET_GRAPH)) this.resetGraphBeforeLoop = true; } public void stop() { if (this.breakLayerOpt) { this.breakLayer = true; this.breakAllLayer = false; this.stopping = this.breakAllLayer; this.waitAfterLayer = false; } else if (this.breakAllLayerOpt) { this.breakAllLayer = true; this.stopping = this.breakAllLayer; this.breakLayer = false; this.waitAfterLayer = false; } else if(this.waitAfterLayer) { this.stopping = false; this.stoppingRule = true; this.pauseRule = false; this.breakLayer = true; this.breakAllLayer = false; } // else{ // stopping = true; // stoppingRule = true; // pauseRule = false; // breakLayer = true; // breakAllLayer = true; // } } public void unsetStop() { super.unsetStop(); this.breakLayer = false; this.breakAllLayer = false; this.waitAfterLayer = false; } public void nextLayer() { transformLayers(true); } public int getCurrentLayer() { if (this.currentLayer != null) return this.currentLayer.intValue(); return -1; } public void waitAfterLayer(boolean b) { this.waitAfterLayer = b; } public boolean isWaitingAfterLayer(){ return this.waitingAfterLayer; } /** not implemented yet! * */ public Pair<Morphism, Morphism> derivation(Match m) { return (null); } public boolean apply() { // if(!allRulesEnabled) { // // remove disabled rules from currentRuleSet // for(int j=0; j<currentRuleSet.size(); j++) { // if(!((Rule) currentRuleSet.elementAt(j)).isEnabled()) { // currentRuleSet.removeElementAt(j); // j--; // } // } // allRulesEnabled = true; // } if (this.currentRuleSet.isEmpty()) return false; boolean applied = false; // first try to apply a trigger rule int i; String trigger = ""; this.currentRule = this.currentRuleSet.elementAt(0); if (this.currentRule.isTriggerOfLayer()) { if (this.currentRule.isEnabled()) { // System.out.println("trigger rule: "+currentRule.getName()); trigger = "(trigger of layer)"; applied = this.currentRule.canMatch(this.hostgraph, this.strategy) && apply(this.currentRule); // System.out.println(currentRule.getName() + " \t applied: "+ applied); if (applied) { System.out.println(this.currentRule.getName() + " \t applied: "+ applied); this.appliedOnce = true; if (!isGraphConsistent()) this.stopping = true; this.currentRule.setEnabled(false); this.currentRuleSet.removeElement(this.currentRule); if (this.os != null) writeTransformProtocol(this.currentRule.getName() + " " + trigger + " \t applied: " + applied); } else { if (this.os != null) { writeTransformProtocol(this.currentRule.getName() + " " + trigger + " \t applied: " + applied); writeTransformProtocol(getErrorMsg()); writeTransformProtocol("The trigger rule of the current layer failed. \nContinue with the next layer."); } this.currentRuleSet.removeAllElements(); } applied = false; } else this.currentRuleSet.removeElement(this.currentRule); } while (!this.stopping && !this.breakLayer && !applied && this.currentRuleSet.size() > 0) { i = this.ran.nextInt(this.currentRuleSet.size()); this.currentRule = this.currentRuleSet.elementAt(i); if (this.currentRule instanceof RuleScheme) { applied = apply((RuleScheme) this.currentRule); } else { applied = this.currentRule.canMatch(this.hostgraph, this.strategy) && apply(this.currentRule); } if (this.os != null) writeTransformProtocol(this.currentRule.getName() + " \t applied: " + applied); if (!applied) { this.currentRuleSet.remove(this.currentRule); if (this.os != null) { writeTransformProtocol(getErrorMsg()); writeTransformProtocol(getRuleNames(this.currentRuleSet)); } } else { // System.out.println(this.currentRule.getName() + " \t applied: "+ applied); this.appliedOnce = true; if (!isGraphConsistent()) this.stopping = true; } } return applied; } public void transform(List<Rule> ruleSet) { this.layer = new RuleLayer(ruleSet); this.startLayer = this.layer.getStartLayer(); this.invertedRuleLayer = this.layer.invertLayer(); this.ruleLayer = new OrderedSet<Integer>(new IntComparator<Integer>()); for (Enumeration<Integer> en = invertedRuleLayer.keys(); en .hasMoreElements();) { this.ruleLayer.add(en.nextElement()); } this.startTransform = true; transformLayers(true); } public void transformContinue() { this.applyContinue = true; this.pauseRule = false; this.breakLayer = false; transformCurrentLayer(); if (this.pauseRule) return; if (this.layeredLoop && !this.stopping) { if (this.currentLayer == null && (!this.resetGraphBeforeLoop //|| noMoreStopBeforeResetGraph )) { this.startTransform = true; } } // else if (this.currentLayer == null || this.stopping) { // writeTransformProtocol("\nGraph transformation is finished"); // fireGraTra(new GraTraEvent(this,GraTraEvent.TRANSFORM_FINISHED)); // closeTransformProtocol(); // } } public void transformContinueWithNextLayer(){ this.breakLayer = false; if (this.stoppingRule) this.stoppingRule = false; transformCurrentLayer(); if (this.layeredLoop && !this.stopping) { if (this.currentLayer == null && !this.resetGraphBeforeLoop) { this.startTransform = true; } } else if(this.currentLayer == null || this.stopping) { this.stopping = true; writeFinishToProtocol(this.time0); } } public void transformContinueWithNextStep() { this.breakLayer = false; if (this.stoppingRule) this.stoppingRule = false; transformCurrentLayer(); if (this.layeredLoop && !this.stopping) { if (this.currentLayer == null && !this.resetGraphBeforeLoop) { this.startTransform = true; } } else if (this.currentLayer == null || this.stopping) { writeFinishToProtocol(this.time0); } } public void setStartTransform(boolean b) { this.startTransform = b; } int i; @SuppressWarnings({ "unused", "rawtypes" }) private void transformCurrentLayer() { boolean oneApplied = false; this.waitingAfterLayer = false; if (this.startTransform) { this.currentLayer = this.startLayer; i = 0; } // System.out.println("LayeredGraTraImpl.transformCurrentLayer()... "+this.currentLayer); this.startTransform = false; this.nextLayerExists = true; if (!this.stopping && this.nextLayerExists && (this.currentLayer != null)) { Vector<Rule> rules = new Vector<Rule>(); if (!this.applyContinue) { // get rules of the current this.layer HashSet rulesForLayer = this.invertedRuleLayer.get(this.currentLayer); Iterator<?> en = rulesForLayer.iterator(); while (en.hasNext()) { Rule rule = (Rule) en.next(); // add trigger rule as the first element if (rule.isTriggerOfLayer()) rules.add(0, rule); else rules.add(rule); } writeTransformProtocol("\n"); writeTransformProtocol("Layer: " + this.currentLayer.toString()); System.out.println("Layer " + this.currentLayer.toString() + ": " + getRuleNames(rules) + "{*}"); } else rules = this.currentRuleSet; boolean applied = true; while (!this.stopping && applied) { if(this.breakLayer) break; if(!this.applyContinue){ this.currentRuleSet.clear(); this.currentRuleSet.addAll(rules); } applied = apply(); if (applied) oneApplied = true; // in case of input parameter if(this.pauseRule) { return; } if (this.breakLayer) { break; } if(applied && this.waitAfterStep) { return; } } if (this.options.hasOption(GraTraOptions.CONSISTENCY_CHECK_AFTER_GRAPH_TRAFO)) { if (!this.checkGraphConsistencyForLayer(this.currentLayer.intValue())) this.stopping = true; } if (!this.breakLayer) { System.out.println("Layer " + this.currentLayer.toString() + " used time: "+ (System.currentTimeMillis()-this.time0) + "ms"); } else { System.out.println("Layer " + this.currentLayer.toString() + " broken"); this.breakLayer = false; } writeUsedTimeToProtocol("used time: ",this.time0); enableTriggerRuleOfLayer(rules); // get next Layer i++; if (i < this.ruleLayer.size()) { this.currentLayer = this.ruleLayer.get(i); } else { this.nextLayerExists = false; } this.breakLayer = false; this.waitingAfterLayer = true; if (this.nextLayerExists && this.currentLayer != null) { fireGraTra(new GraTraEvent(this, GraTraEvent.LAYER_FINISHED)); } else if (this.layeredLoop && !this.resetGraphBeforeLoop && this.appliedOnce) { this.startTransform = true; fireGraTra(new GraTraEvent(this, GraTraEvent.LAYER_FINISHED)); } else { writeFinishToProtocol(this.time0); fireGraTra(new GraTraEvent(this, GraTraEvent.TRANSFORM_FINISHED)); } } } @SuppressWarnings("rawtypes") private void transformLayers(boolean anApply) { // System.out.println("LayeredGraTraImpl:: this.layeredLoop: "+this.layeredLoop // +" anApply: "+anApply+" this.startTransform: "+this.startTransform // +" reset graph: "+resetGraph); boolean oneApplied = anApply; String layerStr = ""; while (oneApplied) { if (this.startTransform) { fireGraTra(new GraTraEvent(this, GraTraEvent.TRANSFORM_START)); this.currentLayer = this.startLayer; i = 0; this.appliedOnce = false; } this.startTransform = false; oneApplied = false; this.nextLayerExists = true; while (!this.stopping && this.nextLayerExists && this.currentLayer != null) { layerStr = String.valueOf(this.currentLayer.intValue()); // get rules of the current this.layer HashSet rulesForLayer = this.invertedRuleLayer.get(this.currentLayer); Vector<Rule> rules = new Vector<Rule>(); Iterator<?> en = rulesForLayer.iterator(); while (en.hasNext()) { Rule rule = (Rule) en.next(); // add trigger rule as the first element if (rule.isTriggerOfLayer()) rules.add(0, rule); else rules.add(rule); } writeTransformProtocol("\n"); writeTransformProtocol("Layer: " + this.currentLayer.toString()); System.out.println("Layer " + this.currentLayer.toString() + ": " + getRuleNames(rules) + "{*}"); boolean applied = true; while (!this.stopping && applied) { String s = getRuleNames(rules); writeTransformProtocol(s); this.currentRuleSet.clear(); this.currentRuleSet.addAll(rules); applied = apply(); if (applied) { oneApplied = true; } // in case of input parameter if(this.pauseRule) { return; } if (this.breakLayer) { break; } } if (this.options.hasOption(GraTraOptions.CONSISTENCY_CHECK_AFTER_GRAPH_TRAFO)) { if (!this.checkGraphConsistencyForLayer(this.currentLayer.intValue())) this.stopping = true; } if (!this.breakLayer) { System.out.println("Layer " + this.currentLayer.toString() + " used time: "+ (System.currentTimeMillis()-this.time0) + "ms"); } else { System.out.println("Layer " + this.currentLayer.toString() + " broken"); this.breakLayer = false; } // time = time+this.time0; writeUsedTimeToProtocol("used time: ",this.time0); enableTriggerRuleOfLayer(rules); // get next Layer i++; if (i < this.ruleLayer.size()) { this.currentLayer = this.ruleLayer.get(i); } else { this.nextLayerExists = false; } if (!this.nextLayerExists || this.currentLayer == null) { this.nextLayerExists = false; if (this.layeredLoop) { if(this.appliedOnce && !this.resetGraphBeforeLoop && !this.stopping) { this.nextLayerExists = true; this.startTransform = true; break; } else { writeFinishToProtocol(this.time0); fireGraTra(new GraTraEvent(this, GraTraEvent.TRANSFORM_FINISHED)); } } } if (stopLayerAndWait(Integer.valueOf(layerStr).intValue())) { break; } // fireGraTra(new GraTraEvent(this, GraTraEvent.LAYER_FINISHED, layerStr)); } if ((!"".equals(layerStr) && stopLayerAndWait(Integer.valueOf(layerStr).intValue())) || !this.layeredLoop) { break; } } if ((!"".equals(layerStr) && stopLayerAndWait(Integer.valueOf(layerStr).intValue())) && this.nextLayerExists && !this.stopping) { fireGraTra(new GraTraEvent(this, GraTraEvent.LAYER_FINISHED, layerStr)); } else if (!this.startTransform) { writeFinishToProtocol(this.time0); fireGraTra(new GraTraEvent(this, GraTraEvent.TRANSFORM_FINISHED)); } } private boolean stopLayerAndWait(int layerNm) { if (this.stopLayerAndWait) { if (this.layerToStop == -1 || (this.currentLayer != null && this.layerToStop == layerNm) ){ return true; } } return false; } public void transform() { this.stopping = false; if(!this.grammar.getListOfRules().isEmpty() && this.currentRuleSet.isEmpty()) { setRuleSet(); } if (this.time0 > 0 && this.options.hasOption(GraTraOptions.RESET_GRAPH) && this.options.hasOption(GraTraOptions.LOOP_OVER_LAYER)) { this.transformWhenResetGraph(); return; } 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 = "Layered graph transformation of : " + this.grammar.getName(); String s1 = "on graph : " + this.grammar.getGraph().getName(); String s2 = getRuleNames(this.currentRuleSet); 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 s0 = checkpair.second + "\nTransformation stopped."; if (test instanceof Type) ((GraTra) this).fireGraTra(new GraTraEvent(this, GraTraEvent.ATTR_TYPE_FAILED, s0)); else if (test instanceof Rule) ((GraTra) this).fireGraTra(new GraTraEvent(this, GraTraEvent.RULE_FAILED, s0)); else if (test instanceof AtomConstraint) ((GraTra) this).fireGraTra(new GraTraEvent(this, GraTraEvent.ATOMIC_GC_FAILED, s0)); transformFailed(s0); return; } } // now check the host graph else if (!this.grammar.isGraphReadyForTransform()) { String s0 = "Transformation stopped.\nThe graph <" + this.grammar.getGraph().getName() +"> isn't fine." + "\nPlease check attribute settings of nodes and edges."; ((GraTra) this).fireGraTra(new GraTraEvent(this, GraTraEvent.GRAPH_FAILED, s0)); transformFailed(s0); 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; } // System.out.println(this.options.getOptions()); // stop start time long startTime = System.currentTimeMillis(); this.time0 = startTime; Vector<Rule> ruleSet = getEnabledRules(this.currentRuleSet); transform(ruleSet); if (this.options.hasOption(GraTraOptions.CONSISTENCY_CHECK_AFTER_GRAPH_TRAFO)) { this.checkGraphConsistency(); } System.out.println("Used time for graph transformation: " + (System.currentTimeMillis() - startTime) + "ms"); if (this.writeLogFile) { writeUsedTimeToProtocol("Used time for graph transformation: ", startTime); writeTransformProtocol("\nGraph transformation finished"); closeTransformProtocol(); } } private void transformWhenResetGraph() { // System.out.println(this.options.getOptions()); // stop start time long startTime = System.currentTimeMillis(); this.time0 = startTime; Vector<Rule> ruleSet = getEnabledRules(this.currentRuleSet); transform(ruleSet); if (this.options.hasOption(GraTraOptions.CONSISTENCY_CHECK_AFTER_GRAPH_TRAFO)) { this.checkGraphConsistency(); } System.out.println("Used time for graph transformation: " + (System.currentTimeMillis() - startTime) + "ms"); if (this.writeLogFile) { writeUsedTimeToProtocol("Used time for graph transformation: ", startTime); writeTransformProtocol("\nGraph transformation finished"); closeTransformProtocol(); } } private 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; } private 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(); } private void writeUsedTimeToProtocol(String text, long beginTime) { writeTransformProtocol(text+ + (System.currentTimeMillis()-beginTime) + "ms"); this.time0 = System.currentTimeMillis(); } private void writeFinishToProtocol(long beginTime) { writeTransformProtocol("\nNo more layers.\nGraph transformation finished"); // fireGraTra(new GraTraEvent(this, GraTraEvent.TRANSFORM_FINISHED)); closeTransformProtocol(); } public void setLayeredLoop(boolean b) { this.layeredLoop = b; } public void setResetGraphBeforeLoop(boolean b) { this.resetGraphBeforeLoop = b; } public void setStopLayerAndWait(boolean b) { this.stopLayerAndWait = b; this.layerToStop = -1; } public void setLayerToStop(int l) { this.layerToStop = l; } public void setBreakLayer(boolean b) { this.breakLayerOpt = b; } public void setBreakAllLayer(boolean b) { this.breakAllLayerOpt = b; } public boolean transformationDone() { return this.appliedOnce; } public String getProtocolName() { return this.protocolFileName; } // public long getUsedTime() { // return time; // } private void enableTriggerRuleOfLayer(Vector<Rule> rules) { for (int j = 0; j < rules.size(); j++) { Rule r = rules.elementAt(j); if (r.isTriggerOfLayer()) { r.setEnabled(true); break; } } } private String getRuleNames(List<Rule> rules) { String names = "[ "; for (int j = 0; j < rules.size(); j++) { Rule r = rules.get(j); names = names + r.getName() + " "; } names = names + "]"; return names; } private void openTransformProtocol(String dirName, String fileName) { String dName = dirName; String fName = "LayeredGraTra.log"; // System.out.println("DefaultGraTraImpl.openTransformProtocol: dirName: // "+dirName); // System.out.println("DefaultGraTraImpl.openTransformProtocol: // fileName: "+fileName); 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(dName); 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()); } private 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(); } } private void closeTransformProtocol() { if (this.os == null) return; try { this.os.close(); } catch (IOException ex) { ex.printStackTrace(); } } }