View Javadoc
1   package org.apache.maven.plugins.dependency.tree;
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.ArrayList;
23  import java.util.List;
24  import java.util.Stack;
25  
26  import org.apache.maven.artifact.Artifact;
27  import org.apache.maven.model.Exclusion;
28  import org.apache.maven.shared.dependency.graph.DependencyNode;
29  import org.apache.maven.shared.dependency.graph.traversal.DependencyNodeVisitor;
30  
31  /**
32   * A dependency node visitor that clones visited nodes into a new dependency tree. This can be used in conjunction with
33   * a dependency node filter to construct subtrees.
34   *
35   * @author <a href="mailto:markhobson@gmail.com">Mark Hobson</a>
36   */
37  public class BuildingDependencyNodeVisitor
38          implements DependencyNodeVisitor
39  {
40      // fields -----------------------------------------------------------------
41  
42      /**
43       * The dependency node visitor to apply on the resultant dependency tree, or <code>null</code> for none.
44       */
45      private final DependencyNodeVisitor visitor;
46  
47      /**
48       * The resultant tree parent nodes for the currently visited node.
49       */
50      private final Stack<DependencyNode> parentNodes;
51  
52      /**
53       * The root node of the resultant tree.
54       */
55      private DependencyNode rootNode;
56  
57      // constructors -----------------------------------------------------------
58  
59      /**
60       * Creates a dependency node visitor that clones visited nodes into a new dependency tree.
61       */
62      public BuildingDependencyNodeVisitor()
63      {
64          this( null );
65      }
66  
67      /**
68       * Creates a dependency node visitor that clones visited nodes into a new dependency tree, and then applies the
69       * specified dependency node visitor on the resultant dependency tree.
70       *
71       * @param visitor the dependency node visitor to apply on the resultant dependency tree, or <code>null</code> for
72       *            none
73       */
74      public BuildingDependencyNodeVisitor( DependencyNodeVisitor visitor )
75      {
76          this.visitor = visitor;
77  
78          parentNodes = new Stack<DependencyNode>();
79      }
80  
81      // DependencyNodeVisitor methods ------------------------------------------
82  
83      /**
84       * {@inheritDoc}
85       */
86      @Override
87      public boolean visit( DependencyNode node )
88      {
89          // clone the node
90          WrapperNode newNode = new WrapperNode(
91                  parentNodes.isEmpty() ? null : parentNodes.peek(),
92                  node.getArtifact(),
93                  node.getPremanagedVersion(),
94                  node.getPremanagedScope(),
95                  node.getVersionConstraint(),
96                  node.getOptional(),
97                  node.getExclusions(),
98                  node.toNodeString()
99          );
100         newNode.setChildren( new ArrayList<DependencyNode>() );
101 
102         if ( parentNodes.empty() )
103         {
104             rootNode = newNode;
105         }
106         else
107         {
108             DependencyNode parentNode = parentNodes.peek();
109             parentNode.getChildren().add( newNode );
110         }
111 
112         parentNodes.push( newNode );
113 
114         return true;
115     }
116 
117     /**
118      * {@inheritDoc}
119      */
120     @Override
121     public boolean endVisit( DependencyNode node )
122     {
123         parentNodes.pop();
124 
125         // apply the visitor to the resultant tree on the last visit
126         if ( parentNodes.empty() && visitor != null )
127         {
128             rootNode.accept( visitor );
129         }
130 
131         return true;
132     }
133 
134     // public methods ---------------------------------------------------------
135 
136     /**
137      * Gets the dependency node visitor that this visitor applies on the resultant dependency tree.
138      *
139      * @return the dependency node visitor, or <code>null</code> for none
140      */
141     public DependencyNodeVisitor getDependencyNodeVisitor()
142     {
143         return visitor;
144     }
145 
146     /**
147      * Gets the root node of the resultant dependency tree constructed by this visitor.
148      *
149      * @return the root node, or <code>null</code> if the source tree has not yet been visited
150      */
151     public DependencyNode getDependencyTree()
152     {
153         return rootNode;
154     }
155 
156     private static class WrapperNode implements DependencyNode
157     {
158 
159         private final Artifact artifact;
160 
161         private final DependencyNode parent;
162 
163         private final String premanagedVersion;
164 
165         private final String premanagedScope;
166 
167         private final String versionConstraint;
168 
169         private List<DependencyNode> children;
170 
171         private final Boolean optional;
172 
173         private final List<Exclusion> exclusions;
174 
175         private final String nodeString;
176 
177         private WrapperNode( DependencyNode parent,
178                              Artifact artifact,
179                              String premanagedVersion,
180                              String premanagedScope,
181                              String versionConstraint,
182                              Boolean optional,
183                              List<Exclusion> exclusions,
184                              String nodeString )
185         {
186             this.artifact = artifact;
187             this.parent = parent;
188             this.premanagedVersion = premanagedVersion;
189             this.premanagedScope = premanagedScope;
190             this.versionConstraint = versionConstraint;
191             this.optional = optional;
192             this.exclusions = exclusions;
193             this.nodeString = nodeString;
194         }
195 
196         @Override
197         public Artifact getArtifact()
198         {
199             return artifact;
200         }
201 
202         @Override
203         public List<DependencyNode> getChildren()
204         {
205             return children;
206         }
207 
208         @Override
209         public boolean accept( DependencyNodeVisitor visitor )
210         {
211             if ( visitor.visit( this ) )
212             {
213                 for ( DependencyNode child : getChildren() )
214                 {
215                     if ( !child.accept( visitor ) )
216                     {
217                         break;
218                     }
219                 }
220             }
221 
222             return visitor.endVisit( this );
223         }
224 
225         @Override
226         public DependencyNode getParent()
227         {
228             return parent;
229         }
230 
231         @Override
232         public String getPremanagedVersion()
233         {
234             return premanagedVersion;
235         }
236 
237         @Override
238         public String getPremanagedScope()
239         {
240             return premanagedScope;
241         }
242 
243         @Override
244         public String getVersionConstraint()
245         {
246             return versionConstraint;
247         }
248 
249         @Override
250         public String toNodeString()
251         {
252             return nodeString;
253         }
254 
255         @Override
256         public Boolean getOptional()
257         {
258             return optional;
259         }
260 
261         @Override
262         public List<Exclusion> getExclusions()
263         {
264             return exclusions;
265         }
266 
267         public void setChildren( List<DependencyNode> children )
268         {
269             this.children = children;
270         }
271     }
272 }