/* * Copyright (C) 2011 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 com.android.sdklib.internal.repository.updater; import com.android.annotations.Nullable; import com.android.sdklib.AndroidVersion; import com.android.sdklib.repository.IDescription; import com.android.sdklib.internal.repository.archives.Archive; import com.android.sdklib.internal.repository.packages.IAndroidVersionProvider; import com.android.sdklib.internal.repository.packages.Package; import com.android.sdklib.internal.repository.packages.Package.UpdateInfo; import com.android.sdklib.internal.repository.sources.SdkSource; import com.android.sdklib.repository.FullRevision; /** * A {@link PkgItem} represents one main {@link Package} combined with its state * and an optional update package. * <p/> * The main package is final and cannot change since it's what "defines" this PkgItem. * The state or update package can change later. * * @deprecated * com.android.sdklib.internal.repository has moved into Studio as * com.android.tools.idea.sdk.remote.internal. */ @Deprecated public class PkgItem implements Comparable<PkgItem> { private final PkgState mState; private final Package mMainPkg; private Package mUpdatePkg; private boolean mChecked; /** * The state of the a given {@link PkgItem}, that is the relationship between * a given remote package and the local repository. */ public enum PkgState { // Implementation detail: if this is changed then PackageDiffLogic#STATES // and PackageDiffLogic#processSource() need to be changed accordingly. /** * Package is locally installed and may or may not have an update. */ INSTALLED, /** * There's a new package available on the remote site that isn't installed locally. */ NEW } /** * Create a new {@link PkgItem} for this main package. * The main package is final and cannot change since it's what "defines" this PkgItem. * The state or update package can change later. */ public PkgItem(Package mainPkg, PkgState state) { mMainPkg = mainPkg; mState = state; assert mMainPkg != null; } public boolean isObsolete() { return mMainPkg.isObsolete(); } public boolean isChecked() { return mChecked; } public void setChecked(boolean checked) { mChecked = checked; } public Package getUpdatePkg() { return mUpdatePkg; } public boolean hasUpdatePkg() { return mUpdatePkg != null; } public String getName() { return mMainPkg.getListDescription(); } public FullRevision getRevision() { return mMainPkg.getRevision(); } /** * @deprecated Use {@link #getMainPackage()} with the {@link IDescription} interface instead. */ @Deprecated public String getDescription() { return mMainPkg.getLongDescription(); } public Package getMainPackage() { return mMainPkg; } public PkgState getState() { return mState; } public SdkSource getSource() { return mMainPkg.getParentSource(); } @Nullable public AndroidVersion getAndroidVersion() { return mMainPkg instanceof IAndroidVersionProvider ? ((IAndroidVersionProvider) mMainPkg).getAndroidVersion() : null; } public Archive[] getArchives() { return mMainPkg.getArchives(); } @Override public int compareTo(PkgItem pkg) { return getMainPackage().compareTo(pkg.getMainPackage()); } /** * Returns true if this package or its updating packages contains * the exact given archive. * Important: This compares object references, not object equality. */ public boolean hasArchive(Archive archive) { if (mMainPkg.hasArchive(archive)) { return true; } if (mUpdatePkg != null && mUpdatePkg.hasArchive(archive)) { return true; } return false; } /** * Returns true if the main package has at least one archive * compatible with the current platform. */ public boolean hasCompatibleArchive() { return mMainPkg.hasCompatibleArchive(); } /** * Checks whether the main packages are of the same type and are * not an update of each other and have the same revision number. */ public boolean isSameMainPackageAs(Package pkg) { if (mMainPkg.canBeUpdatedBy(pkg) == UpdateInfo.NOT_UPDATE) { // package revision numbers must match return mMainPkg.getRevision().equals(pkg.getRevision()); } return false; } /** * Checks whether the update packages are of the same type and are * not an update of each other and have the same revision numbers. */ public boolean isSameUpdatePackageAs(Package pkg) { if (mUpdatePkg != null && mUpdatePkg.canBeUpdatedBy(pkg) == UpdateInfo.NOT_UPDATE) { // package revision numbers must match return mUpdatePkg.getRevision().equals(pkg.getRevision()); } return false; } /** * Checks whether too {@link PkgItem} are the same. * This checks both items have the same state, both main package are similar * and that they have the same updating packages. */ public boolean isSameItemAs(PkgItem item) { if (this == item) { return true; } boolean same = this.mState == item.mState; if (same) { same = isSameMainPackageAs(item.getMainPackage()); } if (same) { // check updating packages are the same Package p1 = this.mUpdatePkg; Package p2 = item.getUpdatePkg(); same = (p1 == p2) || (p1 == null && p2 == null) || (p1 != null && p2 != null); if (same && p1 != null) { same = p1.canBeUpdatedBy(p2) == UpdateInfo.NOT_UPDATE; } } return same; } /** * Equality is defined as {@link #isSameItemAs(PkgItem)}: state, main package * and update package must be the similar. */ @Override public boolean equals(Object obj) { return (obj instanceof PkgItem) && this.isSameItemAs((PkgItem) obj); } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((mState == null) ? 0 : mState.hashCode()); result = prime * result + ((mMainPkg == null) ? 0 : mMainPkg.hashCode()); result = prime * result + ((mUpdatePkg == null) ? 0 : mUpdatePkg.hashCode()); return result; } /** * Check whether the 'pkg' argument is an update for this package. * If it is, record it as an updating package. * If there's already an updating package, only keep the most recent update. * Returns true if it is update (even if there was already an update and this * ended up not being the most recent), false if incompatible or not an update. * * This should only be used for installed packages. */ public boolean mergeUpdate(Package pkg) { if (mUpdatePkg == pkg) { return true; } if (mMainPkg.canBeUpdatedBy(pkg) == UpdateInfo.UPDATE) { if (mUpdatePkg == null) { mUpdatePkg = pkg; } else if (mUpdatePkg.canBeUpdatedBy(pkg) == UpdateInfo.UPDATE) { // If we have more than one, keep only the most recent update mUpdatePkg = pkg; } return true; } return false; } public void removeUpdate() { mUpdatePkg = null; } /** Returns a string representation of this item, useful when debugging. */ @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append('<'); if (mChecked) { sb.append(" * "); //$NON-NLS-1$ } sb.append(mState.toString()); if (mMainPkg != null) { sb.append(", pkg:"); //$NON-NLS-1$ sb.append(mMainPkg.toString()); } if (mUpdatePkg != null) { sb.append(", updated by:"); //$NON-NLS-1$ sb.append(mUpdatePkg.toString()); } sb.append('>'); return sb.toString(); } }