/** * <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.model.actions; import java.util.ArrayList; import org.eclipse.emf.ecore.util.EcoreUtil; import org.eclipse.emf.henshin.model.Edge; import org.eclipse.emf.henshin.model.Graph; import org.eclipse.emf.henshin.model.Mapping; import org.eclipse.emf.henshin.model.MappingList; import org.eclipse.emf.henshin.model.Node; import org.eclipse.emf.henshin.model.Rule; /** * A helper class for editing node maps, e.g. for copying and * mapping nodes from the source to the target graph etc. * * @author Christian Krause */ public class NodeMapEditor extends AbstractMapEditor<Node> { // Edge map editor: private EdgeMapEditor edgeMapEditor; /** * Default constructor. */ public NodeMapEditor(Graph source, Graph target, MappingList mappings) { super(source, target, mappings); edgeMapEditor = new EdgeMapEditor(this); } /** * Alternative constructor. */ public NodeMapEditor(Graph target) { super(target); edgeMapEditor = new EdgeMapEditor(this); } /** * Alternative constructor. */ public NodeMapEditor(EdgeMapEditor edgeMapEditor) { super(edgeMapEditor); this.edgeMapEditor = edgeMapEditor; } /* * (non-Javadoc) * @see org.eclipse.emf.henshin.diagram.edit.maps.AbstractMapEditor#doRemove(java.lang.Object) */ protected void doRemove(Node node) { node.getGraph().removeNode(node); } /* * (non-Javadoc) * @see org.eclipse.emf.henshin.diagram.edit.maps.AbstractMapEditor#doCopy(java.lang.Object) */ protected Node doCopy(Node node) { // Create the copy: Node copy = performCopy(node); // Copy the incoming and outgoing edges: for (Edge incoming : node.getIncoming()) { performCopy(incoming.getSource()); edgeMapEditor.copy(incoming); } for (Edge outgoing : node.getOutgoing()) { performCopy(outgoing.getTarget()); edgeMapEditor.copy(outgoing); } // Done. return copy; } /* * (non-Javadoc) * @see org.eclipse.emf.henshin.diagram.edit.maps.AbstractMapEditor#doMove(java.lang.Object) */ protected void doMove(Node node) { // The graph where we move the node to: Graph newGraph = getOpposite(node.getGraph()); // Move all incoming and outgoing edges: for (Edge incoming : node.getIncoming()) { incoming.setSource(performCopy(incoming.getSource())); incoming.setGraph(newGraph); } for (Edge outgoing : node.getOutgoing()) { outgoing.setTarget(performCopy(outgoing.getTarget())); outgoing.setGraph(newGraph); } // Move the node itself: node.setGraph(newGraph); } /* * (non-Javadoc) * @see org.eclipse.emf.henshin.diagram.edit.maps.AbstractMapEditor#doReplace(java.lang.Object) */ protected Node doReplace(Node node) { Node opposite = getOpposite(node); Graph graph = node.getGraph(); // Migrate the new edges: for (Edge incoming : opposite.getIncoming()) { // Remove old edges first: Edge oldEdge = edgeMapEditor.getOpposite(incoming); if (oldEdge!=null) { graph.removeEdge(oldEdge); } // Now wire the new edge and move it to the other graph: incoming.setSource(performCopy(incoming.getSource())); incoming.setGraph(graph); } for (Edge outgoing : opposite.getOutgoing()) { // Remove old edges first: Edge oldEdge = edgeMapEditor.getOpposite(outgoing); if (oldEdge!=null) { graph.removeEdge(oldEdge); } // Now wire the new edge and move it to the other graph: outgoing.setTarget(performCopy(outgoing.getTarget())); outgoing.setGraph(graph); } // Take care of the old edges that are not mapped (the others are removed by now): for (Edge incoming : new ArrayList<Edge>(node.getIncoming())) { incoming.setTarget(opposite); } for (Edge outgoing : new ArrayList<Edge>(node.getOutgoing())) { outgoing.setSource(opposite); } // Remove the mapping now (not earlier): removeMapping(node, opposite); // Replace the old node by the new node: int index = graph.getNodes().indexOf(node); graph.getNodes().set(index, opposite); // Update the multi-mappings: updateMappings(node, opposite); // Done. return opposite; } /* * Update all related mappings. */ void updateMappings(Node oldNode, Node newNode) { Rule rule = newNode.getGraph().getRule(); for (Mapping m : rule.getAllMappings()) { if (m.getOrigin()==oldNode) { m.setOrigin(newNode); } if (m.getImage()==oldNode) { m.setImage(newNode); } } } /* * Perform a copy operation. */ Node performCopy(Node node) { Node opposite = getOpposite(node); if (opposite==null) { opposite = (Node) EcoreUtil.copy(node); opposite.setGraph(getOpposite(node.getGraph())); createMapping(node, opposite); } return opposite; } /* * (non-Javadoc) * @see org.eclipse.emf.henshin.diagram.edit.maps.AbstractMapEditor#doRemoveMapping(java.lang.Object, java.lang.Object) */ @Override protected void doRemoveMapping(Node origin, Node image) { getMappings().remove(origin, image); } /* * (non-Javadoc) * @see org.eclipse.emf.henshin.diagram.edit.maps.AbstractMapEditor#doCreateMapping(java.lang.Object, java.lang.Object) */ @Override protected void doCreateMapping(Node origin, Node image) { getMappings().add(origin, image); } }