1   /****************************************************************************
2    **
3    ** This file is part of yFiles-2.9. 
4    ** 
5    ** yWorks proprietary/confidential. Use is subject to license terms.
6    **
7    ** Redistribution of this file or of an unauthorized byte-code version
8    ** of this file is strictly forbidden.
9    **
10   ** Copyright (c) 2000-2011 by yWorks GmbH, Vor dem Kreuzberg 28, 
11   ** 72070 Tuebingen, Germany. All rights reserved.
12   **
13   ***************************************************************************/
14  package demo.layout.multipage;
15  
16  import y.base.DataProvider;
17  import y.base.Edge;
18  import y.base.Graph;
19  import y.base.GraphFactory;
20  import y.base.Node;
21  import y.base.NodeMap;
22  import y.geom.YDimension;
23  import y.geom.YPoint;
24  import y.geom.YPointCursor;
25  import y.layout.EdgeLabelLayout;
26  import y.layout.LayoutGraph;
27  import y.layout.NodeLabelLayout;
28  import y.layout.multipage.EdgeInfo;
29  import y.layout.multipage.EdgeLabelInfo;
30  import y.layout.multipage.ElementInfoManager;
31  import y.layout.multipage.MultiPageLayout;
32  import y.layout.multipage.NodeInfo;
33  import y.layout.multipage.NodeLabelInfo;
34  import y.util.GraphCopier;
35  import y.util.Maps;
36  import y.view.EdgeLabel;
37  import y.view.EdgeRealizer;
38  import y.view.Graph2D;
39  import y.view.NodeLabel;
40  import y.view.NodeRealizer;
41  import y.view.ShapeNodeRealizer;
42  import y.view.hierarchy.DefaultHierarchyGraphFactory;
43  import y.view.hierarchy.HierarchyManager;
44  
45  import java.awt.Color;
46  import java.util.Map;
47  
48  /**
49   * Builds {@link Graph2D} page graphs from a {@link MultiPageLayout} instance.
50   *
51   * @see y.layout.multipage.MultiPageLayout
52   */
53  public class MultiPageGraph2DBuilder {
54    /**
55     * DataProvider-Key used to store the ids of the referencing node elements, see
56     * {@link y.layout.multipage.NodeInfo#getReferencingNode()}.
57     * The DataProvider is automatically added to the Graph2D page representation.
58     */
59    private static final Object REFERENCING_NODE_ID_DPKEY =
60            "demo.layout.multipage.MultiPageGraph2DBuilder.REFERENCING_NODE_ID_DPKEY";
61  
62    private static final Object NODE_INFO_DPKEY =
63            "demo.layout.multipage.MultiPageGraph2DBuilder.NODE_INFO_DPKEY";
64  
65  
66    private Graph2D model;
67    private MultiPageLayout layout;
68    private GraphCopier.CopyFactory copyFactory;
69  
70    /**
71     * Creates a new instance.
72     *
73     * @param model the underlying graph.
74     * @param layout the result of the page layout applied to the model.
75     */
76    public MultiPageGraph2DBuilder(Graph2D model, MultiPageLayout layout) {
77      this.model = model;
78      this.layout = layout;
79    }
80  
81    public void reset(Graph2D model, MultiPageLayout layout) {
82      this.model = model;
83      this.layout = layout;
84      this.copyFactory = null;
85    }
86  
87    /**
88     * Returns the copy factory that is used to create the Graph2D elements.
89     *
90     * @return the copy factory used to create the Graph2D elements.
91     */
92    private GraphCopier.CopyFactory getCopyFactory() {
93      return copyFactory;
94    }
95  
96    /**
97     * Returns the result of the page layout applied to the model.
98     *
99     * @return the page layout.
100    * @see #getModel()
101    */
102   public MultiPageLayout getLayout() {
103     return layout;
104   }
105 
106   /**
107    * Returns the underlying graph.
108    * 
109    * @return the underlying graph.
110    */
111   public Graph2D getModel() {
112     return model;
113   }
114 
115   /**
116    * Returns the ID of the specified node.
117    * 
118    * @param node the node whose ID is retrieved.
119    * @return the ID of the specified node or <code>null</code> if the node
120    * does not belong to a page graph created by
121    * <code>MultiPageGraph2DBuilder</code>.
122    */
123   public Object getNodeId( final Node node ) {
124     final Graph graph = node.getGraph();
125     if (graph != null) {
126       final DataProvider dp = graph.getDataProvider(NODE_INFO_DPKEY);
127       if (dp != null) {
128         final NodeInfo info = (NodeInfo) dp.get(node);
129         if (info != null) {
130           return info.getId();
131         }
132       }
133     }
134     return null;
135   }
136 
137   public byte getNodeType( final Node node ) {
138     final Graph graph = node.getGraph();
139     if (graph != null) {
140       final DataProvider dp = graph.getDataProvider(NODE_INFO_DPKEY);
141       if (dp != null) {
142         final NodeInfo info = (NodeInfo) dp.get(node);
143         if (info != null) {
144           return info.getType();
145         }
146       }
147     }
148     return -1;
149   }
150 
151   public int getPageNo( final Node node ) {
152     final Graph graph = node.getGraph();
153     if (graph != null) {
154       final DataProvider dp = graph.getDataProvider(NODE_INFO_DPKEY);
155       if (dp != null) {
156         final NodeInfo info = (NodeInfo) dp.get(node);
157         if (info != null) {
158           return info.getPageNo();
159         }
160       }
161     }
162     return -1;
163   }
164 
165   public int getReferencedPageNo( final Node node ) {
166     final Graph graph = node.getGraph();
167     if (graph != null) {
168       final DataProvider dp = graph.getDataProvider(NODE_INFO_DPKEY);
169       if (dp != null) {
170         final NodeInfo info = (NodeInfo) dp.get(node);
171         if (info != null) {
172           final Node mpRef = info.getReferencingNode();
173           if (mpRef != null) {
174             final NodeInfo mpRefInfo = layout.getNodeInfo(mpRef);
175             return mpRefInfo.getPageNo();
176           }
177         }
178       }
179     }
180     return -1;
181   }
182 
183   public Object getReferencingNodeId( final Node node ) {
184     final Graph graph = node.getGraph();
185     if (graph != null) {
186       final DataProvider dp = graph.getDataProvider(REFERENCING_NODE_ID_DPKEY);
187       if (dp != null) {
188         return dp.get(node);
189       }
190     }
191     return null;
192   }
193 
194   /**
195    * Creates a <code>Graph2D</code> representation for the specified page.
196    *
197    * @param page the <code>Graph2D</code> to store the specified page.
198    * @param pageNo the number of the page that should be transformed to a Graph2D
199    * @return a <code>Graph2D</code> that represents the specified page.
200    */
201   public Graph2D createPageView( final Graph2D page, final int pageNo ) {
202     copyFactory = page.getGraphCopyFactory();
203     final GraphCopier graphCopier = new GraphCopier(new MyGraphCopyFactory());
204     graphCopier.copy(getLayout().getPage(pageNo), page);
205     return page;
206   }
207 
208   /**
209    * Callback method for adding a connector node (a node of type {@link NodeInfo#TYPE_CONNECTOR})
210    * to the Graph2D (including the configuration of its realizer).
211    *
212    * @param sourceNode the source node (a node on a page of the MultiPageLayout) that should be replicated.
213    * @param targetGraph the new node should be added to this graph.
214    * @return the added connector node.
215    *
216    * @see NodeInfo#TYPE_CONNECTOR
217    * @see #getLayout()
218    */
219   protected Node createConnectorNode( final Node sourceNode, final Graph2D targetGraph ) {
220     final NodeInfo info = getLayout().getNodeInfo(sourceNode);
221     final Node connector = getCopyFactory().copyNode(targetGraph, sourceNode);
222     final YPoint center = targetGraph.getCenter(connector);
223     final YDimension size = targetGraph.getSize(connector);
224 
225     targetGraph.setRealizer(connector, new ShapeNodeRealizer(ShapeNodeRealizer.ROUND_RECT));
226     targetGraph.getRealizer(connector).setFillColor(Color.YELLOW);
227     final Object referencingNodeID = getLayout().getNodeInfo(info.getReferencingNode()).getId();
228     ((NodeMap) targetGraph.getDataProvider(REFERENCING_NODE_ID_DPKEY)).set(connector, referencingNodeID);
229     addLabels(sourceNode, targetGraph.getRealizer(connector), getLayout());
230     targetGraph.setSize(connector, size);
231     targetGraph.setCenter(connector, center);
232 
233     return connector;
234   }
235 
236   /**
237    * Callback method for adding a
238    * {@link NodeInfo#TYPE_PROXY_REFERENCE proxy reference} node
239    * to the graph (including the configuration of its realizer).
240    *
241    * @param sourceNode the source node (a node on a page of the MultiPageLayout) that should be replicated.
242    * @param targetGraph the new node should be added to this graph.
243    * @return the newly added proxy reference node.
244    *
245    * @see NodeInfo#TYPE_PROXY_REFERENCE
246    * @see NodeInfo#TYPE_PROXY
247    * @see #createProxyNode(y.base.Node, y.view.Graph2D)
248    * @see #getLayout()
249    */
250   protected Node createProxyReferenceNode( final Node sourceNode, final Graph2D targetGraph ) {
251     final NodeInfo info = getLayout().getNodeInfo(sourceNode);
252     final Node pageNode = getCopyFactory().copyNode(targetGraph, sourceNode);
253     final YPoint center = targetGraph.getCenter(pageNode);
254     final YDimension size = targetGraph.getSize(pageNode);
255 
256     final NodeInfo referencingNodeInfo = getLayout().getNodeInfo(
257         info.getReferencingNode());
258     targetGraph.setRealizer(pageNode, new ShapeNodeRealizer(ShapeNodeRealizer.ELLIPSE));
259     targetGraph.getRealizer(pageNode).setFillColor(Color.GREEN);
260     targetGraph.setLabelText(pageNode, "p " + (referencingNodeInfo.getPageNo() + 1)); 
261     final Object referencingNodeID = getLayout().getNodeInfo(info.getReferencingNode()).getId();
262     ((NodeMap) targetGraph.getDataProvider(REFERENCING_NODE_ID_DPKEY)).set(pageNode, referencingNodeID);
263     targetGraph.setSize(pageNode, size);
264     targetGraph.setCenter(pageNode, center);
265 
266     return pageNode;
267   }
268 
269   /**
270    * Callback method for adding a {@link NodeInfo#TYPE_PROXY proxy} node
271    * to the graph (including the configuration of its realizer).
272    *
273    * @param sourceNode the source node (a node on a page of the MultiPageLayout) that should be replicated.
274    * @param targetGraph the new node should be added to this graph.
275    * @return the newly added proxy node.
276    *
277    * @see NodeInfo#TYPE_PROXY
278    * @see NodeInfo#TYPE_PROXY_REFERENCE
279    * @see #createProxyReferenceNode(y.base.Node, y.view.Graph2D)
280    * @see #getLayout()
281    */
282   protected Node createProxyNode( final Node sourceNode, final Graph2D targetGraph ) {
283     final NodeInfo info = getLayout().getNodeInfo(sourceNode);
284     final Node proxy = getCopyFactory().copyNode(targetGraph, sourceNode);
285     final YPoint center = targetGraph.getCenter(proxy);
286     final YDimension size = targetGraph.getSize(proxy);
287 
288     targetGraph.setRealizer(proxy, new ShapeNodeRealizer(ShapeNodeRealizer.ROUND_RECT));
289     targetGraph.getRealizer(proxy).setFillColor(Color.LIGHT_GRAY);
290     final Object referencingNodeID = getLayout().getNodeInfo(info.getReferencingNode()).getId();
291     ((NodeMap) targetGraph.getDataProvider(REFERENCING_NODE_ID_DPKEY)).set(proxy, referencingNodeID);
292     addLabels(sourceNode, targetGraph.getRealizer(proxy), getLayout());
293     targetGraph.setSize(proxy, size);
294     targetGraph.setCenter(proxy, center);
295 
296     return proxy;
297   }
298 
299   /**
300    * Callback method for adding a group node to the Graph2D (including the configuration of its realizer).
301    *
302    * @param sourceNode the source node (a node on a page of the MultiPageLayout) that should be replicated.
303    * @param targetGraph the new node should be added to this graph.
304    * @return the added group node.
305    *
306    * @see NodeInfo#TYPE_GROUP
307    * @see #getLayout()
308    */
309   protected Node createGroupNode(final Node sourceNode, final Graph2D targetGraph) {
310     final NodeInfo info = getLayout().getNodeInfo(sourceNode);
311     final Node groupNode = getCopyFactory().copyNode(targetGraph, sourceNode);
312     final YPoint center = targetGraph.getCenter(groupNode);
313     final YDimension size = targetGraph.getSize(groupNode);
314 
315     final NodeInfo representingNodeInfo = getLayout().getNodeInfo(info.getRepresentedNode());
316     targetGraph.setRealizer(groupNode, getRealizer((Node) representingNodeInfo.getId()));
317     targetGraph.setSize(groupNode, size);
318     targetGraph.setCenter(groupNode, center);
319 
320     return groupNode;
321   }
322 
323   /**
324    * Callback method for adding a normal node (a node of type {@link NodeInfo#TYPE_NORMAL})
325    * to the Graph2D (including the configuration of its realizer).
326    *
327    * @param sourceNode the source node (a node on a page of the MultiPageLayout) that should be replicated.
328    * @param targetGraph the new node should be added to this graph.
329    * @return the added node.
330    *
331    * @see NodeInfo#TYPE_NORMAL
332    * @see #getLayout()
333    */
334   protected Node createNormalNode(final Node sourceNode, final Graph2D targetGraph) {
335     final NodeInfo info = getLayout().getNodeInfo(sourceNode);
336     final Node node = getCopyFactory().copyNode(targetGraph, sourceNode);
337     final YPoint center = targetGraph.getCenter(node);
338     final YDimension size = targetGraph.getSize(node);
339 
340     final NodeInfo representingNodeInfo = getLayout().getNodeInfo(info.getRepresentedNode());
341     targetGraph.setRealizer(node, getRealizer((Node) representingNodeInfo.getId()));
342     addLabels(sourceNode, targetGraph.getRealizer(node), getLayout());
343     targetGraph.setSize(node, size);
344     targetGraph.setCenter(node, center);
345 
346     return node;
347   }
348 
349   /**
350    * Callback method for adding a normal edge (an edge of type {@link y.layout.multipage.EdgeInfo#TYPE_NORMAL})
351    * to the Graph2D (including the configuration of its realizer).
352    *
353    * @param sourceEdge the source edge (an edge on a page of the MultiPageLayout) that should be replicated.
354    * @param newSource the source of the new edge.
355    * @param newTarget the target of the new edge.
356    * @param targetGraph the new edge should be added to this graph.
357    * @return the added edge.
358    *
359    * @see EdgeInfo#TYPE_NORMAL
360    * @see #getLayout()
361    */
362   protected Edge createNormalEdge(final Edge sourceEdge, final Node newSource, final Node newTarget,
363                                   final Graph2D targetGraph) {
364     final EdgeInfo edgeInfo = getLayout().getEdgeInfo(sourceEdge);
365     final Edge newEdge = getCopyFactory().copyEdge(targetGraph, newSource, newTarget, sourceEdge);
366 
367     final EdgeRealizer realizer = createCopyOfRealizer((Edge) edgeInfo.getId());
368     if (realizer != null) {
369       addLabels(sourceEdge, realizer, getLayout());
370       applyRealizer(newEdge, targetGraph, realizer);
371     }
372 
373     return newEdge;
374   }
375 
376   /**
377    * Callback method for adding a
378    * {@link EdgeInfo#TYPE_PROXY_REFERENCE proxy reference} edge
379    * to the graph (including the configuration of its realizer).
380    *
381    * @param sourceEdge the source edge (an edge on a page of the MultiPageLayout) that should be replicated.
382    * @param newSource the source of the new edge.
383    * @param newTarget the target of the new edge.
384    * @param targetGraph the new edge should be added to this graph.
385    * @return the newly added proxy reference edge.
386    *
387    * @see EdgeInfo#TYPE_PROXY_REFERENCE
388    * @see #getLayout()
389    */
390   protected Edge createProxyReferenceEdge( final Edge sourceEdge, final Node newSource, final Node newTarget,
391                                            final Graph2D targetGraph ) {
392     final EdgeInfo edgeInfo = getLayout().getEdgeInfo(sourceEdge);
393     final Edge newEdge = getCopyFactory().copyEdge(targetGraph, newSource, newTarget, sourceEdge);
394 
395     final EdgeRealizer realizer = createCopyOfRealizer((Edge) edgeInfo.getId());
396     if (realizer != null) {
397       addLabels(sourceEdge, realizer, getLayout());
398       applyRealizer(newEdge, targetGraph, realizer);
399     }
400 
401     return newEdge;
402   }
403 
404   /**
405    * Callback method for adding a {@link EdgeInfo#TYPE_CONNECTOR connector} edge
406    * to the graph (including the configuration of its realizer).
407    *
408    * @param sourceEdge the source edge (an edge on a page of the MultiPageLayout) that should be replicated.
409    * @param newSource the source of the new edge.
410    * @param newTarget the target of the new edge.
411    * @param targetGraph the new edge should be added to this graph.
412    * @return the newly added connector edge.
413    *
414    * @see EdgeInfo#TYPE_CONNECTOR
415    * @see #getLayout()
416    */
417   protected Edge createConnectorEdge(final Edge sourceEdge, final Node newSource, final Node newTarget,
418                                      final Graph2D targetGraph) {
419     final EdgeInfo edgeInfo = getLayout().getEdgeInfo(sourceEdge);
420     final Edge newEdge = getCopyFactory().copyEdge(targetGraph, newSource, newTarget, sourceEdge);
421 
422     final Object representingEdgeId = getLayout().getEdgeInfo(edgeInfo.getRepresentedEdge()).getId();
423     final Edge origEdge = (Edge) representingEdgeId;
424     final EdgeRealizer origRealizerCopy = createCopyOfRealizer(origEdge);
425     addLabels(sourceEdge, origRealizerCopy, getLayout());
426     applyRealizer(newEdge, targetGraph, origRealizerCopy);
427     return newEdge;
428   }
429 
430   /**
431    * Callback method for adding a {@link EdgeInfo#TYPE_PROXY proxy} edge
432    * to the graph (including the configuration of its realizer).
433    *
434    * @param sourceEdge the source edge (an edge on a page of the MultiPageLayout) that should be replicated.
435    * @param newSource the source of the new edge.
436    * @param newTarget the target of the new edge.
437    * @param targetGraph the new edge should be added to this graph.
438    * @return the newly added proxy edge.
439    *
440    * @see EdgeInfo#TYPE_PROXY
441    * @see #getLayout()
442    */
443   protected Edge createProxyEdge( final Edge sourceEdge, final Node newSource, final Node newTarget,
444                                   final Graph2D targetGraph ) {
445     final EdgeInfo edgeInfo = getLayout().getEdgeInfo(sourceEdge);
446     final Edge newEdge = getCopyFactory().copyEdge(targetGraph, newSource, newTarget, sourceEdge);
447 
448     final EdgeRealizer realizer = createCopyOfRealizer((Edge) edgeInfo.getId());
449     if (realizer != null) {
450       addLabels(sourceEdge, realizer, getLayout());
451       applyRealizer(newEdge, targetGraph, realizer);
452     }
453 
454     return newEdge;
455   }
456 
457   private static NodeRealizer getRealizer(final Node origNode) {
458     final Graph2D graph = (Graph2D) origNode.getGraph();
459     final NodeRealizer realizer = graph.getRealizer(origNode);
460     return realizer.createCopy();
461   }
462 
463   private static void addLabels(final Node source, final NodeRealizer targetRealizer, final ElementInfoManager infoManager) {
464     //remove existing labels
465     for (int i = targetRealizer.labelCount(); i --> 0;) {
466       targetRealizer.removeLabel(i);
467     }
468 
469     //add labels of source to target realizer
470     final LayoutGraph sourceGraph = (LayoutGraph) source.getGraph();
471     final NodeLabelLayout[] nll = sourceGraph.getNodeLabelLayout(source);
472     for (int i = 0; i < nll.length; i++) {
473       final NodeLabelInfo labelInfo = infoManager.getNodeLabelInfo(nll[i]);
474       final NodeLabel origLabel = (NodeLabel) labelInfo.getId();
475       final NodeLabel newLabel = (NodeLabel) origLabel.clone();
476       newLabel.setModelParameter(nll[i].getModelParameter());
477       targetRealizer.setLabel(newLabel);
478     }
479   }
480 
481   private static void applyRealizer(final Edge e, final Graph2D g, final EdgeRealizer realizer) {
482     if (realizer == null) {
483       return;
484     }
485 
486     realizer.clearPoints();
487     for (YPointCursor cur = g.getPoints(e).points(); cur.ok(); cur.next()) {
488       final YPoint p = cur.point();
489       realizer.addPoint(p.x, p.y);
490     }
491     realizer.setSourcePoint(g.getSourcePointRel(e));
492     realizer.setTargetPoint(g.getTargetPointRel(e));
493     g.setRealizer(e, realizer);
494   }
495 
496   private static EdgeRealizer createCopyOfRealizer(Edge e) {
497     if (e.getGraph() != null && e.getGraph() instanceof Graph2D) {
498       final Graph2D origGraph = (Graph2D) e.getGraph();
499       final EdgeRealizer realizer = origGraph.getRealizer(e);
500       return realizer.createCopy();
501     } else {
502       return null;
503     }
504   }
505 
506   private static void addLabels(final Edge source, final EdgeRealizer targetRealizer, final ElementInfoManager infoManager) {
507     //remove existing labels
508     while (targetRealizer.labelCount() > 0) {
509       targetRealizer.removeLabel(targetRealizer.getLabel());
510     }
511 
512     //add labels of source to target realizer
513     final LayoutGraph sourceGraph = (LayoutGraph) source.getGraph();
514     final EdgeLabelLayout[] ell = sourceGraph.getEdgeLabelLayout(source);
515     for (int i = 0; i < ell.length; i++) {
516       final EdgeLabelInfo labelInfo = infoManager.getEdgeLabelInfo(ell[i]);
517       final EdgeLabel origLabel = (EdgeLabel) labelInfo.getId();
518       final EdgeLabel newLabel = (EdgeLabel) origLabel.clone();
519       newLabel.setModelParameter(ell[i].getModelParameter());
520       targetRealizer.addLabel(newLabel);
521     }
522   }
523 
524   private class MyGraphCopyFactory implements GraphCopier.CopyFactory {
525     public Node copyNode(Graph targetGraph, Node originalNode) {
526       final NodeInfo info = getLayout().getNodeInfo(originalNode);
527       final Graph2D targetGraph2D = (Graph2D) targetGraph;
528 
529       Node graph2DNode;
530       if (info.getType() == NodeInfo.TYPE_NORMAL) {
531         graph2DNode = createNormalNode(originalNode, targetGraph2D);
532       } else if (info.getType() == NodeInfo.TYPE_GROUP) {
533         graph2DNode = createGroupNode(originalNode, targetGraph2D);
534       } else if (info.getType() == NodeInfo.TYPE_CONNECTOR) {
535         graph2DNode = createConnectorNode(originalNode, targetGraph2D);
536       } else if (info.getType() == NodeInfo.TYPE_PROXY) {
537         graph2DNode = createProxyNode(originalNode, targetGraph2D);
538       } else {
539         graph2DNode = createProxyReferenceNode(originalNode, targetGraph2D);
540       }
541       ((NodeMap) targetGraph.getDataProvider(NODE_INFO_DPKEY)).set(graph2DNode, info);
542 
543       return graph2DNode;
544     }
545 
546     public Edge copyEdge(Graph targetGraph, Node newSource, Node newTarget, Edge sourceEdge) {
547       final EdgeInfo edgeInfo = getLayout().getEdgeInfo(sourceEdge);
548       final Graph2D targetGraph2D = (Graph2D) targetGraph;
549 
550       Edge newEdge;
551       if (edgeInfo.getType() == EdgeInfo.TYPE_CONNECTOR) {
552         newEdge = createConnectorEdge(sourceEdge, newSource, newTarget, targetGraph2D);
553       } else  if (edgeInfo.getType() == EdgeInfo.TYPE_PROXY_REFERENCE) {
554         newEdge = createProxyReferenceEdge(sourceEdge, newSource, newTarget, targetGraph2D);
555       } else if (edgeInfo.getType() == EdgeInfo.TYPE_PROXY) {
556         newEdge = createProxyEdge(sourceEdge, newSource, newTarget, targetGraph2D);
557       } else {
558         newEdge = createNormalEdge(sourceEdge, newSource, newTarget, targetGraph2D);
559       }
560 
561       return newEdge;
562     }
563 
564     public Graph createGraph() {
565       final Graph2D graph = (Graph2D) getCopyFactory().createGraph();
566       if (graph.getHierarchyManager() == null) {
567         final HierarchyManager hm = new HierarchyManager(graph);
568         final GraphFactory baseFactory = getModel().getHierarchyManager().getGraphFactory();
569         if (baseFactory instanceof DefaultHierarchyGraphFactory) {
570           hm.setGraphFactory(baseFactory);
571         }
572       }
573 
574       return graph;
575     }
576 
577     public void preCopyGraphData(Graph sourceGraph, Graph targetGraph) {
578       targetGraph.addDataProvider(NODE_INFO_DPKEY, Maps.createHashedNodeMap());
579       targetGraph.addDataProvider(REFERENCING_NODE_ID_DPKEY, Maps.createHashedNodeMap());
580       getCopyFactory().preCopyGraphData(sourceGraph, targetGraph);
581     }
582 
583     public void postCopyGraphData(Graph sourceGraph, Graph targetGraph, Map nodeMap, Map edgeMap) {
584       getCopyFactory().postCopyGraphData(sourceGraph, targetGraph, nodeMap, edgeMap);
585     }
586   }
587 }
588