View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.maven.shared.dependency.graph.traversal;
20  
21  import java.util.ArrayList;
22  import java.util.Stack;
23  
24  import org.apache.maven.shared.dependency.graph.DependencyNode;
25  import org.apache.maven.shared.dependency.graph.internal.DefaultDependencyNode;
26  
27  /**
28   * A dependency node visitor that clones visited nodes into a new dependency tree. This can be used in conjunction with
29   * a dependency node filter to construct subtrees.
30   *
31   * @author <a href="mailto:markhobson@gmail.com">Mark Hobson</a>
32   */
33  public class BuildingDependencyNodeVisitor implements DependencyNodeVisitor {
34      // fields -----------------------------------------------------------------
35  
36      /**
37       * The dependency node visitor to apply on the resultant dependency tree, or <code>null</code> for none.
38       */
39      private final DependencyNodeVisitor visitor;
40  
41      /**
42       * The resultant tree parent nodes for the currently visited node.
43       */
44      private final Stack<DependencyNode> parentNodes;
45  
46      /**
47       * The root node of the resultant tree.
48       */
49      private DependencyNode rootNode;
50  
51      // constructors -----------------------------------------------------------
52  
53      /**
54       * Creates a dependency node visitor that clones visited nodes into a new dependency tree.
55       */
56      public BuildingDependencyNodeVisitor() {
57          this(null);
58      }
59  
60      /**
61       * Creates a dependency node visitor that clones visited nodes into a new dependency tree, and then applies the
62       * specified dependency node visitor on the resultant dependency tree.
63       *
64       * @param visitor the dependency node visitor to apply on the resultant dependency tree, or <code>null</code> for
65       *            none
66       */
67      public BuildingDependencyNodeVisitor(DependencyNodeVisitor visitor) {
68          this.visitor = visitor;
69  
70          parentNodes = new Stack<>();
71      }
72  
73      // DependencyNodeVisitor methods ------------------------------------------
74  
75      /**
76       * {@inheritDoc}
77       */
78      @Override
79      public boolean visit(DependencyNode node) {
80          // clone the node
81          DefaultDependencyNode newNode = new DefaultDependencyNode(
82                  parentNodes.isEmpty() ? null : parentNodes.peek(),
83                  node.getArtifact(),
84                  node.getPremanagedVersion(),
85                  node.getPremanagedScope(),
86                  node.getVersionConstraint(),
87                  node.getOptional(),
88                  node.getExclusions());
89          newNode.setChildren(new ArrayList<>());
90  
91          if (parentNodes.empty()) {
92              rootNode = newNode;
93          } else {
94              DependencyNode parentNode = parentNodes.peek();
95              parentNode.getChildren().add(newNode);
96          }
97  
98          parentNodes.push(newNode);
99  
100         return true;
101     }
102 
103     /**
104      * {@inheritDoc}
105      */
106     @Override
107     public boolean endVisit(DependencyNode node) {
108         parentNodes.pop();
109 
110         // apply the visitor to the resultant tree on the last visit
111         if (parentNodes.empty() && visitor != null) {
112             rootNode.accept(visitor);
113         }
114 
115         return true;
116     }
117 
118     // public methods ---------------------------------------------------------
119 
120     /**
121      * Gets the dependency node visitor that this visitor applies on the resultant dependency tree.
122      *
123      * @return the dependency node visitor, or <code>null</code> for none
124      */
125     public DependencyNodeVisitor getDependencyNodeVisitor() {
126         return visitor;
127     }
128 
129     /**
130      * Gets the root node of the resultant dependency tree constructed by this visitor.
131      *
132      * @return the root node, or <code>null</code> if the source tree has not yet been visited
133      */
134     public DependencyNode getDependencyTree() {
135         return rootNode;
136     }
137 }