/*******************************************************************************
* 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.
*******************************************************************************/
/**
* CollapseNodeCommand.java
* created on 14.07.2012 12:31:58
*/
package de.tub.tfs.henshin.editor.commands.graph;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.henshin.model.Edge;
import org.eclipse.emf.henshin.model.Graph;
import org.eclipse.emf.henshin.model.Node;
import org.eclipse.gef.commands.CompoundCommand;
import de.tub.tfs.henshin.editor.editparts.graph.graphical.EdgeEditPart;
import de.tub.tfs.henshin.editor.editparts.graph.graphical.GraphEditPart;
import de.tub.tfs.henshin.editor.editparts.graph.graphical.NodeEditPart;
import de.tub.tfs.henshin.editor.editparts.graph.graphical.SubtreeEdgeEditPart;
import de.tub.tfs.henshin.editor.editparts.graph.graphical.SubtreeEditPart;
import de.tub.tfs.henshin.editor.util.HenshinCache;
import de.tub.tfs.henshin.editor.util.HenshinSelectionUtil;
import de.tub.tfs.henshin.model.layout.NodeLayout;
import de.tub.tfs.henshin.model.subtree.Subtree;
import de.tub.tfs.henshin.model.subtree.SubtreeFactory;
/**
* @author huuloi
*
*/
public class CollapseNodeCommand extends CompoundCommand {
private Node node;
private Graph graph;
private Subtree subtree;
private GraphEditPart graphEditPart;
private Map<?, ?> editPartRegistry;
public CollapseNodeCommand(Node node) {
this.node = node;
this.graph = node.getGraph();
editPartRegistry = HenshinSelectionUtil.getInstance().getEditPartRegistry(graph);
graphEditPart = (GraphEditPart) editPartRegistry.get(graph);
// create new subtrees node with new edges
subtree = SubtreeFactory.eINSTANCE.createSubtree();
subtree.setRoot(node);
// create layout for subtree
NodeEditPart nodeEditPart = (NodeEditPart) editPartRegistry.get(node);
NodeLayout nodeLayout = nodeEditPart.getLayoutModel();
SubtreeEditPart subtreeEditPart = new SubtreeEditPart(subtree);
subtreeEditPart.getLayoutModel().setX(nodeLayout.getX());
subtreeEditPart.getLayoutModel().setY(nodeLayout.getY());
graphEditPart.addChild(subtreeEditPart, 0);
// remove all edgeEditParts
removeAllEdgeEditParts(node);
// remove all nodeEditParts
removeAllNodeEditParts(node);
// create new incoming edge from parent
Node parent = getParent();
add(new CreateSubtreeEdgeCommand(parent, subtree, getEdgeType()));
// get all outgoing edges of nodes children
Set<Edge> oldOutgoing = getOutgoingWithoutContainment(node);
// create new outgoing edges for subtree
for (Edge edge : oldOutgoing) {
Node targetNode = edge.getTarget();
add(new CreateSubtreeEdgeCommand(subtree, targetNode, edge.getType()));
}
// get all subtreeOutgoing edges of node and its children
Set<de.tub.tfs.henshin.model.subtree.Edge> oldSubtreeOutgoing = getSubtreeEdgeOutgoing(node);
// create new outgoing edges for subtree
for (de.tub.tfs.henshin.model.subtree.Edge edge : oldSubtreeOutgoing) {
if (!edge.getType().isContainment()) {
if (edge.getTarget() != null) {
Subtree target = edge.getTarget();
add(new CreateSubtreeEdgeCommand(subtree, target, edge.getType()));
}
else if (edge.getTargetNode() != null) {
Node target = edge.getTargetNode();
add(new CreateSubtreeEdgeCommand(subtree, target, edge.getType()));
}
}
}
// get all incoming edges of node and its children
Set<Edge> oldIncoming = getIncomingWithoutContainment(node);
// create new incoming edges for subtree
for (Edge edge : oldIncoming) {
Node sourceNode = edge.getSource();
add(new CreateSubtreeEdgeCommand(sourceNode, subtree, edge.getType()));
}
// get all subtreeIncoming edges of node and its children
Set<de.tub.tfs.henshin.model.subtree.Edge> oldSubtreeIncoming = getSubtreeEdgeIncoming(node);
// create new incoming edges for subtree
for (de.tub.tfs.henshin.model.subtree.Edge edge : oldSubtreeIncoming) {
if (!edge.getType().isContainment()) {
if (edge.getSource() != null) {
Subtree source = edge.getSource();
add(new CreateSubtreeEdgeCommand(source, subtree, edge.getType()));
}
else if (edge.getSourceNode() != null) {
Node sourceNode = edge.getSourceNode();
add(new CreateSubtreeEdgeCommand(sourceNode, subtree, edge.getType()));
}
}
}
}
@Override
public boolean canExecute() {
return node != null /* && new ValidateGraphAction(null).validate(node.getGraph())*/;
}
private Set<de.tub.tfs.henshin.model.subtree.Edge> getSubtreeEdgeOutgoing(Node node) {
Set<de.tub.tfs.henshin.model.subtree.Edge> edges = new HashSet<de.tub.tfs.henshin.model.subtree.Edge>();
Set<de.tub.tfs.henshin.model.subtree.Edge> outgoings = HenshinCache.getInstance().getOutgoingEdgeMap().get(node);
if (outgoings != null && !outgoings.isEmpty()) {
for (de.tub.tfs.henshin.model.subtree.Edge edge : outgoings) {
edges.add(edge);
if (edge.getType().isContainment()) {
Subtree subtree = edge.getTarget();
edges.addAll(subtree.getOutgoing());
}
}
edges.addAll(outgoings);
}
EList<Edge> outgoing = node.getOutgoing();
for (Edge edge : outgoing) {
if (edge.getType().isContainment()) {
Set<de.tub.tfs.henshin.model.subtree.Edge> outgoingList = HenshinCache.getInstance().getOutgoingEdgeMap().get(edge.getTarget());
if (outgoingList != null && !outgoingList.isEmpty()) {
edges.addAll(outgoingList);
}
}
}
return edges;
}
private Set<de.tub.tfs.henshin.model.subtree.Edge> getSubtreeEdgeIncoming(Node node) {
Set<de.tub.tfs.henshin.model.subtree.Edge> edges = new HashSet<de.tub.tfs.henshin.model.subtree.Edge>();
Set<de.tub.tfs.henshin.model.subtree.Edge> incomings = HenshinCache.getInstance().getIncomingEdgeMap().get(node);
if (incomings != null && !incomings.isEmpty()) {
edges.addAll(incomings);
}
EList<Edge> outgoing = node.getOutgoing();
for (Edge edge : outgoing) {
if (edge.getType().isContainment()) {
edges.addAll(getSubtreeEdgeIncoming(edge.getTarget()));
}
}
Set<de.tub.tfs.henshin.model.subtree.Edge> subtreeEdgeOutgoing = HenshinCache.getInstance().getOutgoingEdgeMap().get(node);
if (subtreeEdgeOutgoing != null) {
for (de.tub.tfs.henshin.model.subtree.Edge edge : subtreeEdgeOutgoing) {
if (edge.getType().isContainment()) {
edges.addAll(HenshinCache.getInstance().getIncomingSubtreeEdgeMap().get(edge.getTarget()));
}
}
}
return edges;
}
private Set<Edge> getOutgoingWithoutContainment(Node node) {
Set<Edge> edges = new HashSet<Edge>();
EList<Edge> outgoing = node.getOutgoing();
for (Edge edge : outgoing) {
if (!edge.getType().isContainment() && !HenshinCache.getInstance().getCollapsedEdges().contains(edge)) {
HenshinCache.getInstance().getCollapsedEdges().add(edge);
edges.add(edge);
}
else {
edges.addAll(getOutgoingWithoutContainment(edge.getTarget()));
}
}
return edges;
}
private Set<Edge> getIncomingWithoutContainment(Node node) {
Set<Edge> edges = new HashSet<Edge>();
EList<Edge> incoming = node.getIncoming();
for (Edge edge : incoming) {
if (!edge.getType().isContainment() && !HenshinCache.getInstance().getCollapsedEdges().contains(edge)) {
HenshinCache.getInstance().getCollapsedEdges().add(edge);
edges.add(edge);
}
}
EList<Edge> outgoing = node.getOutgoing();
for (Edge edge : outgoing) {
if (edge.getType().isContainment()) {
edges.addAll(getIncomingWithoutContainment(edge.getTarget()));
}
}
return edges;
}
private void removeAllEdgeEditParts(Node node) {
NodeEditPart nodeEditPart = (NodeEditPart) editPartRegistry.get(node);
// remove all incoming edges
EList<Edge> incoming = node.getIncoming();
for (Edge edge : incoming) {
EdgeEditPart edgeEditPart = (EdgeEditPart) editPartRegistry.get(edge);
if (edgeEditPart != null) {
nodeEditPart.getTargetConnections().remove(edgeEditPart);
edgeEditPart.removeNotify();
}
}
// remove all incoming subtreeEdges
Set<de.tub.tfs.henshin.model.subtree.Edge> subtreeEdgeIncoming = HenshinCache.getInstance().getIncomingEdgeMap().get(node);
if (subtreeEdgeIncoming != null) {
for (de.tub.tfs.henshin.model.subtree.Edge edge : subtreeEdgeIncoming) {
SubtreeEdgeEditPart subtreeEdgeEditPart = (SubtreeEdgeEditPart) editPartRegistry.get(edge);
if (subtreeEdgeEditPart != null) {
nodeEditPart.getTargetConnections().remove(subtreeEdgeEditPart);
subtreeEdgeEditPart.removeNotify();
}
}
}
// remove all outgoing edges
EList<Edge> outgoing = node.getOutgoing();
for (Edge edge : outgoing) {
EdgeEditPart edgeEditPart = (EdgeEditPart) editPartRegistry.get(edge);
if (edgeEditPart != null) {
nodeEditPart.getSourceConnections().remove(edgeEditPart);
edgeEditPart.removeNotify();
}
// call recursive by children
if (edge.getType().isContainment()) {
removeAllEdgeEditParts(edge.getTarget());
}
}
// remove all outgoing subtreeEdges
Set<de.tub.tfs.henshin.model.subtree.Edge> subtreeEdgeOutgoing = HenshinCache.getInstance().getOutgoingEdgeMap().get(node);
if (subtreeEdgeOutgoing != null) {
for (de.tub.tfs.henshin.model.subtree.Edge edge : subtreeEdgeOutgoing) {
SubtreeEdgeEditPart subtreeEdgeEditPart = (SubtreeEdgeEditPart) editPartRegistry.get(edge);
if (subtreeEdgeEditPart != null) {
nodeEditPart.getSourceConnections().remove(subtreeEdgeEditPart);
subtreeEdgeEditPart.removeNotify();
}
// call recursive by children
if (edge.getType().isContainment()) {
removeAllEdgeEditParts(edge.getTarget());
}
}
}
}
private void removeAllEdgeEditParts(Subtree subtree) {
SubtreeEditPart subtreeEditPart = (SubtreeEditPart) editPartRegistry.get(subtree);
EList<de.tub.tfs.henshin.model.subtree.Edge> incoming = subtree.getIncoming();
for (de.tub.tfs.henshin.model.subtree.Edge edge : incoming) {
SubtreeEdgeEditPart subtreeEdgeEditPart = (SubtreeEdgeEditPart) editPartRegistry.get(edge);
if (subtreeEdgeEditPart != null) {
subtreeEditPart.getTargetConnections().remove(subtreeEdgeEditPart);
subtreeEdgeEditPart.removeNotify();
}
}
EList<de.tub.tfs.henshin.model.subtree.Edge> outgoing = subtree.getOutgoing();
for (de.tub.tfs.henshin.model.subtree.Edge edge : outgoing) {
SubtreeEdgeEditPart subtreeEdgeEditPart = (SubtreeEdgeEditPart) editPartRegistry.get(edge);
if (subtreeEdgeEditPart != null) {
subtreeEditPart.getSourceConnections().remove(subtreeEdgeEditPart);
subtreeEdgeEditPart.removeNotify();
}
}
}
private void removeAllNodeEditParts(Node node) {
NodeEditPart nodeEditPart = (NodeEditPart) editPartRegistry.get(node);
if (nodeEditPart != null) {
graphEditPart.removeChild(nodeEditPart);
HenshinCache.getInstance().getRemovedEditParts().add(node);
}
EList<Edge> outgoing = node.getOutgoing();
for (Edge edge : outgoing) {
if (edge.getType().isContainment()) {
removeAllNodeEditParts(edge.getTarget());
}
}
Set<de.tub.tfs.henshin.model.subtree.Edge> subtreeEdges = HenshinCache.getInstance().getOutgoingEdgeMap().get(node);
if (subtreeEdges != null) {
for (de.tub.tfs.henshin.model.subtree.Edge edge : subtreeEdges) {
if (edge.getType().isContainment()) {
Subtree subtree = edge.getTarget();
graphEditPart.removeChild((SubtreeEditPart) editPartRegistry.get(subtree));
}
}
}
}
private Node getParent() {
if (node != null) {
EList<Edge> incoming = node.getIncoming();
for (Edge edge : incoming) {
if (edge.getType().isContainment()) {
return edge.getSource();
}
}
}
return null;
}
private EReference getEdgeType() {
if (node != null) {
EList<Edge> incoming = node.getIncoming();
for (Edge edge : incoming) {
if (edge.getType().isContainment()) {
return edge.getType();
}
}
}
return null;
}
}