Version.java
/*
* The contents of this file are subject to the terms of the Common Development and
* Distribution License (the License). You may not use this file except in compliance with the
* License.
*
* You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
* specific language governing permission and limitations under the License.
*
* When distributing Covered Software, include this CDDL Header Notice in each file and include
* the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
* Header, with the fields enclosed by brackets [] replaced by your own identifying
* information: "Portions copyright [year] [name of copyright owner]".
*
* Copyright 2015 ForgeRock AS.
*/
package org.forgerock.http.routing;
import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Represents some version in the form majorNumber.minorNumber,
* for instance 2.4.
*/
public final class Version implements Comparable<Version> {
private static final Version[] DOT_ZERO_CACHE = new Version[10];
private static final Pattern REGEX = Pattern.compile("(\\d+)(\\.(\\d+))?");
static {
for (int i = 0; i < DOT_ZERO_CACHE.length; i++) {
DOT_ZERO_CACHE[i] = new Version(i, 0);
}
}
private final int major;
private final int minor;
/**
* Creates a new version using the provided version information.
*
* @param major
* Major version number.
* @param minor
* Minor version number.
*
* @return The version.
*/
public static Version version(final int major, final int minor) {
if (minor == 0 && major >= 0 && major < DOT_ZERO_CACHE.length) {
return DOT_ZERO_CACHE[major];
}
return new Version(major, minor);
}
/**
* Creates a new version using the provided version information and a minor.
*
* @param major
* Major version number.
*
* @return The version.
*/
public static Version version(final int major) {
return version(major, 0);
}
private Version(final int major, final int minor) {
this.major = major;
this.minor = minor;
}
/**
* Parses the string argument as a version. The string must be one of the
* following forms:
* <pre>
* major
* major.minor
* </pre>
*
* @param s
* The non-{@code null} string to be parsed as a version.
*
* @return The parsed version.
*
* @throws IllegalArgumentException
* If the string does not contain a parsable version.
*/
public static Version version(final String s) {
Matcher matcher = REGEX.matcher(s);
if (matcher.matches()) {
if (matcher.group(3) == null) {
return version(Integer.parseInt(matcher.group(1)));
} else {
return version(Integer.parseInt(matcher.group(1)), Integer.parseInt(matcher.group(3)));
}
} else {
throw new IllegalArgumentException("Invalid version string " + s);
}
}
/**
* Returns the major version number.
*
* @return The major version number.
*/
public int getMajor() {
return major;
}
/**
* Returns the minor version number.
*
* @return The minor version number.
*/
public int getMinor() {
return minor;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
Version version = (Version) o;
return Objects.equals(major, version.major)
&& Objects.equals(minor, version.minor);
}
@Override
public int hashCode() {
return Objects.hash(major, minor);
}
@Override
public int compareTo(final Version that) {
if (major != that.major) {
return major - that.major;
}
if (minor != that.minor) {
return minor - that.minor;
}
return 0;
}
@Override
public String toString() {
return major + "." + minor;
}
/**
* Returns {@code false} if:
* <ul>
* <li>
* the MAJOR version numbers are not the same.
* </li>
* <li>
* the MAJOR version numbers are the same but {@code this} MINOR
* version number is LOWER than {@code that} MINOR version number.
* </li>
* </ul>
*
* <p>i.e. this version number - "2.0", that version number - "2.1" WILL
* NOT match, but this version number - "2.4", that version number - "2.1"
* WILL match. In other words, verifies ascending compatibility.</p>
*
* @param that The {@code Version} to match against.
* @return {@code true} if both MAJOR version numbers are the same and if
* {@code this} MINOR version number is HIGHER than {@code that} MINOR
* version number.
*/
public boolean isCompatibleWith(Version that) {
return that != null && this.major == that.major && this.minor >= that.minor;
}
}