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 * @since 2.0.0 040 * 041 * @see PreorderDependencyNodeConsumerVisitor 042 * @see PostorderDependencyNodeConsumerVisitor 043 * @see LevelOrderDependencyNodeConsumerVisitor 044 */ 045public final class NodeListGenerator implements Consumer<DependencyNode> { 046 047 private final ArrayList<DependencyNode> nodes; 048 049 public NodeListGenerator() { 050 nodes = new ArrayList<>(128); 051 } 052 053 @Override 054 public void accept(DependencyNode dependencyNode) { 055 nodes.add(dependencyNode); 056 } 057 058 /** 059 * Gets the list of dependency nodes that was generated during the graph traversal. 060 * 061 * @return The list of dependency nodes, never {@code null}. 062 */ 063 public List<DependencyNode> getNodes() { 064 return nodes; 065 } 066 067 /** 068 * Gets the list of dependency nodes that was generated during the graph traversal and have {@code non-null} 069 * {@link DependencyNode#getDependency()}. 070 * 071 * @return The list of dependency nodes having dependency, never {@code null}. 072 */ 073 public List<DependencyNode> getNodesWithDependencies() { 074 return getNodesWithDependencies(getNodes()); 075 } 076 077 /** 078 * Gets the dependencies seen during the graph traversal. 079 * 080 * @param includeUnresolved Whether unresolved dependencies shall be included in the result or not. 081 * @return The list of dependencies, never {@code null}. 082 */ 083 public List<Dependency> getDependencies(boolean includeUnresolved) { 084 return getDependencies(getNodes(), includeUnresolved); 085 } 086 087 /** 088 * Gets the artifacts associated with the list of dependency nodes generated during the graph traversal. 089 * 090 * @param includeUnresolved Whether unresolved artifacts shall be included in the result or not. 091 * @return The list of artifacts, never {@code null}. 092 */ 093 public List<Artifact> getArtifacts(boolean includeUnresolved) { 094 return getArtifacts(getNodes(), includeUnresolved); 095 } 096 097 /** 098 * Gets the files of resolved artifacts seen during the graph traversal. 099 * 100 * @return The list of artifact files, never {@code null}. 101 * @deprecated Use {@link #getPaths()} instead. 102 */ 103 @Deprecated 104 public List<File> getFiles() { 105 return getFiles(getNodes()); 106 } 107 108 /** 109 * Gets the files of resolved artifacts seen during the graph traversal. 110 * 111 * @return The list of artifact files, never {@code null}. 112 * @since 2.0.0 113 */ 114 public List<Path> getPaths() { 115 return getPaths(getNodes()); 116 } 117 118 /** 119 * Gets a class path by concatenating the artifact files of the visited dependency nodes. Nodes with unresolved 120 * artifacts are automatically skipped. 121 * 122 * @return The class path, using the platform-specific path separator, never {@code null}. 123 */ 124 public String getClassPath() { 125 return getClassPath(getNodes()); 126 } 127 128 static List<DependencyNode> getNodesWithDependencies(List<DependencyNode> nodes) { 129 return nodes.stream().filter(d -> d.getDependency() != null).collect(toList()); 130 } 131 132 static List<Dependency> getDependencies(List<DependencyNode> nodes, boolean includeUnresolved) { 133 return getNodesWithDependencies(nodes).stream() 134 .map(DependencyNode::getDependency) 135 .filter(d -> includeUnresolved || d.getArtifact().getPath() != null) 136 .collect(toList()); 137 } 138 139 static List<Artifact> getArtifacts(List<DependencyNode> nodes, boolean includeUnresolved) { 140 return getNodesWithDependencies(nodes).stream() 141 .map(d -> d.getDependency().getArtifact()) 142 .filter(artifact -> includeUnresolved || artifact.getPath() != null) 143 .collect(toList()); 144 } 145 146 @Deprecated 147 static List<File> getFiles(List<DependencyNode> nodes) { 148 return getNodesWithDependencies(nodes).stream() 149 .map(d -> d.getDependency().getArtifact().getFile()) 150 .filter(Objects::nonNull) 151 .collect(toList()); 152 } 153 154 static List<Path> getPaths(List<DependencyNode> nodes) { 155 return getNodesWithDependencies(nodes).stream() 156 .map(d -> d.getDependency().getArtifact().getPath()) 157 .filter(Objects::nonNull) 158 .collect(toList()); 159 } 160 161 static String getClassPath(List<DependencyNode> nodes) { 162 return getPaths(nodes).stream() 163 .map(Path::toAbsolutePath) 164 .map(Path::toString) 165 .collect(joining(File.pathSeparator)); 166 } 167}