/******************************************************************************* * Copyright (c) 2010-2015 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 * * Contributors: * TU Berlin, University of Luxembourg, SES S.A. *******************************************************************************/ /** * FlowControlInterpreter.java * * Created 02.01.2012 - 00:55:09 */ package de.tub.tfs.henshin.editor.util.flowcontrol; import java.util.Collection; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import org.eclipse.emf.henshin.model.ConditionalUnit; import org.eclipse.emf.henshin.model.Graph; import org.eclipse.emf.henshin.model.HenshinFactory; import org.eclipse.emf.henshin.model.IndependentUnit; import org.eclipse.emf.henshin.model.LoopUnit; import org.eclipse.emf.henshin.model.NamedElement; import org.eclipse.emf.henshin.model.NestedCondition; import org.eclipse.emf.henshin.model.Not; import org.eclipse.emf.henshin.model.Parameter; import org.eclipse.emf.henshin.model.Rule; import org.eclipse.emf.henshin.model.SequentialUnit; import org.eclipse.emf.henshin.model.Unit; import de.tub.tfs.henshin.model.flowcontrol.Activity; import de.tub.tfs.henshin.model.flowcontrol.CompoundActivity; import de.tub.tfs.henshin.model.flowcontrol.ConditionalActivity; import de.tub.tfs.henshin.model.flowcontrol.End; import de.tub.tfs.henshin.model.flowcontrol.FlowDiagram; import de.tub.tfs.henshin.model.flowcontrol.FlowElement; import de.tub.tfs.henshin.model.flowcontrol.ParameterMapping; import de.tub.tfs.henshin.model.flowcontrol.ParameterProvider; import de.tub.tfs.henshin.model.flowcontrol.Transition; /** * * * @author nam */ public class FlowControlInterpreter { private static class ParameterTrace extends LinkedList<Unit> { private static final long serialVersionUID = 1L; private boolean found = false; /** * */ public ParameterTrace() { super(); // TODO Auto-generated constructor stub } /** * @param c */ public ParameterTrace(Collection<? extends Unit> c) { super(c); } /** * @return the found */ public boolean isFound() { return found; } /** * @param found * the found to set */ public void setFound(boolean found) { this.found = found; } } private FlowDiagram diagram; private Map<Unit, FlowElement> generated; /** * @param diagram */ public FlowControlInterpreter(FlowDiagram diagram) { super(); this.diagram = diagram; generated = new HashMap<Unit, FlowElement>(); } /** * @return */ public Unit parse() { LinkedList<Unit> result = new LinkedList<Unit>(); generated.clear(); parse(diagram.getStart(), result, new LinkedList<Object>()); Unit parsed = merge(result); if (parsed == null || parsed instanceof Rule) { SequentialUnit u = HenshinFactory.eINSTANCE.createSequentialUnit(); if (parsed instanceof Rule) { u.getSubUnits().add(parsed); } parsed = u; } parsed.setName(diagram.getName()); createInputParameters(parsed); createOutputParameters(parsed); for (ParameterMapping m : diagram.getParameterMappings()) { if (m.getSrc().getProvider() == diagram || m.getTarget().getProvider() == diagram) { continue; } Parameter src = m.getSrc().getHenshinParameter(); ParameterTrace srcTrace = new ParameterTrace(); Parameter target = m.getTarget().getHenshinParameter(); ParameterTrace targetTrace = new ParameterTrace(); buildTrace(srcTrace, m.getSrc(), parsed); buildTrace(targetTrace, m.getTarget(), parsed); ParameterTrace merged = new ParameterTrace(targetTrace); ParameterTrace srcList = new ParameterTrace(srcTrace); ParameterTrace targetList = new ParameterTrace(targetTrace); merged.retainAll(srcTrace); srcList.removeAll(targetTrace); targetList.removeAll(srcTrace); target = createHenshinParameters(targetList, false, target.getName()); src = createHenshinParameters(srcList, true, src.getName()); Unit top = merged.getLast(); org.eclipse.emf.henshin.model.ParameterMapping newMappingSrc = HenshinFactory.eINSTANCE .createParameterMapping(); org.eclipse.emf.henshin.model.ParameterMapping newMappingTarget = HenshinFactory.eINSTANCE .createParameterMapping(); Parameter newParameter = HenshinFactory.eINSTANCE.createParameter(); newParameter.setName(src.getName() + "2" + target.getName()); newParameter.setUnit(top); top.getParameters().add(newParameter); newMappingSrc.setSource(src); newMappingSrc.setTarget(newParameter); newMappingTarget.setSource(newParameter); newMappingTarget.setTarget(target); top.getParameterMappings().add(newMappingSrc); top.getParameterMappings().add(newMappingTarget); } return parsed; } /** * @param e * @param parsed * @param context */ private void parse(FlowElement e, LinkedList<Unit> parsed, LinkedList<Object> context) { if (!(e instanceof End)) { if (e instanceof Activity) { parseActivity((Activity) e, parsed, context); } else { parse(e.getOut(), parsed, context); } } } /** * @param t * @param parsed * @param context */ private void parse(Transition t, LinkedList<Unit> parsed, LinkedList<Object> context) { if (t != null) { parse(t.getNext(), parsed, context); } } /** * @param a * @param parsed * @param context */ private void parseActivity(Activity a, LinkedList<Unit> parsed, LinkedList<Object> context) { if (a instanceof ConditionalActivity) { parseConditionalActivity((ConditionalActivity) a, parsed, context); } else { if (a instanceof CompoundActivity) { parseCompoundActivity((CompoundActivity) a, parsed, context); } else { NamedElement c = a.getContent(); if (c instanceof Rule) { Rule newRule = (Rule) (c); generated.put(newRule, a); parsed.add(newRule); } else if (c instanceof FlowDiagram) { Unit parseUnit = new FlowControlInterpreter( (FlowDiagram) c).parse(); generated.put(parseUnit, a); parsed.add(parseUnit); } } parse(a.getOut(), parsed, context); } } /** * @param a * @param parsed * @param context */ private void parseCompoundActivity(CompoundActivity a, LinkedList<Unit> parsed, LinkedList<Object> context) { List<Activity> children = a.getChildren(); IndependentUnit u = HenshinFactory.eINSTANCE.createIndependentUnit(); u.setName("__tmp__"); if (!children.isEmpty()) { for (Activity child : children) { LinkedList<Unit> childResult = new LinkedList<Unit>(); parseActivity(child, childResult, context); for (Object o : childResult) { u.getSubUnits().add((Unit) o); } } } parsed.add(u); } /** * @param a * @param parsed * @param context */ private void parseConditionalActivity(ConditionalActivity a, LinkedList<Unit> parsed, LinkedList<Object> context) { if (context.contains(a)) { context.add(a); } else { LinkedList<Unit> thenContent = new LinkedList<Unit>(); LinkedList<Unit> elseContent = new LinkedList<Unit>(); LinkedList<Object> thenContext = new LinkedList<Object>(context); LinkedList<Object> elseContext = new LinkedList<Object>(context); thenContext.add(a); elseContext.add(a); parse(a.getOut(), thenContent, thenContext); parse(a.getAltOut(), elseContent, elseContext); thenContext.remove(a); elseContext.remove(a); ConditionalUnit conditionalUnit = HenshinFactory.eINSTANCE .createConditionalUnit(); Unit thenUnit = merge(thenContent); Unit elseUnit = merge(elseContent); NamedElement content = a.getContent(); conditionalUnit.setName(content.getName()); Unit result = conditionalUnit; if (content instanceof Rule) { Rule newRule = (Rule) content; generated.put(newRule, a); conditionalUnit.setIf(newRule); } else if (content instanceof FlowDiagram) { Unit parsedUnit = new FlowControlInterpreter( (FlowDiagram) content).parse(); generated.put(parsedUnit, a); conditionalUnit.setIf(parsedUnit); } if (thenContext.contains(a) || elseContext.contains(a)) { Rule trueRule = HenshinFactory.eINSTANCE.createRule(); Rule falseRule = HenshinFactory.eINSTANCE.createRule(); NestedCondition nac = HenshinFactory.eINSTANCE .createNestedCondition(); Not not = HenshinFactory.eINSTANCE.createNot(); ConditionalUnit seq = HenshinFactory.eINSTANCE .createConditionalUnit(); Graph ac = HenshinFactory.eINSTANCE.createGraph(); ac.setName("false_ac"); seq.setName("seq"); trueRule.setName("true"); falseRule.setName("false"); nac.setConclusion(ac); not.setChild(nac); falseRule.getLhs().setFormula(not); if (thenContext.contains(a)) { if (thenUnit == null) { thenUnit = trueRule; } else if (elseUnit != null) { seq.setIf(elseUnit); elseUnit = seq; } } if (elseContext.contains(a)) { if (elseUnit == null) { elseUnit = trueRule; } else if (thenUnit != null) { seq.setIf(thenUnit); thenUnit = seq; } } LoopUnit loopUnit = HenshinFactory.eINSTANCE.createLoopUnit(); loopUnit.setSubUnit(conditionalUnit); result = loopUnit; } if (thenUnit != null) { conditionalUnit.setThen(thenUnit); } if (elseUnit != null) { conditionalUnit.setElse(elseUnit); } parsed.add(result); } } /** * @param l * @return */ private Unit merge(List<Unit> l) { if (l.isEmpty()) { return null; } else if (l.size() == 1) { return l.get(0); } else { SequentialUnit u = HenshinFactory.eINSTANCE.createSequentialUnit(); u.setName("__tmp__"); u.getSubUnits().addAll(l); return u; } } private void createInputParameters(Unit parsed) { for (ParameterMapping m : diagram.getParameterMappings()) { if (m.getSrc().getProvider() == diagram) { ParameterTrace trace = new ParameterTrace(); buildTrace(trace, m.getTarget(), parsed); createHenshinParameters(trace, false, m.getTarget().getName()); break; } } } private void createOutputParameters(Unit parsed) { for (ParameterMapping m : diagram.getParameterMappings()) { if (m.getTarget().getProvider() == diagram) { ParameterTrace trace = new ParameterTrace(); buildTrace(trace, m.getSrc(), parsed); createHenshinParameters(trace, true, m.getSrc().getName()); break; } } } private void buildTrace(ParameterTrace trace, de.tub.tfs.henshin.model.flowcontrol.Parameter p, Unit parsed) { if (parsed == null) { return; } ParameterProvider pProvider = p.getProvider(); if (pProvider instanceof FlowElement) { if (generated.get(parsed) == p.getProvider()) { trace.add(parsed); trace.setFound(true); return; } } List<Unit> subUnits = parsed.getSubUnits(false); if (!subUnits.isEmpty()) { trace.add(parsed); for (Unit u : subUnits) { buildTrace(trace, p, u); if (trace.isFound()) { break; } } if (!trace.isFound()) { trace.removeLast(); } } } private Parameter createHenshinParameters(ParameterTrace units, boolean isSrc, String name) { if(units.isEmpty()){ return null; } Parameter curr = units.getLast().getParameter(name); for (int i = units.size() - 2; i >= 0; i--) { Parameter newParameter = HenshinFactory.eINSTANCE.createParameter(); org.eclipse.emf.henshin.model.ParameterMapping newMapping = HenshinFactory.eINSTANCE .createParameterMapping(); Unit currUnit = units.get(i); newParameter.setName(name); if (isSrc) { newMapping.setSource(curr); newMapping.setTarget(newParameter); } else { newMapping.setTarget(curr); newMapping.setSource(newParameter); } currUnit.getParameters().add(newParameter); currUnit.getParameterMappings().add(newMapping); curr = newParameter; } return curr; } }