You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by cs...@apache.org on 2026/04/17 15:56:26 UTC
(maven-resolver) branch master updated: GH-1835: Expose qualifiers for generic version scheme (#1837)
This is an automated email from the ASF dual-hosted git repository.
cstamas pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/maven-resolver.git
The following commit(s) were added to refs/heads/master by this push:
new 283b54202 GH-1835: Expose qualifiers for generic version scheme (#1837)
283b54202 is described below
commit 283b542024f6a45d46c89cf0bcc5ec3495c7b8c6
Author: Tamas Cservenak <ta...@cservenak.net>
AuthorDate: Fri Apr 17 17:56:20 2026 +0200
GH-1835: Expose qualifiers for generic version scheme (#1837)
This allows nice version selection. Also, provide a version filter that
leaves out preview (sans snapshot) versions.
Cleaned up existing filters, and added new context predicate one.
Finally, made generic classes public, they were package protected.
Fixes #1835
---
...er.java => ArtifactPredicateVersionFilter.java} | 10 +-
...> ContextPredicateDelegatingVersionFilter.java} | 43 +++----
.../version/GenericQualifiersVersionFilter.java | 69 ++++++++++++
.../util/graph/version/PredicateVersionFilter.java | 51 +--------
.../util/graph/version/ReleaseVersionFilter.java | 8 +-
.../util/graph/version/SnapshotVersionFilter.java | 6 +-
.../version/VersionPredicateVersionFilter.java | 2 +-
.../aether/util/version/GenericQualifiers.java | 123 +++++++++++++++++++++
.../aether/util/version/GenericVersion.java | 47 ++------
.../util/version/GenericVersionConstraint.java | 2 +-
.../aether/util/version/GenericVersionRange.java | 2 +-
.../aether/util/version/GenericVersionScheme.java | 4 +
.../aether/util/version/VersionSchemeSupport.java | 2 +-
.../eclipse/aether/util/version/package-info.java | 1 +
.../AbstractVersionFilterTest.java | 7 +-
.../ArtifactPredicateVersionFilterTest.java} | 21 ++--
.../ChainedVersionFilterTest.java | 5 +-
.../ContextualSnapshotVersionFilterTest.java | 4 +-
.../GenericQualifiersVersionFilterTest.java | 90 +++++++++++++++
.../HighestVersionFilterTest.java | 3 +-
.../LowestVersionFilterTest.java | 3 +-
.../PredicateVersionFilterTest.java | 3 +-
.../ReleaseVersionFilterTest.java | 3 +-
.../SnapshotVersionFilterTest.java | 3 +-
.../aether/util/version/GenericQualifiersTest.java | 87 +++++++++++++++
25 files changed, 452 insertions(+), 147 deletions(-)
diff --git a/maven-resolver-util/src/main/java/org/eclipse/aether/util/graph/version/PredicateVersionFilter.java b/maven-resolver-util/src/main/java/org/eclipse/aether/util/graph/version/ArtifactPredicateVersionFilter.java
similarity index 87%
copy from maven-resolver-util/src/main/java/org/eclipse/aether/util/graph/version/PredicateVersionFilter.java
copy to maven-resolver-util/src/main/java/org/eclipse/aether/util/graph/version/ArtifactPredicateVersionFilter.java
index 2f66d6c7c..1544beadd 100644
--- a/maven-resolver-util/src/main/java/org/eclipse/aether/util/graph/version/PredicateVersionFilter.java
+++ b/maven-resolver-util/src/main/java/org/eclipse/aether/util/graph/version/ArtifactPredicateVersionFilter.java
@@ -30,17 +30,17 @@ import org.eclipse.aether.version.Version;
import static java.util.Objects.requireNonNull;
/**
- * A version filter that excludes any version that is blacklisted.
+ * A version filter that excludes any version that is not-matched by artifact predicate.
*
- * @since 2.0.0
+ * @since 2.0.17
*/
-public class PredicateVersionFilter implements VersionFilter {
+public class ArtifactPredicateVersionFilter implements VersionFilter {
private final Predicate<Artifact> artifactPredicate;
/**
* Creates a new instance of this version filter.
*/
- public PredicateVersionFilter(Predicate<Artifact> artifactPredicate) {
+ public ArtifactPredicateVersionFilter(Predicate<Artifact> artifactPredicate) {
this.artifactPredicate = requireNonNull(artifactPredicate);
}
@@ -69,7 +69,7 @@ public class PredicateVersionFilter implements VersionFilter {
if (o == null || getClass() != o.getClass()) {
return false;
}
- PredicateVersionFilter that = (PredicateVersionFilter) o;
+ ArtifactPredicateVersionFilter that = (ArtifactPredicateVersionFilter) o;
return Objects.equals(artifactPredicate, that.artifactPredicate);
}
diff --git a/maven-resolver-util/src/main/java/org/eclipse/aether/util/graph/version/PredicateVersionFilter.java b/maven-resolver-util/src/main/java/org/eclipse/aether/util/graph/version/ContextPredicateDelegatingVersionFilter.java
similarity index 54%
copy from maven-resolver-util/src/main/java/org/eclipse/aether/util/graph/version/PredicateVersionFilter.java
copy to maven-resolver-util/src/main/java/org/eclipse/aether/util/graph/version/ContextPredicateDelegatingVersionFilter.java
index 2f66d6c7c..7ebb7a4af 100644
--- a/maven-resolver-util/src/main/java/org/eclipse/aether/util/graph/version/PredicateVersionFilter.java
+++ b/maven-resolver-util/src/main/java/org/eclipse/aether/util/graph/version/ContextPredicateDelegatingVersionFilter.java
@@ -18,47 +18,48 @@
*/
package org.eclipse.aether.util.graph.version;
-import java.util.Iterator;
import java.util.Objects;
import java.util.function.Predicate;
-import org.eclipse.aether.artifact.Artifact;
+import org.eclipse.aether.RepositoryException;
import org.eclipse.aether.collection.DependencyCollectionContext;
import org.eclipse.aether.collection.VersionFilter;
-import org.eclipse.aether.version.Version;
import static java.util.Objects.requireNonNull;
/**
- * A version filter that excludes any version that is blacklisted.
+ * A version filter that applies delegate version filter if context predicate applies.
*
- * @since 2.0.0
+ * @since 2.0.17
*/
-public class PredicateVersionFilter implements VersionFilter {
- private final Predicate<Artifact> artifactPredicate;
+public class ContextPredicateDelegatingVersionFilter implements VersionFilter {
+ private final Predicate<VersionFilterContext> contextPredicate;
+ private final VersionFilter delegate;
/**
* Creates a new instance of this version filter.
*/
- public PredicateVersionFilter(Predicate<Artifact> artifactPredicate) {
- this.artifactPredicate = requireNonNull(artifactPredicate);
+ public ContextPredicateDelegatingVersionFilter(
+ Predicate<VersionFilterContext> contextPredicate, VersionFilter delegate) {
+ this.contextPredicate = requireNonNull(contextPredicate);
+ this.delegate = requireNonNull(delegate);
}
@Override
- public void filterVersions(VersionFilterContext context) {
- Artifact dependencyArtifact = context.getDependency().getArtifact();
- Iterator<Version> it = context.iterator();
- while (it.hasNext()) {
- Version version = it.next();
- if (!artifactPredicate.test(dependencyArtifact.setVersion(version.toString()))) {
- it.remove();
- }
+ public void filterVersions(VersionFilterContext context) throws RepositoryException {
+ if (contextPredicate.test(context)) {
+ delegate.filterVersions(context);
}
}
@Override
public VersionFilter deriveChildFilter(DependencyCollectionContext context) {
- return this;
+ VersionFilter derived = delegate.deriveChildFilter(context);
+ if (derived == delegate) {
+ return this;
+ } else {
+ return new ContextPredicateDelegatingVersionFilter(contextPredicate, derived);
+ }
}
@Override
@@ -69,12 +70,12 @@ public class PredicateVersionFilter implements VersionFilter {
if (o == null || getClass() != o.getClass()) {
return false;
}
- PredicateVersionFilter that = (PredicateVersionFilter) o;
- return Objects.equals(artifactPredicate, that.artifactPredicate);
+ ContextPredicateDelegatingVersionFilter that = (ContextPredicateDelegatingVersionFilter) o;
+ return Objects.equals(contextPredicate, that.contextPredicate) && Objects.equals(delegate, that.delegate);
}
@Override
public int hashCode() {
- return Objects.hash(artifactPredicate);
+ return Objects.hash(contextPredicate, delegate);
}
}
diff --git a/maven-resolver-util/src/main/java/org/eclipse/aether/util/graph/version/GenericQualifiersVersionFilter.java b/maven-resolver-util/src/main/java/org/eclipse/aether/util/graph/version/GenericQualifiersVersionFilter.java
new file mode 100644
index 000000000..3dee8efca
--- /dev/null
+++ b/maven-resolver-util/src/main/java/org/eclipse/aether/util/graph/version/GenericQualifiersVersionFilter.java
@@ -0,0 +1,69 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.eclipse.aether.util.graph.version;
+
+import java.util.function.Predicate;
+
+import org.eclipse.aether.util.version.GenericQualifiers;
+
+/**
+ * A version filter that (unconditionally) blocks based on qualifiers, as defined by {@link GenericQualifiers}.
+ * Note: while SNAPSHOT string is also a qualifier, this filter does not deal with them, see {@link SnapshotVersionFilter},
+ * {@link ContextualSnapshotVersionFilter} and {@link ContextualAncestorSnapshotVersionFilter}.
+ *
+ * @since 2.0.17
+ * @see GenericQualifiers
+ * @see SnapshotVersionFilter
+ * @see ContextualSnapshotVersionFilter
+ * @see ContextualAncestorSnapshotVersionFilter
+ */
+public class GenericQualifiersVersionFilter extends VersionPredicateVersionFilter {
+ /**
+ * Filters any version that contains "preview" qualifiers (alpha, beta, milestone).
+ */
+ public static GenericQualifiersVersionFilter previewVersionFilter() {
+ return new GenericQualifiersVersionFilter(i -> i > GenericQualifiers.QUALIFIER_MILESTONE);
+ }
+
+ /**
+ * Filters any version that contains "pre-release" qualifiers (alpha, beta, milestone, rc/cr).
+ */
+ public static GenericQualifiersVersionFilter preReleaseVersionFilter() {
+ return new GenericQualifiersVersionFilter(i -> i > GenericQualifiers.QUALIFIER_RC);
+ }
+
+ /**
+ * Filters any version that contains any qualifiers.
+ */
+ public static GenericQualifiersVersionFilter anyQualifierVersionFilter() {
+ return new GenericQualifiersVersionFilter(i -> false);
+ }
+
+ /**
+ * Constructor that is able to select which qualifier to accept. Passed in predicate is invoked for version with
+ * detected qualifiers only, while versions without qualifiers are accepted.
+ *
+ * @see GenericQualifiers
+ */
+ public GenericQualifiersVersionFilter(Predicate<Integer> qualifierPredicate) {
+ super(v -> GenericQualifiers.qualifier(v.toString())
+ .map(qualifierPredicate::test)
+ .orElse(true));
+ }
+}
diff --git a/maven-resolver-util/src/main/java/org/eclipse/aether/util/graph/version/PredicateVersionFilter.java b/maven-resolver-util/src/main/java/org/eclipse/aether/util/graph/version/PredicateVersionFilter.java
index 2f66d6c7c..506ad7fae 100644
--- a/maven-resolver-util/src/main/java/org/eclipse/aether/util/graph/version/PredicateVersionFilter.java
+++ b/maven-resolver-util/src/main/java/org/eclipse/aether/util/graph/version/PredicateVersionFilter.java
@@ -18,63 +18,22 @@
*/
package org.eclipse.aether.util.graph.version;
-import java.util.Iterator;
-import java.util.Objects;
import java.util.function.Predicate;
import org.eclipse.aether.artifact.Artifact;
-import org.eclipse.aether.collection.DependencyCollectionContext;
-import org.eclipse.aether.collection.VersionFilter;
-import org.eclipse.aether.version.Version;
-
-import static java.util.Objects.requireNonNull;
/**
- * A version filter that excludes any version that is blacklisted.
+ * A version filter that excludes any version that is blacklisted by predicate.
*
* @since 2.0.0
+ * @deprecated Use {@link ArtifactPredicateVersionFilter} instead.
*/
-public class PredicateVersionFilter implements VersionFilter {
- private final Predicate<Artifact> artifactPredicate;
-
+@Deprecated
+public class PredicateVersionFilter extends ArtifactPredicateVersionFilter {
/**
* Creates a new instance of this version filter.
*/
public PredicateVersionFilter(Predicate<Artifact> artifactPredicate) {
- this.artifactPredicate = requireNonNull(artifactPredicate);
- }
-
- @Override
- public void filterVersions(VersionFilterContext context) {
- Artifact dependencyArtifact = context.getDependency().getArtifact();
- Iterator<Version> it = context.iterator();
- while (it.hasNext()) {
- Version version = it.next();
- if (!artifactPredicate.test(dependencyArtifact.setVersion(version.toString()))) {
- it.remove();
- }
- }
- }
-
- @Override
- public VersionFilter deriveChildFilter(DependencyCollectionContext context) {
- return this;
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) {
- return true;
- }
- if (o == null || getClass() != o.getClass()) {
- return false;
- }
- PredicateVersionFilter that = (PredicateVersionFilter) o;
- return Objects.equals(artifactPredicate, that.artifactPredicate);
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(artifactPredicate);
+ super(artifactPredicate);
}
}
diff --git a/maven-resolver-util/src/main/java/org/eclipse/aether/util/graph/version/ReleaseVersionFilter.java b/maven-resolver-util/src/main/java/org/eclipse/aether/util/graph/version/ReleaseVersionFilter.java
index 08a250122..2ba57c9b2 100644
--- a/maven-resolver-util/src/main/java/org/eclipse/aether/util/graph/version/ReleaseVersionFilter.java
+++ b/maven-resolver-util/src/main/java/org/eclipse/aether/util/graph/version/ReleaseVersionFilter.java
@@ -18,15 +18,17 @@
*/
package org.eclipse.aether.util.graph.version;
+import org.eclipse.aether.artifact.Artifact;
+
/**
- * A version filter that (unconditionally) blocks non "*-SNAPSHOT" versions.
+ * A version filter that (unconditionally) blocks non-snapshot versions.
*/
-public class ReleaseVersionFilter extends VersionPredicateVersionFilter {
+public class ReleaseVersionFilter extends ArtifactPredicateVersionFilter {
/**
* Creates a new instance of this version filter.
*/
public ReleaseVersionFilter() {
- super(v -> v.toString().endsWith("SNAPSHOT"));
+ super(Artifact::isSnapshot);
}
}
diff --git a/maven-resolver-util/src/main/java/org/eclipse/aether/util/graph/version/SnapshotVersionFilter.java b/maven-resolver-util/src/main/java/org/eclipse/aether/util/graph/version/SnapshotVersionFilter.java
index f933551b0..ecb91be70 100644
--- a/maven-resolver-util/src/main/java/org/eclipse/aether/util/graph/version/SnapshotVersionFilter.java
+++ b/maven-resolver-util/src/main/java/org/eclipse/aether/util/graph/version/SnapshotVersionFilter.java
@@ -19,15 +19,15 @@
package org.eclipse.aether.util.graph.version;
/**
- * A version filter that (unconditionally) blocks "*-SNAPSHOT" versions. For practical purposes,
+ * A version filter that (unconditionally) blocks snapshot versions. For practical purposes,
* {@link ContextualSnapshotVersionFilter} is usually more desirable.
*/
-public class SnapshotVersionFilter extends VersionPredicateVersionFilter {
+public class SnapshotVersionFilter extends ArtifactPredicateVersionFilter {
/**
* Creates a new instance of this version filter.
*/
public SnapshotVersionFilter() {
- super(v -> !v.toString().endsWith("SNAPSHOT"));
+ super(a -> !a.isSnapshot());
}
}
diff --git a/maven-resolver-util/src/main/java/org/eclipse/aether/util/graph/version/VersionPredicateVersionFilter.java b/maven-resolver-util/src/main/java/org/eclipse/aether/util/graph/version/VersionPredicateVersionFilter.java
index 65a4d9fc9..7241006be 100644
--- a/maven-resolver-util/src/main/java/org/eclipse/aether/util/graph/version/VersionPredicateVersionFilter.java
+++ b/maven-resolver-util/src/main/java/org/eclipse/aether/util/graph/version/VersionPredicateVersionFilter.java
@@ -29,7 +29,7 @@ import org.eclipse.aether.version.Version;
import static java.util.Objects.requireNonNull;
/**
- * A version filter that excludes any version that is blacklisted.
+ * A version filter that excludes any version that is not-matched by version predicate.
*
* @since 2.0.11
*/
diff --git a/maven-resolver-util/src/main/java/org/eclipse/aether/util/version/GenericQualifiers.java b/maven-resolver-util/src/main/java/org/eclipse/aether/util/version/GenericQualifiers.java
new file mode 100644
index 000000000..ff3f532cd
--- /dev/null
+++ b/maven-resolver-util/src/main/java/org/eclipse/aether/util/version/GenericQualifiers.java
@@ -0,0 +1,123 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.eclipse.aether.util.version;
+
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Optional;
+
+/**
+ * The recognized generic version qualifiers. Qualifiers may apply a "shift" to versions (ie when sorting), if present.
+ *
+ * @since 2.0.17
+ */
+public final class GenericQualifiers {
+ private GenericQualifiers() {}
+
+ public static final String LABEL_ALPHA = "alpha";
+
+ public static final String LABEL_BETA = "beta";
+
+ public static final String LABEL_MILESTONE = "milestone";
+
+ public static final Integer QUALIFIER_ALPHA = -5;
+
+ public static final Integer QUALIFIER_BETA = -4;
+
+ public static final Integer QUALIFIER_MILESTONE = -3;
+
+ public static final Integer QUALIFIER_RC = -2;
+
+ public static final Integer QUALIFIER_SNAPSHOT = -1;
+
+ public static final Integer QUALIFIER_ZERO = 0;
+
+ public static final Integer QUALIFIER_SP = 1;
+
+ private static final Map<String, Integer> QUALIFIERS;
+
+ static {
+ Map<String, Integer> qualifiers = new LinkedHashMap<>();
+ qualifiers.put(LABEL_ALPHA, QUALIFIER_ALPHA);
+ qualifiers.put(LABEL_BETA, QUALIFIER_BETA);
+ qualifiers.put(LABEL_MILESTONE, QUALIFIER_MILESTONE);
+ qualifiers.put("rc", QUALIFIER_RC);
+ qualifiers.put("cr", QUALIFIER_RC);
+ qualifiers.put("snapshot", QUALIFIER_SNAPSHOT);
+ qualifiers.put("ga", QUALIFIER_ZERO);
+ qualifiers.put("final", QUALIFIER_ZERO);
+ qualifiers.put("release", QUALIFIER_ZERO);
+ qualifiers.put("sp", QUALIFIER_SP);
+ QUALIFIERS = Collections.unmodifiableMap(qualifiers);
+ }
+
+ /**
+ * Returns qualifier (an {@link Integer} for given token, if detected. This method is used in {@link GenericVersion}
+ * that tokenizes version, and uses string token in call. The input must have {@link String#toLowerCase(Locale)}
+ * applied.
+ */
+ static Optional<Integer> tokenQualifier(String token) {
+ return Optional.ofNullable(QUALIFIERS.get(token));
+ }
+
+ /**
+ * Returns qualifier (an {@link Integer} for given string, if detected. Qualifier, if present, defines "shift",
+ * if negative, it is a "preview version" (e.g. alpha, beta, milestone, release candidate or snapshot), if zero,
+ * it is a "final version" (e.g. ga, final, release), if positive, it is a "service pack" version (e.g. sp).
+ * If no qualifier is detected, an empty optional is returned.
+ *
+ * @param token the string to analyze for qualifier, must not be {@code null}
+ */
+ public static Optional<Integer> qualifier(String token) {
+ // most trivial preview version is "a1"
+ if (token.length() > 1) {
+ String v = token.toLowerCase(Locale.ENGLISH);
+ // simple case: full qualifier label is present (assuming once)
+ for (Map.Entry<String, Integer> entry : QUALIFIERS.entrySet()) {
+ String label = entry.getKey();
+ int pos = v.indexOf(label);
+ if (pos > -1
+ && (pos == 0 || !Character.isLetter(v.charAt(pos - 1)))
+ && (pos >= v.length() - label.length()
+ || !Character.isLetter(v.charAt(pos + label.length())))) {
+ // it must be surrounded by "transition" (non-char; to avoid "rc" detection in "1.0-arc")
+ return Optional.of(entry.getValue());
+ }
+ }
+ // complex case: contains 'a', 'b' or 'm' followed immediately by number
+ for (char ch : new char[] {'a', 'b', 'm'}) {
+ int idx = v.lastIndexOf(ch);
+ if (idx > -1 && v.length() > idx + 1) {
+ if (Character.isDigit(v.charAt(idx + 1))) {
+ if (ch == 'a') {
+ return Optional.of(QUALIFIER_ALPHA);
+ } else if (ch == 'b') {
+ return Optional.of(QUALIFIER_BETA);
+ } else {
+ return Optional.of(QUALIFIER_MILESTONE);
+ }
+ }
+ }
+ }
+ }
+ return Optional.empty();
+ }
+}
diff --git a/maven-resolver-util/src/main/java/org/eclipse/aether/util/version/GenericVersion.java b/maven-resolver-util/src/main/java/org/eclipse/aether/util/version/GenericVersion.java
index 759b01b2a..9b841efd3 100644
--- a/maven-resolver-util/src/main/java/org/eclipse/aether/util/version/GenericVersion.java
+++ b/maven-resolver-util/src/main/java/org/eclipse/aether/util/version/GenericVersion.java
@@ -23,8 +23,6 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
-import java.util.Map;
-import java.util.TreeMap;
import org.eclipse.aether.version.Version;
@@ -34,7 +32,7 @@ import static java.util.Objects.requireNonNull;
* A generic version, that is a version that accepts any input string and tries to apply common sense sorting. See
* {@link GenericVersionScheme} for details.
*/
-final class GenericVersion implements Version {
+public final class GenericVersion implements Version {
private final String version;
@@ -175,30 +173,6 @@ final class GenericVersion implements Version {
}
static final class Tokenizer {
-
- private static final Integer QUALIFIER_ALPHA = -5;
-
- private static final Integer QUALIFIER_BETA = -4;
-
- private static final Integer QUALIFIER_MILESTONE = -3;
-
- private static final Map<String, Integer> QUALIFIERS;
-
- static {
- QUALIFIERS = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
- QUALIFIERS.put("alpha", QUALIFIER_ALPHA);
- QUALIFIERS.put("beta", QUALIFIER_BETA);
- QUALIFIERS.put("milestone", QUALIFIER_MILESTONE);
- QUALIFIERS.put("cr", -2);
- QUALIFIERS.put("rc", -2);
- QUALIFIERS.put("snapshot", -1);
- QUALIFIERS.put("ga", 0);
- QUALIFIERS.put("final", 0);
- QUALIFIERS.put("release", 0);
- QUALIFIERS.put("", 0);
- QUALIFIERS.put("sp", 1);
- }
-
private final String version;
private final int versionLength;
@@ -296,22 +270,23 @@ final class GenericVersion implements Version {
switch (token.charAt(0)) {
case 'a':
case 'A':
- return new Item(Item.KIND_QUALIFIER, QUALIFIER_ALPHA);
+ token = GenericQualifiers.LABEL_ALPHA;
+ break;
case 'b':
case 'B':
- return new Item(Item.KIND_QUALIFIER, QUALIFIER_BETA);
+ token = GenericQualifiers.LABEL_BETA;
+ break;
case 'm':
case 'M':
- return new Item(Item.KIND_QUALIFIER, QUALIFIER_MILESTONE);
+ token = GenericQualifiers.LABEL_MILESTONE;
+ break;
default:
}
}
- Integer qualifier = QUALIFIERS.get(token);
- if (qualifier != null) {
- return new Item(Item.KIND_QUALIFIER, qualifier);
- } else {
- return new Item(Item.KIND_STRING, token.toLowerCase(Locale.ENGLISH));
- }
+ token = token.toLowerCase(Locale.ENGLISH);
+ return GenericQualifiers.tokenQualifier(token)
+ .map(integer -> new Item(Item.KIND_QUALIFIER, integer))
+ .orElseGet(() -> new Item(Item.KIND_STRING, token));
}
}
}
diff --git a/maven-resolver-util/src/main/java/org/eclipse/aether/util/version/GenericVersionConstraint.java b/maven-resolver-util/src/main/java/org/eclipse/aether/util/version/GenericVersionConstraint.java
index ecaef4aff..7ac0f65a7 100644
--- a/maven-resolver-util/src/main/java/org/eclipse/aether/util/version/GenericVersionConstraint.java
+++ b/maven-resolver-util/src/main/java/org/eclipse/aether/util/version/GenericVersionConstraint.java
@@ -31,7 +31,7 @@ import static java.util.Objects.requireNonNull;
* <p>
* Despite its name, this class is generic in a sense it works with any {@link Version}.
*/
-final class GenericVersionConstraint implements VersionConstraint {
+public final class GenericVersionConstraint implements VersionConstraint {
private final VersionRange range;
diff --git a/maven-resolver-util/src/main/java/org/eclipse/aether/util/version/GenericVersionRange.java b/maven-resolver-util/src/main/java/org/eclipse/aether/util/version/GenericVersionRange.java
index 93c4d20b5..38be79876 100644
--- a/maven-resolver-util/src/main/java/org/eclipse/aether/util/version/GenericVersionRange.java
+++ b/maven-resolver-util/src/main/java/org/eclipse/aether/util/version/GenericVersionRange.java
@@ -32,7 +32,7 @@ import static java.util.Objects.requireNonNull;
* <p>
* Despite its name, this class is generic in a sense it works with any {@link Version}
*/
-final class GenericVersionRange implements VersionRange {
+public final class GenericVersionRange implements VersionRange {
private final VersionScheme versionScheme;
private final Bound lowerBound;
diff --git a/maven-resolver-util/src/main/java/org/eclipse/aether/util/version/GenericVersionScheme.java b/maven-resolver-util/src/main/java/org/eclipse/aether/util/version/GenericVersionScheme.java
index 32ba67f4b..3dd7c5ca7 100644
--- a/maven-resolver-util/src/main/java/org/eclipse/aether/util/version/GenericVersionScheme.java
+++ b/maven-resolver-util/src/main/java/org/eclipse/aether/util/version/GenericVersionScheme.java
@@ -18,6 +18,7 @@
*/
package org.eclipse.aether.util.version;
+import java.nio.charset.StandardCharsets;
import java.util.Collections;
import java.util.Map;
import java.util.WeakHashMap;
@@ -165,6 +166,9 @@ public class GenericVersionScheme extends VersionSchemeSupport {
GenericVersion prev = null;
int i = 1;
for (String version : args) {
+ if (!StandardCharsets.US_ASCII.newEncoder().canEncode(version)) {
+ System.out.println("WW Use of non-ASCII characters for version strings is not recommended.");
+ }
try {
GenericVersion c = scheme.parseVersion(version);
diff --git a/maven-resolver-util/src/main/java/org/eclipse/aether/util/version/VersionSchemeSupport.java b/maven-resolver-util/src/main/java/org/eclipse/aether/util/version/VersionSchemeSupport.java
index 65721218a..c64ad5bad 100644
--- a/maven-resolver-util/src/main/java/org/eclipse/aether/util/version/VersionSchemeSupport.java
+++ b/maven-resolver-util/src/main/java/org/eclipse/aether/util/version/VersionSchemeSupport.java
@@ -34,7 +34,7 @@ import static java.util.Objects.requireNonNull;
*
* @since 2.0.0
*/
-abstract class VersionSchemeSupport implements VersionScheme {
+public abstract class VersionSchemeSupport implements VersionScheme {
@Override
public GenericVersionRange parseVersionRange(final String range) throws InvalidVersionSpecificationException {
return new GenericVersionRange(this, range);
diff --git a/maven-resolver-util/src/main/java/org/eclipse/aether/util/version/package-info.java b/maven-resolver-util/src/main/java/org/eclipse/aether/util/version/package-info.java
index ad3f40473..191f1bfe5 100644
--- a/maven-resolver-util/src/main/java/org/eclipse/aether/util/version/package-info.java
+++ b/maven-resolver-util/src/main/java/org/eclipse/aether/util/version/package-info.java
@@ -63,6 +63,7 @@
* <ul>
* <li>Using "min" or "max" special segments as a non-trailing segment. This yields in "undefined" behaviour and should be avoided.</li>
* <li>Having a non-number as the first segment of a version. Versions are expected (but not enforced) to start with numbers.</li>
+ * <li>Using special, non-ASCII characters in version. The recommendation is to keep version strings simple.</li>
* </ul>
*/
package org.eclipse.aether.util.version;
diff --git a/maven-resolver-util/src/test/java/org/eclipse/aether/util/graph/versions/AbstractVersionFilterTest.java b/maven-resolver-util/src/test/java/org/eclipse/aether/util/graph/version/AbstractVersionFilterTest.java
similarity index 92%
rename from maven-resolver-util/src/test/java/org/eclipse/aether/util/graph/versions/AbstractVersionFilterTest.java
rename to maven-resolver-util/src/test/java/org/eclipse/aether/util/graph/version/AbstractVersionFilterTest.java
index 45152a248..7795dd567 100644
--- a/maven-resolver-util/src/test/java/org/eclipse/aether/util/graph/versions/AbstractVersionFilterTest.java
+++ b/maven-resolver-util/src/test/java/org/eclipse/aether/util/graph/version/AbstractVersionFilterTest.java
@@ -16,8 +16,9 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.eclipse.aether.util.graph.versions;
+package org.eclipse.aether.util.graph.version;
+import java.util.ArrayList;
import java.util.Iterator;
import org.eclipse.aether.DefaultRepositorySystemSession;
@@ -73,7 +74,9 @@ public abstract class AbstractVersionFilterTest {
}
protected void assertVersions(VersionFilter.VersionFilterContext context, String... versions) {
- assertEquals(versions.length, context.getCount());
+ ArrayList<Version> filtered = new ArrayList<>();
+ context.iterator().forEachRemaining(filtered::add);
+ assertEquals(versions.length, context.getCount(), filtered.toString());
Iterator<Version> it = context.iterator();
for (String version : versions) {
assertTrue(it.hasNext());
diff --git a/maven-resolver-util/src/test/java/org/eclipse/aether/util/graph/versions/PredicateVersionFilterTest.java b/maven-resolver-util/src/test/java/org/eclipse/aether/util/graph/version/ArtifactPredicateVersionFilterTest.java
similarity index 65%
copy from maven-resolver-util/src/test/java/org/eclipse/aether/util/graph/versions/PredicateVersionFilterTest.java
copy to maven-resolver-util/src/test/java/org/eclipse/aether/util/graph/version/ArtifactPredicateVersionFilterTest.java
index a4cc08478..fa102e2ec 100644
--- a/maven-resolver-util/src/test/java/org/eclipse/aether/util/graph/versions/PredicateVersionFilterTest.java
+++ b/maven-resolver-util/src/test/java/org/eclipse/aether/util/graph/version/ArtifactPredicateVersionFilterTest.java
@@ -16,23 +16,24 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.eclipse.aether.util.graph.versions;
+package org.eclipse.aether.util.graph.version;
import java.util.function.Predicate;
import org.eclipse.aether.artifact.Artifact;
import org.eclipse.aether.collection.VersionFilter.VersionFilterContext;
-import org.eclipse.aether.util.graph.version.PredicateVersionFilter;
import org.junit.jupiter.api.Test;
-import static org.junit.jupiter.api.Assertions.*;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotEquals;
+import static org.junit.jupiter.api.Assertions.assertSame;
-public class PredicateVersionFilterTest extends AbstractVersionFilterTest {
+public class ArtifactPredicateVersionFilterTest extends AbstractVersionFilterTest {
@Test
void testFilterVersions() {
Predicate<Artifact> oddVersions = a -> Integer.parseInt(a.getVersion()) % 2 != 0;
- PredicateVersionFilter filter = new PredicateVersionFilter(oddVersions);
+ ArtifactPredicateVersionFilter filter = new ArtifactPredicateVersionFilter(oddVersions);
VersionFilterContext ctx = newContext("g:a:[1,9]", "1", "2", "3", "4", "5", "6", "7", "8", "9");
filter.filterVersions(ctx);
assertVersions(ctx, "1", "3", "5", "7", "9");
@@ -40,7 +41,7 @@ public class PredicateVersionFilterTest extends AbstractVersionFilterTest {
@Test
void testDeriveChildFilter() {
- PredicateVersionFilter filter = new PredicateVersionFilter(a -> true);
+ ArtifactPredicateVersionFilter filter = new ArtifactPredicateVersionFilter(a -> true);
assertSame(filter, derive(filter, "g:a:1"));
}
@@ -48,12 +49,12 @@ public class PredicateVersionFilterTest extends AbstractVersionFilterTest {
void testEquals() {
Predicate<Artifact> falsePredicate = a -> false;
Predicate<Artifact> truePredicate = a -> true;
- PredicateVersionFilter filter1 = new PredicateVersionFilter(falsePredicate);
- PredicateVersionFilter filter2 = new PredicateVersionFilter(falsePredicate);
- PredicateVersionFilter filter3 = new PredicateVersionFilter(truePredicate);
+ ArtifactPredicateVersionFilter filter1 = new ArtifactPredicateVersionFilter(falsePredicate);
+ ArtifactPredicateVersionFilter filter2 = new ArtifactPredicateVersionFilter(falsePredicate);
+ ArtifactPredicateVersionFilter filter3 = new ArtifactPredicateVersionFilter(truePredicate);
assertNotEquals(null, filter1);
assertEquals(filter1, filter2);
assertNotEquals(filter2, filter3);
- assertEquals(filter1, new PredicateVersionFilter(falsePredicate));
+ assertEquals(filter1, new ArtifactPredicateVersionFilter(falsePredicate));
}
}
diff --git a/maven-resolver-util/src/test/java/org/eclipse/aether/util/graph/versions/ChainedVersionFilterTest.java b/maven-resolver-util/src/test/java/org/eclipse/aether/util/graph/version/ChainedVersionFilterTest.java
similarity index 91%
rename from maven-resolver-util/src/test/java/org/eclipse/aether/util/graph/versions/ChainedVersionFilterTest.java
rename to maven-resolver-util/src/test/java/org/eclipse/aether/util/graph/version/ChainedVersionFilterTest.java
index 7afc74433..546b31fa3 100644
--- a/maven-resolver-util/src/test/java/org/eclipse/aether/util/graph/versions/ChainedVersionFilterTest.java
+++ b/maven-resolver-util/src/test/java/org/eclipse/aether/util/graph/version/ChainedVersionFilterTest.java
@@ -16,14 +16,11 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.eclipse.aether.util.graph.versions;
+package org.eclipse.aether.util.graph.version;
import org.eclipse.aether.collection.DependencyCollectionContext;
import org.eclipse.aether.collection.VersionFilter;
import org.eclipse.aether.collection.VersionFilter.VersionFilterContext;
-import org.eclipse.aether.util.graph.version.ChainedVersionFilter;
-import org.eclipse.aether.util.graph.version.HighestVersionFilter;
-import org.eclipse.aether.util.graph.version.SnapshotVersionFilter;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
diff --git a/maven-resolver-util/src/test/java/org/eclipse/aether/util/graph/versions/ContextualSnapshotVersionFilterTest.java b/maven-resolver-util/src/test/java/org/eclipse/aether/util/graph/version/ContextualSnapshotVersionFilterTest.java
similarity index 92%
rename from maven-resolver-util/src/test/java/org/eclipse/aether/util/graph/versions/ContextualSnapshotVersionFilterTest.java
rename to maven-resolver-util/src/test/java/org/eclipse/aether/util/graph/version/ContextualSnapshotVersionFilterTest.java
index 44e66498c..30a7e37e2 100644
--- a/maven-resolver-util/src/test/java/org/eclipse/aether/util/graph/versions/ContextualSnapshotVersionFilterTest.java
+++ b/maven-resolver-util/src/test/java/org/eclipse/aether/util/graph/version/ContextualSnapshotVersionFilterTest.java
@@ -16,12 +16,10 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.eclipse.aether.util.graph.versions;
+package org.eclipse.aether.util.graph.version;
import org.eclipse.aether.collection.VersionFilter;
import org.eclipse.aether.collection.VersionFilter.VersionFilterContext;
-import org.eclipse.aether.util.graph.version.ContextualSnapshotVersionFilter;
-import org.eclipse.aether.util.graph.version.SnapshotVersionFilter;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
diff --git a/maven-resolver-util/src/test/java/org/eclipse/aether/util/graph/version/GenericQualifiersVersionFilterTest.java b/maven-resolver-util/src/test/java/org/eclipse/aether/util/graph/version/GenericQualifiersVersionFilterTest.java
new file mode 100644
index 000000000..4eda2392f
--- /dev/null
+++ b/maven-resolver-util/src/test/java/org/eclipse/aether/util/graph/version/GenericQualifiersVersionFilterTest.java
@@ -0,0 +1,90 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.eclipse.aether.util.graph.version;
+
+import org.eclipse.aether.collection.VersionFilter.VersionFilterContext;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertSame;
+
+public class GenericQualifiersVersionFilterTest extends AbstractVersionFilterTest {
+
+ @Test
+ void testPreviewVersionFilter() {
+ GenericQualifiersVersionFilter filter = GenericQualifiersVersionFilter.previewVersionFilter();
+ VersionFilterContext ctx = newContext(
+ "g:a:[1,9]",
+ "1-alpha-1",
+ "1-M1",
+ "1",
+ "2-SNAPSHOT",
+ "3.0-GA",
+ "3.1",
+ "4.0-SNAPSHOT",
+ "5.0.0.rc",
+ "5.0.0",
+ "5.0.0-sp");
+ filter.filterVersions(ctx);
+ assertVersions(ctx, "1", "2-SNAPSHOT", "3.0-GA", "3.1", "4.0-SNAPSHOT", "5.0.0.rc", "5.0.0", "5.0.0-sp");
+ }
+
+ @Test
+ void testPreReleaseVersionFilter() {
+ GenericQualifiersVersionFilter filter = GenericQualifiersVersionFilter.preReleaseVersionFilter();
+ VersionFilterContext ctx = newContext(
+ "g:a:[1,9]",
+ "1-alpha-1",
+ "1-M1",
+ "1",
+ "2-SNAPSHOT",
+ "3.0-GA",
+ "3.1",
+ "4.0-SNAPSHOT",
+ "5.0.0.rc",
+ "5.0.0",
+ "5.0.0-sp");
+ filter.filterVersions(ctx);
+ assertVersions(ctx, "1", "2-SNAPSHOT", "3.0-GA", "3.1", "4.0-SNAPSHOT", "5.0.0", "5.0.0-sp");
+ }
+
+ @Test
+ void testAnyQualifierVersionFilter() {
+ GenericQualifiersVersionFilter filter = GenericQualifiersVersionFilter.anyQualifierVersionFilter();
+ VersionFilterContext ctx = newContext(
+ "g:a:[1,9]",
+ "1-alpha-1",
+ "1-M1",
+ "1",
+ "2-SNAPSHOT",
+ "3.0-GA",
+ "3.1",
+ "4.0-SNAPSHOT",
+ "5.0.0.rc",
+ "5.0.0",
+ "5.0.0-sp");
+ filter.filterVersions(ctx);
+ assertVersions(ctx, "1", "3.1", "5.0.0");
+ }
+
+ @Test
+ void testDeriveChildFilter() {
+ GenericQualifiersVersionFilter filter = GenericQualifiersVersionFilter.previewVersionFilter();
+ assertSame(filter, derive(filter, "g:a:1"));
+ }
+}
diff --git a/maven-resolver-util/src/test/java/org/eclipse/aether/util/graph/versions/HighestVersionFilterTest.java b/maven-resolver-util/src/test/java/org/eclipse/aether/util/graph/version/HighestVersionFilterTest.java
similarity index 94%
rename from maven-resolver-util/src/test/java/org/eclipse/aether/util/graph/versions/HighestVersionFilterTest.java
rename to maven-resolver-util/src/test/java/org/eclipse/aether/util/graph/version/HighestVersionFilterTest.java
index 31ff8834b..23ae00161 100644
--- a/maven-resolver-util/src/test/java/org/eclipse/aether/util/graph/versions/HighestVersionFilterTest.java
+++ b/maven-resolver-util/src/test/java/org/eclipse/aether/util/graph/version/HighestVersionFilterTest.java
@@ -16,10 +16,9 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.eclipse.aether.util.graph.versions;
+package org.eclipse.aether.util.graph.version;
import org.eclipse.aether.collection.VersionFilter.VersionFilterContext;
-import org.eclipse.aether.util.graph.version.HighestVersionFilter;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
diff --git a/maven-resolver-util/src/test/java/org/eclipse/aether/util/graph/versions/LowestVersionFilterTest.java b/maven-resolver-util/src/test/java/org/eclipse/aether/util/graph/version/LowestVersionFilterTest.java
similarity index 94%
rename from maven-resolver-util/src/test/java/org/eclipse/aether/util/graph/versions/LowestVersionFilterTest.java
rename to maven-resolver-util/src/test/java/org/eclipse/aether/util/graph/version/LowestVersionFilterTest.java
index 80508231f..dbe2dd30b 100644
--- a/maven-resolver-util/src/test/java/org/eclipse/aether/util/graph/versions/LowestVersionFilterTest.java
+++ b/maven-resolver-util/src/test/java/org/eclipse/aether/util/graph/version/LowestVersionFilterTest.java
@@ -16,10 +16,9 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.eclipse.aether.util.graph.versions;
+package org.eclipse.aether.util.graph.version;
import org.eclipse.aether.collection.VersionFilter.VersionFilterContext;
-import org.eclipse.aether.util.graph.version.LowestVersionFilter;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
diff --git a/maven-resolver-util/src/test/java/org/eclipse/aether/util/graph/versions/PredicateVersionFilterTest.java b/maven-resolver-util/src/test/java/org/eclipse/aether/util/graph/version/PredicateVersionFilterTest.java
similarity index 95%
rename from maven-resolver-util/src/test/java/org/eclipse/aether/util/graph/versions/PredicateVersionFilterTest.java
rename to maven-resolver-util/src/test/java/org/eclipse/aether/util/graph/version/PredicateVersionFilterTest.java
index a4cc08478..c9fbbfae4 100644
--- a/maven-resolver-util/src/test/java/org/eclipse/aether/util/graph/versions/PredicateVersionFilterTest.java
+++ b/maven-resolver-util/src/test/java/org/eclipse/aether/util/graph/version/PredicateVersionFilterTest.java
@@ -16,13 +16,12 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.eclipse.aether.util.graph.versions;
+package org.eclipse.aether.util.graph.version;
import java.util.function.Predicate;
import org.eclipse.aether.artifact.Artifact;
import org.eclipse.aether.collection.VersionFilter.VersionFilterContext;
-import org.eclipse.aether.util.graph.version.PredicateVersionFilter;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
diff --git a/maven-resolver-util/src/test/java/org/eclipse/aether/util/graph/versions/ReleaseVersionFilterTest.java b/maven-resolver-util/src/test/java/org/eclipse/aether/util/graph/version/ReleaseVersionFilterTest.java
similarity index 94%
rename from maven-resolver-util/src/test/java/org/eclipse/aether/util/graph/versions/ReleaseVersionFilterTest.java
rename to maven-resolver-util/src/test/java/org/eclipse/aether/util/graph/version/ReleaseVersionFilterTest.java
index bf27548eb..746126cd3 100644
--- a/maven-resolver-util/src/test/java/org/eclipse/aether/util/graph/versions/ReleaseVersionFilterTest.java
+++ b/maven-resolver-util/src/test/java/org/eclipse/aether/util/graph/version/ReleaseVersionFilterTest.java
@@ -16,10 +16,9 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.eclipse.aether.util.graph.versions;
+package org.eclipse.aether.util.graph.version;
import org.eclipse.aether.collection.VersionFilter.VersionFilterContext;
-import org.eclipse.aether.util.graph.version.ReleaseVersionFilter;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
diff --git a/maven-resolver-util/src/test/java/org/eclipse/aether/util/graph/versions/SnapshotVersionFilterTest.java b/maven-resolver-util/src/test/java/org/eclipse/aether/util/graph/version/SnapshotVersionFilterTest.java
similarity index 94%
rename from maven-resolver-util/src/test/java/org/eclipse/aether/util/graph/versions/SnapshotVersionFilterTest.java
rename to maven-resolver-util/src/test/java/org/eclipse/aether/util/graph/version/SnapshotVersionFilterTest.java
index d866ce03d..ccd5fd266 100644
--- a/maven-resolver-util/src/test/java/org/eclipse/aether/util/graph/versions/SnapshotVersionFilterTest.java
+++ b/maven-resolver-util/src/test/java/org/eclipse/aether/util/graph/version/SnapshotVersionFilterTest.java
@@ -16,10 +16,9 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.eclipse.aether.util.graph.versions;
+package org.eclipse.aether.util.graph.version;
import org.eclipse.aether.collection.VersionFilter.VersionFilterContext;
-import org.eclipse.aether.util.graph.version.SnapshotVersionFilter;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
diff --git a/maven-resolver-util/src/test/java/org/eclipse/aether/util/version/GenericQualifiersTest.java b/maven-resolver-util/src/test/java/org/eclipse/aether/util/version/GenericQualifiersTest.java
new file mode 100644
index 000000000..cd8623fbf
--- /dev/null
+++ b/maven-resolver-util/src/test/java/org/eclipse/aether/util/version/GenericQualifiersTest.java
@@ -0,0 +1,87 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.eclipse.aether.util.version;
+
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+
+public class GenericQualifiersTest {
+ private static final int NO_QUALIFIER = Integer.MIN_VALUE;
+
+ @Test
+ void fullCases() {
+ assertEquals(
+ GenericQualifiers.QUALIFIER_ALPHA,
+ GenericQualifiers.qualifier("1-alpha-1").orElse(NO_QUALIFIER));
+ assertEquals(
+ GenericQualifiers.QUALIFIER_ALPHA,
+ GenericQualifiers.qualifier("alpha-1").orElse(NO_QUALIFIER));
+ assertEquals(
+ GenericQualifiers.QUALIFIER_ALPHA,
+ GenericQualifiers.qualifier("1-alpha").orElse(NO_QUALIFIER));
+ assertEquals(
+ GenericQualifiers.QUALIFIER_BETA,
+ GenericQualifiers.qualifier("1-beta").orElse(NO_QUALIFIER));
+ assertEquals(
+ GenericQualifiers.QUALIFIER_MILESTONE,
+ GenericQualifiers.qualifier("milestone").orElse(NO_QUALIFIER));
+ assertEquals(
+ GenericQualifiers.QUALIFIER_MILESTONE,
+ GenericQualifiers.qualifier("1-milestone").orElse(NO_QUALIFIER));
+ assertEquals(
+ GenericQualifiers.QUALIFIER_ZERO,
+ GenericQualifiers.qualifier("1-ga-1").orElse(NO_QUALIFIER));
+ assertEquals(
+ GenericQualifiers.QUALIFIER_ZERO,
+ GenericQualifiers.qualifier("1-final").orElse(NO_QUALIFIER));
+ assertEquals(
+ GenericQualifiers.QUALIFIER_SP,
+ GenericQualifiers.qualifier("1-sp").orElse(NO_QUALIFIER));
+ }
+
+ @Test
+ void shortCases() {
+ // special: alpha, beta and milestone are detected also when in form of "a1" (a, b, or m immediately followed by
+ // number)
+ assertEquals(
+ GenericQualifiers.QUALIFIER_ALPHA,
+ GenericQualifiers.qualifier("1-a1").orElse(NO_QUALIFIER));
+ assertEquals(
+ GenericQualifiers.QUALIFIER_ALPHA,
+ GenericQualifiers.qualifier("a1").orElse(NO_QUALIFIER));
+ assertEquals(
+ GenericQualifiers.QUALIFIER_BETA,
+ GenericQualifiers.qualifier("1-b1").orElse(NO_QUALIFIER));
+ assertEquals(
+ GenericQualifiers.QUALIFIER_MILESTONE,
+ GenericQualifiers.qualifier("1-m1").orElse(NO_QUALIFIER));
+ assertEquals(
+ GenericQualifiers.QUALIFIER_MILESTONE,
+ GenericQualifiers.qualifier("m1").orElse(NO_QUALIFIER));
+ }
+
+ @Test
+ void edgeCases() {
+ assertFalse(GenericQualifiers.qualifier("1.0-arced").isPresent()); // rc
+ assertFalse(GenericQualifiers.qualifier("1.0-legacy").isPresent()); // ga
+ assertFalse(GenericQualifiers.qualifier("1.0-sacred").isPresent()); // cr
+ }
+}