1 /* 2 * Copyright (C) 2023 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.extensions.util; 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 * This is used for {@link SidecarUtil}. 34 */ 35 public final class Version implements Comparable<Version> { 36 public static final Version UNKNOWN = new Version(0, 0, 0, ""); 37 38 private static final String VERSION_PATTERN_STRING = 39 "(\\d+)(?:\\.(\\d+))(?:\\.(\\d+))(?:-(.+))?"; 40 41 private final int mMajor; 42 private final int mMinor; 43 private final int mPatch; 44 private final String mDescription; 45 // Cached BigInteger value of the version. 46 private BigInteger mBigInteger; 47 Version(int major, int minor, int patch, String description)48 public Version(int major, int minor, int patch, String description) { 49 mMajor = major; 50 mMinor = minor; 51 mPatch = patch; 52 mDescription = description; 53 } 54 55 /** 56 * Parses a string to a version object. 57 * 58 * @param versionString string in the format "1.2.3" or "1.2.3-Description" 59 * (major.minor.patch[-description]) 60 * @return the parsed Version object or {@code null}> if the versionString format is invalid. 61 */ 62 @Nullable parse(String versionString)63 public static Version parse(String versionString) { 64 if (TextUtils.isEmpty(versionString)) { 65 return null; 66 } 67 68 Matcher matcher = Pattern.compile(VERSION_PATTERN_STRING).matcher(versionString); 69 if (!matcher.matches()) { 70 return null; 71 } 72 73 int major = Integer.parseInt(matcher.group(1)); 74 int minor = Integer.parseInt(matcher.group(2)); 75 int patch = Integer.parseInt(matcher.group(3)); 76 String description = matcher.group(4) != null ? matcher.group(4) : ""; 77 return new Version(major, minor, patch, description); 78 } 79 80 /** Checks whether the version is in the correct format. */ isValidVersion(String versionString)81 public static boolean isValidVersion(String versionString) { 82 Matcher matcher = Pattern.compile(VERSION_PATTERN_STRING).matcher(versionString); 83 return matcher.matches(); 84 } 85 86 /** Major version of the vendor implementation. */ getMajor()87 public int getMajor() { 88 return mMajor; 89 } 90 getMinor()91 int getMinor() { 92 return mMinor; 93 } 94 getPatch()95 int getPatch() { 96 return mPatch; 97 } 98 getDescription()99 String getDescription() { 100 return mDescription; 101 } 102 103 @NonNull 104 @Override toString()105 public String toString() { 106 final StringBuilder sb = new StringBuilder() 107 .append(getMajor()) 108 .append(".") 109 .append(getMinor()) 110 .append(".") 111 .append(getPatch()); 112 if (!TextUtils.isEmpty(getDescription())) { 113 sb.append("-").append(getDescription()); 114 } 115 return sb.toString(); 116 } 117 118 /** 119 * To compare the major, minor and patch version with another. 120 * 121 * @param other The version to compare to this one. 122 * @return 0 if it have the same major minor and patch version; less than 0 if this version 123 * sorts ahead of <var>other</var>; greater than 0 if this version sorts after <var>other</var>. 124 */ 125 @Override compareTo(@onNull Version other)126 public int compareTo(@NonNull Version other) { 127 return toBigInteger().compareTo(other.toBigInteger()); 128 } 129 130 @NonNull toBigInteger()131 private BigInteger toBigInteger() { 132 if (mBigInteger == null) { 133 mBigInteger = BigInteger.valueOf(mMajor) 134 .shiftLeft(32) 135 .or(BigInteger.valueOf(mMinor)) 136 .shiftLeft(32) 137 .or(BigInteger.valueOf(mPatch)); 138 } 139 return mBigInteger; 140 } 141 142 @Override equals(Object obj)143 public boolean equals(Object obj) { 144 if (!(obj instanceof Version)) { 145 return false; 146 } 147 148 Version otherVersionObj = (Version) obj; 149 150 // The equals checking ignores the description. 151 return mMajor == otherVersionObj.mMajor 152 && mMinor == otherVersionObj.mMinor 153 && mPatch == otherVersionObj.mPatch; 154 } 155 156 @Override hashCode()157 public int hashCode() { 158 // The hash code ignores the description. 159 int result = 17; 160 result = result * 31 + mMajor; 161 result = result * 31 + mMinor; 162 result = result * 31 + mPatch; 163 return result; 164 } 165 } 166