1 /* 2 * Copyright (C) 2009 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.cooliris.media; 18 19 import java.util.ArrayList; 20 import java.util.HashMap; 21 22 public final class MediaBucketList { 23 private static final Boolean TRUE = new Boolean(true); 24 private static final Boolean FALSE = new Boolean(false); 25 26 private ArrayList<MediaBucket> mBuckets = new ArrayList<MediaBucket>(1024); 27 private boolean mDirtyCount; 28 private boolean mDirtyAcceleratedLookup; 29 private int mCount; 30 private HashMap<MediaItem, Boolean> mCachedItems = new HashMap<MediaItem, Boolean>(1024); 31 32 // If only albums are selected, a bucket contains mediaSets. 33 // If items are selected, a bucket contains mediaSets and mediaItems. 34 35 // Returns the first item selection (ignoring items within set selections). getFirstItemSelection(ArrayList<MediaBucket> buckets)36 public static MediaItem getFirstItemSelection(ArrayList<MediaBucket> buckets) { 37 MediaItem item = null; 38 if (buckets != null) { 39 int numBuckets = buckets.size(); 40 for (int i = 0; i < numBuckets; i++) { 41 MediaBucket bucket = buckets.get(0); 42 if (bucket != null && !isSetSelection(bucket)) { 43 ArrayList<MediaItem> items = bucket.mediaItems; 44 if (items != null && items.size() > 0) { 45 item = items.get(0); 46 break; 47 } 48 } 49 } 50 } 51 return item; 52 } 53 54 // Returns the first set selection (ignoring sets corresponding to item 55 // selections). getFirstSetSelection(ArrayList<MediaBucket> buckets)56 public static MediaSet getFirstSetSelection(ArrayList<MediaBucket> buckets) { 57 MediaSet set = null; 58 if (buckets != null) { 59 int numBuckets = buckets.size(); 60 for (int i = 0; i < numBuckets; i++) { 61 MediaBucket bucket = buckets.get(0); 62 if (bucket != null && isSetSelection(bucket)) { 63 set = bucket.mediaSet; 64 } 65 } 66 } 67 return set; 68 } 69 get()70 public ArrayList<MediaBucket> get() { 71 return mBuckets; 72 } 73 size()74 public int size() { 75 if (mDirtyCount) { 76 ArrayList<MediaBucket> buckets = mBuckets; 77 int numBuckets = buckets.size(); 78 int count = 0; 79 for (int i = 0; i < numBuckets; ++i) { 80 MediaBucket bucket = buckets.get(i); 81 int numItems = 0; 82 if (bucket.mediaItems == null && bucket.mediaSet != null) { 83 numItems = bucket.mediaSet.getNumItems(); 84 // This selection reflects the bucket itself, and not the 85 // items inside the bucket (which is 0). 86 if (numItems == 0) { 87 numItems = 1; 88 } 89 } else if (bucket.mediaItems != null && bucket.mediaItems != null) { 90 numItems = bucket.mediaItems.size(); 91 } 92 count += numItems; 93 } 94 mCount = count; 95 mDirtyCount = false; 96 } 97 return mCount; 98 } 99 add(int slotId, MediaFeed feed, boolean removeIfAlreadyAdded)100 public void add(int slotId, MediaFeed feed, boolean removeIfAlreadyAdded) { 101 if (slotId == Shared.INVALID) { 102 return; 103 } 104 setDirty(); 105 final ArrayList<MediaBucket> selectedBuckets = mBuckets; 106 final int numSelectedBuckets = selectedBuckets.size(); 107 MediaSet mediaSetToAdd = null; 108 ArrayList<MediaItem> selectedItems = null; 109 MediaBucket bucket = null; 110 final boolean hasExpandedMediaSet = feed.hasExpandedMediaSet(); 111 if (!hasExpandedMediaSet) { 112 ArrayList<MediaSet> mediaSets = feed.getMediaSets(); 113 if (slotId >= mediaSets.size()) { 114 return; 115 } 116 mediaSetToAdd = mediaSets.get(slotId); 117 } else { 118 int numSlots = feed.getNumSlots(); 119 if (slotId < numSlots) { 120 MediaSet set = feed.getSetForSlot(slotId); 121 if (set != null) { 122 ArrayList<MediaItem> items = set.getItems(); 123 if (set.getNumItems() > 0) { 124 mediaSetToAdd = items.get(0).mParentMediaSet; 125 } 126 } 127 } 128 } 129 130 // Search for the bucket for this media set 131 for (int i = 0; i < numSelectedBuckets; ++i) { 132 final MediaBucket bucketCompare = selectedBuckets.get(i); 133 if (bucketCompare != null && bucketCompare.mediaSet != null 134 && mediaSetToAdd != null && bucketCompare.mediaSet == mediaSetToAdd) { 135 // We found the MediaSet. 136 if (!hasExpandedMediaSet) { 137 // Remove this bucket from the list since this bucket was 138 // already selected. 139 if (removeIfAlreadyAdded) { 140 selectedBuckets.remove(bucketCompare); 141 } 142 return; 143 } else { 144 bucket = bucketCompare; 145 break; 146 } 147 } 148 } 149 if (bucket == null) { 150 // Did not find the media bucket. 151 bucket = new MediaBucket(); 152 bucket.mediaSet = mediaSetToAdd; 153 bucket.mediaItems = selectedItems; 154 selectedBuckets.add(bucket); 155 } 156 if (hasExpandedMediaSet) { 157 int numSlots = feed.getNumSlots(); 158 if (slotId < numSlots) { 159 MediaSet set = feed.getSetForSlot(slotId); 160 if (set != null) { 161 ArrayList<MediaItem> items = set.getItems(); 162 int numItems = set.getNumItems(); 163 selectedItems = bucket.mediaItems; 164 if (selectedItems == null) { 165 selectedItems = new ArrayList<MediaItem>(numItems); 166 bucket.mediaItems = selectedItems; 167 } 168 for (int i = 0; i < numItems; ++i) { 169 MediaItem item = items.get(i); 170 // We see if this item has already been added. 171 int numPresentItems = selectedItems.size(); 172 boolean foundIndex = false; 173 for (int j = 0; j < numPresentItems; ++j) { 174 final MediaItem selectedItem = selectedItems.get(j); 175 if (selectedItem != null && item != null && selectedItem == item) { 176 // This index was already present, we need to 177 // remove it. 178 foundIndex = true; 179 if (removeIfAlreadyAdded) { 180 selectedItems.remove(j); 181 } 182 break; 183 } 184 } 185 if (foundIndex == false) { 186 selectedItems.add(item); 187 } 188 } 189 } 190 } 191 } 192 setDirty(); 193 } 194 find(MediaItem item)195 public boolean find(MediaItem item) { 196 HashMap<MediaItem, Boolean> cachedItems = mCachedItems; 197 if (mDirtyAcceleratedLookup) { 198 cachedItems.clear(); 199 mDirtyAcceleratedLookup = false; 200 } 201 Boolean itemAdded = cachedItems.get(item); 202 if (itemAdded == null) { 203 ArrayList<MediaBucket> selectedBuckets = mBuckets; 204 int numSelectedBuckets = selectedBuckets.size(); 205 for (int i = 0; i < numSelectedBuckets; ++i) { 206 MediaBucket bucket = selectedBuckets.get(i); 207 ArrayList<MediaItem> mediaItems = bucket.mediaItems; 208 if (mediaItems == null) { 209 MediaSet parentMediaSet = item.mParentMediaSet; 210 if (parentMediaSet != null && parentMediaSet.equals(bucket.mediaSet)) { 211 cachedItems.put(item, TRUE); 212 return true; 213 } 214 } else { 215 int numMediaItems = mediaItems.size(); 216 for (int j = 0; j < numMediaItems; ++j) { 217 MediaItem itemCompare = mediaItems.get(j); 218 if (itemCompare == item) { 219 cachedItems.put(item, TRUE); 220 return true; 221 } 222 } 223 } 224 } 225 cachedItems.put(item, FALSE); 226 return false; 227 } else { 228 return itemAdded.booleanValue(); 229 } 230 } 231 clear()232 public void clear() { 233 mBuckets.clear(); 234 setDirty(); 235 } 236 setDirty()237 private void setDirty() { 238 mDirtyCount = true; 239 mDirtyAcceleratedLookup = true; 240 } 241 242 // Assumption: No item and set selection combinations. isSetSelection(ArrayList<MediaBucket> buckets)243 protected static boolean isSetSelection(ArrayList<MediaBucket> buckets) { 244 if (buckets != null) { 245 int numBuckets = buckets.size(); 246 if (numBuckets == 0) { 247 return false; 248 } else if (numBuckets == 1) { 249 return isSetSelection(buckets.get(0)); 250 } else { 251 // If there are multiple sets, must be a set selection. 252 return true; 253 } 254 } 255 return false; 256 } 257 isSetSelection(MediaBucket bucket)258 protected static boolean isSetSelection(MediaBucket bucket) { 259 return (bucket.mediaSet != null && bucket.mediaItems == null) ? true : false; 260 } 261 262 // Assumption: If multiple items are selected, they must all be in the first 263 // bucket. isMultipleItemSelection(ArrayList<MediaBucket> buckets)264 protected static boolean isMultipleItemSelection(ArrayList<MediaBucket> buckets) { 265 if (buckets != null) { 266 int numBuckets = buckets.size(); 267 if (numBuckets == 0) { 268 return false; 269 } else { 270 return isMultipleSetSelection(buckets.get(0)); 271 } 272 } 273 return false; 274 } 275 isMultipleSetSelection(MediaBucket bucket)276 protected static boolean isMultipleSetSelection(MediaBucket bucket) { 277 return (bucket.mediaItems != null && bucket.mediaItems.size() > 1) ? true : false; 278 } 279 } 280