1 /* 2 * Copyright (C) 2021 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.server.wm.jetpack.utils; 18 19 import android.text.TextUtils; 20 21 import androidx.annotation.NonNull; 22 import androidx.annotation.Nullable; 23 24 import java.math.BigInteger; 25 import java.util.regex.Matcher; 26 import java.util.regex.Pattern; 27 28 29 /** 30 * Class encapsulating a version with major, minor, patch and description values. Copied from 31 * androidx.window.Version. 32 */ 33 public final class Version implements Comparable<Version> { 34 public static final Version UNKNOWN = new Version(0, 0, 0, ""); 35 36 private static final String VERSION_PATTERN_STRING = 37 "(\\d+)(?:\\.(\\d+))(?:\\.(\\d+))(?:-(.+))?"; 38 39 private final int mMajor; 40 private final int mMinor; 41 private final int mPatch; 42 private final String mDescription; 43 // Cached BigInteger value of the version. 44 private BigInteger mBigInteger; 45 Version(int major, int minor, int patch, String description)46 public Version(int major, int minor, int patch, String description) { 47 mMajor = major; 48 mMinor = minor; 49 mPatch = patch; 50 mDescription = description; 51 } 52 53 /** 54 * Parses a string to a version object. 55 * 56 * @param versionString string in the format "1.2.3" or "1.2.3-Description" 57 * (major.minor.patch[-description]) 58 * @return the parsed Version object or {@code null}> if the versionString format is invalid. 59 */ 60 @Nullable parse(String versionString)61 public static Version parse(String versionString) { 62 if (TextUtils.isEmpty(versionString)) { 63 return null; 64 } 65 66 Matcher matcher = Pattern.compile(VERSION_PATTERN_STRING).matcher(versionString); 67 if (!matcher.matches()) { 68 return null; 69 } 70 71 int major = Integer.parseInt(matcher.group(1)); 72 int minor = Integer.parseInt(matcher.group(2)); 73 int patch = Integer.parseInt(matcher.group(3)); 74 String description = matcher.group(4) != null ? matcher.group(4) : ""; 75 return new Version(major, minor, patch, description); 76 } 77 78 /** Checks whether the version is in the correct format. */ isValidVersion(String versionString)79 public static boolean isValidVersion(String versionString) { 80 Matcher matcher = Pattern.compile(VERSION_PATTERN_STRING).matcher(versionString); 81 return matcher.matches(); 82 } 83 84 /** Major version of the vendor implementation. */ getMajor()85 public int getMajor() { 86 return mMajor; 87 } 88 getMinor()89 int getMinor() { 90 return mMinor; 91 } 92 getPatch()93 int getPatch() { 94 return mPatch; 95 } 96 getDescription()97 String getDescription() { 98 return mDescription; 99 } 100 101 @NonNull 102 @Override toString()103 public String toString() { 104 final StringBuilder sb = new StringBuilder() 105 .append(getMajor()) 106 .append(".") 107 .append(getMinor()) 108 .append(".") 109 .append(getPatch()); 110 if (!TextUtils.isEmpty(getDescription())) { 111 sb.append("-").append(getDescription()); 112 } 113 return sb.toString(); 114 } 115 116 /** 117 * To compare the major, minor and patch version with another. 118 * 119 * @param other The version to compare to this one. 120 * @return 0 if it have the same major minor and patch version; less than 0 if this version 121 * sorts ahead of <var>other</var>; greater than 0 if this version sorts after <var>other</var>. 122 */ 123 @Override compareTo(@onNull Version other)124 public int compareTo(@NonNull Version other) { 125 return toBigInteger().compareTo(other.toBigInteger()); 126 } 127 128 @NonNull toBigInteger()129 private BigInteger toBigInteger() { 130 if (mBigInteger == null) { 131 mBigInteger = BigInteger.valueOf(mMajor) 132 .shiftLeft(32) 133 .or(BigInteger.valueOf(mMinor)) 134 .shiftLeft(32) 135 .or(BigInteger.valueOf(mPatch)); 136 } 137 return mBigInteger; 138 } 139 140 @Override equals(Object obj)141 public boolean equals(Object obj) { 142 if (!(obj instanceof Version)) { 143 return false; 144 } 145 146 Version otherVersionObj = (Version) obj; 147 148 // The equals checking ignores the description. 149 return mMajor == otherVersionObj.mMajor 150 && mMinor == otherVersionObj.mMinor 151 && mPatch == otherVersionObj.mPatch; 152 } 153 154 @Override hashCode()155 public int hashCode() { 156 // The hash code ignores the description. 157 int result = 17; 158 result = result * 31 + mMajor; 159 result = result * 31 + mMinor; 160 result = result * 31 + mPatch; 161 return result; 162 } 163 } 164