1 package org.eclipse.aether.util.graph.visitor;
2
3 /*
4 * Licensed to the Apache Software Foundation (ASF) under one
5 * or more contributor license agreements. See the NOTICE file
6 * distributed with this work for additional information
7 * regarding copyright ownership. The ASF licenses this file
8 * to you under the Apache License, Version 2.0 (the
9 * "License"); you may not use this file except in compliance
10 * with the License. You may obtain a copy of the License at
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing,
15 * software distributed under the License is distributed on an
16 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17 * KIND, either express or implied. See the License for the
18 * specific language governing permissions and limitations
19 * under the License.
20 */
21
22 import java.util.IdentityHashMap;
23 import java.util.Map;
24
25 import org.eclipse.aether.graph.DefaultDependencyNode;
26 import org.eclipse.aether.graph.DependencyNode;
27 import org.eclipse.aether.graph.DependencyVisitor;
28
29 /**
30 * A dependency visitor that constructs a clone of the visited dependency graph. If such a visitor is passed into a
31 * {@link FilteringDependencyVisitor}, a sub graph can be created. This class creates shallow clones of the visited
32 * dependency nodes (via {@link DefaultDependencyNode#DefaultDependencyNode(DependencyNode)}) but clients can create a
33 * subclass and override {@link #clone(DependencyNode)} to alter the clone process.
34 */
35 public class CloningDependencyVisitor
36 implements DependencyVisitor
37 {
38
39 private final Map<DependencyNode, DependencyNode> clones;
40
41 private final Stack<DependencyNode> parents;
42
43 private DependencyNode root;
44
45 /**
46 * Creates a new visitor that clones the visited nodes.
47 */
48 public CloningDependencyVisitor()
49 {
50 parents = new Stack<DependencyNode>();
51 clones = new IdentityHashMap<DependencyNode, DependencyNode>( 256 );
52 }
53
54 /**
55 * Gets the root node of the cloned dependency graph.
56 *
57 * @return The root node of the cloned dependency graph or {@code null}.
58 */
59 public final DependencyNode getRootNode()
60 {
61 return root;
62 }
63
64 /**
65 * Creates a clone of the specified node.
66 *
67 * @param node The node to clone, must not be {@code null}.
68 * @return The cloned node, never {@code null}.
69 */
70 protected DependencyNode clone( DependencyNode node )
71 {
72 DefaultDependencyNode clone = new DefaultDependencyNode( node );
73 return clone;
74 }
75
76 public final boolean visitEnter( DependencyNode node )
77 {
78 boolean recurse = true;
79
80 DependencyNode clone = clones.get( node );
81 if ( clone == null )
82 {
83 clone = clone( node );
84 clones.put( node, clone );
85 }
86 else
87 {
88 recurse = false;
89 }
90
91 DependencyNode parent = parents.peek();
92
93 if ( parent == null )
94 {
95 root = clone;
96 }
97 else
98 {
99 parent.getChildren().add( clone );
100 }
101
102 parents.push( clone );
103
104 return recurse;
105 }
106
107 public final boolean visitLeave( DependencyNode node )
108 {
109 parents.pop();
110
111 return true;
112 }
113
114 }