summaryrefslogtreecommitdiff
path: root/src/main/java/sevenUnits/utils/SemanticVersionNumber.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/sevenUnits/utils/SemanticVersionNumber.java')
-rw-r--r--src/main/java/sevenUnits/utils/SemanticVersionNumber.java168
1 files changed, 80 insertions, 88 deletions
diff --git a/src/main/java/sevenUnits/utils/SemanticVersionNumber.java b/src/main/java/sevenUnits/utils/SemanticVersionNumber.java
index fc47baa..4bb7ce5 100644
--- a/src/main/java/sevenUnits/utils/SemanticVersionNumber.java
+++ b/src/main/java/sevenUnits/utils/SemanticVersionNumber.java
@@ -1,5 +1,5 @@
/**
- * Copyright (C) 2022 Adrien Hopkins
+ * Copyright (C) 2022, 2024, 2025 Adrien Hopkins
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
@@ -22,7 +22,6 @@ import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Objects;
-import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
@@ -39,8 +38,8 @@ import java.util.regex.Pattern;
* are made
* </ol>
*
- * @since v0.4.0
* @since 2022-02-19
+ * @since v0.4.0
*/
public final class SemanticVersionNumber
implements Comparable<SemanticVersionNumber> {
@@ -52,8 +51,8 @@ public final class SemanticVersionNumber
* throw NullPointerExceptions, everything else throws
* IllegalArgumentException.
*
- * @since v0.4.0
* @since 2022-02-19
+ * @since v0.4.0
*/
public static final class Builder {
private final int major;
@@ -69,8 +68,8 @@ public final class SemanticVersionNumber
* @param major major version number of final version
* @param minor minor version number of final version
* @param patch patch version number of final version
- * @since v0.4.0
* @since 2022-02-19
+ * @since v0.4.0
*/
private Builder(int major, int minor, int patch) {
this.major = major;
@@ -82,8 +81,8 @@ public final class SemanticVersionNumber
/**
* @return version number created by this builder
- * @since v0.4.0
* @since 2022-02-19
+ * @since v0.4.0
*/
public SemanticVersionNumber build() {
return new SemanticVersionNumber(this.major, this.minor, this.patch,
@@ -95,8 +94,8 @@ public final class SemanticVersionNumber
*
* @param identifiers build metadata
* @return this builder
- * @since v0.4.0
* @since 2022-02-19
+ * @since v0.4.0
*/
public Builder buildMetadata(List<String> identifiers) {
Objects.requireNonNull(identifiers, "identifiers may not be null");
@@ -115,8 +114,8 @@ public final class SemanticVersionNumber
*
* @param identifiers build metadata
* @return this builder
- * @since v0.4.0
* @since 2022-02-19
+ * @since v0.4.0
*/
public Builder buildMetadata(String... identifiers) {
Objects.requireNonNull(identifiers, "identifiers may not be null");
@@ -136,7 +135,7 @@ public final class SemanticVersionNumber
return true;
if (!(obj instanceof Builder))
return false;
- final Builder other = (Builder) obj;
+ final var other = (Builder) obj;
return Objects.equals(this.buildMetadata, other.buildMetadata)
&& this.major == other.major && this.minor == other.minor
&& this.patch == other.patch && Objects.equals(
@@ -154,8 +153,8 @@ public final class SemanticVersionNumber
*
* @param identifiers pre-release identifier(s) to add
* @return this builder
- * @since v0.4.0
* @since 2022-02-19
+ * @since v0.4.0
*/
public Builder preRelease(int... identifiers) {
Objects.requireNonNull(identifiers, "identifiers may not be null");
@@ -173,8 +172,8 @@ public final class SemanticVersionNumber
*
* @param identifiers pre-release identifier(s) to add
* @return this builder
- * @since v0.4.0
* @since 2022-02-19
+ * @since v0.4.0
*/
public Builder preRelease(List<String> identifiers) {
Objects.requireNonNull(identifiers, "identifiers may not be null");
@@ -193,8 +192,8 @@ public final class SemanticVersionNumber
*
* @param identifiers pre-release identifier(s) to add
* @return this builder
- * @since v0.4.0
* @since 2022-02-19
+ * @since v0.4.0
*/
public Builder preRelease(String... identifiers) {
Objects.requireNonNull(identifiers, "identifiers may not be null");
@@ -214,8 +213,8 @@ public final class SemanticVersionNumber
* @param identifier1 first identifier
* @param identifier2 second identifier
* @return this builder
- * @since v0.4.0
* @since 2022-02-19
+ * @since v0.4.0
*/
public Builder preRelease(String identifier1, int identifier2) {
Objects.requireNonNull(identifier1, "identifier1 may not be null");
@@ -249,12 +248,11 @@ public final class SemanticVersionNumber
public int compare(SemanticVersionNumber o1, SemanticVersionNumber o2) {
Objects.requireNonNull(o1, "o1 may not be null");
Objects.requireNonNull(o2, "o2 may not be null");
- final int naturalComparison = o1.compareTo(o2);
+ final var naturalComparison = o1.compareTo(o2);
if (naturalComparison == 0)
return SemanticVersionNumber.compareIdentifiers(o1.buildMetadata,
o2.buildMetadata);
- else
- return naturalComparison;
+ return naturalComparison;
};
};
@@ -280,11 +278,11 @@ public final class SemanticVersionNumber
* @param patch patch version number of final version
* @return version number builder
* @throws IllegalArgumentException if any argument is negative
- * @since v0.4.0
* @since 2022-02-19
+ * @since v0.4.0
*/
- public static final SemanticVersionNumber.Builder builder(int major,
- int minor, int patch) {
+ public static SemanticVersionNumber.Builder builder(int major, int minor,
+ int patch) {
if (major < 0)
throw new IllegalArgumentException(
"Major version must be non-negative.");
@@ -304,60 +302,57 @@ public final class SemanticVersionNumber
* @param b second list
* @return result of comparison as in a comparator
* @see Comparator
- * @since v0.4.0
* @since 2022-02-20
+ * @since v0.4.0
*/
- private static final int compareIdentifiers(List<String> a, List<String> b) {
+ private static int compareIdentifiers(List<String> a, List<String> b) {
// test pre-release size
- final int aSize = a.size();
- final int bSize = b.size();
+ final var aSize = a.size();
+ final var bSize = b.size();
// no identifiers is greater than any identifiers
if (aSize != 0 && bSize == 0)
return -1;
- else if (aSize == 0 && bSize != 0)
+ if (aSize == 0 && bSize != 0)
return 1;
// test identifiers one by one
- for (int i = 0; i < Math.min(aSize, bSize); i++) {
- final String aElement = a.get(i);
- final String bElement = b.get(i);
+ for (var i = 0; i < Math.min(aSize, bSize); i++) {
+ final var aElement = a.get(i);
+ final var bElement = b.get(i);
if (NUMERIC_IDENTIFER.matcher(aElement).matches()) {
- if (NUMERIC_IDENTIFER.matcher(bElement).matches()) {
- // both are numbers, compare them
- final int aNumber = Integer.parseInt(aElement);
- final int bNumber = Integer.parseInt(bElement);
-
- if (aNumber < bNumber)
- return -1;
- else if (aNumber > bNumber)
- return 1;
- } else
+ if (!NUMERIC_IDENTIFER.matcher(bElement).matches())
// aElement is a number and bElement is not a number
// by the rules, a goes before b
return -1;
- } else {
- if (NUMERIC_IDENTIFER.matcher(bElement).matches())
- // aElement is not a number but bElement is
- // by the rules, a goes after b
+ // both are numbers, compare them
+ final var aNumber = Integer.parseInt(aElement);
+ final var bNumber = Integer.parseInt(bElement);
+
+ if (aNumber < bNumber)
+ return -1;
+ if (aNumber > bNumber)
return 1;
- else {
- // both are not numbers, compare them
- final int comparison = aElement.compareTo(bElement);
- if (comparison != 0)
- return comparison;
- }
+ } else if (NUMERIC_IDENTIFER.matcher(bElement).matches())
+ // aElement is not a number but bElement is
+ // by the rules, a goes after b
+ return 1;
+ else {
+ // both are not numbers, compare them
+ final var comparison = aElement.compareTo(bElement);
+ if (comparison != 0)
+ return comparison;
}
}
-
- // we just tested the stuff that's in common, maybe someone has more
if (aSize < bSize)
return -1;
- else if (aSize > bSize)
+ if (aSize > bSize)
return 1;
- else
- return 0;
+ return 0;
+
+ // we just tested the stuff that's in common, maybe someone has more
+
}
/**
@@ -365,23 +360,23 @@ public final class SemanticVersionNumber
*
* @param versionString string to parse
* @return {@code SemanticVersionNumber} instance
- * @since v0.4.0
* @since 2022-02-19
- * @see {@link #toString}
+ * @since v0.4.0
+ * @see #toString
*/
- public static final SemanticVersionNumber fromString(String versionString) {
+ public static SemanticVersionNumber fromString(String versionString) {
// parse & validate version string
Objects.requireNonNull(versionString, "versionString may not be null");
- final Matcher m = VERSION_NUMBER.matcher(versionString);
+ final var m = VERSION_NUMBER.matcher(versionString);
if (!m.matches())
throw new IllegalArgumentException(
String.format("Provided string \"%s\" is not a version number",
versionString));
// main parts
- final int major = Integer.parseInt(m.group(1));
- final int minor = Integer.parseInt(m.group(2));
- final int patch = Integer.parseInt(m.group(3));
+ final var major = Integer.parseInt(m.group(1));
+ final var minor = Integer.parseInt(m.group(2));
+ final var patch = Integer.parseInt(m.group(3));
// pre release
final List<String> preRelease;
@@ -406,13 +401,13 @@ public final class SemanticVersionNumber
/**
* Tests whether a string is a valid Semantic Version string
- *
+ *
* @param versionString string to test
* @return true iff string is valid
- * @since v0.4.0
* @since 2022-02-19
+ * @since v0.4.0
*/
- public static final boolean isValidVersionString(String versionString) {
+ public static boolean isValidVersionString(String versionString) {
return VERSION_NUMBER.matcher(versionString).matches();
}
@@ -429,10 +424,10 @@ public final class SemanticVersionNumber
* @throws IllegalArgumentException if any argument is negative or if the
* preReleaseType is null, empty or not
* alphanumeric (0-9, A-Z, a-z, - only)
- * @since v0.4.0
* @since 2022-02-19
+ * @since v0.4.0
*/
- public static final SemanticVersionNumber preRelease(int major, int minor,
+ public static SemanticVersionNumber preRelease(int major, int minor,
int patch, String preReleaseType, int preReleaseNumber) {
if (major < 0)
throw new IllegalArgumentException(
@@ -467,10 +462,10 @@ public final class SemanticVersionNumber
* @param patch patch version number
* @return {@code SemanticVersionNumber} instance
* @throws IllegalArgumentException if any argument is negative
- * @since v0.4.0
* @since 2022-02-19
+ * @since v0.4.0
*/
- public static final SemanticVersionNumber stableVersion(int major, int minor,
+ public static SemanticVersionNumber stableVersion(int major, int minor,
int patch) {
if (major < 0)
throw new IllegalArgumentException(
@@ -500,8 +495,8 @@ public final class SemanticVersionNumber
* @param patch patch version number
* @param preReleaseIdentifiers pre-release version data
* @param buildMetadata build metadata
- * @since v0.4.0
* @since 2022-02-19
+ * @since v0.4.0
*/
private SemanticVersionNumber(int major, int minor, int patch,
List<String> preReleaseIdentifiers, List<String> buildMetadata) {
@@ -514,8 +509,8 @@ public final class SemanticVersionNumber
/**
* @return build metadata (empty if there is none)
- * @since v0.4.0
* @since 2022-02-19
+ * @since v0.4.0
*/
public List<String> buildMetadata() {
return Collections.unmodifiableList(this.buildMetadata);
@@ -536,17 +531,17 @@ public final class SemanticVersionNumber
// test the three big numbers in order first
if (this.major < o.major)
return -1;
- else if (this.major > o.major)
+ if (this.major > o.major)
return 1;
if (this.minor < o.minor)
return -1;
- else if (this.minor > o.minor)
+ if (this.minor > o.minor)
return 1;
if (this.patch < o.patch)
return -1;
- else if (this.patch > o.patch)
+ if (this.patch > o.patch)
return 1;
// now we just compare pre-release identifiers
@@ -569,7 +564,7 @@ public final class SemanticVersionNumber
* </ul>
* If this function returns <b>false</b>, you may have to change your code to
* upgrade it to {@code other}
- *
+ *
* <p>
* Two version numbers that are identical (ignoring build metadata) are
* always compatible. Different version numbers are compatible as long as:
@@ -585,8 +580,8 @@ public final class SemanticVersionNumber
* @param other version to compare with
* @return true if you can definitely upgrade to {@code other} without
* changing code
- * @since v0.4.0
* @since 2022-02-20
+ * @since v0.4.0
*/
public boolean compatibleWith(SemanticVersionNumber other) {
Objects.requireNonNull(other, "other may not be null");
@@ -601,17 +596,14 @@ public final class SemanticVersionNumber
return true;
if (!(obj instanceof SemanticVersionNumber))
return false;
- final SemanticVersionNumber other = (SemanticVersionNumber) obj;
+ final var other = (SemanticVersionNumber) obj;
if (this.buildMetadata == null) {
if (other.buildMetadata != null)
return false;
} else if (!this.buildMetadata.equals(other.buildMetadata))
return false;
- if (this.major != other.major)
- return false;
- if (this.minor != other.minor)
- return false;
- if (this.patch != other.patch)
+ if ((this.major != other.major) || (this.minor != other.minor)
+ || (this.patch != other.patch))
return false;
if (this.preReleaseIdentifiers == null) {
if (other.preReleaseIdentifiers != null)
@@ -624,8 +616,8 @@ public final class SemanticVersionNumber
@Override
public int hashCode() {
- final int prime = 31;
- int result = 1;
+ final var prime = 31;
+ var result = 1;
result = prime * result
+ (this.buildMetadata == null ? 0 : this.buildMetadata.hashCode());
result = prime * result + this.major;
@@ -639,8 +631,8 @@ public final class SemanticVersionNumber
/**
* @return true iff this version is stable (major version > 0 and not a
* pre-release)
- * @since v0.4.0
* @since 2022-02-19
+ * @since v0.4.0
*/
public boolean isStable() {
return this.major > 0 && this.preReleaseIdentifiers.isEmpty();
@@ -649,8 +641,8 @@ public final class SemanticVersionNumber
/**
* @return the MAJOR version number, incremented when you make backwards
* incompatible API changes
- * @since v0.4.0
* @since 2022-02-19
+ * @since v0.4.0
*/
public int majorVersion() {
return this.major;
@@ -659,8 +651,8 @@ public final class SemanticVersionNumber
/**
* @return the MINOR version number, incremented when you add backwards
* compatible functionality
- * @since v0.4.0
* @since 2022-02-19
+ * @since v0.4.0
*/
public int minorVersion() {
return this.minor;
@@ -669,8 +661,8 @@ public final class SemanticVersionNumber
/**
* @return the PATCH version number, incremented when you make backwards
* compatible bug fixes
- * @since v0.4.0
* @since 2022-02-19
+ * @since v0.4.0
*/
public int patchVersion() {
return this.patch;
@@ -679,8 +671,8 @@ public final class SemanticVersionNumber
/**
* @return identifiers describing this pre-release (empty if not a
* pre-release)
- * @since v0.4.0
* @since 2022-02-19
+ * @since v0.4.0
*/
public List<String> preReleaseIdentifiers() {
return Collections.unmodifiableList(this.preReleaseIdentifiers);
@@ -697,13 +689,13 @@ public final class SemanticVersionNumber
* For example, the version with major number 3, minor number 2, patch number
* 1, pre-release identifiers "alpha" and "1" and build metadata "2022-02-19"
* has a string representation "3.2.1-alpha.1+2022-02-19".
- *
+ *
* @since v0.4.0
* @see <a href="https://semver.org">The official SemVer specification</a>
*/
@Override
public String toString() {
- String versionString = String.format("%d.%d.%d", this.major, this.minor,
+ var versionString = String.format("%d.%d.%d", this.major, this.minor,
this.patch);
if (!this.preReleaseIdentifiers.isEmpty()) {
versionString += "-" + String.join(".", this.preReleaseIdentifiers);