/** * <copyright> * Copyright (c) 2010-2014 Henshin developers. All rights reserved. * This program and the accompanying materials are made available * under the terms of the Eclipse Public License v1.0 which * accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * </copyright> */ package org.eclipse.emf.henshin.interpreter.impl; import org.eclipse.emf.henshin.interpreter.ApplicationMonitor; import org.eclipse.emf.henshin.interpreter.Assignment; import org.eclipse.emf.henshin.interpreter.Change; import org.eclipse.emf.henshin.interpreter.EGraph; import org.eclipse.emf.henshin.interpreter.Engine; import org.eclipse.emf.henshin.interpreter.Match; import org.eclipse.emf.henshin.interpreter.RuleApplication; import org.eclipse.emf.henshin.model.Parameter; import org.eclipse.emf.henshin.model.Rule; import org.eclipse.emf.henshin.model.Unit; /** * Default {@link RuleApplication} implementation. * * @author Enrico Biermann, Gregor Bonifer, Christian Krause */ public class RuleApplicationImpl extends AbstractApplicationImpl implements RuleApplication { // Used matches: protected Match partialMatch, completeMatch, resultMatch; // Whether the complete match was derived from the partial match: protected boolean isCompleteMatchDerived; // Used change object: protected Change change; // Flag indicating whether the rule application was executed: protected boolean isExecuted, isUndone; /** * Default constructor. * @param engine Engine to be used. */ public RuleApplicationImpl(Engine engine) { super(engine); isExecuted = false; isUndone = false; isCompleteMatchDerived = false; } /** * Default constructor. * @param engine Engine to be used. * @param graph Object graph to be transformed. * @param rule Rule to be applied. * @param partialMatch Partial match or assignment. */ public RuleApplicationImpl(Engine engine, EGraph graph, Rule rule, Assignment partialMatch) { this(engine); setEGraph(graph); setRule(rule); setAssignment(partialMatch); } /* * (non-Javadoc) * @see org.eclipse.emf.henshin.interpreter.UnitApplication#execute(org.eclipse.emf.henshin.interpreter.ApplicationMonitor) */ @Override public boolean execute(ApplicationMonitor monitor) { if (unit==null) { throw new NullPointerException("No transformation unit set"); } // Already executed? if (isExecuted) { if (isCompleteMatchDerived) { completeMatch = null; // reset the complete match if it was derived isCompleteMatchDerived = false; } isExecuted = false; isUndone = false; change = null; resultMatch = null; } // Do we need to derive a complete match? if (completeMatch==null) { completeMatch = engine.findMatches((Rule) unit, graph, partialMatch).iterator().next(); isCompleteMatchDerived = true; } if (completeMatch==null) { if (monitor!=null) { monitor.notifyExecute(this, false); } return false; } resultMatch = new MatchImpl((Rule) unit, true); change = engine.createChange((Rule) unit, graph, completeMatch, resultMatch); if (change==null) { if (monitor!=null) { monitor.notifyExecute(this, false); } return false; } change.applyAndReverse(); isExecuted = true; if (monitor!=null) { monitor.notifyExecute(this, true); } return true; } /* * (non-Javadoc) * @see org.eclipse.emf.henshin.interpreter.UnitApplication#undo() */ @Override public boolean undo(ApplicationMonitor monitor) { boolean success = false; if (isExecuted && !isUndone) { change.applyAndReverse(); isUndone = true; success = true; } if (monitor!=null) { monitor.notifyUndo(this, success); } return success; } /* * (non-Javadoc) * @see org.eclipse.emf.henshin.interpreter.UnitApplication#redo(org.eclipse.emf.henshin.interpreter.ApplicationMonitor) */ public boolean redo(ApplicationMonitor monitor) { boolean success = false; if (isExecuted && isUndone) { change.applyAndReverse(); isUndone = false; success = true; } if (monitor!=null) { monitor.notifyUndo(this, success); } return success; } /* * (non-Javadoc) * @see org.eclipse.emf.henshin.interpreter.RuleApplication#getRule() */ @Override public Rule getRule() { return (Rule) unit; } /* * (non-Javadoc) * @see org.eclipse.emf.henshin.interpreter.RuleApplication#setRule(org.eclipse.emf.henshin.model.Rule) */ @Override public void setRule(Rule rule) { setUnit(rule); } /* * (non-Javadoc) * @see org.eclipse.emf.henshin.interpreter.impl.AbstractApplicationImpl#setUnit(org.eclipse.emf.henshin.model.Unit) */ @Override public void setUnit(Unit unit) { if (unit!=null && !(unit instanceof Rule)) { throw new IllegalArgumentException("Unit must be a rule"); } if (this.unit!=unit){ this.unit = unit; this.partialMatch = null; this.completeMatch = null; this.resultMatch = null; this.change = null; this.isExecuted = false; this.isUndone = false; this.isCompleteMatchDerived = false; } } /* * (non-Javadoc) * @see org.eclipse.emf.henshin.interpreter.UnitApplication#getAssignment() */ @Override public Assignment getAssignment() { return partialMatch; } /* * (non-Javadoc) * @see org.eclipse.emf.henshin.interpreter.UnitApplication#setAssignment(org.eclipse.emf.henshin.interpreter.Assignment) */ @Override public void setAssignment(Assignment assignment) { if (assignment==null) { partialMatch = null; } else if (assignment instanceof Match) { partialMatch = (Match) assignment; } else { partialMatch = new MatchImpl(assignment, false); } this.completeMatch = null; this.resultMatch = null; this.change = null; this.isExecuted = false; this.isUndone = false; this.isCompleteMatchDerived = false; } /* * (non-Javadoc) * @see org.eclipse.emf.henshin.interpreter.UnitApplication#getParameterValue(java.lang.String) */ @Override public Object getResultParameterValue(String paramName) { if (unit==null) { throw new RuntimeException("Rule not set"); } Parameter param = unit.getParameter(paramName); if (param==null) { throw new RuntimeException("No parameter \"" + paramName + "\" in rule \"" + unit.getName() + "\" found" ); } if (resultMatch!=null) { return resultMatch.getParameterValue(param); } return null; } /* * (non-Javadoc) * @see org.eclipse.emf.henshin.interpreter.UnitApplication#setParameterValue(java.lang.String, java.lang.Object) */ @Override public void setParameterValue(String paramName, Object value) { if (unit==null) { throw new RuntimeException("Rule not set"); } Parameter param = unit.getParameter(paramName); if (param==null) { throw new RuntimeException("No parameter \"" + paramName + "\" in rule \"" + unit.getName() + "\" found" ); } if (partialMatch==null) { partialMatch = new MatchImpl((Rule) unit); } partialMatch.setParameterValue(param, value); completeMatch = null; isCompleteMatchDerived = false; } /* * (non-Javadoc) * @see org.eclipse.emf.henshin.interpreter.RuleApplication#getPartialMatch() */ @Override public Match getPartialMatch() { return partialMatch; } /* * (non-Javadoc) * @see org.eclipse.emf.henshin.interpreter.RuleApplication#setPartialMatch(org.eclipse.emf.henshin.interpreter.Match) */ @Override public void setPartialMatch(Match partialMatch) { this.partialMatch = partialMatch; this.completeMatch = null; this.resultMatch = null; this.change = null; this.isExecuted = false; this.isUndone = false; this.isCompleteMatchDerived = false; } /* * (non-Javadoc) * @see org.eclipse.emf.henshin.interpreter.RuleApplication#getCompleteMatch() */ @Override public Match getCompleteMatch() { return completeMatch; } /* * (non-Javadoc) * @see org.eclipse.emf.henshin.interpreter.RuleApplication#setCompleteMatch(org.eclipse.emf.henshin.interpreter.Match) */ @Override public void setCompleteMatch(Match completeMatch) { // don't change the partial match this.completeMatch = completeMatch; this.resultMatch = null; this.change = null; this.isExecuted = false; this.isUndone = false; this.isCompleteMatchDerived = false; } /* * (non-Javadoc) * @see org.eclipse.emf.henshin.interpreter.RuleApplication#getResultMatch() */ @Override public Match getResultMatch() { return resultMatch; } /* * (non-Javadoc) * @see org.eclipse.emf.henshin.interpreter.UnitApplication#getResultAssignment() */ @Override public Assignment getResultAssignment() { return resultMatch; } }