1 /*** 2 * Ambient - A music player for the Android platform 3 Copyright (C) 2007 Martin Vysny 4 5 This program is free software: you can redistribute it and/or modify 6 it under the terms of the GNU General Public License as published by 7 the Free Software Foundation, either version 3 of the License, or 8 (at your option) any later version. 9 10 This program is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 GNU General Public License for more details. 14 15 You should have received a copy of the GNU General Public License 16 along with this program. If not, see <http://www.gnu.org/licenses/>. 17 */ 18 19 package sk.baka.ambient.collection.local; 20 21 import java.util.ArrayList; 22 import java.util.Collection; 23 import java.util.EnumMap; 24 import java.util.List; 25 import java.util.Map; 26 27 import sk.baka.ambient.AmbientApplication; 28 import sk.baka.ambient.R; 29 import sk.baka.ambient.collection.CategoryEnum; 30 import sk.baka.ambient.collection.CategoryItem; 31 import sk.baka.ambient.collection.ICollection; 32 import sk.baka.ambient.collection.IDynamicPlaylistTrackProvider; 33 import sk.baka.ambient.collection.Statistics; 34 import sk.baka.ambient.collection.TrackMetadataBean; 35 import sk.baka.ambient.collection.TrackOriginEnum; 36 import sk.baka.ambient.commons.MiscUtils; 37 import sk.baka.ambient.library.DBStrategy; 38 import sk.baka.ambient.library.Library; 39 import sk.baka.ambient.library.LibraryUtils; 40 import sk.baka.ambient.playlist.Random; 41 import android.database.Cursor; 42 43 /*** 44 * Collection strategy which uses local database (the {@link Library}). 45 * 46 * @author Martin Vysny 47 */ 48 public final class CollectionImpl implements ICollection { 49 private final DBStrategy library; 50 51 /*** 52 * Creates new collection wrapper. 53 * 54 * @param l 55 * the library to wrap. 56 */ 57 public CollectionImpl(final Library l) { 58 library = l.getBackend(); 59 } 60 61 @SuppressWarnings("unchecked") 62 public List<CategoryItem> getCategoryList(final CategoryEnum request, 63 final CategoryItem context, final String substring, 64 final boolean sortByYear) throws InterruptedException { 65 final EnumMap<CategoryEnum, String> currentSearchCriteria = new EnumMap<CategoryEnum, String>( 66 CategoryEnum.class); 67 if (context != null) { 68 currentSearchCriteria 69 .putAll((EnumMap<CategoryEnum, String>) context.id); 70 currentSearchCriteria.put(context.category, context.name); 71 } 72 if (originFilter != null) { 73 currentSearchCriteria.put(CategoryEnum.Origin, originFilter 74 .toDBString()); 75 } 76 final CategoryEnum[] criterii; 77 if (request == CategoryEnum.Album) { 78 if (sortByYear) { 79 criterii = new CategoryEnum[] { CategoryEnum.YearReleased, 80 request }; 81 } else { 82 criterii = new CategoryEnum[] { request, 83 CategoryEnum.YearReleased }; 84 } 85 } else { 86 criterii = new CategoryEnum[] { request }; 87 } 88 final Cursor c = library.getCriteriaList(criterii, 89 currentSearchCriteria); 90 final CategoryItem.Builder b = new CategoryItem.Builder(); 91 final List<CategoryItem> result = new ArrayList<CategoryItem>(); 92 if (!c.moveToFirst()) { 93 c.close(); 94 return result; 95 } 96 try { 97 do { 98 if (Thread.currentThread().isInterrupted()) { 99 throw new InterruptedException(); 100 } 101 if (request == CategoryEnum.Album) { 102 b.name = c.getString(sortByYear ? 1 : 0); 103 b.year = c.getString(sortByYear ? 0 : 1); 104 } else { 105 b.name = c.getString(0); 106 } 107 b.id = currentSearchCriteria; 108 b.category = request; 109 result.add(b.build()); 110 } while (c.moveToNext()); 111 } finally { 112 c.close(); 113 } 114 return result; 115 } 116 117 @SuppressWarnings("unchecked") 118 public List<TrackMetadataBean> getTracks(CategoryItem context) 119 throws InterruptedException { 120 final EnumMap<CategoryEnum, String> crit = new EnumMap<CategoryEnum, String>( 121 CategoryEnum.class); 122 crit.putAll((EnumMap<CategoryEnum, String>) context.id); 123 crit.put(context.category, context.name); 124 if (originFilter != null) { 125 crit.put(CategoryEnum.Origin, originFilter.toDBString()); 126 } 127 final Cursor c = library.findByCriteria(crit, false, null); 128 if (Thread.currentThread().isInterrupted()) { 129 throw new InterruptedException(); 130 } 131 return LibraryUtils.pollTracks(c); 132 } 133 134 public List<TrackMetadataBean> searchTracks(String substring) 135 throws InterruptedException { 136 String where; 137 final String[] selArgs; 138 if (substring != null) { 139 where = "(title LIKE ? or artist LIKE ? or album LIKE ? or genre LIKE ?)"; 140 final String substr = "%" + substring + "%"; 141 selArgs = new String[] { substr, substr, substr, substr }; 142 if (originFilter != null) { 143 where += " and origin='" + originFilter.toDBString() + "'"; 144 } 145 } else { 146 where = null; 147 selArgs = null; 148 } 149 final Cursor c = library.rawTrackQuery(where, selArgs); 150 if (Thread.currentThread().isInterrupted()) { 151 throw new InterruptedException(); 152 } 153 return LibraryUtils.pollTracks(c); 154 } 155 156 public boolean isLocal() { 157 return true; 158 } 159 160 public String getName() { 161 return AmbientApplication.getInstance().getString( 162 R.string.localCollection); 163 } 164 165 /*** 166 * the origin or <code>null</code> if tracks will be shown regardless of 167 * their origin. 168 */ 169 private TrackOriginEnum originFilter = null; 170 171 /*** 172 * Show tracks only with given origin. 173 * 174 * @param origin 175 * the origin or <code>null</code> if tracks will be shown 176 * regardless of their origin. 177 */ 178 public void filterOrigin(final TrackOriginEnum origin) { 179 originFilter = origin; 180 } 181 182 public Statistics getStatistics() { 183 final Library lib = AmbientApplication.getInstance().getLibrary(); 184 if (originFilter != null) { 185 return lib.getStatistics(originFilter); 186 } 187 final Statistics local = lib.getStatistics(TrackOriginEnum.LocalFs); 188 final Statistics magnatune = lib 189 .getStatistics(TrackOriginEnum.Magnatune); 190 final Statistics total = new Statistics(); 191 total.add(local); 192 total.add(magnatune); 193 return total; 194 } 195 196 public CategoryItem deserializeItem(String id) { 197 return (CategoryItem) MiscUtils.deserialize(MiscUtils.fromHexa(id)); 198 } 199 200 public String serializeItem(CategoryItem item) { 201 final byte[] serialized = MiscUtils.serializeToBytes(item); 202 return MiscUtils.toHexa(serialized); 203 } 204 205 public IDynamicPlaylistTrackProvider newTrackProvider(final Random random) { 206 return new LibraryTrackProvider(random); 207 } 208 209 public List<TrackMetadataBean> findTracks(Map<CategoryEnum, String> criteria) { 210 final Cursor c = library.findByCriteria(criteria, true, null); 211 return LibraryUtils.pollTracks(c); 212 } 213 214 public Map<String, String> fixLocations(Collection<String> locations) { 215 throw new UnsupportedOperationException(); 216 } 217 218 public boolean supportsLocationFix() { 219 return false; 220 } 221 }