• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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