com.github.zafarkhaja.semver.Version Maven / Gradle / Ivy
Show all versions of java-semver Show documentation
/*
* The MIT License
*
* Copyright 2012-2024 Zafar Khaja .
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.github.zafarkhaja.semver;
import com.github.zafarkhaja.semver.expr.Expression;
import com.github.zafarkhaja.semver.expr.ExpressionParser;
import java.io.InvalidObjectException;
import java.io.ObjectInputStream;
import java.io.Serializable;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Locale;
import java.util.Optional;
import java.util.function.Predicate;
import static com.github.zafarkhaja.semver.Version.Validators.*;
import static com.github.zafarkhaja.semver.VersionParser.parseBuild;
import static com.github.zafarkhaja.semver.VersionParser.parsePreRelease;
/**
* A representation of version as defined by the SemVer Specification.
*
* The {@code Version} class is immutable and thread-safe.
*
* @author Zafar Khaja {@literal }
* @since 0.1.0
*/
@SuppressWarnings("serial")
public class Version implements Comparable, Serializable {
/**
* A mutable builder for the immutable {@code Version} class
*/
public static class Builder {
private long major = 0;
private long minor = 0;
private long patch = 0;
private String[] preReleaseIds = {};
private String[] buildIds = {};
/**
* Default constructor, initializes fields with default values (0.0.0)
*/
public Builder() {}
/**
* Sets the major version; the minor and patch versions are assigned 0.
*
* @param major a major version number, non-negative
* @return this {@code Builder} instance
* @throws IllegalArgumentException if {@code major} is negative
* @since 0.10.0
*/
public Builder setVersionCore(long major) {
return setVersionCore(major, 0, 0);
}
/**
* Sets the major and minor versions; the patch version is assigned 0.
*
* @param major a major version number, non-negative
* @param minor a minor version number, non-negative
* @return this {@code Builder} instance
* @throws IllegalArgumentException if any of the arguments is negative
* @since 0.10.0
*/
public Builder setVersionCore(long major, long minor) {
return setVersionCore(major, minor, 0);
}
/**
* Sets major, minor and patch versions.
*
* @param major a major version number, non-negative
* @param minor a minor version number, non-negative
* @param patch a patch version number, non-negative
* @return this {@code Builder} instance
* @throws IllegalArgumentException if any of the arguments is negative
* @since 0.10.0
*/
public Builder setVersionCore(long major, long minor, long patch) {
return
setMajorVersion(major).
setMinorVersion(minor).
setPatchVersion(patch)
;
}
/**
* Sets the major version.
*
* @param major a major version number, non-negative
* @return this {@code Builder} instance
* @throws IllegalArgumentException if {@code major} is negative
* @since 0.10.0
*/
public Builder setMajorVersion(long major) {
this.major = nonNegative(major, "major");
return this;
}
/**
* Sets the minor version.
*
* @param minor a minor version number, non-negative
* @return this {@code Builder} instance
* @throws IllegalArgumentException if {@code minor} is negative
* @since 0.10.0
*/
public Builder setMinorVersion(long minor) {
this.minor = nonNegative(minor, "minor");
return this;
}
/**
* Sets the patch version.
*
* @param patch a patch version number, non-negative
* @return this {@code Builder} instance
* @throws IllegalArgumentException if {@code patch} is negative
* @since 0.10.0
*/
public Builder setPatchVersion(long patch) {
this.patch = nonNegative(patch, "patch");
return this;
}
/**
* Sets the pre-release version.
*
* Multiple identifiers can be specified in a single argument joined
* with dots, or in separate arguments, or both.
*
* @param ids one or more pre-release identifiers, non-null
* @return this {@code Builder} instance
* @throws IllegalArgumentException if {@code ids} is null/empty or contains null
*/
public Builder setPreReleaseVersion(String... ids) {
preReleaseIds = oneOrMoreNonNulls(ids, "ids").clone();
return this;
}
/**
* Appends (additional) pre-release identifier(s).
*
* If no pre-release identifiers have been previously set, the method
* works as {@link #setPreReleaseVersion(String...)}.
*
* Multiple identifiers can be specified in a single argument joined
* with dots, or in separate arguments, or both.
*
* @param ids one or more pre-release identifiers, non-null
* @return this {@code Builder} instance
* @throws IllegalArgumentException if {@code ids} is null/empty or contains null
* @see #setPreReleaseVersion(String...)
* @since 0.10.0
*/
public Builder addPreReleaseIdentifiers(String... ids) {
if (preReleaseIds.length == 0) {
return setPreReleaseVersion(ids);
}
preReleaseIds = concatArrays(preReleaseIds, oneOrMoreNonNulls(ids, "ids"));
return this;
}
/**
* Unsets the pre-release version.
*
* @return this {@code Builder} instance
* @since 0.10.0
*/
public Builder unsetPreReleaseVersion() {
preReleaseIds = new String[0];
return this;
}
/**
* Sets the build metadata.
*
* Multiple identifiers can be specified in a single argument joined
* with dots, or in separate arguments, or both.
*
* @param ids one or more build identifiers, non-null
* @return this {@code Builder} instance
* @throws IllegalArgumentException if {@code ids} is null/empty or contains null
*/
public Builder setBuildMetadata(String... ids) {
buildIds = oneOrMoreNonNulls(ids, "ids").clone();
return this;
}
/**
* Appends (additional) build identifier(s).
*
* If no build identifiers have been previously set, the method works as
* {@link #setBuildMetadata(String...)}.
*
* Multiple identifiers can be specified in a single argument joined
* with dots, or in separate arguments, or both.
*
* @param ids one or more build identifiers, non-null
* @return this {@code Builder} instance
* @throws IllegalArgumentException if {@code ids} is null/empty or contains null
* @see #setBuildMetadata(String...)
* @since 0.10.0
*/
public Builder addBuildIdentifiers(String... ids) {
if (buildIds.length == 0) {
return setBuildMetadata(ids);
}
buildIds = concatArrays(buildIds, oneOrMoreNonNulls(ids, "ids"));
return this;
}
/**
* Unsets the build metadata.
*
* @return this {@code Builder} instance
* @since 0.10.0
*/
public Builder unsetBuildMetadata() {
buildIds = new String[0];
return this;
}
/**
* Obtains a {@code Version} instance with previously set values.
*
* @return a {@code Version} instance
* @throws ParseException if any of the previously set identifiers can't be parsed
* @see Version#of(long, long, long, String, String)
*/
public Version build() {
return Version.of(
major,
minor,
patch,
joinIdentifiers(preReleaseIds),
joinIdentifiers(buildIds)
);
}
private static String[] concatArrays(String[] ids1, String[] ids2) {
String[] ids = new String[ids1.length + ids2.length];
System.arraycopy(ids1, 0, ids, 0, ids1.length);
System.arraycopy(ids2, 0, ids, ids1.length, ids2.length);
return ids;
}
/**
* @deprecated forRemoval since 0.10.0
*
* @param normal a string representing a normal version, non-null
* @throws IllegalArgumentException if (@code normal) is null
*/
@Deprecated
public Builder(String normal) {
setNormalVersion(normal);
}
/**
* @deprecated forRemoval since 0.10.0
*
* @param normal a string representing a normal version, non-null
* @return this {@code Builder} instance
* @throws IllegalArgumentException if (@code normal) is null
*/
@Deprecated
@SuppressWarnings("DeprecatedIsStillUsed")
public Builder setNormalVersion(String normal) {
String[] parts = nonNull(normal, "normal").split("\\" + IDENTIFIER_SEPARATOR);
return setVersionCore(
Long.parseLong(parts[0]),
parts.length > 1 ? Long.parseLong(parts[1]) : 0,
parts.length > 2 ? Long.parseLong(parts[2]) : 0
);
}
}
/**
* A comparator that sorts versions in increment order, from lowest to highest.
*
* The comparator is intended for use in comparison-based data structures.
*
* @see #compareToIgnoreBuildMetadata(Version)
* @since 0.10.0
*/
public static final Comparator INCREMENT_ORDER = Version::compareToIgnoreBuildMetadata;
/**
* A comparator that sorts versions in (highest) precedence order.
*
* The ordering imposed by this comparator is reverse of the "natural"
* increment ordering, that is, versions are arranged in descending order
* from highest-precedence to lowest-precedence.
*
* The comparator is intended for use in comparison-based data structures.
*
* @see #INCREMENT_ORDER
* @since 0.10.0
*/
public static final Comparator PRECEDENCE_ORDER = INCREMENT_ORDER.reversed();
private final long major;
private final long minor;
private final long patch;
private final String[] preReleaseIds;
private final String[] buildIds;
private static final String IDENTIFIER_SEPARATOR = ".";
private static final String PRE_RELEASE_PREFIX = "-";
private static final String BUILD_PREFIX = "+";
/**
* @see #Version(long, long, long, String[], String[]) for documentation
*/
Version(long major, long minor, long patch) {
this(major, minor, patch, new String[0], new String[0]);
}
/**
* @see #Version(long, long, long, String[], String[]) for documentation
*/
Version(long major, long minor, long patch, String[] preReleaseIds) {
this(major, minor, patch, preReleaseIds, new String[0]);
}
/**
* Package-private constructor, for internal use only.
*
* @param major a major version number, non-negative
* @param minor a minor version number, non-negative
* @param patch a patch version number, non-negative
* @param preReleaseIds the pre-release identifiers, non-null
* @param buildIds the build identifiers, non-null
* @throws IllegalArgumentException if any of the numeric arguments is negative,
* or if any of the reference-type arguments is null
*/
Version(long major, long minor, long patch, String[] preReleaseIds, String[] buildIds) {
this.major = nonNegative(major, "major");
this.minor = nonNegative(minor, "minor");
this.patch = nonNegative(patch, "patch");
this.preReleaseIds = nonNull(preReleaseIds, "preReleaseIds").clone();
this.buildIds = nonNull(buildIds, "buildIds").clone();
}
/**
* Obtains a {@code Version} instance by parsing the specified string in
* strict mode, which ensures full compliance with the specification.
*
* @param version a string representing a SemVer version, non-null
* @return a {@code Version} instance
* @throws IllegalArgumentException if {@code version} is null
* @throws ParseException if {@code version} can't be parsed
* @see #parse(String, boolean)
* @since 0.10.0
*/
public static Version parse(String version) {
return parse(version, true);
}
/**
* Obtains a {@code Version} instance by parsing the specified string.
*
* This method provides a way to parse the specified string in lenient mode,
* which accepts shorter version cores, such as "1" or "1.2".
*
* @param version a string representing a SemVer version, non-null
* @param strictly whether to parse the specified string in strict mode
* @return a {@code Version} instance
* @throws IllegalArgumentException if {@code version} is null
* @throws ParseException if {@code version} can't be parsed
* @see #parse(String)
* @since 0.10.0
*/
public static Version parse(String version, boolean strictly) {
return VersionParser.parseValidSemVer(nonNull(version, "version"), strictly);
}
/**
* Tries to obtain a {@code Version} instance by parsing the specified string
* in strict mode, which ensures full compliance with the specification.
*
* @param version a string representing a SemVer version, nullable
* @return an {@code Optional} with a {@code Version} instance, if the
* specified string can be parsed; empty {@code Optional} otherwise
* @see #tryParse(String, boolean)
* @since 0.10.0
*/
public static Optional tryParse(String version) {
return tryParse(version, true);
}
/**
* Tries to obtain a {@code Version} instance by parsing the specified string.
*
* This method provides a way to parse the specified string in lenient mode,
* which accepts shorter version cores, such as "1" or "1.2".
*
* @param version a string representing a SemVer version, nullable
* @param strictly whether to parse the specified string in strict mode
* @return an {@code Optional} with a {@code Version} instance, if the
* specified string can be parsed; empty {@code Optional} otherwise
* @see #tryParse(String)
* @since 0.10.0
*/
public static Optional tryParse(String version, boolean strictly) {
try {
return Optional.of(Version.parse(version, strictly));
} catch (RuntimeException e) {
return Optional.empty();
}
}
/**
* Checks validity of the specified SemVer version string in strict mode,
* which ensures full compliance with the specification.
*
* Note that internally this method makes use of {@link #parse(String)} and
* suppresses any exceptions, so using it to avoid dealing with exceptions
* like so:
*
*
{@code
* String version = "1.2.3";
* if (Version.isValid(version)) {
* Version v = Version.parse(version);
* }
* }
*
* would mean parsing the same version string twice. In this case, as an
* alternative, consider using {@link #tryParse(String)}.
*
* @param version a string representing a SemVer version, nullable
* @return {@code true}, if the specified string is a valid SemVer version;
* {@code false} otherwise
* @see #isValid(String, boolean)
* @since 0.10.0
*/
public static boolean isValid(String version) {
return isValid(version, true);
}
/**
* Checks validity of the specified SemVer version string.
*
* This method provides a way to parse the specified string in lenient mode,
* which accepts shorter version cores, such as "1" or "1.2".
*
* @param version a string representing a SemVer version, nullable
* @param strictly whether to parse the specified string in strict mode
* @return {@code true}, if the specified string is a valid SemVer version;
* {@code false} otherwise
* @see #isValid(String)
* @since 0.10.0
*/
public static boolean isValid(String version, boolean strictly) {
return tryParse(version, strictly).isPresent();
}
/**
* Obtains a {@code Version} instance of the specified major version.
*
* @param major a major version number, non-negative
* @return a {@code Version} instance
* @throws IllegalArgumentException if {@code major} is negative
* @since 0.10.0
*/
public static Version of(long major) {
return Version.of(major, 0, 0, null, null);
}
/**
* Obtains a {@code Version} instance of the specified major and pre-release
* versions.
*
* @param major a major version number, non-negative
* @param preRelease a pre-release version label, nullable
* @return a {@code Version} instance
* @throws IllegalArgumentException if {@code major} is negative
* @throws ParseException if {@code preRelease} can't be parsed
* @since 0.10.0
*/
public static Version of(long major, String preRelease) {
return Version.of(major, 0, 0, preRelease, null);
}
/**
* Obtains a {@code Version} instance of the specified major and pre-release
* versions, as well as build metadata.
*
* @param major a major version number, non-negative
* @param preRelease a pre-release version label, nullable
* @param build a build metadata label, nullable
* @return a {@code Version} instance
* @throws IllegalArgumentException if {@code major} is negative
* @throws ParseException if {@code preRelease} or {@code build} can't be parsed
* @since 0.10.0
*/
public static Version of(long major, String preRelease, String build) {
return Version.of(major, 0, 0, preRelease, build);
}
/**
* Obtains a {@code Version} instance of the specified major and minor versions.
*
* @param major a major version number, non-negative
* @param minor a minor version number, non-negative
* @return a {@code Version} instance
* @throws IllegalArgumentException if {@code major} or {@code minor} is negative
* @since 0.10.0
*/
public static Version of(long major, long minor) {
return Version.of(major, minor, 0, null, null);
}
/**
* Obtains a {@code Version} instance of the specified major, minor and
* pre-release versions.
*
* @param major a major version number, non-negative
* @param minor a minor version number, non-negative
* @param preRelease a pre-release version label, nullable
* @return a {@code Version} instance
* @throws IllegalArgumentException if {@code major} or {@code minor} is negative
* @throws ParseException if {@code preRelease} can't be parsed
* @since 0.10.0
*/
public static Version of(long major, long minor, String preRelease) {
return Version.of(major, minor, 0, preRelease, null);
}
/**
* Obtains a {@code Version} instance of the specified major, minor and
* pre-release versions, as well as build metadata.
*
* @param major a major version number, non-negative
* @param minor a minor version number, non-negative
* @param preRelease a pre-release version label, nullable
* @param build a build metadata label, nullable
* @return a {@code Version} instance
* @throws IllegalArgumentException if {@code major} or {@code minor} is negative
* @throws ParseException if {@code preRelease} or {@code build} can't be parsed
* @since 0.10.0
*/
public static Version of(long major, long minor, String preRelease, String build) {
return Version.of(major, minor, 0, preRelease, build);
}
/**
* Obtains a {@code Version} instance of the specified major, minor and
* patch versions.
*
* @param major a major version number, non-negative
* @param minor a minor version number, non-negative
* @param patch a patch version number, non-negative
* @return a {@code Version} instance
* @throws IllegalArgumentException if any of the arguments is negative
* @since 0.10.0
*/
public static Version of(long major, long minor, long patch) {
return Version.of(major, minor, patch, null, null);
}
/**
* Obtains a {@code Version} instance of the specified major, minor, patch
* and pre-release versions.
*
* @param major a major version number, non-negative
* @param minor a minor version number, non-negative
* @param patch a patch version number, non-negative
* @param preRelease a pre-release version label, nullable
* @return a {@code Version} instance
* @throws IllegalArgumentException if any of the numeric arguments is negative
* @throws ParseException if {@code preRelease} can't be parsed
* @since 0.10.0
*/
public static Version of(long major, long minor, long patch, String preRelease) {
return Version.of(major, minor, patch, preRelease, null);
}
/**
* Obtains a {@code Version} instance of the specified major, minor, patch
* and pre-release versions, as well as build metadata.
*
* @param major a major version number, non-negative
* @param minor a minor version number, non-negative
* @param patch a patch version number, non-negative
* @param preRelease a pre-release version label, nullable
* @param build a build metadata label, nullable
* @return a {@code Version} instance
* @throws IllegalArgumentException if any of the numeric arguments is negative
* @throws ParseException if {@code preRelease} or {@code build} can't be parsed
* @since 0.10.0
*/
public static Version of(long major, long minor, long patch, String preRelease, String build) {
return new Version(
major,
minor,
patch,
preRelease == null ? new String[0] : parsePreRelease(preRelease),
build == null ? new String[0] : parseBuild(build)
);
}
/**
* Returns this {@code Version}'s major version.
*
* @return the major version number
* @since 0.10.0
*/
public long majorVersion() {
return major;
}
/**
* Returns this {@code Version}'s minor version.
*
* @return the minor version number
* @since 0.10.0
*/
public long minorVersion() {
return minor;
}
/**
* Returns this {@code Version}'s patch version.
*
* @return the patch version number
* @since 0.10.0
*/
public long patchVersion() {
return patch;
}
/**
* Returns this {@code Version}'s pre-release version in the form of
* dot-separated identifiers.
*
* @return the pre-release version label, if present
* @since 0.10.0
*/
public Optional preReleaseVersion() {
return Optional.ofNullable(joinIdentifiers(preReleaseIds));
}
/**
* Returns this {@code Version}'s build metadata in the form of
* dot-separated identifiers.
*
* @return the build metadata label, if present
* @since 0.10.0
*/
public Optional buildMetadata() {
return Optional.ofNullable(joinIdentifiers(buildIds));
}
/**
* Obtains the next {@code Version} by incrementing the major version number
* by one, with an optional pre-release version label.
*
* Multiple identifiers can be specified in a single argument joined with
* dots, or in separate arguments, or both.
*
* This method drops the build metadata, if present.
*
* @param preReleaseIds zero or more pre-release identifiers, non-null
* @return a {@code Version} instance
* @throws ArithmeticException if the major version number overflows
* @throws IllegalArgumentException if {@code preReleaseIds} is null or contains null
* @throws ParseException if any of the specified identifiers can't be parsed
* @since 0.10.0
*/
public Version nextMajorVersion(String... preReleaseIds) {
return nextMajorVersion(safeIncrement(major), preReleaseIds);
}
/**
* Obtains the next {@code Version} of the specified major version number,
* with an optional pre-release version label.
*
* The specified major version number must be higher than this {@code Version}'s
* major version.
*
* Multiple identifiers can be specified in a single argument joined with
* dots, or in separate arguments, or both.
*
* This method drops the build metadata, if present.
*
* @param major the next major version number, non-negative
* @param preReleaseIds zero or more pre-release identifiers, non-null
* @return a {@code Version} instance
* @throws IllegalArgumentException if {@code major} is negative, or if
* {@code preReleaseIds} is null or contains null
* @throws IllegalStateException if {@code major} is lower than or equivalent
* to this {@code Version}'s major version
* @throws ParseException if any of the specified identifiers can't be parsed
* @since 0.10.0
*/
public Version nextMajorVersion(long major, String... preReleaseIds) {
if (this.major >= nonNegative(major, "major")) {
throw new IllegalStateException("This major version is higher or equivalent");
}
String preRelease = joinIdentifiers(zeroOrMoreNonNulls(preReleaseIds, "preReleaseIds"));
return Version.of(major, 0, 0, preRelease);
}
/**
* Obtains the next {@code Version} by incrementing the minor version number
* by one, with an optional pre-release version label.
*
* Multiple identifiers can be specified in a single argument joined with
* dots, or in separate arguments, or both.
*
* This method drops the build metadata, if present.
*
* @param preReleaseIds zero or more pre-release identifiers, non-null
* @return a {@code Version} instance
* @throws ArithmeticException if the minor version number overflows
* @throws IllegalArgumentException if {@code preReleaseIds} is null or contains null
* @throws ParseException if any of the specified identifiers can't be parsed
* @since 0.10.0
*/
public Version nextMinorVersion(String... preReleaseIds) {
return nextMinorVersion(safeIncrement(minor), preReleaseIds);
}
/**
* Obtains the next {@code Version} of the specified minor version number,
* with an optional pre-release version label.
*
* The specified minor version number must be higher than this {@code Version}'s
* minor version.
*
* Multiple identifiers can be specified in a single argument joined with
* dots, or in separate arguments, or both.
*
* This method drops the build metadata, if present.
*
* @param minor the next minor version number, non-negative
* @param preReleaseIds zero or more pre-release identifiers, non-null
* @return a {@code Version} instance
* @throws IllegalArgumentException if {@code minor} is negative, or if
* {@code preReleaseIds} is null or contains null
* @throws IllegalStateException if {@code minor} is lower than or equivalent
* to this {@code Version}'s minor version
* @throws ParseException if any of the specified identifiers can't be parsed
* @since 0.10.0
*/
public Version nextMinorVersion(long minor, String... preReleaseIds) {
if (this.minor >= nonNegative(minor, "minor")) {
throw new IllegalStateException("This minor version is higher or equivalent");
}
String preRelease = joinIdentifiers(zeroOrMoreNonNulls(preReleaseIds, "preReleaseIds"));
return Version.of(major, minor, 0, preRelease);
}
/**
* Obtains the next {@code Version} by incrementing the patch version number
* by one, with an optional pre-release version label.
*
* Multiple identifiers can be specified in a single argument joined with
* dots, or in separate arguments, or both.
*
* This method drops the build metadata, if present.
*
* @param preReleaseIds zero or more pre-release identifiers, non-null
* @return a {@code Version} instance
* @throws ArithmeticException if the patch version number overflows
* @throws IllegalArgumentException if {@code preReleaseIds} is null or contains null
* @throws ParseException if any of the specified identifiers can't be parsed
* @since 0.10.0
*/
public Version nextPatchVersion(String... preReleaseIds) {
return nextPatchVersion(safeIncrement(patch), preReleaseIds);
}
/**
* Obtains the next {@code Version} of the specified patch version number,
* with an optional pre-release version label.
*
* The specified patch version number must be higher than this {@code Version}'s
* patch version.
*
* Multiple identifiers can be specified in a single argument joined with
* dots, or in separate arguments, or both.
*
* This method drops the build metadata, if present.
*
* @param patch the next patch version number, non-negative
* @param preReleaseIds zero or more pre-release identifiers, non-null
* @return a {@code Version} instance
* @throws IllegalArgumentException if {@code patch} is negative, or if
* {@code preReleaseIds} is null or contains null
* @throws IllegalStateException if {@code patch} is lower than or equivalent
* to this {@code Version}'s patch version
* @throws ParseException if any of the specified identifiers can't be parsed
* @since 0.10.0
*/
public Version nextPatchVersion(long patch, String... preReleaseIds) {
if (this.patch >= nonNegative(patch, "patch")) {
throw new IllegalStateException("This patch version is higher or equivalent");
}
String preRelease = joinIdentifiers(zeroOrMoreNonNulls(preReleaseIds, "preReleaseIds"));
return Version.of(major, minor, patch, preRelease);
}
/**
* Obtains the next {@code Version} by incrementing or replacing the
* pre-release version.
*
* If no pre-release identifiers are specified, the current pre-release
* version's last numeric identifier is incremented. If the current
* pre-release version's last identifier is not numeric, a new numeric
* identifier of value "0" is appended for this operation. If specified,
* however, the pre-release identifiers replace the current pre-release
* version. The new pre-release version must be higher than this
* {@code Version}'s pre-release version.
*
* Multiple identifiers can be specified in a single argument joined with
* dots, or in separate arguments, or both.
*
* This method drops the build metadata, if present.
*
* @param ids zero or more pre-release identifiers, non-null
* @return a {@code Version} instance
* @throws ArithmeticException if the incremented numeric identifier overflows
* @throws IllegalArgumentException if {@code ids} is null or contains null
* @throws IllegalStateException if invoked on a stable {@code Version}, or
* if the specified pre-release version is lower than or equivalent
* to this {@code Version}'s pre-release version
* @throws ParseException if any of the specified identifiers can't be parsed
* @since 0.10.0
*/
public Version nextPreReleaseVersion(String... ids) {
if (!isPreRelease()) {
throw new IllegalStateException("Not a pre-release version");
}
zeroOrMoreNonNulls(ids, "ids");
String[] newPreReleaseIds;
if (ids.length > 0) {
newPreReleaseIds = parsePreRelease(joinIdentifiers(ids));
if (compareIdentifierArrays(preReleaseIds, newPreReleaseIds) >= 0) {
throw new IllegalStateException("This pre-release version is higher or equivalent");
}
} else {
newPreReleaseIds = incrementIdentifiers(preReleaseIds);
}
return new Version(major, minor, patch, newPreReleaseIds);
}
/**
* Obtains the next {@code Version} by dropping the pre-release version.
*
* This method drops the build metadata, if present.
*
* @return a {@code Version} instance
* @since 0.10.0
*/
public Version toStableVersion() {
return isStable() ? this : new Version(major, minor, patch);
}
/**
* Obtains a new {@code Version} with the specified build identifiers.
*
* Multiple identifiers can be specified in a single argument joined with
* dots, or in separate arguments, or both.
*
* @param ids one or more build identifiers, non-null
* @return a {@code Version} instance
* @throws IllegalArgumentException if {@code ids} is null/empty or contains null
* @throws ParseException if any of the specified identifiers can't be parsed
* @since 0.10.0
*/
public Version withBuildMetadata(String... ids) {
String[] newBuildIds = parseBuild(joinIdentifiers(oneOrMoreNonNulls(ids, "ids")));
return new Version(major, minor, patch, preReleaseIds, newBuildIds);
}
/**
* Obtains a (new) {@code Version} without build metadata.
*
* @return a {@code Version} instance
* @since 0.10.0
*/
public Version withoutBuildMetadata() {
return !buildMetadata().isPresent() ? this : new Version(major, minor, patch, preReleaseIds);
}
/**
* Checks if this {@code Version} satisfies the specified predicate.
*
* @param predicate a predicate to test, non-null
* @return {@code true}, if this {@code Version} satisfies the predicate;
* {@code false} otherwise
* @throws IllegalArgumentException if {@code predicate} is null
* @since 0.10.0
*/
public boolean satisfies(Predicate predicate) {
return nonNull(predicate, "predicate").test(this);
}
/**
* Checks if this {@code Version} satisfies the specified range expression.
*
* @param expr a SemVer Expression string, non-null
* @return {@code true}, if this {@code Version} satisfies the specified
* expression; {@code false} otherwise
* @throws IllegalArgumentException if {@code expr} is null
* @throws ParseException if {@code expr} can't be parsed
* @since 0.7.0
*/
public boolean satisfies(String expr) {
Parser parser = ExpressionParser.newInstance();
return satisfies(parser.parse(nonNull(expr, "expr")));
}
/**
* Checks if this {@code Version} represents a pre-release version.
*
* This method is opposite of {@link #isStable()}.
*
* @return {@code true}, if this {@code Version} represents a pre-release
* version; {@code false} otherwise
* @see #isStable()
* @since 0.10.0
*/
public boolean isPreRelease() {
return preReleaseVersion().isPresent();
}
/**
* Checks if this {@code Version} represents a stable version.
*
* Pre-release versions are considered unstable. (SemVer p.9)
*
* @return {@code true}, if this {@code Version} represents a stable
* version; {@code false} otherwise
* @see #isPreRelease()
* @since 0.10.0
*/
public boolean isStable() {
return !isPreRelease();
}
/**
* Checks if this {@code Version} represents a stable public API.
*
* Versions lower than 1.0.0 are for initial development, therefore the
* public API should not be considered stable. (SemVer p.4)
*
* @return {@code true}, if this {@code Version} represents a stable public
* API; {@code false} otherwise
* @since 0.10.0
*/
public boolean isPublicApiStable() {
return isHigherThanOrEquivalentTo(Version.of(1));
}
/**
* Checks if this {@code Version} is compatible with the specified {@code Version}
* in terms of their public API.
*
* Two versions are compatible in terms of public API iff they have the
* same major version of 1 or higher. Being public API compatible doesn't
* necessarily mean both versions have the same set of public API units.
* It only means that the versions are interchangeable.
*
* @param other the {@code Version} to compare with, non-null
* @return {@code true}, if the versions are compatible in terms of public API;
* {@code false} otherwise
* @throws IllegalArgumentException if {@code other} is null
* @since 0.10.0
*/
public boolean isPublicApiCompatibleWith(Version other) {
return isPublicApiStable() && isSameMajorVersionAs(other);
}
/**
* Checks if this {@code Version} is compatible with the specified {@code Version}
* in terms of their major versions.
*
* @param other the {@code Version} to compare with, non-null
* @return {@code true}, if both versions have the same major version;
* {@code false} otherwise
* @throws IllegalArgumentException if {@code other} is null
* @since 0.10.0
*/
public boolean isSameMajorVersionAs(Version other) {
nonNull(other, "other");
return major == other.major;
}
/**
* Checks if this {@code Version} is compatible with the specified {@code Version}
* in terms of their major and minor versions.
*
* @param other the {@code Version} to compare with, non-null
* @return {@code true}, if both versions have the same major and minor versions;
* {@code false} otherwise
* @throws IllegalArgumentException if {@code other} is null
* @since 0.10.0
*/
public boolean isSameMinorVersionAs(Version other) {
nonNull(other, "other");
return major == other.major && minor == other.minor;
}
/**
* Checks if this {@code Version} is compatible with the specified {@code Version}
* in terms of their major, minor and patch versions.
*
* @param other the {@code Version} to compare with, non-null
* @return {@code true}, if both versions have the same major, minor and patch
* versions; {@code false} otherwise
* @throws IllegalArgumentException if {@code other} is null
* @since 0.10.0
*/
public boolean isSamePatchVersionAs(Version other) {
nonNull(other, "other");
return major == other.major && minor == other.minor && patch == other.patch;
}
/**
* Determines if this {@code Version} has a higher precedence compared with
* the specified {@code Version}.
*
* @param other the {@code Version} to compare with, non-null
* @return {@code true}, if this {@code Version} is higher than the other
* {@code Version}; {@code false} otherwise
* @throws IllegalArgumentException if {@code other} is null
* @see #compareToIgnoreBuildMetadata(Version)
* @since 0.10.0
*/
public boolean isHigherThan(Version other) {
return compareToIgnoreBuildMetadata(other) > 0;
}
/**
* Determines if this {@code Version} has a higher or equal precedence
* compared with the specified {@code Version}.
*
* @param other the {@code Version} to compare with, non-null
* @return {@code true}, if this {@code Version} is higher than or equivalent
* to the other {@code Version}; {@code false} otherwise
* @throws IllegalArgumentException if {@code other} is null
* @see #compareToIgnoreBuildMetadata(Version)
* @since 0.10.0
*/
public boolean isHigherThanOrEquivalentTo(Version other) {
return compareToIgnoreBuildMetadata(other) >= 0;
}
/**
* Determines if this {@code Version} has a lower precedence compared with
* the specified {@code Version}.
*
* @param other the {@code Version} to compare with, non-null
* @return {@code true}, if this {@code Version} is lower than the other
* {@code Version}; {@code false} otherwise
* @throws IllegalArgumentException if {@code other} is null
* @see #compareToIgnoreBuildMetadata(Version)
* @since 0.10.0
*/
public boolean isLowerThan(Version other) {
return compareToIgnoreBuildMetadata(other) < 0;
}
/**
* Determines if this {@code Version} has a lower or equal precedence
* compared with the specified {@code Version}.
*
* @param other the {@code Version} to compare with, non-null
* @return {@code true}, if this {@code Version} is lower than or equivalent
* to the other {@code Version}; {@code false} otherwise
* @throws IllegalArgumentException if {@code other} is null
* @see #compareToIgnoreBuildMetadata(Version)
* @since 0.10.0
*/
public boolean isLowerThanOrEquivalentTo(Version other) {
return compareToIgnoreBuildMetadata(other) <= 0;
}
/**
* Determines if this {@code Version} has the same precedence as the
* specified {@code Version}.
*
* As per SemVer p.10, build metadata is ignored when determining version
* precedence. To test for exact equality, including build metadata, use
* {@link #equals(Object)}.
*
* @param other the {@code Version} to compare with, non-null
* @return {@code true}, if this {@code Version} is equivalent to the other
* {@code Version}; {@code false} otherwise
* @throws IllegalArgumentException if {@code other} is null
* @see #compareToIgnoreBuildMetadata(Version)
* @since 0.10.0
*/
public boolean isEquivalentTo(Version other) {
return compareToIgnoreBuildMetadata(other) == 0;
}
/**
* Compares versions, along with their build metadata.
*
* Note that this method violates the SemVer p.10 ("build metadata must be
* ignored") rule, hence can't be used for determining version precedence.
* It was made so intentionally for it to be consistent with {@code equals}
* as defined by {@link Comparable}, and to be used in comparison-based data
* structures.
*
* As the Specification defines no comparison rules for build metadata, this
* behavior is strictly implementation-defined. Build metadata are compared
* similarly to pre-release versions. A version with build metadata is
* ordered after an equivalent one without it.
*
* To compare Versions without their build metadata in order to determine
* precedence use {@link #compareToIgnoreBuildMetadata(Version)}.
*
* @param other the {@code Version} to compare with, non-null
* @return a negative integer, zero or a positive integer if this
* {@code Version} is less than, equal to or greater than the
* specified {@code Version}
* @throws IllegalArgumentException if {@code other} is null
*/
@Override
public int compareTo(Version other) {
int result = compareToIgnoreBuildMetadata(other);
if (result != 0) {
return result;
}
result = compareIdentifierArrays(this.buildIds, other.buildIds);
if (this.buildIds.length == 0 || other.buildIds.length == 0) {
result = -1 * result;
}
return result;
}
/**
* Compares versions, ignoring their build metadata.
*
* This method adheres to the comparison rules defined by the Specification,
* and as such can be used for determining version precedence, either as a
* natural-order comparator ({@code Version::compareToIgnoreBuildMetadata}),
* or as a regular method.
*
* @param other the {@code Version} to compare with, non-null
* @return a negative integer, zero or a positive integer if this
* {@code Version} is lower than, equivalent to or higher than the
* specified {@code Version}
* @throws IllegalArgumentException if {@code other} is null
* @since 0.10.0
*/
public int compareToIgnoreBuildMetadata(Version other) {
nonNull(other, "other");
long result = major - other.major;
if (result == 0) {
result = minor - other.minor;
if (result == 0) {
result = patch - other.patch;
if (result == 0) {
return compareIdentifierArrays(this.preReleaseIds, other.preReleaseIds);
}
}
}
return result < 0 ? -1 : 1;
}
/**
* Checks if this {@code Version} exactly equals the specified {@code Version}.
*
* Although primarily intended for use in hash-based data structures, it
* can be used for testing for exact equality, including build metadata, if
* needed. To test for equivalence use {@link #isEquivalentTo(Version)}.
*
* @param other the {@code Version} to compare with, nullable
* @return {@code true}, if this {@code Version} exactly equals the other
* {@code Version}; {@code false} otherwise
*/
@Override
public boolean equals(Object other) {
if (this == other) {
return true;
}
if (!(other instanceof Version)) {
return false;
}
return compareTo((Version) other) == 0;
}
/**
* {@inheritDoc}
*/
@Override
public int hashCode() {
int hash = 5;
hash = 97 * hash + Long.hashCode(major);
hash = 97 * hash + Long.hashCode(minor);
hash = 97 * hash + Long.hashCode(patch);
hash = 97 * hash + Arrays.hashCode(preReleaseIds);
hash = 97 * hash + Arrays.hashCode(buildIds);
return hash;
}
/**
* {@inheritDoc}
*/
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append(major);
sb.append(IDENTIFIER_SEPARATOR);
sb.append(minor);
sb.append(IDENTIFIER_SEPARATOR);
sb.append(patch);
preReleaseVersion().ifPresent(r -> sb.append(PRE_RELEASE_PREFIX).append(r));
buildMetadata().ifPresent(b -> sb.append(BUILD_PREFIX).append(b));
return sb.toString();
}
/**
* Converts this {@code Version} to {@code Builder}.
*
* This method allows to use an instance of {@code Version} as a template
* for new instances.
*
* @return a {@code Builder} instance populated with values from
* this {@code Version}
* @since 0.10.0
*/
public Builder toBuilder() {
Builder b = new Builder();
b.setVersionCore(major, minor, patch);
preReleaseVersion().ifPresent(b::setPreReleaseVersion);
buildMetadata().ifPresent(b::setBuildMetadata);
return b;
}
private static long safeIncrement(long l) {
return Math.incrementExact(l);
}
private static String joinIdentifiers(String... ids) {
return ids.length == 0 ? null : String.join(IDENTIFIER_SEPARATOR, ids);
}
private static String[] incrementIdentifiers(String[] ids) {
String[] newIds;
String lastId = ids[ids.length - 1];
if (isNumeric(lastId)) {
newIds = Arrays.copyOf(ids, ids.length);
newIds[newIds.length - 1] = String.valueOf(safeIncrement(Long.parseLong(lastId)));
} else {
newIds = Arrays.copyOf(ids, ids.length + 1);
newIds[newIds.length - 1] = String.valueOf(1);
}
return newIds;
}
private static int compareIdentifierArrays(String[] thisIds, String[] otherIds) {
if (thisIds.length == 0 && otherIds.length == 0) {
return 0;
}
if (thisIds.length == 0 || otherIds.length == 0) {
// Pre-release versions have a lower precedence than
// the associated normal version. (SemVer p.9)
return thisIds.length == 0 ? 1 : -1;
}
int result = 0;
int minLength = Math.min(thisIds.length, otherIds.length);
for (int i = 0; i < minLength; i++) {
result = compareIdentifiers(thisIds[i], otherIds[i]);
if (result != 0) {
break;
}
}
if (result == 0) {
// A larger set of pre-release fields has a higher
// precedence than a smaller set, if all of the
// preceding identifiers are equal. (SemVer p.11)
result = thisIds.length - otherIds.length;
}
return result;
}
private static int compareIdentifiers(String thisId, String otherId) {
if (isNumeric(thisId) && isNumeric(otherId)) {
return Long.valueOf(thisId).compareTo(Long.valueOf(otherId));
} else {
return thisId.compareTo(otherId);
}
}
private static boolean isNumeric(String id) {
// filters out
if (id.startsWith("0")) {
return false;
}
return id.chars().allMatch(Character::isDigit);
}
static class Validators {
static long nonNegative(long arg, String name) {
if (arg < 0) {
throw new IllegalArgumentException(name + " must not be negative");
}
return arg;
}
static T nonNull(T arg, String name) {
return nonNullOrThrow(arg, name + " must not be null");
}
static T[] nonEmpty(T[] arg, String name) {
if (nonNull(arg, name).length == 0) {
throw new IllegalArgumentException(name + " must not be empty");
}
return arg;
}
static T[] zeroOrMoreNonNulls(T[] arg, String name) {
for (T t : nonNull(arg, name)) {
nonNullOrThrow(t, name + " must not contain null");
}
return arg;
}
static T[] oneOrMoreNonNulls(T[] arg, String name) {
for (T t : nonEmpty(arg, name)) {
nonNullOrThrow(t, name + " must not contain null");
}
return arg;
}
private static T nonNullOrThrow(T arg, String msg) {
if (arg == null) {
throw new IllegalArgumentException(msg);
}
return arg;
}
}
private static class SerializationProxy implements Serializable {
private static final long serialVersionUID = 0L;
/**
* @serial string representation of valid SemVer version, the most
* stable logical form of the {@code Version} class, which doesn't
* depend on its internal implementation. Only Specification can
* affect it by redefining its semantics and hence changing the way
* it's parsed. The only downside of this form is that it requires
* parsing on deserialization, which shouldn't be that big of a
* problem considering the size of a typical version string.
*/
private final String version;
SerializationProxy(Version version) {
this.version = version.toString();
}
private Object readResolve() {
return Version.parse(version);
}
}
private Object writeReplace() {
return new SerializationProxy(this);
}
private void readObject(ObjectInputStream ois) throws InvalidObjectException {
throw new InvalidObjectException("Proxy required");
}
/**
* @deprecated forRemoval since 0.10.0, use {@link #compareTo(Version)}
*/
@Deprecated
public static final Comparator BUILD_AWARE_ORDER = Version::compareTo;
/**
* @deprecated forRemoval since 0.10.0, use {@link #parse(String)}
*
* @param version a string representing a SemVer version, non-null
* @return a {@code Version} instance
* @throws IllegalArgumentException if {@code version} is null
* @throws ParseException if {@code version} can't be parsed
*/
@Deprecated
public static Version valueOf(String version) {
return Version.parse(version);
}
/**
* @deprecated forRemoval since 0.10.0, use {@link #of(long)}
*
* @param major a major version number, non-negative
* @return a {@code Version} instance
* @throws IllegalArgumentException if {@code major} is negative
*/
@Deprecated
public static Version forIntegers(int major) {
return Version.of(major);
}
/**
* @deprecated forRemoval since 0.10.0, use {@link #of(long, long)}
*
* @param major a major version number, non-negative
* @param minor a minor version number, non-negative
* @return a {@code Version} instance
* @throws IllegalArgumentException if {@code major} or {@code minor} is negative
*/
@Deprecated
public static Version forIntegers(int major, int minor) {
return Version.of(major, minor);
}
/**
* @deprecated forRemoval since 0.10.0, use {@link #of(long, long, long)}
*
* @param major a major version number, non-negative
* @param minor a minor version number, non-negative
* @param patch a patch version number, non-negative
* @return a {@code Version} instance
* @throws IllegalArgumentException if any of the arguments is negative
*/
@Deprecated
public static Version forIntegers(int major, int minor, int patch) {
return Version.of(major, minor, patch);
}
/**
* @deprecated forRemoval since 0.10.0
*
* @return the version core of this {@code Version}
*/
@Deprecated
public String getNormalVersion() {
return String.format(Locale.ROOT, "%d.%d.%d", major, minor, patch);
}
/**
* @deprecated forRemoval since 0.10.0, use {@link #majorVersion()}
*
* @return the major version number
*/
@Deprecated
public int getMajorVersion() {
long major = majorVersion();
if (major > Integer.MAX_VALUE) {
throw new RuntimeException("major > Integer.MAX_VALUE");
}
return (int) major;
}
/**
* @deprecated forRemoval since 0.10.0, use {@link #minorVersion()}
*
* @return the minor version number
*/
@Deprecated
public int getMinorVersion() {
long minor = minorVersion();
if (minor > Integer.MAX_VALUE) {
throw new RuntimeException("minor > Integer.MAX_VALUE");
}
return (int) minor;
}
/**
* @deprecated forRemoval since 0.10.0, use {@link #patchVersion()}
*
* @return the patch version number
*/
@Deprecated
public int getPatchVersion() {
long patch = patchVersion();
if (patch > Integer.MAX_VALUE) {
throw new RuntimeException("patch > Integer.MAX_VALUE");
}
return (int) patch;
}
/**
* @deprecated forRemoval since 0.10.0, use {@link #preReleaseVersion()}
*
* @return the pre-release version label, if present; empty string otherwise
*/
@Deprecated
public String getPreReleaseVersion() {
return preReleaseVersion().orElse("");
}
/**
* @deprecated forRemoval since 0.10.0, use {@link #buildMetadata()}
*
* @return the build metadata label, if present; empty string otherwise
*/
@Deprecated
public String getBuildMetadata() {
return buildMetadata().orElse("");
}
/**
* @deprecated forRemoval since 0.10.0, consider using {@link #nextPreReleaseVersion(String...)}
*
* @param preRelease the pre-release version label, non-null
* @return a {@code Version} instance
* @throws IllegalArgumentException if {@code preRelease} is null
* @throws ParseException if {@code preRelease} can't be parsed
*/
@Deprecated
@SuppressWarnings("DeprecatedIsStillUsed")
public Version setPreReleaseVersion(String preRelease) {
return new Version(major, minor, patch, parsePreRelease(preRelease));
}
/**
* @deprecated forRemoval since 0.10.0, use {@link #withBuildMetadata(String...)}
*
* @param build the build metadata label, non-null
* @return a {@code Version} instance
* @throws IllegalArgumentException if {@code build} is null
* @throws ParseException if {@code build} can't be parsed
*/
@Deprecated
public Version setBuildMetadata(String build) {
return withBuildMetadata(build);
}
/**
* @deprecated forRemoval since 0.10.0, use {@link #nextMajorVersion(String...)}
*
* @return a {@code Version} instance
* @throws ArithmeticException if the major version number overflows
*/
@Deprecated
public Version incrementMajorVersion() {
return nextMajorVersion();
}
/**
* @deprecated forRemoval since 0.10.0, use {@link #nextMajorVersion(String...)}
*
* @param preRelease the pre-release version label, non-null
* @return a {@code Version} instance
* @throws ArithmeticException if the major version number overflows
* @throws IllegalArgumentException if {@code preRelease} is null
* @throws ParseException if {@code preRelease} can't be parsed
*/
@Deprecated
public Version incrementMajorVersion(String preRelease) {
return nextMajorVersion(preRelease);
}
/**
* @deprecated forRemoval since 0.10.0, use {@link #nextMinorVersion(String...)}
*
* @return a {@code Version} instance
* @throws ArithmeticException if the minor version number overflows
*/
@Deprecated
public Version incrementMinorVersion() {
return nextMinorVersion();
}
/**
* @deprecated forRemoval since 0.10.0, use {@link #nextMinorVersion(String...)}
*
* @param preRelease the pre-release version label, non-null
* @return a {@code Version} instance
* @throws ArithmeticException if the minor version number overflows
* @throws IllegalArgumentException if {@code preRelease} is null
* @throws ParseException if {@code preRelease} can't be parsed
*/
@Deprecated
public Version incrementMinorVersion(String preRelease) {
return nextMinorVersion(preRelease);
}
/**
* @deprecated forRemoval since 0.10.0, use {@link #nextPatchVersion(String...)}
*
* @return a {@code Version} instance
* @throws ArithmeticException if the patch version number overflows
*/
@Deprecated
public Version incrementPatchVersion() {
return nextPatchVersion();
}
/**
* @deprecated forRemoval since 0.10.0, use {@link #nextPatchVersion(String...)}
*
* @param preRelease the pre-release version label, non-null
* @return a {@code Version} instance
* @throws ArithmeticException if the patch version number overflows
* @throws IllegalArgumentException if {@code preRelease} is null
* @throws ParseException if {@code preRelease} can't be parsed
*/
@Deprecated
public Version incrementPatchVersion(String preRelease) {
return nextPatchVersion(preRelease);
}
/**
* @deprecated forRemoval since 0.10.0, use {@link #nextPreReleaseVersion(String...)}
*
* @return a {@code Version} instance
* @throws ArithmeticException if the incremented numeric identifier overflows
* @throws IllegalStateException if invoked on a stable {@code Version}
*/
@Deprecated
public Version incrementPreReleaseVersion() {
return nextPreReleaseVersion();
}
/**
* @deprecated forRemoval since 0.10.0
*
* @return a {@code Version} instance
* @throws IllegalStateException if this {@code Version} doesn't have build metadata
*/
@Deprecated
@SuppressWarnings("DeprecatedIsStillUsed")
public Version incrementBuildMetadata() {
if (!buildMetadata().isPresent()) {
throw new IllegalStateException("Build metadata empty");
}
return new Version(major, minor, patch, preReleaseIds, incrementIdentifiers(buildIds));
}
/**
* @deprecated forRemoval since 0.10.0, use {@link #isHigherThan(Version)}
*
* @param other the {@code Version} to compare with, non-null
* @return {@code true}, if this {@code Version} is higher than the other
* {@code Version}; {@code false} otherwise
* @throws IllegalArgumentException if {@code other} is null
*/
@Deprecated
public boolean greaterThan(Version other) {
return isHigherThan(other);
}
/**
* @deprecated forRemoval since 0.10.0, use {@link #isHigherThanOrEquivalentTo(Version)}
*
* @param other the {@code Version} to compare with, non-null
* @return {@code true}, if this {@code Version} is higher than or equivalent
* to the other {@code Version}; {@code false} otherwise
* @throws IllegalArgumentException if {@code other} is null
*/
@Deprecated
public boolean greaterThanOrEqualTo(Version other) {
return isHigherThanOrEquivalentTo(other);
}
/**
* @deprecated forRemoval since 0.10.0, use {@link #isLowerThan(Version)}
*
* @param other the {@code Version} to compare with, non-null
* @return {@code true}, if this {@code Version} is lower than the other
* {@code Version}; {@code false} otherwise
* @throws IllegalArgumentException if {@code other} is null
*/
@Deprecated
public boolean lessThan(Version other) {
return isLowerThan(other);
}
/**
* @deprecated forRemoval since 0.10.0, use {@link #isLowerThanOrEquivalentTo(Version)}
*
* @param other the {@code Version} to compare with, non-null
* @return {@code true}, if this {@code Version} is lower than or equivalent
* to the other {@code Version}; {@code false} otherwise
* @throws IllegalArgumentException if {@code other} is null
*/
@Deprecated
public boolean lessThanOrEqualTo(Version other) {
return isLowerThanOrEquivalentTo(other);
}
/**
* @deprecated forRemoval since 0.10.0, use {@link #compareTo(Version)}
*
* @param other the {@code Version} to compare with, non-null
* @return a negative integer, zero or a positive integer if this
* {@code Version} is less than, equal to or greater than the
* specified {@code Version}
* @throws IllegalArgumentException if {@code other} is null
*/
@Deprecated
public int compareWithBuildsTo(Version other) {
return compareTo(other);
}
}