From 7433129ad176609f53fc4da643c6782c5800400c Mon Sep 17 00:00:00 2001
From: Alexey Loubyansky <loubyansky@gmail.com>
Date: Tue, 10 Dec 2024 22:02:09 +0100
Subject: [PATCH] Minor change to add Dependency.isAnyFlagSet(int flags) and
 make FlagDependencyIterator use that

---
 .../bootstrap/model/ApplicationModel.java     | 19 ++++++++++-
 .../model/DefaultApplicationModel.java        | 32 +++++++++++++------
 .../quarkus/maven/dependency/Dependency.java  | 15 ++++++++-
 .../test/DevModeTestApplicationModel.java     |  2 +-
 4 files changed, 56 insertions(+), 12 deletions(-)

diff --git a/independent-projects/bootstrap/app-model/src/main/java/io/quarkus/bootstrap/model/ApplicationModel.java b/independent-projects/bootstrap/app-model/src/main/java/io/quarkus/bootstrap/model/ApplicationModel.java
index d9eb54f92c73e..76e223bf92fdc 100644
--- a/independent-projects/bootstrap/app-model/src/main/java/io/quarkus/bootstrap/model/ApplicationModel.java
+++ b/independent-projects/bootstrap/app-model/src/main/java/io/quarkus/bootstrap/model/ApplicationModel.java
@@ -40,13 +40,30 @@ public interface ApplicationModel {
      */
     Iterable<ResolvedDependency> getDependencies(int flags);
 
+    /**
+     * Returns application dependencies that have any of the flags combined in the value of the {@code flags} arguments set.
+     *
+     * @param flags dependency flags to match
+     * @return application dependencies that matched the flags
+     */
+    Iterable<ResolvedDependency> getDependenciesWithAnyFlag(int flags);
+
     /**
      * Returns application dependencies that have any of the flags passed in as arguments set.
      *
      * @param flags dependency flags to match
      * @return application dependencies that matched the flags
      */
-    Iterable<ResolvedDependency> getDependenciesWithAnyFlag(int... flags);
+    default Iterable<ResolvedDependency> getDependenciesWithAnyFlag(int... flags) {
+        if (flags.length == 0) {
+            throw new IllegalArgumentException("Flags are empty");
+        }
+        int combined = flags[0];
+        for (int i = 1; i < flags.length; ++i) {
+            combined |= flags[i];
+        }
+        return getDependenciesWithAnyFlag(combined);
+    }
 
     /**
      * Runtime dependencies of an application
diff --git a/independent-projects/bootstrap/app-model/src/main/java/io/quarkus/bootstrap/model/DefaultApplicationModel.java b/independent-projects/bootstrap/app-model/src/main/java/io/quarkus/bootstrap/model/DefaultApplicationModel.java
index 3e6cc090723d6..08246386a6c0d 100644
--- a/independent-projects/bootstrap/app-model/src/main/java/io/quarkus/bootstrap/model/DefaultApplicationModel.java
+++ b/independent-projects/bootstrap/app-model/src/main/java/io/quarkus/bootstrap/model/DefaultApplicationModel.java
@@ -53,11 +53,12 @@ public Collection<ResolvedDependency> getRuntimeDependencies() {
 
     @Override
     public Iterable<ResolvedDependency> getDependencies(int flags) {
-        return new FlagDependencyIterator(new int[] { flags });
+        return new FlagDependencyIterator(flags, false);
     }
 
-    public Iterable<ResolvedDependency> getDependenciesWithAnyFlag(int... flags) {
-        return new FlagDependencyIterator(flags);
+    @Override
+    public Iterable<ResolvedDependency> getDependenciesWithAnyFlag(int flags) {
+        return new FlagDependencyIterator(flags, true);
     }
 
     @Override
@@ -118,10 +119,20 @@ private Set<ArtifactKey> collectKeys(int flags) {
 
     private class FlagDependencyIterator implements Iterable<ResolvedDependency> {
 
-        private final int[] flags;
-
-        private FlagDependencyIterator(int[] flags) {
+        private final int flags;
+        private final boolean any;
+
+        /**
+         * Iterates over application model dependencies that match requested flags.
+         * The {@code any} boolean argument controls whether any or all the flags have to match
+         * for a dependency to be selected.
+         *
+         * @param flags flags to match
+         * @param any whether any or all of the flags have to be matched
+         */
+        private FlagDependencyIterator(int flags, boolean any) {
             this.flags = flags;
+            this.any = any;
         }
 
         @Override
@@ -152,11 +163,14 @@ public ResolvedDependency next() {
 
                 private void moveOn() {
                     next = null;
-                    while (index < dependencies.size()) {
+                    while (index < dependencies.size() && next == null) {
                         var d = dependencies.get(index++);
-                        if (d.hasAnyFlag(flags)) {
+                        if (any) {
+                            if (d.isAnyFlagSet(flags)) {
+                                next = d;
+                            }
+                        } else if (d.isFlagSet(flags)) {
                             next = d;
-                            break;
                         }
                     }
                 }
diff --git a/independent-projects/bootstrap/app-model/src/main/java/io/quarkus/maven/dependency/Dependency.java b/independent-projects/bootstrap/app-model/src/main/java/io/quarkus/maven/dependency/Dependency.java
index 2a95f37474117..2a6df30caab3c 100644
--- a/independent-projects/bootstrap/app-model/src/main/java/io/quarkus/maven/dependency/Dependency.java
+++ b/independent-projects/bootstrap/app-model/src/main/java/io/quarkus/maven/dependency/Dependency.java
@@ -62,14 +62,27 @@ default boolean isClassLoaderParentFirst() {
 
     /**
      * Checks whether a dependency has a given flag set.
+     * If the value of the {@code flag} argument combines multiple flags,
+     * the implementation will return {@code true} only if the dependency
+     * has all the flags set.
      *
-     * @param flag flag to check
+     * @param flag flag (or flags) to check
      * @return true if the flag is set, otherwise false
      */
     default boolean isFlagSet(int flag) {
         return (getFlags() & flag) == flag;
     }
 
+    /**
+     * Checks whether a dependency has any of the flags combined in the value of {@code flags} set.
+     *
+     * @param flags flags to check
+     * @return true, if any of the flags is set, otherwise - false
+     */
+    default boolean isAnyFlagSet(int flags) {
+        return (getFlags() & flags) > 0;
+    }
+
     /**
      * Checks whether any of the flags are set on a dependency
      *
diff --git a/test-framework/junit5-internal/src/main/java/io/quarkus/test/DevModeTestApplicationModel.java b/test-framework/junit5-internal/src/main/java/io/quarkus/test/DevModeTestApplicationModel.java
index 5864ff6f5fa68..ba8633abac8b1 100644
--- a/test-framework/junit5-internal/src/main/java/io/quarkus/test/DevModeTestApplicationModel.java
+++ b/test-framework/junit5-internal/src/main/java/io/quarkus/test/DevModeTestApplicationModel.java
@@ -41,7 +41,7 @@ public Iterable<ResolvedDependency> getDependencies(int flags) {
     }
 
     @Override
-    public Iterable<ResolvedDependency> getDependenciesWithAnyFlag(int... flags) {
+    public Iterable<ResolvedDependency> getDependenciesWithAnyFlag(int flags) {
         return delegate.getDependenciesWithAnyFlag(flags);
     }