2 * Copyright (C) 2009 The Android Open Source Project
\r
4 * Licensed under the Apache License, Version 2.0 (the "License");
\r
5 * you may not use this file except in compliance with the License.
\r
6 * You may obtain a copy of the License at
\r
8 * http://www.apache.org/licenses/LICENSE-2.0
\r
10 * Unless required by applicable law or agreed to in writing, software
\r
11 * distributed under the License is distributed on an "AS IS" BASIS,
\r
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
\r
13 * See the License for the specific language governing permissions and
\r
14 * limitations under the License.
\r
17 package com.android.sdkuilib.internal.repository;
\r
19 import com.android.sdklib.internal.repository.Archive;
\r
20 import com.android.sdklib.internal.repository.IDescription;
\r
21 import com.android.sdklib.internal.repository.ITask;
\r
22 import com.android.sdklib.internal.repository.ITaskMonitor;
\r
23 import com.android.sdklib.internal.repository.Package;
\r
24 import com.android.sdklib.internal.repository.RepoSource;
\r
25 import com.android.sdklib.internal.repository.Package.UpdateInfo;
\r
26 import com.android.sdkuilib.internal.repository.icons.ImageFactory;
\r
28 import org.eclipse.jface.viewers.IContentProvider;
\r
29 import org.eclipse.jface.viewers.ILabelProvider;
\r
30 import org.eclipse.jface.viewers.ITreeContentProvider;
\r
31 import org.eclipse.jface.viewers.LabelProvider;
\r
32 import org.eclipse.jface.viewers.Viewer;
\r
33 import org.eclipse.swt.graphics.Image;
\r
35 import java.util.ArrayList;
\r
38 * A list of sdk-repository sources.
\r
40 * This implementation is UI dependent.
\r
42 public class RepoSourcesAdapter {
\r
44 private final UpdaterData mUpdaterData;
\r
46 public static class RepoSourceError implements IDescription {
\r
48 private final RepoSource mSource;
\r
50 public RepoSourceError(RepoSource source) {
\r
54 public String getLongDescription() {
\r
55 return mSource.getLongDescription();
\r
58 public String getShortDescription() {
\r
59 return mSource.getFetchError();
\r
64 public RepoSourcesAdapter(UpdaterData updaterData) {
\r
65 mUpdaterData = updaterData;
\r
68 public ILabelProvider getLabelProvider() {
\r
69 return new ViewerLabelProvider();
\r
73 public IContentProvider getContentProvider() {
\r
74 return new TreeContentProvider();
\r
79 private class ViewerLabelProvider extends LabelProvider {
\r
81 /** Returns an image appropriate for this element. */
\r
83 public Image getImage(Object element) {
\r
85 ImageFactory imgFactory = mUpdaterData.getImageFactory();
\r
87 if (imgFactory != null) {
\r
88 return imgFactory.getImageForObject(element);
\r
91 return super.getImage(element);
\r
94 /** Returns the toString of the element. */
\r
96 public String getText(Object element) {
\r
97 if (element instanceof IDescription) {
\r
98 return ((IDescription) element).getShortDescription();
\r
100 return super.getText(element);
\r
106 private class TreeContentProvider implements ITreeContentProvider {
\r
108 // Called when the viewer is disposed
\r
109 public void dispose() {
\r
113 // Called when the input is set or changed on the provider
\r
114 public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
\r
115 assert newInput == RepoSourcesAdapter.this;
\r
119 * Called to collect the root elements for the given input.
\r
120 * The input here is a {@link RepoSourcesAdapter} object, this returns an array
\r
121 * of {@link RepoSource}.
\r
123 public Object[] getElements(Object inputElement) {
\r
124 return getChildren(inputElement);
\r
128 * Get the children of the given parent. This is requested on-demand as
\r
129 * nodes are expanded.
\r
131 * For a {@link RepoSourcesAdapter} object, returns an array of {@link RepoSource}s.
\r
132 * For a {@link RepoSource}, returns an array of {@link Package}s.
\r
133 * For a {@link Package}, returns an array of {@link Archive}s.
\r
135 public Object[] getChildren(Object parentElement) {
\r
136 if (parentElement == RepoSourcesAdapter.this) {
\r
137 return mUpdaterData.getSources().getSources();
\r
139 } else if (parentElement instanceof RepoSource) {
\r
140 final RepoSource source = (RepoSource) parentElement;
\r
141 Package[] packages = source.getPackages();
\r
143 if (packages == null && source.getFetchError() == null) {
\r
144 final boolean forceHttp = mUpdaterData.getSettingsController().getForceHttp();
\r
146 mUpdaterData.getTaskFactory().start("Loading Source", new ITask() {
\r
147 public void run(ITaskMonitor monitor) {
\r
148 source.load(monitor, forceHttp);
\r
152 packages = source.getPackages();
\r
154 if (packages != null) {
\r
155 // filter out only the packages that are new/upgrade.
\r
156 if (mUpdaterData.getSettingsController().getShowUpdateOnly()) {
\r
157 return filteredPackages(packages);
\r
160 } else if (source.getFetchError() != null) {
\r
161 // Return a dummy entry to display the fetch error
\r
162 return new Object[] { new RepoSourceError(source) };
\r
165 } else if (parentElement instanceof Package) {
\r
166 Archive[] archives = ((Package) parentElement).getArchives();
\r
167 if (mUpdaterData.getSettingsController().getShowUpdateOnly()) {
\r
168 for (Archive archive : archives) {
\r
169 // if we only want the compatible archives, then we just take the first
\r
170 // one. it's unlikely there are 2 compatible archives for the same
\r
172 if (archive.isCompatible()) {
\r
173 return new Object[] { archive };
\r
181 return new Object[0];
\r
185 * Returns the parent of a given element.
\r
186 * The input {@link RepoSourcesAdapter} is the parent of all {@link RepoSource} elements.
\r
188 public Object getParent(Object element) {
\r
190 if (element instanceof RepoSource) {
\r
191 return RepoSourcesAdapter.this;
\r
193 } else if (element instanceof Package) {
\r
194 return ((Package) element).getParentSource();
\r
200 * Returns true if a given element has children, which is used to display a
\r
201 * "+/expand" box next to the tree node.
\r
202 * All {@link RepoSource} and {@link Package} are expandable, whether they actually
\r
203 * have any children or not.
\r
205 public boolean hasChildren(Object element) {
\r
206 return element instanceof RepoSource || element instanceof Package;
\r
211 * Filters out a list of remote packages to only keep the ones that are either new or
\r
212 * updates of existing package.
\r
213 * @param remotePackages the list of packages to filter.
\r
214 * @return a non null (but maybe empty) list of new or update packages.
\r
216 private Object[] filteredPackages(Package[] remotePackages) {
\r
217 // get the installed packages
\r
218 Package[] installedPackages = mUpdaterData.getInstalledPackage();
\r
220 ArrayList<Package> filteredList = new ArrayList<Package>();
\r
222 // for each remote packages, we look for an existing version.
\r
223 // If no existing version -> add to the list
\r
224 // if existing version but with older revision -> add it to the list
\r
225 for (Package remotePkg : remotePackages) {
\r
226 boolean newPkg = true;
\r
228 // For all potential packages, we also make sure that there's an archive for the current
\r
229 // platform, or we simply skip them.
\r
230 if (remotePkg.hasCompatibleArchive()) {
\r
231 for (Package installedPkg : installedPackages) {
\r
232 UpdateInfo info = installedPkg.canBeUpdatedBy(remotePkg);
\r
233 if (info == UpdateInfo.UPDATE) {
\r
234 filteredList.add(remotePkg);
\r
236 break; // there shouldn't be 2 revision of the same package
\r
237 } else if (info != UpdateInfo.INCOMPATIBLE) {
\r
239 break; // there shouldn't be 2 revision of the same package
\r
243 // if we have not found the same package, then we add it (it's a new package)
\r
245 filteredList.add(remotePkg);
\r
250 return filteredList.toArray();
\r