1 /* 2 * Copyright (C) 2011 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 com.android.sdkuilib.internal.repository.sdkman2; 18 19 import com.android.sdklib.internal.repository.archives.Archive; 20 import com.android.sdklib.internal.repository.packages.IPackageVersion; 21 import com.android.sdklib.internal.repository.packages.Package; 22 import com.android.sdklib.internal.repository.packages.Package.UpdateInfo; 23 import com.android.sdklib.internal.repository.sources.SdkSource; 24 25 /** 26 * A {@link PkgItem} represents one main {@link Package} combined with its state 27 * and an optional update package. 28 * <p/> 29 * The main package is final and cannot change since it's what "defines" this PkgItem. 30 * The state or update package can change later. 31 */ 32 public class PkgItem implements Comparable<PkgItem> { 33 private final PkgState mState; 34 private final Package mMainPkg; 35 private Package mUpdatePkg; 36 private boolean mChecked; 37 38 /** 39 * The state of the a given {@link PkgItem}, that is the relationship between 40 * a given remote package and the local repository. 41 */ 42 public enum PkgState { 43 // Implementation detail: if this is changed then PackageDiffLogic#STATES 44 // and PackageDiffLogic#processSource() need to be changed accordingly. 45 46 /** 47 * Package is locally installed and may or may not have an update. 48 */ 49 INSTALLED, 50 51 /** 52 * There's a new package available on the remote site that isn't installed locally. 53 */ 54 NEW 55 } 56 57 /** 58 * Create a new {@link PkgItem} for this main package. 59 * The main package is final and cannot change since it's what "defines" this PkgItem. 60 * The state or update package can change later. 61 */ PkgItem(Package mainPkg, PkgState state)62 public PkgItem(Package mainPkg, PkgState state) { 63 mMainPkg = mainPkg; 64 mState = state; 65 assert mMainPkg != null; 66 } 67 isObsolete()68 public boolean isObsolete() { 69 return mMainPkg.isObsolete(); 70 } 71 isChecked()72 public boolean isChecked() { 73 return mChecked; 74 } 75 setChecked(boolean checked)76 public void setChecked(boolean checked) { 77 mChecked = checked; 78 } 79 getUpdatePkg()80 public Package getUpdatePkg() { 81 return mUpdatePkg; 82 } 83 hasUpdatePkg()84 public boolean hasUpdatePkg() { 85 return mUpdatePkg != null; 86 } 87 getName()88 public String getName() { 89 return mMainPkg.getListDescription(); 90 } 91 getRevision()92 public int getRevision() { 93 return mMainPkg.getRevision(); 94 } 95 getDescription()96 public String getDescription() { 97 return mMainPkg.getDescription(); 98 } 99 getMainPackage()100 public Package getMainPackage() { 101 return mMainPkg; 102 } 103 getState()104 public PkgState getState() { 105 return mState; 106 } 107 getSource()108 public SdkSource getSource() { 109 return mMainPkg.getParentSource(); 110 } 111 getApi()112 public int getApi() { 113 return mMainPkg instanceof IPackageVersion ? 114 ((IPackageVersion) mMainPkg).getVersion().getApiLevel() : 115 -1; 116 } 117 getArchives()118 public Archive[] getArchives() { 119 return mMainPkg.getArchives(); 120 } 121 122 @Override compareTo(PkgItem pkg)123 public int compareTo(PkgItem pkg) { 124 return getMainPackage().compareTo(pkg.getMainPackage()); 125 } 126 127 /** 128 * Returns true if this package or its updating packages contains 129 * the exact given archive. 130 * Important: This compares object references, not object equality. 131 */ hasArchive(Archive archive)132 public boolean hasArchive(Archive archive) { 133 if (mMainPkg.hasArchive(archive)) { 134 return true; 135 } 136 if (mUpdatePkg != null && mUpdatePkg.hasArchive(archive)) { 137 return true; 138 } 139 return false; 140 } 141 142 /** 143 * Returns true if the main package has at least one archive 144 * compatible with the current platform. 145 */ hasCompatibleArchive()146 public boolean hasCompatibleArchive() { 147 return mMainPkg.hasCompatibleArchive(); 148 } 149 150 /** 151 * Checks whether the main packages are of the same type and are 152 * not an update of each other. 153 */ isSameMainPackageAs(Package pkg)154 public boolean isSameMainPackageAs(Package pkg) { 155 if (mMainPkg.canBeUpdatedBy(pkg) == UpdateInfo.NOT_UPDATE) { 156 // package revision numbers must match 157 return mMainPkg.getRevision() == pkg.getRevision(); 158 } 159 return false; 160 } 161 162 /** 163 * Checks whether the update packages are of the same type and are 164 * not an update of each other. 165 */ isSameUpdatePackageAs(Package pkg)166 public boolean isSameUpdatePackageAs(Package pkg) { 167 if (mUpdatePkg != null && mUpdatePkg.canBeUpdatedBy(pkg) == UpdateInfo.NOT_UPDATE) { 168 // package revision numbers must match 169 return mUpdatePkg.getRevision() == pkg.getRevision(); 170 } 171 return false; 172 } 173 174 /** 175 * Checks whether too {@link PkgItem} are the same. 176 * This checks both items have the same state, both main package are similar 177 * and that they have the same updating packages. 178 */ isSameItemAs(PkgItem item)179 public boolean isSameItemAs(PkgItem item) { 180 if (this == item) { 181 return true; 182 } 183 boolean same = this.mState == item.mState; 184 if (same) { 185 same = isSameMainPackageAs(item.getMainPackage()); 186 } 187 188 if (same) { 189 // check updating packages are the same 190 Package p1 = this.mUpdatePkg; 191 Package p2 = item.getUpdatePkg(); 192 same = (p1 == p2) || (p1 == null && p2 == null) || (p1 != null && p2 != null); 193 194 if (same && p1 != null) { 195 same = p1.canBeUpdatedBy(p2) == UpdateInfo.NOT_UPDATE; 196 } 197 } 198 199 return same; 200 } 201 202 /** 203 * Equality is defined as {@link #isSameItemAs(PkgItem)}: state, main package 204 * and update package must be the similar. 205 */ 206 @Override equals(Object obj)207 public boolean equals(Object obj) { 208 return (obj instanceof PkgItem) && this.isSameItemAs((PkgItem) obj); 209 } 210 211 @Override hashCode()212 public int hashCode() { 213 final int prime = 31; 214 int result = 1; 215 result = prime * result + ((mState == null) ? 0 : mState.hashCode()); 216 result = prime * result + ((mMainPkg == null) ? 0 : mMainPkg.hashCode()); 217 result = prime * result + ((mUpdatePkg == null) ? 0 : mUpdatePkg.hashCode()); 218 return result; 219 } 220 221 /** 222 * Check whether the 'pkg' argument is an update for this package. 223 * If it is, record it as an updating package. 224 * If there's already an updating package, only keep the most recent update. 225 * Returns true if it is update (even if there was already an update and this 226 * ended up not being the most recent), false if incompatible or not an update. 227 * 228 * This should only be used for installed packages. 229 */ mergeUpdate(Package pkg)230 public boolean mergeUpdate(Package pkg) { 231 if (mUpdatePkg == pkg) { 232 return true; 233 } 234 if (mMainPkg.canBeUpdatedBy(pkg) == UpdateInfo.UPDATE) { 235 if (mUpdatePkg == null) { 236 mUpdatePkg = pkg; 237 } else if (mUpdatePkg.canBeUpdatedBy(pkg) == UpdateInfo.UPDATE) { 238 // If we have more than one, keep only the most recent update 239 mUpdatePkg = pkg; 240 } 241 return true; 242 } 243 244 return false; 245 } 246 removeUpdate()247 public void removeUpdate() { 248 mUpdatePkg = null; 249 } 250 251 /** Returns a string representation of this item, useful when debugging. */ 252 @Override toString()253 public String toString() { 254 StringBuilder sb = new StringBuilder(); 255 sb.append('<'); 256 257 if (mChecked) { 258 sb.append(" * "); //$NON-NLS-1$ 259 } 260 261 sb.append(mState.toString()); 262 263 if (mMainPkg != null) { 264 sb.append(", pkg:"); //$NON-NLS-1$ 265 sb.append(mMainPkg.toString()); 266 } 267 268 if (mUpdatePkg != null) { 269 sb.append(", updated by:"); //$NON-NLS-1$ 270 sb.append(mUpdatePkg.toString()); 271 } 272 273 sb.append('>'); 274 return sb.toString(); 275 } 276 } 277