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