3434 */
3535class FilteredProjectDependencyGraph implements ProjectDependencyGraph {
3636
37- private ProjectDependencyGraph projectDependencyGraph ;
37+ private final ProjectDependencyGraph projectDependencyGraph ;
3838
39- private Map <MavenProject , ?> whiteList ;
39+ private final Map <MavenProject , ?> whiteList ;
4040
41- private List <MavenProject > sortedProjects ;
41+ private final List <MavenProject > sortedProjects ;
4242
4343 /**
4444 * Creates a new project dependency graph from the specified graph.
@@ -50,46 +50,58 @@ class FilteredProjectDependencyGraph implements ProjectDependencyGraph {
5050 ProjectDependencyGraph projectDependencyGraph , Collection <? extends MavenProject > whiteList ) {
5151 this .projectDependencyGraph =
5252 Objects .requireNonNull (projectDependencyGraph , "projectDependencyGraph cannot be null" );
53-
5453 this .whiteList = new IdentityHashMap <>();
55-
5654 for (MavenProject project : whiteList ) {
5755 this .whiteList .put (project , null );
5856 }
57+ this .sortedProjects = projectDependencyGraph .getSortedProjects ().stream ()
58+ .filter (this .whiteList ::containsKey )
59+ .toList ();
5960 }
6061
6162 /**
6263 * @since 3.5.0
6364 */
65+ @ Override
6466 public List <MavenProject > getAllProjects () {
6567 return this .projectDependencyGraph .getAllProjects ();
6668 }
6769
70+ @ Override
6871 public List <MavenProject > getSortedProjects () {
69- if (sortedProjects == null ) {
70- sortedProjects = applyFilter (projectDependencyGraph .getSortedProjects ());
71- }
72-
7372 return new ArrayList <>(sortedProjects );
7473 }
7574
75+ @ Override
7676 public List <MavenProject > getDownstreamProjects (MavenProject project , boolean transitive ) {
77- return applyFilter (projectDependencyGraph .getDownstreamProjects (project , transitive ));
77+ return applyFilter (projectDependencyGraph .getDownstreamProjects (project , transitive ), transitive , false );
7878 }
7979
80+ @ Override
8081 public List <MavenProject > getUpstreamProjects (MavenProject project , boolean transitive ) {
81- return applyFilter (projectDependencyGraph .getUpstreamProjects (project , transitive ));
82+ return applyFilter (projectDependencyGraph .getUpstreamProjects (project , transitive ), transitive , true );
8283 }
8384
84- private List <MavenProject > applyFilter (Collection <? extends MavenProject > projects ) {
85+ /**
86+ * Filter out whitelisted projects with a big twist:
87+ * Assume we have all projects {@code a, b, c} while active are {@code a, c} and relation among all projects
88+ * is {@code a -> b -> c}. This method handles well the case for transitive list. But, for non-transitive we need
89+ * to "pull in" transitive dependencies of eliminated projects, as for case above, the properly filtered list would
90+ * be {@code a -> c}.
91+ * <p>
92+ * Original code would falsely report {@code a} project as "without dependencies", basically would lose link due
93+ * filtering. This causes build ordering issues in concurrent builders.
94+ */
95+ private List <MavenProject > applyFilter (
96+ Collection <? extends MavenProject > projects , boolean transitive , boolean upstream ) {
8597 List <MavenProject > filtered = new ArrayList <>(projects .size ());
86-
8798 for (MavenProject project : projects ) {
8899 if (whiteList .containsKey (project )) {
89100 filtered .add (project );
101+ } else if (!transitive ) {
102+ filtered .addAll (upstream ? getUpstreamProjects (project , false ) : getDownstreamProjects (project , false ));
90103 }
91104 }
92-
93105 return filtered ;
94106 }
95107
0 commit comments