/*******************************************************************************
* Copyright (c) 2016 itemis AG and others.
* 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:
* Alexander Nyßen (itemis AG) - initial API and implementation
* Matthias Wienand (itemis AG) - provide input to output maps (bug #497662)
*
*******************************************************************************/
package org.eclipse.gef.graph;
import java.util.Collections;
import java.util.IdentityHashMap;
import java.util.Map;
import org.eclipse.gef.common.attributes.IAttributeCopier;
import org.eclipse.gef.common.attributes.IAttributeStore;
/**
* A copier for {@link Graph}s.
*
* @author anyssen
*
*/
public class GraphCopier {
private Map<Node, Node> inputToOutputNodes = new IdentityHashMap<>();
private Map<Edge, Edge> inputToOutputEdges = new IdentityHashMap<>();
private IAttributeCopier attributeCopier;
/**
* Creates a new {@link GraphCopier} instance with the given
* {@link IAttributeCopier}.
*
* @param attributeCopier
* The {@link IAttributeCopier} used to copy the attributes of
* {@link Graph}, {@link Node}s, and {@link Edge}s.
*/
public GraphCopier(IAttributeCopier attributeCopier) {
this.attributeCopier = attributeCopier;
}
/**
* Creates a copy of the given {@link Graph}.
*
* @param graph
* The Graph to copy.
* @return A new graph that is the result of the copy operation.
*/
public Graph copy(Graph graph) {
// clear input to output maps
inputToOutputNodes.clear();
inputToOutputEdges.clear();
return copyGraph(graph);
}
/**
* Transfers attributes from the given input {@link Graph}, {@link Node}, or
* {@link Edge} to the given output {@link Graph}, {@link Node}, or
* {@link Edge}. The attributes may be copied or simply transferred. This
* lies within the responsibility of the {@link IAttributeCopier} that was
* passed in on construction of the {@link GraphCopier}.
*
* @param inputStore
* The {@link Graph}, {@link Node}, or {@link Edge} from which to
* copy attributes.
* @param outputStore
* The {@link Graph}, {@link Node}, or {@link Edge} to copy
* attributes to.
*/
// TODO: This callback should be removed (inlined); we will need to refactor
// the Dot2ZestGraphConverter first into a pure IAttributeCopier.
protected void copyAttributes(IAttributeStore inputStore, IAttributeStore outputStore) {
attributeCopier.copy(inputStore, outputStore);
}
/**
* Creates a copy of the given edge.
*
* @param edge
* The Edge to copy.
* @return A new {@link Edge} with transferred relations and (copied)
* attributes.
*/
protected Edge copyEdge(Edge edge) {
// find nodes
Node outputSource = inputToOutputNodes.get(edge.getSource());
Node outputTarget = inputToOutputNodes.get(edge.getTarget());
// create edge
Edge outputEdge = new Edge(outputSource, outputTarget);
copyAttributes(edge, outputEdge);
return outputEdge;
}
/**
* Copies the given {@link Graph} using the current
* {@link IAttributeCopier}. Records the copied nodes in the
* {@link #getInputToOutputNodeMap()} and the copied edges in the
* {@link #getInputToOutputEdgeMap()}.
*
* @param graph
* The input {@link Graph} to copy.
* @return The copied result {@link Graph}.
*/
protected Graph copyGraph(Graph graph) {
// create new graph to hold the copy
Graph outputGraph = new Graph();
copyAttributes(graph, outputGraph);
// copy nodes, keeping track of copied nodes (so we can relocate them to
// link edges)
for (Node inputNode : graph.getNodes()) {
Node outputNode = copyNode(inputNode);
if (outputNode != null) {
inputToOutputNodes.put(inputNode, outputNode);
outputGraph.getNodes().add(outputNode);
}
}
// copy edges
for (Edge inputEdge : graph.getEdges()) {
Edge outputEdge = copyEdge(inputEdge);
if (outputEdge != null) {
inputToOutputEdges.put(inputEdge, outputEdge);
outputGraph.getEdges().add(outputEdge);
}
}
return outputGraph;
}
/**
* Creates a copy of the given node.
*
* @param node
* The {@link Node} to copy.
* @return A new Node with transferred relations and (copied) attributes.
*/
protected Node copyNode(Node node) {
Node outputNode = new Node();
copyAttributes(node, outputNode);
// convert nested graph
if (node.getNestedGraph() != null) {
Graph nested = copyGraph(node.getNestedGraph());
outputNode.setNestedGraph(nested);
}
return outputNode;
}
/**
* Returns the {@link IAttributeCopier} used by this {@link GraphCopier}.
*
* @return The {@link IAttributeCopier} used by this {@link GraphCopier}.
*/
public IAttributeCopier getAttributeCopier() {
return attributeCopier;
}
/**
* Returns an (unmodifiable) {@link Map} from input {@link Edge}s to output
* {@link Edge}s.
*
* @return An (unmodifiable) {@link Map} from input {@link Edge}s to output
* {@link Edge}s.
*/
public Map<Edge, Edge> getInputToOutputEdgeMap() {
return Collections.unmodifiableMap(inputToOutputEdges);
}
/**
* Returns an (unmodifiable) {@link Map} from input {@link Node}s to output
* {@link Node}s.
*
* @return An (unmodifiable) {@link Map} from input {@link Node}s to output
* {@link Node}s.
*/
public Map<Node, Node> getInputToOutputNodeMap() {
return Collections.unmodifiableMap(inputToOutputNodes);
}
}