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.CollectionUtils;
32 import sk.baka.ambient.collection.ICollection;
33 import sk.baka.ambient.collection.IDynamicPlaylistTrackProvider;
34 import sk.baka.ambient.collection.Statistics;
35 import sk.baka.ambient.collection.TrackMetadataBean;
36 import sk.baka.ambient.collection.TrackOriginEnum;
37 import sk.baka.ambient.commons.MiscUtils;
38 import sk.baka.ambient.library.DBStrategy;
39 import sk.baka.ambient.library.Library;
40 import sk.baka.ambient.library.LibraryUtils;
41 import sk.baka.ambient.playlist.Random;
42 import android.database.Cursor;
43
44 /***
45 * Collection strategy which uses local database (the {@link Library}).
46 *
47 * @author Martin Vysny
48 */
49 public final class LibraryCollection implements ICollection {
50 private final DBStrategy library;
51
52 /***
53 * Creates new collection wrapper.
54 *
55 * @param l
56 * the library to wrap.
57 */
58 public LibraryCollection(final Library l) {
59 library = l.getBackend();
60 }
61
62 @SuppressWarnings("unchecked")
63 public List<CategoryItem> getCategoryList(final CategoryEnum request,
64 final CategoryItem context, final String substring,
65 final boolean sortByYear) throws InterruptedException {
66 final EnumMap<CategoryEnum, String> currentSearchCriteria = new EnumMap<CategoryEnum, String>(
67 CategoryEnum.class);
68 if (context != null) {
69 currentSearchCriteria
70 .putAll((EnumMap<CategoryEnum, String>) context.id);
71 currentSearchCriteria.put(context.category, context.name);
72 }
73 if (originFilter != null) {
74 currentSearchCriteria.put(CategoryEnum.Origin, originFilter
75 .toDBString());
76 }
77 final CategoryEnum[] criterii;
78 if (request == CategoryEnum.Album) {
79 if (sortByYear) {
80 criterii = new CategoryEnum[] { CategoryEnum.YearReleased,
81 CategoryEnum.Album };
82 } else {
83 criterii = new CategoryEnum[] { CategoryEnum.Album,
84 CategoryEnum.YearReleased };
85 }
86 } else {
87 criterii = new CategoryEnum[] { request };
88 }
89 final Cursor c = library.getCriteriaList(criterii,
90 currentSearchCriteria);
91 final CategoryItem.Builder b = new CategoryItem.Builder();
92 final List<CategoryItem> result = new ArrayList<CategoryItem>();
93 if (!c.moveToFirst()) {
94 c.close();
95 return result;
96 }
97 try {
98 do {
99 if (Thread.currentThread().isInterrupted()) {
100 throw new InterruptedException();
101 }
102 if (request == CategoryEnum.Album) {
103 b.name = c.getString(sortByYear ? 1 : 0);
104 b.year = c.getString(sortByYear ? 0 : 1);
105 } else {
106 b.name = c.getString(0);
107 }
108 b.id = currentSearchCriteria;
109 b.category = request;
110 result.add(b.build());
111 } while (c.moveToNext());
112 } finally {
113 c.close();
114 }
115
116 if ((request == CategoryEnum.Album) && sortByYear) {
117 CollectionUtils.sortByYearKey(result);
118 } else {
119 CollectionUtils.sortByKey(result);
120 }
121 return result;
122 }
123
124 @SuppressWarnings("unchecked")
125 public List<TrackMetadataBean> getTracks(CategoryItem context)
126 throws InterruptedException {
127 final EnumMap<CategoryEnum, String> crit = new EnumMap<CategoryEnum, String>(
128 CategoryEnum.class);
129 crit.putAll((EnumMap<CategoryEnum, String>) context.id);
130 crit.put(context.category, context.name);
131 if (originFilter != null) {
132 crit.put(CategoryEnum.Origin, originFilter.toDBString());
133 }
134 final Cursor c = library.findByCriteria(crit, false, null);
135 if (Thread.currentThread().isInterrupted()) {
136 throw new InterruptedException();
137 }
138 return LibraryUtils.pollTracks(c);
139 }
140
141 public List<TrackMetadataBean> findTracks(String substring)
142 throws InterruptedException {
143 String where;
144 final String[] selArgs;
145 if (substring != null) {
146 where = "(title LIKE ? or artist LIKE ? or album LIKE ? or genre LIKE ?)";
147 final String substr = "%" + substring + "%";
148 selArgs = new String[] { substr, substr, substr, substr };
149 if (originFilter != null) {
150 where += " and origin='" + originFilter.toDBString() + "'";
151 }
152 } else {
153 where = null;
154 selArgs = null;
155 }
156 final Cursor c = library.rawTrackQuery(where, selArgs);
157 if (Thread.currentThread().isInterrupted()) {
158 throw new InterruptedException();
159 }
160 return LibraryUtils.pollTracks(c);
161 }
162
163 public boolean isLocal() {
164 return true;
165 }
166
167 public String getName() {
168 return AmbientApplication.getInstance().getString(
169 R.string.localCollection);
170 }
171
172 /***
173 * the origin or <code>null</code> if tracks will be shown regardless of
174 * their origin.
175 */
176 private TrackOriginEnum originFilter = null;
177
178 /***
179 * Show tracks only with given origin.
180 *
181 * @param origin
182 * the origin or <code>null</code> if tracks will be shown
183 * regardless of their origin.
184 */
185 public void filterOrigin(final TrackOriginEnum origin) {
186 originFilter = origin;
187 }
188
189 public Statistics getStatistics() {
190 final Library lib = AmbientApplication.getInstance().getLibrary();
191 if (originFilter != null) {
192 return lib.getStatistics(originFilter);
193 }
194 final Statistics magnatune = lib
195 .getStatistics(TrackOriginEnum.Magnatune);
196 return magnatune;
197 }
198
199 public CategoryItem deserializeItem(String id) {
200 return (CategoryItem) MiscUtils.deserialize(MiscUtils.fromHexa(id));
201 }
202
203 public String serializeItem(CategoryItem item) {
204 final byte[] serialized = MiscUtils.serializeToBytes(item);
205 return MiscUtils.toHexa(serialized);
206 }
207
208 public IDynamicPlaylistTrackProvider newTrackProvider(final Random random) {
209 return new LibraryTrackProvider(random);
210 }
211
212 public List<TrackMetadataBean> findTracks(Map<CategoryEnum, String> criteria) {
213 final Cursor c = library.findByCriteria(criteria, true, null);
214 return LibraryUtils.pollTracks(c);
215 }
216
217 public Map<String, String> fixLocations(Collection<String> locations) {
218 throw new UnsupportedOperationException();
219 }
220
221 public boolean supportsLocationFix() {
222 return false;
223 }
224 }