001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 */ 019package org.eclipse.aether.util.graph.visitor; 020 021import java.io.File; 022import java.nio.file.Path; 023import java.util.ArrayList; 024import java.util.List; 025import java.util.Objects; 026import java.util.function.Consumer; 027 028import org.eclipse.aether.artifact.Artifact; 029import org.eclipse.aether.graph.Dependency; 030import org.eclipse.aether.graph.DependencyNode; 031 032import static java.util.stream.Collectors.joining; 033import static java.util.stream.Collectors.toList; 034 035/** 036 * Node list generator usable with different traversing strategies. It is wrapped {@link List}{@code <DependencyNode>} but 037 * offers several transformations, that are handy. 038 * 039 * @see PreorderDependencyNodeConsumerVisitor 040 * @see PostorderDependencyNodeConsumerVisitor 041 * @see LevelOrderDependencyNodeConsumerVisitor 042 * @since 2.0.0 043 */ 044public final class NodeListGenerator implements Consumer<DependencyNode> { 045 046 private final ArrayList<DependencyNode> nodes; 047 048 public NodeListGenerator() { 049 nodes = new ArrayList<>(128); 050 } 051 052 @Override 053 public void accept(DependencyNode dependencyNode) { 054 nodes.add(dependencyNode); 055 } 056 057 /** 058 * Gets the list of dependency nodes that was generated during the graph traversal. 059 * 060 * @return the list of dependency nodes, never {@code null} 061 */ 062 public List<DependencyNode> getNodes() { 063 return nodes; 064 } 065 066 /** 067 * Gets the list of dependency nodes that was generated during the graph traversal and have {@code non-null} 068 * {@link DependencyNode#getDependency()}. 069 * 070 * @return the list of dependency nodes having dependency, never {@code null} 071 */ 072 public List<DependencyNode> getNodesWithDependencies() { 073 return getNodesWithDependencies(getNodes()); 074 } 075 076 /** 077 * Gets the dependencies seen during the graph traversal. 078 * 079 * @param includeUnresolved whether unresolved dependencies shall be included in the result or not 080 * @return the list of dependencies, never {@code null} 081 */ 082 public List<Dependency> getDependencies(boolean includeUnresolved) { 083 return getDependencies(getNodes(), includeUnresolved); 084 } 085 086 /** 087 * Gets the artifacts associated with the list of dependency nodes generated during the graph traversal. 088 * 089 * @param includeUnresolved whether unresolved artifacts shall be included in the result or not 090 * @return the list of artifacts, never {@code null} 091 */ 092 public List<Artifact> getArtifacts(boolean includeUnresolved) { 093 return getArtifacts(getNodes(), includeUnresolved); 094 } 095 096 /** 097 * Gets the files of resolved artifacts seen during the graph traversal. 098 * 099 * @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}