diff options
author | Raphael Moll <ralf@android.com> | 2011-06-24 12:22:00 -0700 |
---|---|---|
committer | Android Code Review <code-review@android.com> | 2011-06-24 12:22:00 -0700 |
commit | c233709ec350fd0b2364c84a98194fa3351b2017 (patch) | |
tree | 2c7293abdd4058f3e35618934284e85c595df03c | |
parent | 148fe1908137e7f5ce24a5f2170a7254a71fc57d (diff) | |
parent | cc556534e4b9e8e42e65f6ded684430858238471 (diff) | |
download | sdk-c233709ec350fd0b2364c84a98194fa3351b2017.zip sdk-c233709ec350fd0b2364c84a98194fa3351b2017.tar.gz sdk-c233709ec350fd0b2364c84a98194fa3351b2017.tar.bz2 |
Merge "Sdkman2: Simplify packages names, fix extra package sort."
3 files changed, 226 insertions, 67 deletions
diff --git a/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/ExtraPackage.java b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/ExtraPackage.java index c142faf..793c98d 100755 --- a/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/ExtraPackage.java +++ b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/ExtraPackage.java @@ -526,6 +526,24 @@ public class ExtraPackage extends MinToolsPackage return false;
}
+ /**
+ * For extra packages, we want to add vendor|path to the sorting key
+ * <em>before<em/> the revision number.
+ * <p/>
+ * {@inheritDoc}
+ */
+ @Override
+ protected String comparisonKey() {
+ String s = super.comparisonKey();
+ int pos = s.indexOf("|r:"); //$NON-NLS-1$
+ assert pos > 0;
+ s = s.substring(0, pos) +
+ "|ve:" + getVendor() + //$NON-NLS-1$
+ "|pa:" + getPath() + //$NON-NLS-1$
+ s.substring(pos);
+ return s;
+ }
+
// ---
/**
diff --git a/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/Package.java b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/Package.java index baa6706..faf5a00 100755 --- a/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/Package.java +++ b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/Package.java @@ -557,46 +557,83 @@ public abstract class Package implements IDescription, Comparable<Package> { * <p/>
* This {@link #compareTo(Package)} method is purely an implementation detail to
* perform the right ordering of the packages in the list of available or installed packages.
+ * <p/>
+ * <em>Important</em>: Derived classes should consider overriding {@link #comparisonKey()}
+ * instead of this method.
*/
public int compareTo(Package other) {
- int s1 = this.sortingScore();
- int s2 = other.sortingScore();
- return s1 - s2;
+ String s1 = this.comparisonKey();
+ String s2 = other.comparisonKey();
+
+ return s1.compareTo(s2);
}
/**
- * Computes the score for each package used by {@link #compareTo(Package)}.
+ * Computes a comparison key for each package used by {@link #compareTo(Package)}.
+ * The key is a string.
+ * The base package class return a string that encodes the package type,
+ * the revision number and the platform version, if applicable, in the form:
+ * <pre>
+ * t:N|v:NNNN.P|r:NNNN|
+ * </pre>
+ * All fields must start by a "letter colon" prefix and end with a vertical pipe (|, ASCII 124).
+ * <p/>
+ * The string format <em>may</em> change between releases and clients should not
+ * store them outside of the session or expect them to be consistent between
+ * different releases. They are purely an internal implementation details of the
+ * {@link #compareTo(Package)} method.
+ * <p/>
+ * Derived classes should get the string from the super class and then append
+ * or <em>insert</em> their own |-separated content.
+ * For example an extra vendor name & path can be inserted before the revision
+ * number, since it has more sorting weight.
*/
- private int sortingScore() {
- // up to 31 bits (for signed stuff)
- int type = 0; // max type=7 => 3 bits
- int rev = getRevision(); // 12 bits... 4095
- int offset = 0; // 16 bits...
+ protected String comparisonKey() {
+
+ StringBuilder sb = new StringBuilder();
+
+ sb.append("t:"); //$NON-NLS-1$
if (this instanceof ToolPackage) {
- type = 6;
+ sb.append(0);
} else if (this instanceof PlatformToolPackage) {
- type = 5;
+ sb.append(1);
} else if (this instanceof DocPackage) {
- type = 4;
+ sb.append(2);
} else if (this instanceof PlatformPackage) {
- type = 3;
+ sb.append(3);
} else if (this instanceof SamplePackage) {
- type = 2;
+ sb.append(4);
} else if (this instanceof AddonPackage) {
- type = 1;
+ sb.append(5);
} else {
// extras and everything else
- type = 0;
+ sb.append(9);
}
+ sb.append("|v:"); //$NON-NLS-1$
+
+
+ // We insert the package version here because it is more important
+ // than the revision number. We want package version to be sorted
+ // top-down, so we'll use 10k-api as the sorting key. The day we
+ // get reach 10k APIs, we'll need to revisit this.
if (this instanceof IPackageVersion) {
AndroidVersion v = ((IPackageVersion) this).getVersion();
- offset = v.getApiLevel();
- offset = offset * 2 + (v.isPreview() ? 1 : 0);
+
+ sb.append(String.format("%1$04d.%2$d", //$NON-NLS-1$
+ 10000 - v.getApiLevel(),
+ v.isPreview() ? 1 : 0
+ ));
}
+ sb.append("|r:"); //$NON-NLS-1$
+
- int n = (type << 28) + (offset << 12) + rev;
- return 0 - n;
+ // Append revision number
+
+ sb.append(String.format("%1$04d", getRevision())); //$NON-NLS-1$
+ sb.append('|');
+
+ return sb.toString();
}
}
diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/PackagesPage.java b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/PackagesPage.java index 570f769..2b7a0db 100755 --- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/PackagesPage.java +++ b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/PackagesPage.java @@ -147,6 +147,7 @@ public class PackagesPage extends UpdaterPage private TreeViewerColumn mColumnStatus; private Font mTreeFontItalic; private TreeColumn mTreeColumnName; + private boolean mLastSortWasByApi; public PackagesPage(Composite parent, int swtStyle, UpdaterData updaterData) { super(parent, swtStyle); @@ -532,7 +533,7 @@ public class PackagesPage extends UpdaterPage } private void sortPackages(boolean updateButtons) { - if (mCheckSortApi != null && !mCheckSortApi.isDisposed() && mCheckSortApi.getSelection()) { + if (isSortByApi()) { sortByApiLevel(); } else { sortBySource(); @@ -543,6 +544,10 @@ public class PackagesPage extends UpdaterPage } } + private boolean isSortByApi() { + return mCheckSortApi != null && !mCheckSortApi.isDisposed() && mCheckSortApi.getSelection(); + } + /** * Recompute the tree by sorting all the packages by API. * This does an update in-place of the mCategories list so that the table @@ -556,34 +561,44 @@ public class PackagesPage extends UpdaterPage mTreeColumnName.setImage(getImage(ICON_SORT_BY_API)); } + // If the sorting mode changed, clear the categories. + if (!mLastSortWasByApi) { + mLastSortWasByApi = true; + mCategories.clear(); + } + // keep a map of the initial state so that we can detect which items or categories are // no longer being used, so that we can removed them at the end of the in-place update. - final Map<Integer, Pair<PkgCategory, HashSet<PkgItem>> > unusedItemsMap = - new HashMap<Integer, Pair<PkgCategory, HashSet<PkgItem>> >(); - final Set<PkgCategory> unusedCatSet = new HashSet<PkgCategory>(); + final Map<Integer, Pair<PkgApiCategory, HashSet<PkgItem>> > unusedItemsMap = + new HashMap<Integer, Pair<PkgApiCategory, HashSet<PkgItem>> >(); + final Set<PkgApiCategory> unusedCatSet = new HashSet<PkgApiCategory>(); // get existing categories for (PkgCategory cat : mCategories) { - unusedCatSet.add(cat); - unusedItemsMap.put(cat.getKey(), Pair.of(cat, new HashSet<PkgItem>(cat.getItems()))); + if (cat instanceof PkgApiCategory) { + PkgApiCategory acat = (PkgApiCategory) cat; + unusedCatSet.add(acat); + unusedItemsMap.put(acat.getKey(), + Pair.of(acat, new HashSet<PkgItem>(acat.getItems()))); + } } // always add the tools & extras categories, even if empty (unlikely anyway) - if (!unusedItemsMap.containsKey(PkgCategory.KEY_TOOLS)) { - PkgCategory cat = new PkgCategory( - PkgCategory.KEY_TOOLS, - "Tools", + if (!unusedItemsMap.containsKey(PkgApiCategory.KEY_TOOLS)) { + PkgApiCategory cat = new PkgApiCategory( + PkgApiCategory.KEY_TOOLS, + null, imgFactory.getImageByName(ICON_CAT_OTHER)); - unusedItemsMap.put(PkgCategory.KEY_TOOLS, Pair.of(cat, new HashSet<PkgItem>())); + unusedItemsMap.put(PkgApiCategory.KEY_TOOLS, Pair.of(cat, new HashSet<PkgItem>())); mCategories.add(cat); } - if (!unusedItemsMap.containsKey(PkgCategory.KEY_EXTRA)) { - PkgCategory cat = new PkgCategory( - PkgCategory.KEY_EXTRA, - "Extras", + if (!unusedItemsMap.containsKey(PkgApiCategory.KEY_EXTRA)) { + PkgApiCategory cat = new PkgApiCategory( + PkgApiCategory.KEY_EXTRA, + null, imgFactory.getImageByName(ICON_CAT_OTHER)); - unusedItemsMap.put(PkgCategory.KEY_EXTRA, Pair.of(cat, new HashSet<PkgItem>())); + unusedItemsMap.put(PkgApiCategory.KEY_EXTRA, Pair.of(cat, new HashSet<PkgItem>())); mCategories.add(cat); } @@ -597,13 +612,13 @@ public class PackagesPage extends UpdaterPage if (apiKey < 1) { Package p = item.getPackage(); if (p instanceof ToolPackage || p instanceof PlatformToolPackage) { - apiKey = PkgCategory.KEY_TOOLS; + apiKey = PkgApiCategory.KEY_TOOLS; } else { - apiKey = PkgCategory.KEY_EXTRA; + apiKey = PkgApiCategory.KEY_EXTRA; } } - Pair<PkgCategory, HashSet<PkgItem>> mapEntry = unusedItemsMap.get(apiKey); + Pair<PkgApiCategory, HashSet<PkgItem>> mapEntry = unusedItemsMap.get(apiKey); if (mapEntry == null) { // This is a new category. Create it and add it to the map. @@ -613,28 +628,25 @@ public class PackagesPage extends UpdaterPage // If we don't (e.g. when installing a new platform that isn't yet available // locally in the SDK Manager), it's OK we'll try to find the first platform // package available. - String label = null; + String platformName = null; if (apiKey != -1) { for (IAndroidTarget target : mUpdaterData.getSdkManager().getTargets()) { if (target.isPlatform() && target.getVersion().getApiLevel() == apiKey) { - label = target.getVersionName(); - if (label != null) { - label = String.format("Android %1$s (API %2$d)", label, apiKey); - break; - } + platformName = target.getVersionName(); + break; } } } - PkgCategory cat = new PkgCategory( + PkgApiCategory cat = new PkgApiCategory( apiKey, - label, + platformName, imgFactory.getImageByName(ICON_CAT_PLATFORM)); mapEntry = Pair.of(cat, new HashSet<PkgItem>()); unusedItemsMap.put(apiKey, mapEntry); mCategories.add(0, cat); } - PkgCategory cat = mapEntry.getFirst(); + PkgApiCategory cat = mapEntry.getFirst(); assert cat != null; unusedCatSet.remove(cat); @@ -644,14 +656,13 @@ public class PackagesPage extends UpdaterPage cat.getItems().add(item); } - if (apiKey != -1 && cat.getLabel() == null) { + if (apiKey != -1 && cat.getPlatformName() == null) { // Check whether we can get the actual platform version name (e.g. "1.5") // from the first Platform package we find in this category. Package p = item.getPackage(); if (p instanceof PlatformPackage) { - String vn = ((PlatformPackage) p).getVersionName(); - String name = String.format("Android %1$s (API %2$d)", vn, apiKey); - cat.setLabel(name); + String platformName = ((PlatformPackage) p).getVersionName(); + cat.setPlatformName(platformName); } } } @@ -667,7 +678,10 @@ public class PackagesPage extends UpdaterPage // Remove any unused items in the category. int apikey = cat.getKey(); - Pair<PkgCategory, HashSet<PkgItem>> mapEntry = unusedItemsMap.get(apikey); + Pair<PkgApiCategory, HashSet<PkgItem>> mapEntry = unusedItemsMap.get(apikey); + if (mapEntry == null) { //DEBUG + apikey = (apikey + 1) - 1; + } assert mapEntry != null; HashSet<PkgItem> unusedItems = mapEntry.getSecond(); for (Iterator<PkgItem> iterItem = cat.getItems().iterator(); iterItem.hasNext(); ) { @@ -679,13 +693,6 @@ public class PackagesPage extends UpdaterPage // Sort the items Collections.sort(cat.getItems()); - - // Fix the category name for any API where we might not have found a platform package. - if (cat.getLabel() == null) { - int api = cat.getKey(); - String name = String.format("API %1$d", api); - cat.setLabel(name); - } } // Sort the categories list. @@ -716,6 +723,7 @@ public class PackagesPage extends UpdaterPage mTreeColumnName.setImage(getImage(ICON_SORT_BY_SOURCE)); } + mLastSortWasByApi = false; mCategories.clear(); Set<SdkSource> sourceSet = new HashSet<SdkSource>(); @@ -1075,7 +1083,7 @@ public class PackagesPage extends UpdaterPage if (element instanceof PkgCategory) { return ((PkgCategory) element).getLabel(); } else if (element instanceof PkgItem) { - return ((PkgItem) element).getName(); + return getPkgItemname((PkgItem) element); } else if (element instanceof IDescription) { return ((IDescription) element).getShortDescription(); } @@ -1133,6 +1141,41 @@ public class PackagesPage extends UpdaterPage return ""; //$NON-NLS-1$ } + private String getPkgItemname(PkgItem item) { + String name = item.getName().trim(); + + if (isSortByApi()) { + // When sorting by API, the package name might contains the API number + // or the platform name at the end. If we find it, cut it out since it's + // redundant. + + PkgApiCategory cat = (PkgApiCategory) findCategoryForItem(item); + String apiLabel = cat.getApiLabel(); + String platLabel = cat.getPlatformName(); + + if (platLabel != null && name.endsWith(platLabel)) { + return name.substring(0, name.length() - platLabel.length()); + + } else if (apiLabel != null && name.endsWith(apiLabel)) { + return name.substring(0, name.length() - apiLabel.length()); + } + } + + return name; + } + + private PkgCategory findCategoryForItem(PkgItem item) { + for (PkgCategory cat : mCategories) { + for (PkgItem i : cat.getItems()) { + if (i == item) { + return cat; + } + } + } + + return null; + } + @Override public Image getImage(Object element) { ImageFactory imgFactory = mUpdaterData.getImageFactory(); @@ -1263,14 +1306,9 @@ public class PackagesPage extends UpdaterPage private final List<PkgItem> mItems = new ArrayList<PkgItem>(); private String mLabel; - // When sorting by Source, key is the hash of the source's name. // When storing by API, key is the API level (>=1). Tools and extra have the - // special values so they get naturally sorted the way we want them. - // (Note: don't use max to avoid integers wrapping in comparisons. We can - // revisit the day we get 2^30 platforms.) - public final static int KEY_TOOLS = Integer.MAX_VALUE / 2; - public final static int KEY_EXTRA = -1; + // special values. public PkgCategory(int key, String label, Object iconRef) { mKey = key; @@ -1299,6 +1337,72 @@ public class PackagesPage extends UpdaterPage } } + private static class PkgApiCategory extends PkgCategory { + + /** Platform name, in the form "Android 1.2". Can be null if we don't have the name. */ + private String mPlatformName; + + // When sorting by Source, key is the hash of the source's name. + // When storing by API, key is the API level (>=1). Tools and extra have the + // special values so they get naturally sorted the way we want them. + // (Note: don't use max to avoid integers wrapping in comparisons. We can + // revisit the day we get 2^30 platforms.) + public final static int KEY_TOOLS = Integer.MAX_VALUE / 2; + public final static int KEY_EXTRA = -1; + + public PkgApiCategory(int apiKey, String platformName, Object iconRef) { + super(apiKey, null /*label*/, iconRef); + setPlatformName(platformName); + } + + public String getPlatformName() { + return mPlatformName; + } + + public void setPlatformName(String platformName) { + if (platformName != null) { + // Normal case for actual platform categories + mPlatformName = String.format("Android %1$s", platformName); + super.setLabel(null); + } + } + + public String getApiLabel() { + int api = getKey(); + if (api > 0) { + return String.format("API %1$d", getKey()); + } + return null; + } + + @Override + public String getLabel() { + String label = super.getLabel(); + if (label == null) { + int key = getKey(); + + if (key == KEY_TOOLS) { + label = "Tools"; + } else if (key == KEY_EXTRA) { + label = "Extras"; + } else { + if (mPlatformName != null) { + label = String.format("%1$s (%2$s)", mPlatformName, getApiLabel()); + } else { + label = getApiLabel(); + } + } + super.setLabel(label); + } + return label; + } + + @Override + public void setLabel(String label) { + throw new UnsupportedOperationException("Use setPlatformName() instead."); //$NON-NLS-1$ + } + } + private class PackageManagerImpl extends PackageManager { public PackageManagerImpl(UpdaterData updaterData) { |