org.conqat.lib.commons.version.Version Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of teamscale-lib-commons Show documentation
Show all versions of teamscale-lib-commons Show documentation
Provides common utility functions
The newest version!
/*
* Copyright (c) CQSE GmbH
*
* Licensed 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.conqat.lib.commons.version;
import java.io.Serializable;
import java.util.Comparator;
import java.util.Objects;
import java.util.Optional;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.conqat.lib.commons.error.FormatException;
import org.conqat.lib.commons.test.IndexValueClass;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
/**
* A class to describe versions of software (or other) artifacts. A version has a major and a minor
* version number. Version are ordered. This class is immutable.
*/
@IndexValueClass
public final class Version implements Comparable, Serializable {
/** The name of the JSON property name for {@link #major}. */
private static final String MAJOR_PROPERTY = "major";
/** The name of the JSON property name for {@link #minor}. */
private static final String MINOR_PROPERTY = "minor";
/** The name of the JSON property name for {@link #patch}. */
private static final String PATCH_PROPERTY = "patch";
/** Version used for serialization. */
private static final long serialVersionUID = 1;
/** Major version. */
@JsonProperty(MAJOR_PROPERTY)
private final int major;
/** Minor version. */
@JsonProperty(MINOR_PROPERTY)
private final int minor;
/** Patch level. */
@JsonProperty(PATCH_PROPERTY)
private final int patch;
/**
* Create a new version.
*
* @param major
* major version number.
* @param minor
* minor version number.
* @throws IllegalArgumentException
* if one of the version numbers is less than 0.
*/
public Version(int major, int minor) {
this(major, minor, 0);
}
/**
* Create a new version.
*
* @param major
* major version number.
* @param minor
* minor version number.
* @param patch
* patch version number.
* @throws IllegalArgumentException
* if one of the version numbers is less than 0.
*/
@JsonCreator
public Version(@JsonProperty(MAJOR_PROPERTY) int major, @JsonProperty(MINOR_PROPERTY) int minor,
@JsonProperty(PATCH_PROPERTY) int patch) {
if (major < 0 || minor < 0 || patch < 0) {
throw new IllegalArgumentException("Versions may not be less than 0.");
}
this.major = major;
this.minor = minor;
this.patch = patch;
}
/**
* Parses a version from a string. The format has to be "major.minor.patch", while patch is
* optional.
*
* @throws FormatException
* if the string does not follow the expected pattern.
*/
public static Version parseVersion(String s) throws FormatException {
Matcher m = Pattern.compile("\\s*(\\d+)\\.(\\d+)(?:\\.(\\d+))?\\s*").matcher(s);
if (!m.matches()) {
throw new FormatException("The provided string did not match the pattern!");
}
int major = Integer.parseInt(m.group(1));
int minor = Integer.parseInt(m.group(2));
int patch = Optional.ofNullable(m.group(3)).map(Integer::parseInt).orElse(0);
return new Version(major, minor, patch);
}
/**
* Compares to version numbers by their major and minor numbers.
*/
@Override
public int compareTo(Version other) {
return Comparator.comparingInt(Version::getMajor).thenComparingInt(Version::getMinor)
.thenComparingInt(Version::getPatch).compare(this, other);
}
/**
* Two version are equal if their major and minor version numbers are equal.
*/
@Override
public boolean equals(Object other) {
if (other == this) {
return true;
}
if (!(other instanceof Version)) {
return false;
}
return compareTo((Version) other) == 0;
}
/** Get major version number. */
public int getMajor() {
return major;
}
/** Get minor version number. */
public int getMinor() {
return minor;
}
/** Get patch version number. */
public int getPatch() {
return patch;
}
@Override
public int hashCode() {
return Objects.hash(major, minor, patch);
}
/**
* This method is used to check version compatibility in dependency management.
*
* Consider the following situation and artifact A (the depender) depends on another artifact B (the
* dependee). A claims that it requires B in version 1.3. B states that it has version 1.5 but is
* downward compatible to version 1.1.
*
* Using this method one can find out if the version provided by B satisfies A's requirement. It is
* satisfied iff
*
*
* requiredVersion <= currentVersion && requiredVersion >= compatibleVersion
*
*
* where requiredVersion
is this instance and the other two are provided as method
* parameters.
*
* @throws IllegalArgumentException
* if compatibleVersion
is greater than currentVersion
.
*/
public boolean isSatisfied(Version currentVersion, Version compatibleVersion) {
if (compatibleVersion.compareTo(currentVersion) > 0) {
throw new IllegalArgumentException("Compatible version greater than current version.");
}
return compareTo(currentVersion) <= 0 && compareTo(compatibleVersion) >= 0;
}
/**
* Returns whether this version is greater or equal to the given other version
*/
public boolean isGreaterOrEqual(Version other) {
return compareTo(other) >= 0;
}
/**
* String representation: major.minor
*/
@Override
public String toString() {
String result = major + "." + minor;
if (patch > 0) {
result += "." + patch;
}
return result;
}
/**
* Returns the full string representation: major.minor.patch
*
* Note that the difference to {@link #toString()} is that {@code patch} is always included even if
* it is {@code 0}.
*/
public String toFullString() {
return major + "." + minor + "." + patch;
}
}