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.util.ArrayList; 023import java.util.Iterator; 024import java.util.List; 025import java.util.function.Consumer; 026 027import org.eclipse.aether.artifact.Artifact; 028import org.eclipse.aether.graph.Dependency; 029import org.eclipse.aether.graph.DependencyNode; 030 031import static java.util.stream.Collectors.toList; 032 033/** 034 * Node list generator usable with different traversing strategies. It is wrapped {@link List}{@code <DependencyNode>} but 035 * offers several transformations, that are handy. 036 * 037 * @since 2.0.0 038 * 039 * @see PreorderDependencyNodeConsumerVisitor 040 * @see PostorderDependencyNodeConsumerVisitor 041 * @see LevelOrderDependencyNodeConsumerVisitor 042 */ 043public final class NodeListGenerator implements Consumer<DependencyNode> { 044 045 private final ArrayList<DependencyNode> nodes; 046 047 public NodeListGenerator() { 048 nodes = new ArrayList<>(128); 049 } 050 051 @Override 052 public void accept(DependencyNode dependencyNode) { 053 nodes.add(dependencyNode); 054 } 055 056 /** 057 * Gets the list of dependency nodes that was generated during the graph traversal. 058 * 059 * @return The list of dependency nodes, never {@code null}. 060 */ 061 public List<DependencyNode> getNodes() { 062 return nodes; 063 } 064 065 /** 066 * Gets the list of dependency nodes that was generated during the graph traversal and have {@code non-null} 067 * {@link DependencyNode#getDependency()}. 068 * 069 * @return The list of dependency nodes having dependency, never {@code null}. 070 */ 071 public List<DependencyNode> getNodesWithDependencies() { 072 return getNodesWithDependencies(getNodes()); 073 } 074 075 /** 076 * Gets the dependencies seen during the graph traversal. 077 * 078 * @param includeUnresolved Whether unresolved dependencies shall be included in the result or not. 079 * @return The list of dependencies, never {@code null}. 080 */ 081 public List<Dependency> getDependencies(boolean includeUnresolved) { 082 return getDependencies(getNodes(), includeUnresolved); 083 } 084 085 /** 086 * Gets the artifacts associated with the list of dependency nodes generated during the graph traversal. 087 * 088 * @param includeUnresolved Whether unresolved artifacts shall be included in the result or not. 089 * @return The list of artifacts, never {@code null}. 090 */ 091 public List<Artifact> getArtifacts(boolean includeUnresolved) { 092 return getArtifacts(getNodes(), includeUnresolved); 093 } 094 095 /** 096 * Gets the files of resolved artifacts seen during the graph traversal. 097 * 098 * @return The list of artifact files, never {@code null}. 099 */ 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}