Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use ComparableVersion from Maven and remove the duplicate #898

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -267,7 +267,11 @@
<artifactId>commons-text</artifactId>
<version>1.10.0</version>
</dependency>

<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-collections4</artifactId>
<version>4.4</version>
</dependency>
<dependency>
<groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-utils</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,13 @@

import org.apache.maven.artifact.ArtifactUtils;
import org.apache.maven.artifact.versioning.ArtifactVersion;
import org.apache.maven.artifact.versioning.DefaultArtifactVersion;
import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException;
import org.apache.maven.artifact.versioning.Restriction;
import org.apache.maven.artifact.versioning.VersionRange;
import org.codehaus.mojo.versions.ordering.BoundArtifactVersion;
import org.codehaus.mojo.versions.ordering.InvalidSegmentException;
import org.codehaus.mojo.versions.ordering.VersionComparator;
import org.codehaus.mojo.versions.utils.DefaultArtifactVersionCache;

import static java.util.Collections.reverseOrder;
import static java.util.Optional.empty;
Expand Down Expand Up @@ -123,7 +123,7 @@ public final void setCurrentVersion(ArtifactVersion currentVersion) {

@Override
public final void setCurrentVersion(String currentVersion) {
setCurrentVersion(currentVersion == null ? null : new DefaultArtifactVersion(currentVersion));
setCurrentVersion(currentVersion == null ? null : DefaultArtifactVersionCache.of(currentVersion));
}

@Override
Expand Down Expand Up @@ -194,7 +194,7 @@ private ArtifactVersion[] getNewerVersions(ArtifactVersion version, boolean incl

@Override
public final ArtifactVersion[] getNewerVersions(String version, boolean includeSnapshots) {
return getNewerVersions(new DefaultArtifactVersion(version), includeSnapshots);
return getNewerVersions(DefaultArtifactVersionCache.of(version), includeSnapshots);
}

@Deprecated
Expand All @@ -209,10 +209,10 @@ public final ArtifactVersion[] getNewerVersions(
public final ArtifactVersion[] getNewerVersions(
String versionString, Optional<Segment> unchangedSegment, boolean includeSnapshots, boolean allowDowngrade)
throws InvalidSegmentException {
ArtifactVersion currentVersion = new DefaultArtifactVersion(versionString);
ArtifactVersion currentVersion = DefaultArtifactVersionCache.of(versionString);
ArtifactVersion lowerBound = allowDowngrade
? getLowerBound(currentVersion, unchangedSegment)
.map(DefaultArtifactVersion::new)
.map(DefaultArtifactVersionCache::of)
.orElse(null)
: currentVersion;
ArtifactVersion upperBound = unchangedSegment
Expand All @@ -228,10 +228,10 @@ public final ArtifactVersion[] getNewerVersions(
public Optional<ArtifactVersion> getNewestVersion(
String versionString, Optional<Segment> upperBoundSegment, boolean includeSnapshots, boolean allowDowngrade)
throws InvalidSegmentException {
ArtifactVersion currentVersion = new DefaultArtifactVersion(versionString);
ArtifactVersion currentVersion = DefaultArtifactVersionCache.of(versionString);
ArtifactVersion lowerBound = allowDowngrade
? getLowerBound(currentVersion, upperBoundSegment)
.map(DefaultArtifactVersion::new)
.map(DefaultArtifactVersionCache::of)
.orElse(null)
: currentVersion;
ArtifactVersion upperBound = upperBoundSegment
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,6 @@
import org.apache.maven.artifact.ArtifactUtils;
import org.apache.maven.artifact.resolver.ArtifactResolutionException;
import org.apache.maven.artifact.versioning.ArtifactVersion;
import org.apache.maven.artifact.versioning.DefaultArtifactVersion;
import org.apache.maven.artifact.versioning.Restriction;
import org.apache.maven.artifact.versioning.VersionRange;
import org.apache.maven.execution.MavenSession;
Expand All @@ -73,6 +72,7 @@
import org.codehaus.mojo.versions.model.io.xpp3.RuleXpp3Reader;
import org.codehaus.mojo.versions.ordering.VersionComparator;
import org.codehaus.mojo.versions.ordering.VersionComparators;
import org.codehaus.mojo.versions.utils.DefaultArtifactVersionCache;
import org.codehaus.mojo.versions.utils.DependencyBuilder;
import org.codehaus.mojo.versions.utils.DependencyComparator;
import org.codehaus.mojo.versions.utils.PluginComparator;
Expand Down Expand Up @@ -228,7 +228,7 @@ public ArtifactVersions lookupArtifactVersions(

return false;
}))
.map(v -> new DefaultArtifactVersion(v.toString()))
.map(v -> DefaultArtifactVersionCache.of(v.toString()))
.collect(Collectors.toList()),
getVersionComparator(artifact));
} catch (VersionRangeResolutionException e) {
Expand Down Expand Up @@ -425,7 +425,7 @@ public Set<Artifact> extractArtifacts(Collection<MavenProject> mavenProjects) {

@Override
public ArtifactVersion createArtifactVersion(String version) {
return new DefaultArtifactVersion(version);
return DefaultArtifactVersionCache.of(version);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@
import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.ArtifactUtils;
import org.apache.maven.artifact.versioning.ArtifactVersion;
import org.apache.maven.artifact.versioning.DefaultArtifactVersion;
import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException;
import org.apache.maven.artifact.versioning.OverConstrainedVersionException;
import org.apache.maven.artifact.versioning.Restriction;
Expand All @@ -42,6 +41,7 @@
import org.codehaus.mojo.versions.ordering.BoundArtifactVersion;
import org.codehaus.mojo.versions.ordering.InvalidSegmentException;
import org.codehaus.mojo.versions.ordering.VersionComparator;
import org.codehaus.mojo.versions.utils.DefaultArtifactVersionCache;

import static java.util.Optional.empty;
import static org.codehaus.mojo.versions.api.Segment.SUBINCREMENTAL;
Expand Down Expand Up @@ -306,10 +306,10 @@ public ArtifactVersion getNewestVersion(
property.getVersion() != null ? VersionRange.createFromVersionSpec(property.getVersion()) : null;
helper.getLog().debug("Property ${" + property.getName() + "}: Restricting results to " + range);

ArtifactVersion currentVersion = new DefaultArtifactVersion(versionString);
ArtifactVersion currentVersion = DefaultArtifactVersionCache.of(versionString);
ArtifactVersion lowerBound = allowDowngrade
? getLowerBound(currentVersion, upperBoundSegment)
.map(DefaultArtifactVersion::new)
.map(DefaultArtifactVersionCache::of)
.orElse(null)
: currentVersion;
if (helper.getLog().isDebugEnabled()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@

import java.util.function.Predicate;

import org.apache.maven.artifact.versioning.DefaultArtifactVersion;
import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException;
import org.apache.maven.artifact.versioning.VersionRange;
import org.codehaus.mojo.versions.utils.DefaultArtifactVersionCache;

public class WildcardMatcher implements Predicate<String> {
public static final String WILDCARD = "*";
Expand Down Expand Up @@ -61,7 +61,7 @@ else if (pattern.startsWith("[") || pattern.startsWith("(")) {

private boolean isVersionIncludedInRange(final String version, final String range) {
try {
return VersionRange.createFromVersionSpec(range).containsVersion(new DefaultArtifactVersion(version));
return VersionRange.createFromVersionSpec(range).containsVersion(DefaultArtifactVersionCache.of(version));
} catch (InvalidVersionSpecificationException e) {
return false;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,44 +1,106 @@
package org.codehaus.mojo.versions.ordering;

import java.util.Iterator;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;
import org.apache.maven.artifact.versioning.ArtifactVersion;
import org.apache.maven.artifact.versioning.DefaultArtifactVersion;
import org.codehaus.mojo.versions.api.Segment;

import static org.codehaus.mojo.versions.ordering.ComparableVersion.IntegerItem.ZERO;
import org.codehaus.mojo.versions.utils.DefaultArtifactVersionCache;
import org.codehaus.plexus.util.StringUtils;

/**
* <p>Represents an artifact version with all segments more major or equal to a given segment
* held in place. It can be thought of as an artifact having +&infin; as its upper bound
* on all segments less major than the held segment.</p>
* <p>When compared with another artifact versions, this results with the other object
* <p>Represents an <b>immutable</b> artifact version with all segments <em>major</em> to the given segment
* held in place. It can be thought of as an artifact having +∞ as its upper bound
* on all segments minor to the held segment.</p>
* <p>For example:</p>
* <p>A {@link BoundArtifactVersion} of {@code [1.2.3-2, INCREMENTAL]} can be seen as {@code 1.2.+∞}
* and will be greater than all versions matching the {@code 1.2.*} pattern.</p>
* <p>A {@link BoundArtifactVersion} of {@code [1.2.3-2, SUBINCREMENTAL]} will be greater
* * than all versions matching the {@code 1.2.3-2.*} pattern.</p>
* <p>When compared to another artifact versions, this results with the other object
* with the segment versions up to the held segment being equal,
* always comparing lower than this object.</p>
* <p>This is particularly helpful for -SNAPSHOT and other versions with qualifiers, which
* are lower than version 0 in the Maven versioning system.</p>
*/
public class BoundArtifactVersion extends DefaultArtifactVersion {
public class BoundArtifactVersion implements ArtifactVersion {
/**
* Most major segment that can change, i.e. not held in place.
* All segments that are more major than this one are held in place.
*/
private final Segment segment;

private final BoundComparableVersion comparator;
private final ArtifactVersion comparable;

/**
* Constructs the instance
* Constructs the instance given the version in a text format.
* @param artifactVersion version in a text format
* @param segment most major segment that can change, i.e. <em>not</em> held in place
*/
public BoundArtifactVersion(String artifactVersion, Segment segment) {
Copy link
Contributor Author

@jarmoniuk jarmoniuk Jan 3, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So this is the key method, I guess...

Hope this is clear, looks a bit like first year's comp-sci exercise, but we're simply parsing the version and splitting it to tokens upon:

  • a change from numbers to letters or vice-versa
  • an - character
  • a dot

The newly constructed version will have Inetger.MAX_VALUE on all places less than the fixed segment. Also, all non-strandard tokens will be replaced by zeros (like in the old impl).

this.segment = segment;
StringBuilder versionBuilder = new StringBuilder();
String[] segments = tokens(artifactVersion);
for (int segNr = 0;
segNr <= segments.length || segNr <= Segment.SUBINCREMENTAL.value();
segNr++, versionBuilder.append(".")) {
if (segNr < segment.value()) {
versionBuilder.append(segNr < segments.length ? integerItemOrZero(segments[segNr]) : "0");
} else {
versionBuilder.append(Integer.MAX_VALUE);
}
}
versionBuilder.append(Integer.MAX_VALUE);
comparable = DefaultArtifactVersionCache.of(versionBuilder.toString());
}

/**
* Constructs the instance given a {@link ArtifactVersion instance}
* @param artifactVersion artifact version containing the segment version values
* @param segment most major segment that can change, i.e. <em>not</em> held in place
*/
public BoundArtifactVersion(ArtifactVersion artifactVersion, Segment segment) {
super(artifactVersion.toString());
this.segment = segment;
this.comparator = new BoundComparableVersion(this);
this(artifactVersion.toString(), segment);
}

/**
* Splits the given version string into tokens, splitting them on the {@code .} or {@code -} characters
* as well as on letter/digit boundaries.
* @param version version string
* @return tokens of the parsed version string
*/
private static String[] tokens(String version) {
if (version == null) {
return new String[0];
}
List<String> result = new ArrayList<>();
for (int begin = 0, end = 0; end <= version.length(); end++) {
if (end == version.length()
|| version.charAt(end) == '.'
|| version.charAt(end) == '-'
|| isTokenBoundary(version.charAt(begin), version.charAt(end))) {
if (end > begin) {
result.add(version.substring(begin, end));
}
begin = end + 1;
}
}
return result.toArray(new String[0]);
}

/**
* @param c1 character
* @param c2 another character
* @return will only return {@code true} if one of the characters is a digit and the other a letter
*/
private static boolean isTokenBoundary(char c1, char c2) {
return Character.isDigit(c1) ^ Character.isDigit(c2);
}

private static String integerItemOrZero(String item) {
return StringUtils.isNumeric(item) ? item : "0";
}

/**
Expand All @@ -56,7 +118,7 @@ public int compareTo(ArtifactVersion other) {
return -1;
}

return comparator.compareTo(ComparableVersion.of(other.toString()));
return comparable.compareTo(other);
}

@Override
Expand All @@ -74,7 +136,7 @@ public boolean equals(Object o) {
return new EqualsBuilder()
.appendSuper(super.equals(o))
.append(getSegment(), that.getSegment())
.append(comparator, that.comparator)
.append(comparable, that.comparable)
.isEquals();
}

Expand All @@ -83,48 +145,42 @@ public int hashCode() {
return new HashCodeBuilder(17, 37)
.appendSuper(super.hashCode())
.append(getSegment())
.append(comparator)
.append(comparable)
.toHashCode();
}

protected static class BoundComparableVersion extends ComparableVersion {
private BoundArtifactVersion artifactVersion;

protected BoundComparableVersion(BoundArtifactVersion artifactVersion) {
super(artifactVersion.toString());
this.artifactVersion = artifactVersion;
}

@Override
public int compareTo(ComparableVersion o) {
// all segments more or equally major than artifactVersion.segment can change
return compareTo(
((List<Item>) items).iterator(),
((Iterable<Item>) o.items).iterator(),
artifactVersion.segment.value());
}
@Override
public int getMajorVersion() {
return comparable.getMajorVersion();
}

private int compareTo(Iterator<Item> left, Iterator<Item> right, int comparisonsLeft) {
if (comparisonsLeft <= 0) {
// always greater than the other version if all more major segments are equal
return 1;
}
@Override
public int getMinorVersion() {
return comparable.getMinorVersion();
}

int result = left.hasNext() && right.hasNext()
? integerItemOrZero(left.next()).compareTo(right.next())
: left.hasNext() || right.hasNext() ? compareToZero(left, right) : 1;
@Override
public int getIncrementalVersion() {
return comparable.getIncrementalVersion();
}

return result != 0 ? result : compareTo(left, right, comparisonsLeft - 1);
}
@Override
public int getBuildNumber() {
return comparable.getBuildNumber();
}

private static int compareToZero(Iterator<Item> left, Iterator<Item> right) {
return left.hasNext()
? integerItemOrZero(left.next()).compareTo(ZERO)
: -right.next().compareTo(ZERO);
}
@Override
public String getQualifier() {
return comparable.getQualifier();
}

private static Item integerItemOrZero(Item item) {
return item instanceof IntegerItem ? item : ZERO;
}
/**
* @deprecated do not use: this method would mutate the state and therefore is illegal to use
* @throws UnsupportedOperationException thrown if the method is called
*/
@Override
@Deprecated
public void parseVersion(String version) {
throw new UnsupportedOperationException();
}
}
Loading