/******************************************************************************* * 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. *******************************************************************************/ package de.tub.tfs.henshin.tggeditor.commands.create.rule; import java.util.HashMap; import java.util.HashSet; import org.eclipse.emf.common.util.EList; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.util.EcoreUtil.Copier; import org.eclipse.emf.henshin.model.Attribute; import org.eclipse.emf.henshin.model.Edge; 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.Mapping; import org.eclipse.emf.henshin.model.Node; import org.eclipse.emf.henshin.model.Rule; import org.eclipse.gef.commands.Command; import de.tub.tfs.henshin.tgg.TAttribute; import de.tub.tfs.henshin.tgg.TEdge; import de.tub.tfs.henshin.tgg.TGG; import de.tub.tfs.henshin.tgg.TGGRule; import de.tub.tfs.henshin.tgg.TNode; import de.tub.tfs.henshin.tgg.TggFactory; import de.tub.tfs.henshin.tgg.TripleComponent; import de.tub.tfs.henshin.tgg.TripleGraph; import de.tub.tfs.henshin.tgg.interpreter.util.NodeUtil; import de.tub.tfs.henshin.tgg.interpreter.util.RuleUtil; import de.tub.tfs.henshin.tggeditor.util.GraphOptimizer; import de.tub.tfs.henshin.tggeditor.util.GraphicalNodeUtil; /** * this command generates an forward translation rule from a given triple graph * grammar rule * */ public abstract class ProcessRuleCommand extends Command { protected Rule oldRule; protected Graph tRuleLhs; protected TripleGraph tRuleRhs; protected Rule newRule; protected TGG tgg; protected HashMap<Node, Node> oldLhsNodes2TLhsNodes; protected HashMap<Node, Node> oldRhsNodes2TRhsNodes; protected String prefix = "UNK_"; protected int oldruleIndex; protected boolean update = false; protected IndependentUnit container; public interface NodeProcessor{ public boolean filter(Node oldNode,Node newNode); public void process(Node oldNode,Node newNode); } public interface EdgeProcessor{ public boolean filter(Edge oldNode); public void process(Edge oldNode,Edge newNode); } protected HashMap<TripleComponent,NodeProcessor> nodeProcessors = new HashMap<TripleComponent,NodeProcessor>(); protected HashSet<EdgeProcessor> edgeProcessors = new HashSet<EdgeProcessor>(); private Copier copier; protected EObject getCopiedObject(EObject obj){ return copier.get(obj); } /** * the constructor * * @param rule * @see tggeditor.create.rule.CreateRuleCommand */ public ProcessRuleCommand(Rule rule) { this(rule,null); } public abstract IndependentUnit getContainer(IndependentUnit container); /** * the constructor * * @param rule * @see tggeditor.create.rule.CreateRuleCommand */ public ProcessRuleCommand(Rule rule,IndependentUnit container) { this.oldRule = rule; this.container = container; oldLhsNodes2TLhsNodes = new HashMap<Node, Node>(); oldRhsNodes2TRhsNodes = new HashMap<Node, Node>(); // oldNacNodes2TLhsNodes = new HashMap<Node, Node>(); } protected abstract void preProcess(); protected abstract String getRuleMarker(); /** * executes the command */ @Override public void execute() { tgg = GraphicalNodeUtil.getLayoutSystem(oldRule); // preProcess(); // if rule is empty: nothing to do, possibly warning copier = new Copier(); EObject result = copier.copy(oldRule); copier.copyReferences(); newRule = (Rule) result; newRule.setCheckDangling(false); newRule.setName(prefix + oldRule.getName()); ((TGGRule) newRule).setMarkerType(getRuleMarker()); ((TGGRule) newRule).setIsMarked(true); // add new rule to the module oldRule.getModule().getUnits().add(newRule); IndependentUnit con = (IndependentUnit) getContainer(container); if (!con.getSubUnits().contains(newRule)) con.getSubUnits().add(newRule); setGraphLayout(); // old graphs Graph oldRHS = oldRule.getRhs(); EList<Graph> graphsToProcess = RuleUtil.getNACGraphs(oldRule); graphsToProcess.add(oldRHS); /* * process all nodes in the RHS and NAC graphs */ for (Graph g : graphsToProcess) { for (Node o : g.getNodes()) { NodeProcessor np = nodeProcessors.get(NodeUtil .guessTripleComponent((TNode) o)); if (np != null && np.filter(o, (Node) copier.get(o))) np.process(o, (Node) copier.get(o)); ((TNode) copier.get(o)).setComponent(NodeUtil .guessTripleComponent((TNode) o)); TNode lhs = (TNode) RuleUtil.getLHSNode(o); if (lhs != null) lhs.setComponent(NodeUtil.guessTripleComponent((TNode) o)); } /* * process all edges in RHS and NAC graphs */ for (Edge ruleEdge : g.getEdges()) { for (EdgeProcessor ep : edgeProcessors) { if (ep.filter(ruleEdge)) ep.process(ruleEdge, (Edge) copier.get(ruleEdge)); } } } super.execute(); GraphOptimizer.optimize(newRule.getLhs()); } protected void setEdgeMarker(Edge newEdgeRHS, String markerType) { if(newEdgeRHS!=null) ((TEdge) newEdgeRHS).setMarkerType(markerType); } protected Attribute copyAtt(Attribute att, Node newNode) { Attribute newAtt = TggFactory.eINSTANCE.createTAttribute(); newAtt.setType(att.getType()); newAtt.setValue(att.getValue()); newAtt.setNode(newNode); newNode.getAttributes().add(newAtt); return newAtt; } // /* // * copy NacMappings // */ // protected List<Mapping> copyNacMappings(EList<Mapping> nacMappings) { // List<Mapping> newMappings = new ArrayList<Mapping>(); // // for (Mapping m : nacMappings) { // // Node newMappingImage = oldNacNodes2TLhsNodes.get(m.getImage()); // Node newMappingOrigin = oldLhsNodes2TLhsNodes.get(m.getOrigin()); // // Mapping newM = HenshinFactory.eINSTANCE.createMapping( // newMappingOrigin, newMappingImage); // // newMappings.add(newM); // } // // return newMappings; // } // /* // * copy graph with all nodes and edges // */ // protected Graph copyGraph(Graph graph, Graph newGraph) { // newGraph.setName(graph.getName()); // for (Node n : graph.getNodes()) { // TNode oldNode = (TNode) n; // Node tNode = copyNode(oldNode, newGraph); // setNodeLayout(tNode, oldNode); // oldNacNodes2TLhsNodes.put(oldNode, tNode); // } // // for (Edge edge : graph.getEdges()) { // TNode sourceNode = (TNode) edge.getSource(); // TNode targetNode = (TNode) edge.getTarget(); // Edge tEdge = copyEdge(edge, newGraph); // Node sourceTNode = oldNacNodes2TLhsNodes.get(sourceNode); // Node targetTNode = oldNacNodes2TLhsNodes.get(targetNode); // setReferences(sourceTNode, targetTNode, tEdge, newGraph); // ((TEdge) tEdge).setMarkerType(null); // } // return newGraph; // } protected void setReferences(Node sourceNode, Node targetNode, Edge edge, Graph tRuleGraph) { edge.setSource(sourceNode); edge.setTarget(targetNode); edge.setGraph(tRuleGraph); } @Override public boolean canExecute() { return oldRule != null && !oldRule.getRhs().getNodes().isEmpty(); } protected Node copyNode(Node originalNode, Graph destinationGraph) { Node newNode = TggFactory.eINSTANCE.createTNode(); newNode.setName(originalNode.getName()); newNode.setType(originalNode.getType()); for (Attribute att : originalNode.getAttributes()) { Attribute newAtt = TggFactory.eINSTANCE.createTAttribute(); newAtt.setType(att.getType()); newAtt.setValue(att.getValue()); newAtt.setNode(newNode); newNode.getAttributes().add(newAtt); } newNode.setGraph(destinationGraph); destinationGraph.getNodes().add(newNode); ((TNode)newNode).setComponent(NodeUtil.guessTripleComponent((TNode) originalNode)); return newNode; } protected Node copyNodePure(Node originalNode, Graph destinationGraph) { Node newNode = TggFactory.eINSTANCE.createTNode(); newNode.setName(originalNode.getName()); newNode.setType(originalNode.getType()); ((TNode)newNode).setComponent(NodeUtil.guessTripleComponent((TNode) originalNode)); newNode.setGraph(destinationGraph); destinationGraph.getNodes().add(newNode); return newNode; } /* * creates a mapping, sets image and origin and adds the mapping to the * tRule */ protected void setMapping(Node tNodeLHS, Node tNodeRHS) { Mapping mapping = HenshinFactory.eINSTANCE.createMapping(); mapping.setImage(tNodeRHS); mapping.setOrigin(tNodeLHS); newRule.getMappings().add(mapping); } protected void setNodeLayoutAndMarker(Node rhsNode, Node oldNode, String markerType) { setNodeLayout(rhsNode,oldNode); setNodeMarker(rhsNode,markerType); } protected void setNodeMarker(Node rhsNode, String markerType) { ((TNode) rhsNode).setMarkerType(markerType); } protected void setNodeLayout(Node rhsNode, Node oldNode) { ((TNode) rhsNode).setX(((TNode) oldNode).getX()); ((TNode) rhsNode).setY(((TNode) oldNode).getY()); } protected Edge copyEdge(Edge edge, Graph graph) { Edge tEdge = TggFactory.eINSTANCE.createTEdge(); tEdge.setType(edge.getType()); return tEdge; } protected void setGraphLayout() { TripleGraph oldTripleGraph = (TripleGraph) oldRule.getRhs(); TripleGraph newTripleGraph = (TripleGraph) newRule.getRhs(); newTripleGraph.setDividerSC_X(oldTripleGraph.getDividerSC_X()); newTripleGraph.setDividerCT_X(oldTripleGraph.getDividerCT_X()); newTripleGraph.setDividerMaxY(oldTripleGraph.getDividerMaxY()); } protected void setNACGraphLayout(Graph oldNAC, Graph newNAC) { TripleGraph oldTripleGraph = (TripleGraph) oldNAC; TripleGraph newTripleGraph = (TripleGraph) newNAC; newTripleGraph.setDividerSC_X(oldTripleGraph.getDividerSC_X()); newTripleGraph.setDividerCT_X(oldTripleGraph.getDividerCT_X()); newTripleGraph.setDividerMaxY(oldTripleGraph.getDividerMaxY()); } }