View Javadoc

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 }