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.eclipse.aether.util.graph.visitor;
20  
21  import java.io.File;
22  import java.util.ArrayList;
23  import java.util.Iterator;
24  import java.util.List;
25  import java.util.function.Consumer;
26  
27  import org.eclipse.aether.artifact.Artifact;
28  import org.eclipse.aether.graph.Dependency;
29  import org.eclipse.aether.graph.DependencyNode;
30  
31  import static java.util.stream.Collectors.toList;
32  
33  /**
34   * Node list generator usable with different traversing strategies. It is wrapped {@link List}{@code <DependencyNode>} but
35   * offers several transformations, that are handy.
36   *
37   * @since 2.0.0
38   *
39   * @see PreorderDependencyNodeConsumerVisitor
40   * @see PostorderDependencyNodeConsumerVisitor
41   * @see LevelOrderDependencyNodeConsumerVisitor
42   */
43  public final class NodeListGenerator implements Consumer<DependencyNode> {
44  
45      private final ArrayList<DependencyNode> nodes;
46  
47      public NodeListGenerator() {
48          nodes = new ArrayList<>(128);
49      }
50  
51      @Override
52      public void accept(DependencyNode dependencyNode) {
53          nodes.add(dependencyNode);
54      }
55  
56      /**
57       * Gets the list of dependency nodes that was generated during the graph traversal.
58       *
59       * @return The list of dependency nodes, never {@code null}.
60       */
61      public List<DependencyNode> getNodes() {
62          return nodes;
63      }
64  
65      /**
66       * Gets the list of dependency nodes that was generated during the graph traversal and have {@code non-null}
67       * {@link DependencyNode#getDependency()}.
68       *
69       * @return The list of dependency nodes having dependency, never {@code null}.
70       */
71      public List<DependencyNode> getNodesWithDependencies() {
72          return getNodesWithDependencies(getNodes());
73      }
74  
75      /**
76       * Gets the dependencies seen during the graph traversal.
77       *
78       * @param includeUnresolved Whether unresolved dependencies shall be included in the result or not.
79       * @return The list of dependencies, never {@code null}.
80       */
81      public List<Dependency> getDependencies(boolean includeUnresolved) {
82          return getDependencies(getNodes(), includeUnresolved);
83      }
84  
85      /**
86       * Gets the artifacts associated with the list of dependency nodes generated during the graph traversal.
87       *
88       * @param includeUnresolved Whether unresolved artifacts shall be included in the result or not.
89       * @return The list of artifacts, never {@code null}.
90       */
91      public List<Artifact> getArtifacts(boolean includeUnresolved) {
92          return getArtifacts(getNodes(), includeUnresolved);
93      }
94  
95      /**
96       * Gets the files of resolved artifacts seen during the graph traversal.
97       *
98       * @return The list of artifact files, never {@code null}.
99       */
100     public List<File> getFiles() {
101         return getFiles(getNodes());
102     }
103 
104     /**
105      * Gets a class path by concatenating the artifact files of the visited dependency nodes. Nodes with unresolved
106      * artifacts are automatically skipped.
107      *
108      * @return The class path, using the platform-specific path separator, never {@code null}.
109      */
110     public String getClassPath() {
111         return getClassPath(getNodes());
112     }
113 
114     static List<DependencyNode> getNodesWithDependencies(List<DependencyNode> nodes) {
115         return nodes.stream().filter(d -> d.getDependency() != null).collect(toList());
116     }
117 
118     static List<Dependency> getDependencies(List<DependencyNode> nodes, boolean includeUnresolved) {
119         List<Dependency> dependencies = new ArrayList<>(nodes.size());
120         for (DependencyNode node : getNodesWithDependencies(nodes)) {
121             Dependency dependency = node.getDependency();
122             if (includeUnresolved || dependency.getArtifact().getFile() != null) {
123                 dependencies.add(dependency);
124             }
125         }
126         return dependencies;
127     }
128 
129     static List<Artifact> getArtifacts(List<DependencyNode> nodes, boolean includeUnresolved) {
130         List<Artifact> artifacts = new ArrayList<>(nodes.size());
131         for (DependencyNode node : getNodesWithDependencies(nodes)) {
132             Artifact artifact = node.getDependency().getArtifact();
133             if (includeUnresolved || artifact.getFile() != null) {
134                 artifacts.add(artifact);
135             }
136         }
137 
138         return artifacts;
139     }
140 
141     static List<File> getFiles(List<DependencyNode> nodes) {
142         List<File> files = new ArrayList<>(nodes.size());
143         for (DependencyNode node : getNodesWithDependencies(nodes)) {
144             File file = node.getDependency().getArtifact().getFile();
145             if (file != null) {
146                 files.add(file);
147             }
148         }
149         return files;
150     }
151 
152     static String getClassPath(List<DependencyNode> nodes) {
153         StringBuilder buffer = new StringBuilder(1024);
154         for (Iterator<DependencyNode> it = getNodesWithDependencies(nodes).iterator(); it.hasNext(); ) {
155             DependencyNode node = it.next();
156             Artifact artifact = node.getDependency().getArtifact();
157             if (artifact.getFile() != null) {
158                 buffer.append(artifact.getFile().getAbsolutePath());
159                 if (it.hasNext()) {
160                     buffer.append(File.pathSeparatorChar);
161                 }
162             }
163         }
164         return buffer.toString();
165     }
166 }