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 }