io.strimzi.api.annotations.VersionRange Maven / Gradle / Ivy
The newest version!
/*
* Copyright Strimzi authors.
* License: Apache License 2.0 (see the file LICENSE or http://apache.org/licenses/LICENSE-2.0.html).
*/
package io.strimzi.api.annotations;
import java.util.Objects;
/**
* Represents a range over some comparable version type.
* Ranges can:
*
* - be Empty
* - consist of a single version
* - consist of an inclusive lower bound and no upper bound
* - consist of inclusive lower and upper bounds
*
* It is possible to test {@linkplain #contains(Comparable) inclusion} of a given version in a version range
* and whether two version ranges possibly {@linkplain #intersects(VersionRange) intersect}.
* @param The type of the version. This class assumes that older versions are less than newer versions and
* {@link Comparable#compareTo(Object)} is consistent with {@link Object#equals(Object)}.
*/
public class VersionRange> {
@SuppressWarnings({ "rawtypes" })
private static final VersionRange EMPTY = new VersionRange<>(null, null);
private final Version from;
private final Version to;
/**
* Returns an empty version range
*
* @param The type of version range.
*
* @return The empty version range.
*/
@SuppressWarnings("unchecked")
public static > VersionRange empty() {
return EMPTY;
}
/**
* Returns a VersionRange matching all versions
*
* @param The type of version range.
*
* @return VersionRange matching all versions
*/
public static > VersionRange all() {
return new VersionRange<>(null, null);
}
/**
* Checks whether this version range is empty or not
*
* @return Returns true if this version range is empty. Returns false otherwise.
*/
public boolean isEmpty() {
return this == EMPTY;
}
/**
* Checks whether this version range matches all versions
*
* @return Returns true if this version range matches all versions. Returns false otherwise.
*/
public boolean isAll() {
return this.equals(all());
}
private VersionRange(Version from, Version to) {
// invariant from == null => "all" => null must be null too
if (from == null && to != null) {
throw new IllegalArgumentException();
}
if (from != null && to != null && from.compareTo(to) > 0) {
throw new IllegalArgumentException("Bad version range");
}
this.from = from;
this.to = to;
}
/**
* Abstracts the parsing of a version.
*
* @param Custom Resource API Version
*/
interface VersionParser> {
Version parse(String version) throws IllegalArgumentException;
default boolean isValid(String version) {
try {
parse(version);
return true;
} catch (IllegalArgumentException e) {
return false;
}
}
}
/**
* Parse a version range specified as:
*
* - {@code empty} -- matches no versions
* - {@code all} -- matches all version
* - {@code $version} -- matches precisely the given {@code version}.
* - {@code $from+} -- matches all versions >= the given {@code from} version.
* - {@code $from-$to} -- matches all versions between the given {@code from} version and {@code to} versions, inclusive.
*
* Obviously this makes assumptions about what constitutes valid syntax for versions, e.g. "empty" cannot be a valid version
*
* @param versionRange VersionRange String which should be parsed
* @param parser A parser for versions.
* @param The type of version range.
*
* @return Parsed version range
*/
static > VersionRange parse(String versionRange, VersionParser parser) {
if ("empty".equals(versionRange)) {
return empty();
} else if ("all".equals(versionRange)) {
// all
return all();
} else if (parser.isValid(versionRange)) {
// version
Version v = parser.parse(versionRange);
return new VersionRange<>(v, v);
} else if (versionRange.endsWith("+")) {
// version+
String s1 = versionRange.substring(0, versionRange.length() - 1);
if (parser.isValid(s1)) {
Version v = parser.parse(s1);
return new VersionRange<>(v, null);
} else {
throw new IllegalArgumentException("Invalid from version " + s1);
}
} else {
// version-version
int index = versionRange.indexOf('-');
if (index != -1) {
String from = versionRange.substring(0, index);
String to = versionRange.substring(index + 1);
if (parser.isValid(from)) {
if (parser.isValid(to)) {
return new VersionRange<>(parser.parse(from), parser.parse(to));
} else {
throw new IllegalArgumentException("Invalid to version " + to);
}
} else {
throw new IllegalArgumentException("Invalid from version " + from);
}
} else {
throw new IllegalArgumentException("Invalid version range: None of the expected patterns applied");
}
}
}
/**
* Returns the lower boundary of the version range
*
* @return The lower boundary of the range
*/
public Version lower() {
return from;
}
/**
* Returns the upper boundary of the version range
*
* @return The upper boundary of the range
*/
public Version upper() {
return to;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
@SuppressWarnings({ "rawtypes" })
VersionRange that = (VersionRange) o;
return Objects.equals(from, that.from) &&
Objects.equals(to, that.to);
}
@Override
public int hashCode() {
return Objects.hash(from, to);
}
/**
* Checks when the version is part of the version range
*
* @param apiVersion API Version which should be checked whether it is in the range or not
*
* @return True when the range contains the version. False otherwise
*/
public boolean contains(Version apiVersion) {
return this != EMPTY
&& apiVersion != null
&& (from == null || from.compareTo(apiVersion) <= 0 && (to == null || to.compareTo(apiVersion) >= 0));
}
/**
* Checks whether two version ranges intersect
*
* @param other The version range which should be compared with this version range
*
* @return Returns true if the version ranges intersect. Returns false otherwise.
*/
public boolean intersects(VersionRange other) {
if (this == EMPTY) {
return false;
} else if (from == null) {
return true;
} else if (to == null) {
return from.compareTo(other.from) <= 0;
} else {
return !(to.compareTo(other.from) < 0 || (other.to != null && from.compareTo(other.to) > 0));
}
}
@Override
public String toString() {
if (this == EMPTY) {
return "empty";
} else if (from == null) {
return "all";
} else if (to == null) {
return from + "+";
} else if (from.equals(to)) {
return from.toString();
} else {
return from + "-" + to;
}
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy