blob: 02ea2887ec6290114e9ce427a3149078008defc2 [file] [log] [blame]
/*
* Copyright (C) 2015 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.tools.idea.sdk.remote.internal.updater;
import com.android.annotations.Nullable;
import com.android.sdklib.AndroidVersion;
import com.android.sdklib.repository.FullRevision;
import com.android.sdklib.repository.local.LocalPkgInfo;
import com.android.tools.idea.sdk.remote.RemotePkgInfo;
import com.android.tools.idea.sdk.remote.internal.archives.Archive;
import com.android.tools.idea.sdk.remote.internal.packages.IAndroidVersionProvider;
import com.android.tools.idea.sdk.remote.internal.sources.SdkSource;
import com.google.common.base.Objects;
/**
* 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.
*/
public class PkgItem implements Comparable<PkgItem> {
private final PkgState mState;
private final LocalPkgInfo mMainPkg;
private RemotePkgInfo 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(LocalPkgInfo mainPkg, PkgState state) {
mMainPkg = mainPkg;
mState = state;
assert mMainPkg != null;
}
public boolean isObsolete() {
return mMainPkg.getDesc().isObsolete();
}
public boolean isChecked() {
return mChecked;
}
public void setChecked(boolean checked) {
mChecked = checked;
}
public RemotePkgInfo getUpdatePkg() {
return mUpdatePkg;
}
public boolean hasUpdatePkg() {
return mUpdatePkg != null;
}
public String getName() {
return mMainPkg.getListDescription();
}
public FullRevision getRevision() {
return mMainPkg.getDesc().getFullRevision();
}
public LocalPkgInfo getMainPackage() {
return mMainPkg;
}
public PkgState getState() {
return mState;
}
@Nullable
public SdkSource getSource() {
return mUpdatePkg == null ? null : mUpdatePkg.getParentSource();
}
@Nullable
public AndroidVersion getAndroidVersion() {
return mMainPkg instanceof IAndroidVersionProvider ? ((IAndroidVersionProvider)mMainPkg).getAndroidVersion() : null;
}
@Nullable
public Archive[] getArchives() {
return mUpdatePkg == null ? null : mUpdatePkg.getArchives();
}
@Override
public int compareTo(PkgItem pkg) {
return getMainPackage().compareTo(pkg.getMainPackage());
}
/**
* Equality is defined as {@link #isSameItemAs(PkgItem)}: state, main package
* and update package must be the similar.
*/
@Override
public boolean equals(Object obj) {
if (!(obj instanceof PkgItem)) {
return false;
}
PkgItem other = (PkgItem)obj;
return mMainPkg.equals(other.mMainPkg)
&& Objects.equal(mUpdatePkg, other.mUpdatePkg)
&& mState.equals(other.mState);
}
@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.
* <p/>
* This should only be used for installed packages.
*/
public boolean mergeUpdate(RemotePkgInfo pkg) {
if (mUpdatePkg == pkg) {
return true;
}
if (pkg.canUpdate(mMainPkg) == RemotePkgInfo.UpdateInfo.UPDATE) {
if (mUpdatePkg == null) {
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();
}
}