Version.java
/*
* Copyright 2020 The Android Open Source Project
*
* 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 androidx.window;
import android.text.TextUtils;
import androidx.annotation.NonNull;
import java.math.BigInteger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Class encapsulating a version with major, minor, patch and description values.
*/
class Version implements Comparable<Version> {
static final Version UNKNOWN = new Version(0, 0, 0, "");
static final Version VERSION_0_1 = new Version(0, 1, 0, "");
static final Version VERSION_1_0 = new Version(1, 0, 0, "");
static final Version CURRENT = VERSION_1_0;
private static final String VERSION_PATTERN_STRING =
"(\d+)(?:\.(\d+))(?:\.(\d+))(?:-(.+))?";
private final int mMajor;
private final int mMinor;
private final int mPatch;
private final String mDescription;
// Cached BigInteger value of the version.
private BigInteger mBigInteger;
private Version(int major, int minor, int patch, String description) {
mMajor = major;
mMinor = minor;
mPatch = patch;
mDescription = description;
}
/**
* Parses a string to a version object.
*
* @param versionString string in the format "1.2.3" or "1.2.3-Description"
* (major.minor.patch[-description])
* @return the parsed Version object or {@code null}> if the versionString format is invalid.
*/
static Version parse(String versionString) {
if (TextUtils.isEmpty(versionString)) {
return null;
}
Matcher matcher = Pattern.compile(VERSION_PATTERN_STRING).matcher(versionString);
if (!matcher.matches()) {
return null;
}
int major = Integer.parseInt(matcher.group(1));
int minor = Integer.parseInt(matcher.group(2));
int patch = Integer.parseInt(matcher.group(3));
String description = matcher.group(4) != null ? matcher.group(4) : "";
return new Version(major, minor, patch, description);
}
int getMajor() {
return mMajor;
}
int getMinor() {
return mMinor;
}
int getPatch() {
return mPatch;
}
String getDescription() {
return mDescription;
}
@NonNull
@Override
public String toString() {
final StringBuilder sb = new StringBuilder(getMajor())
.append(".")
.append(getMinor())
.append(".")
.append(getPatch());
if (!TextUtils.isEmpty(getDescription())) {
sb.append("-").append(getDescription());
}
return sb.toString();
}
/**
* To compare the major, minor and patch version with another.
*
* @param other The version to compare to this one.
* @return 0 if it have the same major minor and patch version; less than 0 if this version
* sorts ahead of <var>other</var>; greater than 0 if this version sorts after <var>other</var>.
*/
@Override
public int compareTo(@NonNull Version other) {
return toBigInteger().compareTo(other.toBigInteger());
}
@NonNull
private BigInteger toBigInteger() {
if (mBigInteger == null) {
mBigInteger = BigInteger.valueOf(mMajor)
.shiftLeft(32)
.or(BigInteger.valueOf(mMinor))
.shiftLeft(32)
.or(BigInteger.valueOf(mPatch));
}
return mBigInteger;
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof Version)) {
return false;
}
Version otherVersionObj = (Version) obj;
// The equals checking ignores the description.
return mMajor == otherVersionObj.mMajor
&& mMinor == otherVersionObj.mMinor
&& mPatch == otherVersionObj.mPatch;
}
@Override
public int hashCode() {
// The hash code ignores the description.
int result = 17;
result = result * 31 + mMajor;
result = result * 31 + mMinor;
result = result * 31 + mPatch;
return result;
}
}