1 /* 2 * Copyright (C) 2013 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.camera.data; 18 19 import android.net.Uri; 20 21 import com.android.camera.debug.Log; 22 import com.android.camera.debug.Log.Tag; 23 24 import java.util.Collections; 25 import java.util.Comparator; 26 import java.util.HashMap; 27 import java.util.LinkedList; 28 import java.util.List; 29 30 /** 31 * Fast access data structure for an ordered LocalData list. 32 */ 33 public class FilmstripItemList { 34 /** 35 * We use this as a way to compare a Uri to LocalData instances inside a 36 * LinkedList. A linked list in indexOf does a other.equals(get(i)). 37 */ 38 private static class UriWrapper { 39 private final Uri mUri; 40 UriWrapper(Uri uri)41 public UriWrapper(Uri uri) { 42 mUri = uri; 43 } 44 45 @Override equals(Object o)46 public boolean equals(Object o) { 47 if (!(o instanceof FilmstripItem)) { 48 return false; 49 } 50 return mUri.equals(((FilmstripItem) o).getData().getUri()); 51 } 52 } 53 54 private static final Tag TAG = new Tag("LocalDataList"); 55 private final LinkedList<FilmstripItem> mList = new LinkedList<FilmstripItem>(); 56 private final HashMap<Uri, FilmstripItem> mUriMap = new HashMap<Uri, FilmstripItem>(); 57 get(int index)58 public FilmstripItem get(int index) { 59 return mList.get(index); 60 } 61 62 /** 63 * Removes the item at the given index. 64 * 65 * @param index the item to delete 66 * @return If the item was found and deleted, it is returned. If the item 67 * was not found, null is returned. 68 */ remove(int index)69 public synchronized FilmstripItem remove(int index) { 70 try { 71 FilmstripItem removedItem = mList.remove(index); 72 mUriMap.remove(removedItem); 73 return removedItem; 74 } catch (IndexOutOfBoundsException ex) { 75 Log.w(TAG, "Could not remove item. Not found: " + index, ex); 76 return null; 77 } 78 } 79 get(Uri uri)80 public FilmstripItem get(Uri uri) { 81 return mUriMap.get(uri); 82 } 83 set(int pos, FilmstripItem data)84 public void set(int pos, FilmstripItem data) { 85 mList.set(pos, data); 86 mUriMap.put(data.getData().getUri(), data); 87 } 88 add(FilmstripItem data)89 public void add(FilmstripItem data) { 90 mList.add(data); 91 mUriMap.put(data.getData().getUri(), data); 92 } 93 add(int pos, FilmstripItem data)94 public void add(int pos, FilmstripItem data) { 95 mList.add(pos, data); 96 mUriMap.put(data.getData().getUri(), data); 97 } 98 addAll(List<? extends FilmstripItem> filmstripItemList)99 public void addAll(List<? extends FilmstripItem> filmstripItemList) { 100 for (FilmstripItem filmstripItem : filmstripItemList) { 101 add(filmstripItem); 102 } 103 } 104 size()105 public int size() { 106 return mList.size(); 107 } 108 sort(Comparator<FilmstripItem> comparator)109 public void sort(Comparator<FilmstripItem> comparator) { 110 Collections.sort(mList, comparator); 111 } 112 113 /** 114 * This implementation routes through to LinkedList.indexOf, so performs in 115 * O(n) but has a fast exit path for when the uri is not contained in the 116 * list, and immediately returns -1; 117 */ indexOf(Uri uri)118 public int indexOf(Uri uri) { 119 if (!mUriMap.containsKey(uri)) { 120 return -1; 121 } 122 return mList.indexOf(new UriWrapper(uri)); 123 } 124 } 125