Merge lp:~ubuntuone-client-engineering/ubuntuone-android-music/metadata-caching-optimisation into lp:ubuntuone-android-music/v2

Proposed by Michał Karnicki
Status: Merged
Merged at revision: 26
Proposed branch: lp:~ubuntuone-client-engineering/ubuntuone-android-music/metadata-caching-optimisation
Merge into: lp:ubuntuone-android-music/v2
Diff against target: 2137 lines (+1333/-185)
19 files modified
src/com/ubuntuone/android/music/UbuntuOneMusic.java (+13/-4)
src/com/ubuntuone/android/music/provider/MusicContentValues.java (+22/-13)
src/com/ubuntuone/android/music/provider/MusicContract.java (+1/-1)
src/com/ubuntuone/android/music/provider/MusicDatabase.java (+3/-3)
src/com/ubuntuone/android/music/provider/MusicProvider.java (+1/-1)
src/com/ubuntuone/android/music/provider/MusicProviderUtils.java (+3/-3)
src/com/ubuntuone/android/music/provider/dao/AlbumDao.java (+130/-0)
src/com/ubuntuone/android/music/provider/dao/ArtistDao.java (+170/-0)
src/com/ubuntuone/android/music/provider/dao/Dao.java (+76/-0)
src/com/ubuntuone/android/music/provider/dao/GenreDao.java (+86/-0)
src/com/ubuntuone/android/music/provider/dao/PlaylistDao.java (+109/-0)
src/com/ubuntuone/android/music/provider/dao/PlaylistSongDao.java (+97/-0)
src/com/ubuntuone/android/music/provider/dao/SongDao.java (+194/-0)
src/com/ubuntuone/android/music/service/MusicService.java (+2/-2)
src/com/ubuntuone/android/music/service/SyncService.java (+136/-78)
src/com/ubuntuone/android/music/ui/HomeActivity.java (+1/-1)
test/src/com/ubuntuone/android/music/UbuntuOneMusicTest.java (+10/-0)
test/src/com/ubuntuone/android/music/provider/MusicContentValuesTest.java (+8/-8)
test/src/com/ubuntuone/android/music/provider/MusicProviderInsertTest.java (+271/-71)
To merge this branch: bzr merge lp:~ubuntuone-client-engineering/ubuntuone-android-music/metadata-caching-optimisation
Reviewer Review Type Date Requested Status
Roberto Alsina (community) code review Approve
Review via email: mp+135477@code.launchpad.net

Commit message

Metadata caching speed optimization.

Description of the change

Metadata caching speed optimization (talking directly to SQLite db in SyncService, instead of talking through content provider abstraction layer). With tests. And some minor test clean-up.

To post a comment you must log in.
Revision history for this message
Roberto Alsina (ralsina) :
review: Approve (code review)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/com/ubuntuone/android/music/UbuntuOneMusic.java'
2--- src/com/ubuntuone/android/music/UbuntuOneMusic.java 2012-11-13 13:58:31 +0000
3+++ src/com/ubuntuone/android/music/UbuntuOneMusic.java 2012-11-21 17:34:22 +0000
4@@ -45,11 +45,20 @@
5 {
6 public static final String TAG = UbuntuOneMusic.class.getSimpleName();
7
8- public static final boolean DEBUG_SHOULD_SYNC = true;
9- public static final boolean DEBUG_SHOULD_BIND = true;
10- public static final boolean DEBUG_SHOULD_PLAY = true;
11+ /** Should always be true. False would indicate a debug build. */
12+ public static final boolean IS_RELEASE = true; // Never commit false.
13+
14+ // Following flags have been introduced to ease proper test suite runs and debugging.
15+
16+ /** Debug flag indicating if the app should attempt metadata sync. */
17+ public static final boolean SHOULD_SYNC = IS_RELEASE;
18+ /** Debug flag indicating if the app should bind to {@link MusicService}. */
19+ public static final boolean SHOULD_BIND = IS_RELEASE;
20+ /** Debug flag indicating if the app should actually playback music. */
21+ public static final boolean SHOULD_PLAY = IS_RELEASE;
22+
23 // Set this to true to enable foreign key constraint enforcing.
24- public static final boolean DEBUG_SHOULD_USE_FK = false;
25+ public static final boolean SHOULD_USE_FK = true;
26
27 private static UbuntuOneMusic instance;
28 private U1MusicAPI mApi;
29
30=== modified file 'src/com/ubuntuone/android/music/provider/MusicContentValues.java'
31--- src/com/ubuntuone/android/music/provider/MusicContentValues.java 2012-11-13 13:58:31 +0000
32+++ src/com/ubuntuone/android/music/provider/MusicContentValues.java 2012-11-21 17:34:22 +0000
33@@ -25,6 +25,7 @@
34
35 import java.util.ArrayList;
36 import java.util.Iterator;
37+import java.util.Locale;
38 import java.util.Map.Entry;
39 import java.util.Random;
40 import java.util.Set;
41@@ -52,12 +53,16 @@
42
43 private static final boolean PRINT_CONTENT_VALUES = false;
44
45- public static ContentValues from(U1Artist artist) {
46+ public static String getAlbumList(U1Artist artist) {
47+ return StringUtils.join(artist.getAlbumIds(), ",");
48+ }
49+
50+ public static ContentValues forArtist(U1Artist artist) {
51 final ContentValues cv = new ContentValues();
52 cv.put(Artists.UPDATED, System.currentTimeMillis());
53 cv.put(Artists.ARTIST_ID, artist.getId());
54 cv.put(Artists.ARTIST_NAME, artist.getArtist());
55- cv.put(Artists.ALBUM_LIST, StringUtils.join(artist.getAlbumIds(), ","));
56+ cv.put(Artists.ALBUM_LIST, getAlbumList(artist));
57 cv.put(Artists.ALBUM_COUNT, artist.getAlbumIds().size());
58 cv.put(Artists.SONG_COUNT, artist.getSongCount());
59 cv.put(Artists.ARTIST_URL, artist.getArtistUrl());
60@@ -66,7 +71,7 @@
61 return cv;
62 }
63
64- public static ArrayList<ContentValues> albumsFrom(U1Artist artist) {
65+ public static ArrayList<ContentValues> forArtistAlbums(U1Artist artist) {
66 ArrayList<ContentValues> values = new ArrayList<ContentValues>();
67 ArrayList<String> albumIds = artist.getAlbumIds();
68 for (String albumId : albumIds) {
69@@ -80,13 +85,13 @@
70 return values;
71 }
72
73- public static ContentValues from(U1Album album) {
74+ public static ContentValues forAlbum(U1Album album) {
75 final ContentValues cv = new ContentValues();
76 cv.put(Albums.UPDATED, System.currentTimeMillis());
77 cv.put(Albums.ALBUM_ID, album.getId());
78 cv.put(Albums.ALBUM_TITLE, album.getTitle());
79 cv.put(Albums.ALBUM_ARTIST, album.getArtist());
80- cv.put(Albums.ALBUM_ARTIST_ID, HashUtils.md5(album.getArtist()));
81+ cv.put(Albums.ALBUM_ARTIST_ID, album.getArtistId());
82 cv.put(Albums.ALBUM_YEAR, album.getYear());
83 cv.put(Albums.ALBUM_DATE_ADDED, album.getParsedDate());
84 cv.put(Albums.ALBUM_URL, album.getAlbumUrl());
85@@ -95,7 +100,7 @@
86 return cv;
87 }
88
89- public static ContentValues from(U1Song song) {
90+ public static ContentValues forSong(U1Song song) {
91 final ContentValues cv = new ContentValues();
92 cv.put(Songs.UPDATED, System.currentTimeMillis());
93 cv.put(Songs.SONG_ID, song.getId());
94@@ -104,10 +109,10 @@
95 cv.put(Songs.SONG_ALBUM_ID, song.getAlbumId());
96 cv.put(Songs.SONG_ALBUM_ARTIST, song.getAlbumArtist());
97 cv.put(Songs.SONG_ARTIST, song.getArtist());
98- cv.put(Songs.SONG_ARTIST_ID, HashUtils.md5(song.getArtist()));
99+ cv.put(Songs.SONG_ARTIST_ID, song.getArtistId());
100 cv.put(Songs.SONG_GENRE, song.getGenre());
101 // TODO Calculate /0 separated genre md5 sums maybe?
102- cv.put(Songs.SONG_GENRE_ID, HashUtils.md5(song.getGenre().toUpperCase()));
103+ cv.put(Songs.SONG_GENRE_ID, getGenreId(song.getGenre()));
104 cv.put(Songs.SONG_YEAR, song.getYear());
105 cv.put(Songs.SONG_DISC_NUMBER, song.getDiscNumber());
106 cv.put(Songs.SONG_TRACK, song.getTrack());
107@@ -125,7 +130,7 @@
108 return cv;
109 }
110
111- public static ContentValues from(U1Playlist playlist) {
112+ public static ContentValues forPlaylist(U1Playlist playlist) {
113 final ContentValues cv = new ContentValues();
114 cv.put(Playlists.UPDATED, System.currentTimeMillis());
115 cv.put(Playlists.PLAYLIST_ID, playlist.getId());
116@@ -136,7 +141,7 @@
117 return cv;
118 }
119
120- public static ContentValues from(String playlistId, String songId) {
121+ public static ContentValues forPlaylistSong(String playlistId, String songId) {
122 final ContentValues cv = new ContentValues();
123 cv.put(PlaylistSongs.UPDATED, System.currentTimeMillis());
124 cv.put(PlaylistSongs.PLAYLIST_ID, playlistId);
125@@ -145,7 +150,7 @@
126 return cv;
127 }
128
129- public static ContentValues from(Random random) {
130+ public static ContentValues forShuffleOrder(Random random) {
131 final ContentValues cv = new ContentValues();
132 cv.put(PlaylistSongs.UPDATED, System.currentTimeMillis());
133 cv.put(PlaylistSongs.SHUFFLE_ORDER, random.nextLong());
134@@ -153,10 +158,14 @@
135 return cv;
136 }
137
138- public static ContentValues fromGenre(String genre) {
139+ public static String getGenreId(String genre) {
140+ return HashUtils.md5(genre.toLowerCase(Locale.US));
141+ }
142+
143+ public static ContentValues forGenre(String genre) {
144 final ContentValues cv = new ContentValues();
145 cv.put(Genres.UPDATED, System.currentTimeMillis());
146- cv.put(Genres.GENRE_ID, HashUtils.md5(genre.toUpperCase()));
147+ cv.put(Genres.GENRE_ID, getGenreId(genre));
148 cv.put(Genres.GENRE_TITLE, genre);
149 return cv;
150 }
151
152=== modified file 'src/com/ubuntuone/android/music/provider/MusicContract.java'
153--- src/com/ubuntuone/android/music/provider/MusicContract.java 2012-11-08 14:14:54 +0000
154+++ src/com/ubuntuone/android/music/provider/MusicContract.java 2012-11-21 17:34:22 +0000
155@@ -273,7 +273,7 @@
156 }
157 }
158
159- /* package */ static class ArtistAlbums implements ArtistAlbumsColumns, SyncColumns,
160+ public static class ArtistAlbums implements ArtistAlbumsColumns, SyncColumns,
161 SongsColumns, BaseColumns
162 {
163 public static final Uri CONTENT_URI = BASE_CONTENT_URI.buildUpon()
164
165=== modified file 'src/com/ubuntuone/android/music/provider/MusicDatabase.java'
166--- src/com/ubuntuone/android/music/provider/MusicDatabase.java 2012-11-13 13:58:31 +0000
167+++ src/com/ubuntuone/android/music/provider/MusicDatabase.java 2012-11-21 17:34:22 +0000
168@@ -61,7 +61,7 @@
169
170 //private static final String NOW = "strftime('%s', 'now')";
171
172- interface Tables
173+ public interface Tables
174 {
175 String ARTISTS = "artists";
176 String ARTISTS_ALBUMS = "artists_albums";
177@@ -115,7 +115,7 @@
178 @Override
179 public SQLiteDatabase getWritableDatabase() {
180 SQLiteDatabase db = super.getWritableDatabase();
181- if (UbuntuOneMusic.DEBUG_SHOULD_USE_FK) {
182+ if (UbuntuOneMusic.SHOULD_USE_FK) {
183 db.execSQL("PRAGMA foreign_keys = ON");
184 }
185 return db;
186@@ -207,7 +207,7 @@
187 // Create the play queue playlist.
188 U1Playlist queuePlaylist = new U1Playlist(
189 MusicProviderUtils.QUEUE_ID, "", MusicProviderUtils.QUEUE_NAME, 0);
190- ContentValues values = MusicContentValues.from(queuePlaylist);
191+ ContentValues values = MusicContentValues.forPlaylist(queuePlaylist);
192 db.insert(Tables.PLAYLISTS, null, values);
193
194 db.execSQL("CREATE TABLE " + Tables.PLAYLISTS_SONGS + "("
195
196=== modified file 'src/com/ubuntuone/android/music/provider/MusicProvider.java'
197--- src/com/ubuntuone/android/music/provider/MusicProvider.java 2012-11-08 14:14:54 +0000
198+++ src/com/ubuntuone/android/music/provider/MusicProvider.java 2012-11-21 17:34:22 +0000
199@@ -325,7 +325,7 @@
200 String lcGenre = genre != null ? genre.trim().toLowerCase() : "";
201 if (!TextUtils.isEmpty(lcGenre) && !lcGenre.equals("null") && !lcGenre.equals("genre")) {
202 // XXX Do we want all genres uppercase? If so, toUpperCase() genre below.
203- ContentValues genreValues = MusicContentValues.fromGenre(genre.trim());
204+ ContentValues genreValues = MusicContentValues.forGenre(genre.trim());
205 db.insertOrThrow(Tables.GENRES, null, genreValues);
206 }
207 }
208
209=== modified file 'src/com/ubuntuone/android/music/provider/MusicProviderUtils.java'
210--- src/com/ubuntuone/android/music/provider/MusicProviderUtils.java 2012-11-08 14:14:54 +0000
211+++ src/com/ubuntuone/android/music/provider/MusicProviderUtils.java 2012-11-21 17:34:22 +0000
212@@ -242,7 +242,7 @@
213 String playlistId = Playlists.getPlaylistId(playlistUri);
214 String songId = Songs.getSongId(songUri);
215
216- ContentValues values = MusicContentValues.from(playlistId, songId);
217+ ContentValues values = MusicContentValues.forPlaylistSong(playlistId, songId);
218 resolver.insert(playlistUri, values);
219 }
220
221@@ -261,7 +261,7 @@
222 if (cursor != null && cursor.isBeforeFirst()) {
223 while (cursor.moveToNext()) {
224 String songId = cursor.getString(cursor.getColumnIndex(Songs.SONG_ID));
225- ContentValues values = MusicContentValues.from(
226+ ContentValues values = MusicContentValues.forPlaylistSong(
227 MusicProviderUtils.QUEUE_ID, songId);
228 resolver.insert(MusicProviderUtils.QUEUE_URI, values);
229 }
230@@ -650,7 +650,7 @@
231 String playlistId = cursor.getString(cursor.getColumnIndex(PlaylistSongs.PLAYLIST_ID));
232 String songId = cursor.getString(cursor.getColumnIndex(PlaylistSongs.SONG_ID));
233 Uri queueSongUri = Playlists.buildPlaylistSongUri(playlistId, songId);
234- ContentValues values = MusicContentValues.from(random);
235+ ContentValues values = MusicContentValues.forShuffleOrder(random);
236
237 resolver.update(queueSongUri, values, null, null);
238 }
239
240=== added directory 'src/com/ubuntuone/android/music/provider/dao'
241=== added file 'src/com/ubuntuone/android/music/provider/dao/AlbumDao.java'
242--- src/com/ubuntuone/android/music/provider/dao/AlbumDao.java 1970-01-01 00:00:00 +0000
243+++ src/com/ubuntuone/android/music/provider/dao/AlbumDao.java 2012-11-21 17:34:22 +0000
244@@ -0,0 +1,130 @@
245+package com.ubuntuone.android.music.provider.dao;
246+
247+import android.content.ContentResolver;
248+import android.content.ContentValues;
249+import android.database.sqlite.SQLiteDatabase;
250+import android.database.sqlite.SQLiteStatement;
251+import android.net.Uri;
252+
253+import com.ubuntuone.android.music.provider.MusicContentValues;
254+import com.ubuntuone.android.music.provider.MusicContract.Albums;
255+import com.ubuntuone.android.music.provider.MusicDatabase;
256+import com.ubuntuone.android.music.provider.MusicDatabase.Tables;
257+import com.ubuntuone.android.music.provider.MusicProvider;
258+import com.ubuntuone.api.music.model.U1Album;
259+
260+public class AlbumDao extends Dao
261+{
262+ public AlbumDao() {
263+ }
264+
265+ /**
266+ * Updates the album. If the album doesn't exist, inserts the album.
267+ * Backed by {@link MusicProvider}.
268+ *
269+ * @param resolver
270+ * The content resolver.
271+ * @param artist
272+ * The {@link U1Album} to save.
273+ */
274+ public void updateOrInsert(ContentResolver resolver, U1Album album) {
275+ ContentValues values = MusicContentValues.forAlbum(album);
276+ Uri albumUri = Albums.buildAlbumUri(album.getId());
277+ int count = resolver.update(albumUri, values, null, null);
278+ if (count == 0) {
279+ resolver.insert(Albums.CONTENT_URI, values);
280+ }
281+ }
282+
283+ /**
284+ * Updates the album. If the album doesn't exist, inserts the album.
285+ * Backed by {@link MusicDatabase}.
286+ *
287+ * @param db
288+ * The {@link MusicDatabase} instance.
289+ * @param artist
290+ * The {@link U1Album} to save.
291+ * @return True if update or insert succeeded, false otherwise.
292+ */
293+ public boolean updateOrInsert(SQLiteDatabase db, U1Album album) {
294+ boolean isSuccess = false;
295+
296+ SQLiteStatement sqlStmt = db.compileStatement(getUpdateSql());
297+ int i = 1; // Index to the parameter to bind.
298+ sqlStmt.bindLong(i++, System.currentTimeMillis());
299+
300+ sqlStmt.bindString(i++, album.getTitle());
301+ sqlStmt.bindString(i++, album.getArtist());
302+ sqlStmt.bindString(i++, album.getArtistId());
303+ sqlStmt.bindLong(i++, album.getYear());
304+
305+ sqlStmt.bindLong(i++, album.getParsedDate());
306+ sqlStmt.bindString(i++, album.getAlbumUrl());
307+ sqlStmt.bindString(i++, album.getAlbumArtUrl());
308+
309+ sqlStmt.bindString(i++, album.getId());
310+ // Can't use executeUpdateDelete on API < 11
311+ sqlStmt.execute();
312+ long rowsUpdated = getChanges(db);
313+
314+ if (rowsUpdated == 0L) {
315+ sqlStmt = db.compileStatement(getInsertSql());
316+ i = 1;
317+ sqlStmt.bindLong(i++, System.currentTimeMillis());
318+ sqlStmt.bindString(i++, album.getId());
319+
320+ sqlStmt.bindString(i++, album.getTitle());
321+ sqlStmt.bindString(i++, album.getArtist());
322+ sqlStmt.bindString(i++, album.getArtistId());
323+ sqlStmt.bindLong(i++, album.getYear());
324+
325+ sqlStmt.bindLong(i++, album.getParsedDate());
326+ sqlStmt.bindString(i++, album.getAlbumUrl());
327+ sqlStmt.bindString(i++, album.getAlbumArtUrl());
328+
329+ long rowId = sqlStmt.executeInsert();
330+ isSuccess = rowId != -1;
331+ } else {
332+ isSuccess = rowsUpdated == 1;
333+ }
334+ return isSuccess;
335+ }
336+
337+ @Override
338+ public String onGetInsertSql() {
339+ return "INSERT INTO " + Tables.ALBUMS + "(" +
340+ Albums.UPDATED + ", " +
341+ Albums.ALBUM_ID + ", " +
342+
343+ Albums.ALBUM_TITLE + ", " +
344+ Albums.ALBUM_ARTIST + ", " +
345+ Albums.ALBUM_ARTIST_ID + ", " +
346+ Albums.ALBUM_YEAR + ", " +
347+
348+ Albums.ALBUM_DATE_ADDED + ", " +
349+ Albums.ALBUM_URL + ", " +
350+ Albums.ALBUM_ART_URL +
351+
352+ ") VALUES (?, ?, " +
353+ "?, ?, ?, ?, " +
354+ "?, ?, ?" +
355+ ")";
356+ }
357+
358+ @Override
359+ public String onGetUpdateSql() {
360+ return "UPDATE " + Tables.ALBUMS + " SET " +
361+ Albums.UPDATED + "=?, " +
362+
363+ Albums.ALBUM_TITLE + "=?, " +
364+ Albums.ALBUM_ARTIST + "=?, " +
365+ Albums.ALBUM_ARTIST_ID + "=?, " +
366+ Albums.ALBUM_YEAR + "=?, " +
367+
368+ Albums.ALBUM_DATE_ADDED + "=?, " +
369+ Albums.ALBUM_URL + "=?, " +
370+ Albums.ALBUM_ART_URL + "=? " +
371+
372+ "WHERE " + Albums.ALBUM_ID + "=?";
373+ }
374+}
375
376=== added file 'src/com/ubuntuone/android/music/provider/dao/ArtistDao.java'
377--- src/com/ubuntuone/android/music/provider/dao/ArtistDao.java 1970-01-01 00:00:00 +0000
378+++ src/com/ubuntuone/android/music/provider/dao/ArtistDao.java 2012-11-21 17:34:22 +0000
379@@ -0,0 +1,170 @@
380+package com.ubuntuone.android.music.provider.dao;
381+
382+import java.util.ArrayList;
383+
384+import android.content.ContentResolver;
385+import android.content.ContentValues;
386+import android.database.sqlite.SQLiteDatabase;
387+import android.database.sqlite.SQLiteStatement;
388+import android.net.Uri;
389+
390+import com.ubuntuone.android.music.provider.MusicContentValues;
391+import com.ubuntuone.android.music.provider.MusicContract.Albums;
392+import com.ubuntuone.android.music.provider.MusicContract.ArtistAlbums;
393+import com.ubuntuone.android.music.provider.MusicContract.Artists;
394+import com.ubuntuone.android.music.provider.MusicDatabase;
395+import com.ubuntuone.android.music.provider.MusicDatabase.Tables;
396+import com.ubuntuone.android.music.provider.MusicProvider;
397+import com.ubuntuone.android.music.util.StringUtils;
398+import com.ubuntuone.api.music.model.U1Artist;
399+
400+public class ArtistDao extends Dao
401+{
402+ public ArtistDao() {
403+ }
404+
405+ /**
406+ * Updates the artist. If the artist doesn't exist, inserts the artist.
407+ * Backed by {@link MusicProvider}.
408+ *
409+ * @param resolver
410+ * The content resolver.
411+ * @param artist
412+ * The {@link U1Artist} to save.
413+ */
414+ public void updateOrInsert(ContentResolver resolver, U1Artist artist) {
415+ ContentValues values = MusicContentValues.forArtist(artist);
416+ Uri artistUri = Artists.buildArtistUri(artist.getId());
417+ int count = resolver.update(artistUri, values, null, null);
418+ if (count == 0) {
419+ resolver.insert(Artists.CONTENT_URI, values);
420+ }
421+ // Insert artist albums.
422+ ArrayList<ContentValues> albumsValues = MusicContentValues.forArtistAlbums(artist);
423+ for (ContentValues albumValues : albumsValues) {
424+ Uri artistAlbumUri = Artists.buildAlbumUri(
425+ artist.getId(), albumValues.getAsString(Albums.ALBUM_ID));
426+ int count2 = resolver.update(artistAlbumUri, albumValues, null, null);
427+ if (count2 == 0) {
428+ resolver.insert(artistAlbumUri, albumValues);
429+ }
430+ }
431+ }
432+
433+ /**
434+ * Updates the artist. If the artist doesn't exist, inserts the artist.
435+ * Backed by {@link MusicDatabase}.
436+ *
437+ * @param db
438+ * The {@link MusicDatabase} instance.
439+ * @param artist
440+ * The {@link U1Artist} to save.
441+ * @return True if update or insert succeeded, false otherwise.
442+ */
443+ public boolean updateOrInsert(SQLiteDatabase db, U1Artist artist) {
444+ boolean isSuccess = false;
445+
446+ SQLiteStatement sqlStmt = db.compileStatement(getUpdateSql());
447+ int i = 1; // Index to the parameter to bind.
448+
449+ final String albumList = StringUtils.join(artist.getAlbumIds(), ",");
450+ final long albumListSize = artist.getAlbumIds().size();
451+
452+ sqlStmt.bindLong(i++, System.currentTimeMillis());
453+
454+ sqlStmt.bindString(i++, artist.getArtist());
455+ sqlStmt.bindString(i++, albumList);
456+ sqlStmt.bindLong(i++, albumListSize);
457+ sqlStmt.bindLong(i++, artist.getSongCount());
458+
459+ sqlStmt.bindString(i++, artist.getArtistUrl());
460+ sqlStmt.bindString(i++, artist.getArtistArtUrl());
461+
462+ sqlStmt.bindString(i++, artist.getId());
463+ // Can't use executeUpdateDelete on API < 11
464+ sqlStmt.execute();
465+ long rowsUpdated = getChanges(db);
466+
467+ if (rowsUpdated == 0L) {
468+ sqlStmt = db.compileStatement(getInsertSql());
469+ i = 1;
470+ sqlStmt.bindLong(i++, System.currentTimeMillis());
471+ sqlStmt.bindString(i++, artist.getId());
472+
473+ sqlStmt.bindString(i++, artist.getArtist());
474+ sqlStmt.bindString(i++, albumList);
475+ sqlStmt.bindLong(i++, albumListSize);
476+ sqlStmt.bindLong(i++, artist.getSongCount());
477+
478+ sqlStmt.bindString(i++, artist.getArtistUrl());
479+ sqlStmt.bindString(i++, artist.getArtistArtUrl());
480+
481+ long rowId = sqlStmt.executeInsert();
482+ isSuccess = rowId != -1;
483+ } else {
484+ isSuccess = rowsUpdated == 1;
485+ }
486+
487+ // Insert artist albums.
488+ sqlStmt = db.compileStatement(getSecondaryInsertSql());
489+ final String artistId = artist.getId();
490+ final ArrayList<String> albumIds = artist.getAlbumIds();
491+ for (String albumId : albumIds) {
492+ sqlStmt.clearBindings();
493+ sqlStmt.bindLong(1, System.currentTimeMillis());
494+ sqlStmt.bindString(2, artistId);
495+ sqlStmt.bindString(3, albumId);
496+ long rowId = sqlStmt.executeInsert();
497+ isSuccess = isSuccess && (rowId != -1);
498+ }
499+
500+ return isSuccess;
501+ }
502+
503+ @Override
504+ public String onGetInsertSql() {
505+ return "INSERT INTO " + Tables.ARTISTS + "(" +
506+ Artists.UPDATED + ", " +
507+ Artists.ARTIST_ID + ", " +
508+
509+ Artists.ARTIST_NAME + ", " +
510+ Artists.ALBUM_LIST + ", " +
511+ Artists.ALBUM_COUNT + ", " +
512+ Artists.SONG_COUNT + ", " +
513+
514+ Artists.ARTIST_URL + ", " +
515+ Artists.ARTIST_ART_URL +
516+
517+ ") VALUES (?, ?, " +
518+ "?, ?, ?, ?, " +
519+ "?, ?" +
520+ ")";
521+ }
522+
523+ @Override
524+ public String onGetSecondaryInsertSql() {
525+ return "INSERT INTO " + Tables.ARTISTS_ALBUMS + "(" +
526+
527+ ArtistAlbums.UPDATED + ", " +
528+ ArtistAlbums.ARTIST_ID + ", " +
529+ ArtistAlbums.ALBUM_ID +
530+
531+ ") VALUES (?, ?, ?)";
532+ }
533+
534+ @Override
535+ public String onGetUpdateSql() {
536+ return "UPDATE " + Tables.ARTISTS + " SET " +
537+ Artists.UPDATED + "=?, " +
538+
539+ Artists.ARTIST_NAME + "=?, " +
540+ Artists.ALBUM_LIST + "=?, " +
541+ Artists.ALBUM_COUNT + "=?, " +
542+ Artists.SONG_COUNT + "=?, " +
543+
544+ Artists.ARTIST_URL + "=?, " +
545+ Artists.ARTIST_ART_URL + "=? " +
546+
547+ "WHERE " + Artists.ARTIST_ID + "=?";
548+ }
549+}
550
551=== added file 'src/com/ubuntuone/android/music/provider/dao/Dao.java'
552--- src/com/ubuntuone/android/music/provider/dao/Dao.java 1970-01-01 00:00:00 +0000
553+++ src/com/ubuntuone/android/music/provider/dao/Dao.java 2012-11-21 17:34:22 +0000
554@@ -0,0 +1,76 @@
555+package com.ubuntuone.android.music.provider.dao;
556+
557+import android.database.sqlite.SQLiteDatabase;
558+import android.database.sqlite.SQLiteStatement;
559+
560+public abstract class Dao
561+{
562+ private String mInsertSql;
563+ private String mSecondaryInsertSql;
564+ private String mUdpateSql;
565+
566+ /**
567+ * Performs a lazy initialization with {@code Dao#onGetInsertSql()}.
568+ *
569+ * @return The cached SQL INSERT string.
570+ */
571+ public String getInsertSql() {
572+ if (mInsertSql == null) {
573+ mInsertSql = onGetInsertSql();
574+ }
575+ return mInsertSql;
576+ }
577+
578+ /**
579+ * Performs a lazy initialization with {@code Dao#onGetSecondaryInsertSql()}.
580+ *
581+ * @return The cached secondary SQL INSERT string.
582+ */
583+ public String getSecondaryInsertSql() {
584+ if (mSecondaryInsertSql == null) {
585+ mSecondaryInsertSql = onGetSecondaryInsertSql();
586+ }
587+ return mSecondaryInsertSql;
588+ }
589+
590+ /**
591+ * Performs a lazy initialization with {@code Dao#onGetUpdateSql()}.
592+ *
593+ * @return The cached SQL UPDATE string.
594+ */
595+ public String getUpdateSql() {
596+ if (mUdpateSql == null) {
597+ mUdpateSql = onGetUpdateSql();
598+ }
599+ return mUdpateSql;
600+ }
601+
602+ public long getChanges(SQLiteDatabase db) {
603+ SQLiteStatement countStmt = db.compileStatement("SELECT changes()");
604+ return countStmt.simpleQueryForLong();
605+ }
606+
607+ /**
608+ * Override to return the SQL INSERT string.
609+ *
610+ * @return The SQL INSERT string.
611+ */
612+ public abstract String onGetInsertSql();
613+
614+
615+ /**
616+ * Override to return the secondary SQL INSERT string.
617+ *
618+ * @return The secondary SQL INSERT string.
619+ */
620+ public String onGetSecondaryInsertSql() {
621+ return null;
622+ }
623+
624+ /**
625+ * Override to return the SQL UPDATE string.
626+ *
627+ * @return The SQL UPDATE string.
628+ */
629+ public abstract String onGetUpdateSql();
630+}
631
632=== added file 'src/com/ubuntuone/android/music/provider/dao/GenreDao.java'
633--- src/com/ubuntuone/android/music/provider/dao/GenreDao.java 1970-01-01 00:00:00 +0000
634+++ src/com/ubuntuone/android/music/provider/dao/GenreDao.java 2012-11-21 17:34:22 +0000
635@@ -0,0 +1,86 @@
636+package com.ubuntuone.android.music.provider.dao;
637+
638+import android.content.ContentResolver;
639+import android.content.ContentValues;
640+import android.database.sqlite.SQLiteDatabase;
641+import android.database.sqlite.SQLiteStatement;
642+import android.text.TextUtils;
643+
644+import com.ubuntuone.android.music.provider.MusicContentValues;
645+import com.ubuntuone.android.music.provider.MusicContract.Genres;
646+import com.ubuntuone.android.music.provider.MusicDatabase;
647+import com.ubuntuone.android.music.provider.MusicDatabase.Tables;
648+import com.ubuntuone.android.music.provider.MusicProvider;
649+import com.ubuntuone.android.music.util.HashUtils;
650+import com.ubuntuone.api.music.model.U1Song;
651+
652+public class GenreDao extends Dao
653+{
654+ public GenreDao() {
655+ }
656+
657+ /**
658+ * Inserts song genre. Backed by {@link MusicProvider}.
659+ *
660+ * @param resolver
661+ * The content resolver.
662+ * @param song
663+ * The {@link U1Song} of which genre to save.
664+ */
665+ public void updateOrInsert(ContentResolver resolver, U1Song song) {
666+ String genre = song.getGenre();
667+ String lcGenre = genre != null ? genre.trim().toLowerCase() : null;
668+ if (!TextUtils.isEmpty(lcGenre) &&
669+ !lcGenre.equals("null") && !lcGenre.equals("genre")) {
670+ // XXX Do we want all genres uppercase? If so, toUpperCase() genre below.
671+ ContentValues genreValues = MusicContentValues.forGenre(genre.trim());
672+ resolver.insert(Genres.CONTENT_URI, genreValues);
673+ }
674+ }
675+
676+ /**
677+ * Inserts song genre. Backed by {@link MusicDatabase}.
678+ *
679+ * @param db
680+ * The {@link MusicDatabase} instance.
681+ * @param song
682+ * The {@link U1Song} of which genre to save.
683+ * @return Always true for genre.
684+ */
685+ public boolean updateOrInsert(SQLiteDatabase db, String genre) {
686+ final SQLiteStatement genreInsert = db.compileStatement(getInsertSql());
687+ genreInsert.clearBindings();
688+
689+ String lcGenre = genre != null ? genre.trim().toLowerCase() : null;
690+ if (TextUtils.isEmpty(lcGenre) ||
691+ lcGenre.equals("null") || lcGenre.equals("genre")) {
692+ // Ignore generic crap. Assume genre was inserted, we don't care.
693+ return true;
694+ }
695+ String genreId = HashUtils.md5(genre.toUpperCase());
696+
697+ int j = 1; // Index to the parameter to bind.
698+ genreInsert.bindLong(j++, System.currentTimeMillis());
699+ genreInsert.bindString(j++, genreId);
700+ genreInsert.bindString(j++, genre);
701+
702+ genreInsert.executeInsert();
703+ // Assume genre was inserted, we don't care.
704+ return true;
705+ }
706+
707+ @Override
708+ public String onGetInsertSql() {
709+ return "INSERT INTO " + Tables.GENRES + "(" +
710+ Genres.UPDATED + ", " +
711+ Genres.GENRE_ID + ", " +
712+ Genres.GENRE_TITLE +
713+ ") VALUES (?, ?, ?)";
714+ }
715+
716+ @Override
717+ public String onGetUpdateSql() {
718+ // Not used for genre.
719+ return null;
720+ }
721+}
722
723=== added file 'src/com/ubuntuone/android/music/provider/dao/PlaylistDao.java'
724--- src/com/ubuntuone/android/music/provider/dao/PlaylistDao.java 1970-01-01 00:00:00 +0000
725+++ src/com/ubuntuone/android/music/provider/dao/PlaylistDao.java 2012-11-21 17:34:22 +0000
726@@ -0,0 +1,109 @@
727+package com.ubuntuone.android.music.provider.dao;
728+
729+import android.content.ContentResolver;
730+import android.content.ContentValues;
731+import android.database.sqlite.SQLiteDatabase;
732+import android.database.sqlite.SQLiteStatement;
733+import android.net.Uri;
734+
735+import com.ubuntuone.android.music.provider.MusicContentValues;
736+import com.ubuntuone.android.music.provider.MusicContract.Playlists;
737+import com.ubuntuone.android.music.provider.MusicDatabase;
738+import com.ubuntuone.android.music.provider.MusicDatabase.Tables;
739+import com.ubuntuone.android.music.provider.MusicProvider;
740+import com.ubuntuone.api.music.model.U1Playlist;
741+
742+public class PlaylistDao extends Dao
743+{
744+ public PlaylistDao() {
745+ }
746+
747+ /**
748+ * Updates the playlist. If the playlist doesn't exist, inserts the playlist.
749+ * Backed by {@link MusicProvider}.
750+ *
751+ * @param resolver
752+ * The content resolver.
753+ * @param playlist
754+ * The {@link U1Playlist} to save.
755+ */
756+ public void updateOrInsert(ContentResolver resolver, U1Playlist playlist) {
757+ ContentValues values = MusicContentValues.forPlaylist(playlist);
758+ Uri playlistUri = Playlists.buildPlaylistUri(playlist.getId());
759+ int count = resolver.update(playlistUri, values, null, null);
760+ if (count == 0) {
761+ resolver.insert(Playlists.CONTENT_URI, values);
762+ }
763+ }
764+
765+ /**
766+ * Updates the playlist. If the playlist doesn't exist, inserts the playlist.
767+ * Backed by {@link MusicDatabase}.
768+ *
769+ * @param db
770+ * The {@link MusicDatabase} instance.
771+ * @param playlist
772+ * The {@link U1Playlist} to save.
773+ * @return True if update or insert succeeded, false otherwise.
774+ */
775+ public boolean updateOrInsert(SQLiteDatabase db, U1Playlist playlist) {
776+ boolean isSuccess = false;
777+
778+ SQLiteStatement sqlStmt = db.compileStatement(getUpdateSql());
779+ int i = 1; // Index to the parameter to bind.
780+
781+ sqlStmt.bindLong(i++, System.currentTimeMillis());
782+
783+ sqlStmt.bindString(i++, playlist.getName());
784+ sqlStmt.bindLong(i++, playlist.getSongCount());
785+ sqlStmt.bindString(i++, playlist.getPlaylistUrl());
786+
787+ sqlStmt.bindString(i++, playlist.getId());
788+ // Can't use executeUpdateDelete on API < 11
789+ sqlStmt.execute();
790+ long rowsUpdated = getChanges(db);
791+
792+ if (rowsUpdated == 0L) {
793+ sqlStmt = db.compileStatement(getInsertSql());
794+ i = 1;
795+ sqlStmt.bindLong(i++, System.currentTimeMillis());
796+
797+ sqlStmt.bindString(i++, playlist.getId());
798+ sqlStmt.bindString(i++, playlist.getName());
799+ sqlStmt.bindLong(i++, playlist.getSongCount());
800+ sqlStmt.bindString(i++, playlist.getPlaylistUrl());
801+
802+ long rowId = sqlStmt.executeInsert();
803+ isSuccess = rowId != -1;
804+ } else {
805+ isSuccess = rowsUpdated == 1;
806+ }
807+ return isSuccess;
808+ }
809+
810+ @Override
811+ public String onGetInsertSql() {
812+ return "INSERT INTO " + Tables.PLAYLISTS + "(" +
813+ Playlists.UPDATED + ", " +
814+ Playlists.PLAYLIST_ID + ", " +
815+
816+ Playlists.PLAYLIST_NAME + ", " +
817+ Playlists.PLAYLIST_SONG_COUNT + ", " +
818+ Playlists.PLAYLIST_URL +
819+
820+ ") VALUES (?, ?, " +
821+ "?, ?, ?" +
822+ ")";
823+ }
824+
825+ @Override
826+ public String onGetUpdateSql() {
827+ return "UPDATE " + Tables.PLAYLISTS + " SET " +
828+ Playlists.UPDATED + "=?, " +
829+ Playlists.PLAYLIST_NAME + "=?, " +
830+ Playlists.PLAYLIST_SONG_COUNT + "=?, " +
831+ Playlists.PLAYLIST_URL + "=? " +
832+ "WHERE " + Playlists.PLAYLIST_ID + "=?";
833+
834+ }
835+}
836
837=== added file 'src/com/ubuntuone/android/music/provider/dao/PlaylistSongDao.java'
838--- src/com/ubuntuone/android/music/provider/dao/PlaylistSongDao.java 1970-01-01 00:00:00 +0000
839+++ src/com/ubuntuone/android/music/provider/dao/PlaylistSongDao.java 2012-11-21 17:34:22 +0000
840@@ -0,0 +1,97 @@
841+package com.ubuntuone.android.music.provider.dao;
842+
843+import android.content.ContentResolver;
844+import android.content.ContentValues;
845+import android.database.sqlite.SQLiteDatabase;
846+import android.database.sqlite.SQLiteStatement;
847+import android.net.Uri;
848+
849+import com.ubuntuone.android.music.provider.MusicContentValues;
850+import com.ubuntuone.android.music.provider.MusicContract.PlaylistSongs;
851+import com.ubuntuone.android.music.provider.MusicContract.Playlists;
852+import com.ubuntuone.android.music.provider.MusicContract.Songs;
853+import com.ubuntuone.android.music.provider.MusicDatabase;
854+import com.ubuntuone.android.music.provider.MusicDatabase.Tables;
855+import com.ubuntuone.android.music.provider.MusicProvider;
856+import com.ubuntuone.api.music.model.U1Song;
857+
858+public class PlaylistSongDao extends Dao
859+{
860+ public PlaylistSongDao() {
861+ }
862+
863+ /**
864+ * Updates the playlist song. If the playlist song doesn't exist, inserts
865+ * the playlist song. Backed by {@link MusicProvider}.
866+ *
867+ * @param resolver
868+ * The content resolver.
869+ * @param playlistId
870+ * The playlist id of the playlist to save the song to.
871+ * @param song
872+ * The {@link U1Song} to save.
873+ */
874+ public void updateOrInsert(ContentResolver resolver, String playlistId, U1Song song) {
875+ ContentValues values = MusicContentValues.forPlaylistSong(playlistId, song.getId());
876+ Uri playlistSongsUri = Playlists.buildPlaylistSongUri(playlistId, song.getId());
877+ int count = resolver.update(playlistSongsUri, values, null, null);
878+ if (count == 0) {
879+ resolver.insert(playlistSongsUri, values);
880+ }
881+ }
882+
883+ /**
884+ * Updates the playlist song. If the playlist song doesn't exist, inserts
885+ * the playlist song. Backed by {@link MusicDatabase}.
886+ *
887+ * @param db
888+ * The {@link MusicDatabase} instance.
889+ * @param playlistId
890+ * The playlist id of the playlist to save the song to.
891+ * @param song
892+ * The {@link U1Song} to save.
893+ * @return True if update or insert succeeded, false otherwise.
894+ */
895+ public boolean updateOrInsert(SQLiteDatabase db, String playlistId, String songId) {
896+ boolean isSuccess = false;
897+
898+ SQLiteStatement sqlStmt = db.compileStatement(getUpdateSql());
899+ int i = 1; // Index to the parameter to bind.
900+ sqlStmt.bindLong(i++, System.currentTimeMillis());
901+ sqlStmt.bindString(i++, playlistId);
902+ sqlStmt.bindString(i++, songId);
903+ // Can't use executeUpdateDelete on API < 11
904+ sqlStmt.execute();
905+ long rowsUpdated = getChanges(db);
906+
907+ if (rowsUpdated == 0L) {
908+ sqlStmt = db.compileStatement(getInsertSql());
909+ i = 1;
910+ sqlStmt.bindLong(i++, System.currentTimeMillis());
911+ sqlStmt.bindString(i++, playlistId);
912+ sqlStmt.bindString(i++, songId);
913+
914+ long rowId = sqlStmt.executeInsert();
915+ isSuccess = rowId != -1;
916+ } else {
917+ isSuccess = rowsUpdated == 1;
918+ }
919+ return isSuccess;
920+ }
921+
922+ @Override
923+ public String onGetInsertSql() {
924+ return "INSERT INTO " + Tables.PLAYLISTS_SONGS + "(" +
925+ PlaylistSongs.UPDATED + ", " +
926+ PlaylistSongs.PLAYLIST_ID + ", " +
927+ PlaylistSongs.SONG_ID +
928+ ") VALUES (?, ?, ?)";
929+ }
930+
931+ @Override
932+ public String onGetUpdateSql() {
933+ return "UPDATE " + Tables.PLAYLISTS_SONGS + " SET " +
934+ PlaylistSongs.UPDATED + "=? " +
935+ "WHERE " + PlaylistSongs.PLAYLIST_ID + "=? AND " + Songs.SONG_ID + "=?";
936+ }
937+}
938
939=== added file 'src/com/ubuntuone/android/music/provider/dao/SongDao.java'
940--- src/com/ubuntuone/android/music/provider/dao/SongDao.java 1970-01-01 00:00:00 +0000
941+++ src/com/ubuntuone/android/music/provider/dao/SongDao.java 2012-11-21 17:34:22 +0000
942@@ -0,0 +1,194 @@
943+package com.ubuntuone.android.music.provider.dao;
944+
945+import static com.ubuntuone.android.music.provider.MusicContentValues.getGenreId;
946+import android.content.ContentResolver;
947+import android.content.ContentValues;
948+import android.database.sqlite.SQLiteDatabase;
949+import android.database.sqlite.SQLiteStatement;
950+import android.net.Uri;
951+
952+import com.ubuntuone.android.music.provider.MusicContentValues;
953+import com.ubuntuone.android.music.provider.MusicContract.Songs;
954+import com.ubuntuone.android.music.provider.MusicDatabase;
955+import com.ubuntuone.android.music.provider.MusicDatabase.Tables;
956+import com.ubuntuone.android.music.provider.MusicProvider;
957+import com.ubuntuone.api.music.model.U1Song;
958+
959+public class SongDao extends Dao
960+{
961+ public SongDao() {
962+ }
963+
964+ /**
965+ * Updates the song. If the song doesn't exist, inserts the song. Backed by
966+ * {@link MusicProvider}.
967+ *
968+ * @param resolver
969+ * The content resolver.
970+ * @param song
971+ * The {@link U1Song} to save.
972+ */
973+ public void updateOrInsert(ContentResolver resolver, U1Song song) {
974+ ContentValues values = MusicContentValues.forSong(song);
975+ Uri songUri = Songs.buildSongUri(song.getId());
976+ int rowsUpdated = resolver.update(songUri, values, null, null);
977+ if (rowsUpdated == 0) {
978+ resolver.insert(Songs.CONTENT_URI, values);
979+ }
980+ }
981+
982+ /**
983+ * Updates the song. If the song doesn't exist, inserts the song. Backed by
984+ * {@link MusicDatabase}.
985+ *
986+ * @param db
987+ * The {@link MusicDatabase} instance.
988+ * @param song
989+ * The {@link U1Song} to save.
990+ * @return True if update or insert succeeded, false otherwise.
991+ */
992+ public boolean updateOrInsert(SQLiteDatabase db, U1Song song) {
993+ boolean isSuccess = false;
994+
995+ SQLiteStatement sqlStmt = db.compileStatement(getUpdateSql());
996+ int i = 1; // Index to the parameter to bind.
997+ sqlStmt.bindLong(i++, System.currentTimeMillis());
998+
999+ sqlStmt.bindString(i++, song.getTitle());
1000+ sqlStmt.bindString(i++, song.getAlbum());
1001+ sqlStmt.bindString(i++, song.getAlbumId());
1002+ sqlStmt.bindString(i++, song.getAlbumArtist());
1003+
1004+ sqlStmt.bindString(i++, song.getArtist());
1005+ sqlStmt.bindString(i++, song.getArtistId());
1006+ sqlStmt.bindString(i++, song.getGenre());
1007+ sqlStmt.bindString(i++, getGenreId(song.getGenre()));
1008+
1009+ sqlStmt.bindLong(i++, song.getYear());
1010+ sqlStmt.bindLong(i++, song.getDiscNumber());
1011+ sqlStmt.bindLong(i++, song.getTrack());
1012+ sqlStmt.bindLong(i++, song.getDuration());
1013+
1014+ sqlStmt.bindLong(i++, song.getSize());
1015+ sqlStmt.bindLong(i++, song.getBitRate());
1016+ sqlStmt.bindString(i++, song.getSuffix());
1017+ sqlStmt.bindString(i++, song.getContentType());
1018+
1019+ sqlStmt.bindString(i++, song.getSongUrl());
1020+ sqlStmt.bindString(i++, song.getSongArtUrl());
1021+ sqlStmt.bindString(i++, song.getSongStreamUrl());
1022+
1023+ sqlStmt.bindString(i++, song.getId());
1024+ // Can't use executeUpdateDelete on API < 11
1025+ sqlStmt.execute();
1026+ long rowsUpdated = getChanges(db);
1027+
1028+ if (rowsUpdated == 0L) {
1029+ sqlStmt = db.compileStatement(getInsertSql());
1030+ i = 1;
1031+ sqlStmt.bindLong(i++, System.currentTimeMillis());
1032+ sqlStmt.bindString(i++, song.getId());
1033+
1034+ sqlStmt.bindString(i++, song.getTitle());
1035+ sqlStmt.bindString(i++, song.getAlbum());
1036+ sqlStmt.bindString(i++, song.getAlbumId());
1037+ sqlStmt.bindString(i++, song.getAlbumArtist());
1038+
1039+ sqlStmt.bindString(i++, song.getArtist());
1040+ sqlStmt.bindString(i++, song.getArtistId());
1041+ sqlStmt.bindString(i++, song.getGenre());
1042+ sqlStmt.bindString(i++, getGenreId(song.getGenre()));
1043+
1044+ sqlStmt.bindLong(i++, song.getYear());
1045+ sqlStmt.bindLong(i++, song.getDiscNumber());
1046+ sqlStmt.bindLong(i++, song.getTrack());
1047+ sqlStmt.bindLong(i++, song.getDuration());
1048+
1049+ sqlStmt.bindLong(i++, song.getSize());
1050+ sqlStmt.bindLong(i++, song.getBitRate());
1051+ sqlStmt.bindString(i++, song.getSuffix());
1052+ sqlStmt.bindString(i++, song.getContentType());
1053+
1054+ sqlStmt.bindString(i++, song.getSongUrl());
1055+ sqlStmt.bindString(i++, song.getSongArtUrl());
1056+ sqlStmt.bindString(i++, song.getSongStreamUrl());
1057+
1058+ long rowId = sqlStmt.executeInsert();
1059+ isSuccess = rowId != -1;
1060+ } else {
1061+ isSuccess = rowsUpdated == 1;
1062+ }
1063+ return isSuccess;
1064+ }
1065+
1066+ @Override
1067+ public String onGetInsertSql() {
1068+ return "INSERT INTO " + Tables.SONGS + "(" +
1069+ Songs.UPDATED + ", " +
1070+ Songs.SONG_ID + ", " +
1071+
1072+ Songs.SONG_TITLE + ", " +
1073+ Songs.SONG_ALBUM + ", " +
1074+ Songs.SONG_ALBUM_ID + ", " +
1075+ Songs.SONG_ALBUM_ARTIST + ", " +
1076+
1077+ Songs.SONG_ARTIST + ", " +
1078+ Songs.SONG_ARTIST_ID + ", " +
1079+ Songs.SONG_GENRE + ", " +
1080+ Songs.SONG_GENRE_ID + ", " +
1081+
1082+ Songs.SONG_YEAR + ", " +
1083+ Songs.SONG_DISC_NUMBER + ", " +
1084+ Songs.SONG_TRACK + ", " +
1085+ Songs.SONG_DURATION + ", " +
1086+
1087+ Songs.SONG_SIZE + ", " +
1088+ Songs.SONG_BIT_RATE + ", " +
1089+ Songs.SONG_SUFFIX + ", " +
1090+ Songs.SONG_CONTENT_TYPE + ", " +
1091+
1092+ Songs.SONG_URL + ", " +
1093+ Songs.SONG_ART_URL + ", " +
1094+ Songs.SONG_STREAM_URL +
1095+
1096+ ") VALUES (?, ?, " +
1097+ "?, ?, ?, ?, " +
1098+ "?, ?, ?, ?, " +
1099+ "?, ?, ?, ?, " +
1100+ "?, ?, ?, ?, " +
1101+ "?, ?, ?" +
1102+ ")";
1103+ }
1104+
1105+ @Override
1106+ public String onGetUpdateSql() {
1107+ return "UPDATE " + Tables.SONGS + " SET " +
1108+ Songs.UPDATED + "=?, " +
1109+
1110+ Songs.SONG_TITLE + "=?, " +
1111+ Songs.SONG_ALBUM + "=?, " +
1112+ Songs.SONG_ALBUM_ID + "=?, " +
1113+ Songs.SONG_ALBUM_ARTIST + "=?, " +
1114+
1115+ Songs.SONG_ARTIST + "=?, " +
1116+ Songs.SONG_ARTIST_ID + "=?, " +
1117+ Songs.SONG_GENRE + "=?, " +
1118+ Songs.SONG_GENRE_ID + "=?, " +
1119+
1120+ Songs.SONG_YEAR + "=?, " +
1121+ Songs.SONG_DISC_NUMBER + "=?, " +
1122+ Songs.SONG_TRACK + "=?, " +
1123+ Songs.SONG_DURATION + "=?, " +
1124+
1125+ Songs.SONG_SIZE + "=?, " +
1126+ Songs.SONG_BIT_RATE + "=?, " +
1127+ Songs.SONG_SUFFIX + "=?, " +
1128+ Songs.SONG_CONTENT_TYPE + "=?, " +
1129+
1130+ Songs.SONG_URL + "=?, " +
1131+ Songs.SONG_ART_URL + "=?, " +
1132+ Songs.SONG_STREAM_URL + "=? " +
1133+
1134+ "WHERE " + Songs.SONG_ID + "=?";
1135+ }
1136+}
1137
1138=== modified file 'src/com/ubuntuone/android/music/service/MusicService.java'
1139--- src/com/ubuntuone/android/music/service/MusicService.java 2012-11-08 23:02:13 +0000
1140+++ src/com/ubuntuone/android/music/service/MusicService.java 2012-11-21 17:34:22 +0000
1141@@ -384,7 +384,7 @@
1142
1143 public synchronized void resume() {
1144 try {
1145- if (UbuntuOneMusic.DEBUG_SHOULD_PLAY) {
1146+ if (UbuntuOneMusic.SHOULD_PLAY) {
1147 mMediaPlayer.start();
1148 }
1149 setPlayerState(STARTED);
1150@@ -594,7 +594,7 @@
1151 mMediaPlayer.seekTo(position);
1152 }
1153
1154- if (UbuntuOneMusic.DEBUG_SHOULD_PLAY) {
1155+ if (UbuntuOneMusic.SHOULD_PLAY) {
1156 mMediaPlayer.start();
1157 }
1158 setPlayerState(STARTED);
1159
1160=== modified file 'src/com/ubuntuone/android/music/service/SyncService.java'
1161--- src/com/ubuntuone/android/music/service/SyncService.java 2012-11-08 14:14:54 +0000
1162+++ src/com/ubuntuone/android/music/service/SyncService.java 2012-11-21 17:34:22 +0000
1163@@ -21,32 +21,32 @@
1164
1165 package com.ubuntuone.android.music.service;
1166
1167-import static com.ubuntuone.android.music.util.LogUtils.LOGD;
1168-import static com.ubuntuone.android.music.util.LogUtils.LOGE;
1169 import static com.ubuntuone.android.music.util.LogUtils.makeLogTag;
1170-
1171-import java.util.ArrayList;
1172-
1173 import android.app.IntentService;
1174 import android.content.ContentResolver;
1175-import android.content.ContentValues;
1176 import android.content.Context;
1177 import android.content.Intent;
1178 import android.database.Cursor;
1179-import android.net.Uri;
1180+import android.database.sqlite.SQLiteDatabase;
1181 import android.os.Bundle;
1182 import android.os.ResultReceiver;
1183 import android.util.Log;
1184
1185 import com.ubuntuone.android.music.R;
1186 import com.ubuntuone.android.music.UbuntuOneMusic;
1187-import com.ubuntuone.android.music.provider.MusicContentValues;
1188 import com.ubuntuone.android.music.provider.MusicContract.Albums;
1189 import com.ubuntuone.android.music.provider.MusicContract.Artists;
1190 import com.ubuntuone.android.music.provider.MusicContract.Playlists;
1191 import com.ubuntuone.android.music.provider.MusicContract.Songs;
1192 import com.ubuntuone.android.music.provider.MusicContract.SyncColumns;
1193+import com.ubuntuone.android.music.provider.MusicDatabase;
1194 import com.ubuntuone.android.music.provider.MusicProviderUtils;
1195+import com.ubuntuone.android.music.provider.dao.AlbumDao;
1196+import com.ubuntuone.android.music.provider.dao.ArtistDao;
1197+import com.ubuntuone.android.music.provider.dao.GenreDao;
1198+import com.ubuntuone.android.music.provider.dao.PlaylistDao;
1199+import com.ubuntuone.android.music.provider.dao.PlaylistSongDao;
1200+import com.ubuntuone.android.music.provider.dao.SongDao;
1201 import com.ubuntuone.android.music.util.AccountUtils;
1202 import com.ubuntuone.android.music.util.UIUtils;
1203 import com.ubuntuone.api.music.U1MusicAPI;
1204@@ -73,7 +73,8 @@
1205 public static final int SYNC_STARTED = 1;
1206 public static final int SYNC_PROGRESS = 2;
1207 public static final int SYNC_FINISHED = 3;
1208-
1209+
1210+ private static final boolean DIRECT_SQL = true;
1211
1212 private static int sSyncStatus = 0;
1213
1214@@ -104,7 +105,7 @@
1215 mReceiver = intent.getParcelableExtra(EXTRA_RECEIVER);
1216 if (action != null && ACTION_SYNC_MUSIC_METADATA.equals(action)) {
1217 mTimeSyncStarted = System.currentTimeMillis();
1218- if (mApi != null && UbuntuOneMusic.DEBUG_SHOULD_SYNC) {
1219+ if (mApi != null && UbuntuOneMusic.SHOULD_SYNC) {
1220 sSyncStatus = SYNC_STARTED;
1221 if (mReceiver != null) mReceiver.send(SYNC_STARTED, Bundle.EMPTY);
1222 syncMusicMetadata();
1223@@ -122,37 +123,49 @@
1224 syncSongs();
1225 syncPlaylists();
1226 syncPlaylistSongs();
1227- // Don't purge if network has gone away.
1228+ // Purge only if network connection still present.
1229 if (UIUtils.isNetworkConnected(this)) {
1230 purgeInvalidData(mTimeSyncStarted);
1231 }
1232 }
1233
1234 private void syncArtists() {
1235+ final long timeMillis = System.currentTimeMillis();
1236 mApi.getArtists(mArtistListener);
1237+ final long nowMillis = System.currentTimeMillis();
1238+ Log.i(TAG, "Artists sync took " + (nowMillis - timeMillis) + "ms");
1239 }
1240
1241 private void syncAlbums() {
1242+ final long timeMillis = System.currentTimeMillis();
1243 mApi.getAlbums(mAlbumListener);
1244+ final long nowMillis = System.currentTimeMillis();
1245+ Log.i(TAG, "Albums sync took " + (nowMillis - timeMillis) + "ms");
1246 }
1247
1248 private void syncSongs() {
1249+ final long timeMillis = System.currentTimeMillis();
1250 mApi.getSongs(mSongListener);
1251+ final long nowMillis = System.currentTimeMillis();
1252+ Log.i(TAG, "Songs sync took " + (nowMillis - timeMillis) + "ms");
1253 }
1254
1255 private void syncPlaylists() {
1256+ final long timeMillis = System.currentTimeMillis();
1257 mApi.getPlaylists(mPlaylistListener);
1258+ final long nowMillis = System.currentTimeMillis();
1259+ Log.i(TAG, "Playlists sync took " + (nowMillis - timeMillis) + "ms");
1260 }
1261
1262 private void syncPlaylistSongs() {
1263+ final long timeMillis = System.currentTimeMillis();
1264 Cursor cursor = null;
1265 try {
1266 String[] projection = new String[] { Playlists.PLAYLIST_ID };
1267 cursor = getContentResolver().query(Playlists.CONTENT_URI, projection,
1268 null, null, null);
1269 while (cursor.moveToNext()) {
1270- String playlistId = cursor.getString(
1271- cursor.getColumnIndexOrThrow(Playlists.PLAYLIST_ID));
1272+ String playlistId = cursor.getString(cursor.getColumnIndex(Playlists.PLAYLIST_ID));
1273 if (MusicProviderUtils.QUEUE_ID.equals(playlistId)) continue;
1274 mPlaylistSongListener.setPlaylist(playlistId);
1275 mApi.getPlaylist(playlistId, mPlaylistSongListener);
1276@@ -160,163 +173,197 @@
1277 } finally {
1278 if (cursor != null) cursor.close();
1279 }
1280+ final long nowMillis = System.currentTimeMillis();
1281+ Log.i(TAG, "Playlist songs sync took " + (nowMillis - timeMillis) + "ms");
1282 }
1283
1284 private U1ArtistListener mArtistListener = new U1ArtistListener() {
1285+ private SQLiteDatabase db;
1286+ private ArtistDao artistDao = new ArtistDao();
1287+ private Bundle progressBundle = new Bundle();
1288+ private Failure failure = null;
1289 private int artistCount = 0;
1290- private int artistAlbumCount = 0;
1291-
1292- private Bundle progressBundle = new Bundle();
1293
1294 @Override
1295 public void onStart() {
1296- LOGD(TAG, "Syncing artists...");
1297+ Log.d(TAG, "Syncing artists...");
1298+ if (DIRECT_SQL) {
1299+ db = new MusicDatabase(SyncService.this).getWritableDatabase();
1300+ db.beginTransaction();
1301+ }
1302 progressBundle.putInt(EXTRA_LOADER_ID, R.id.artist_loader_id);
1303 }
1304
1305 @Override
1306 public void onSuccess(U1Artist artist) {
1307 artistCount++;
1308- ContentValues values = MusicContentValues.from(artist);
1309- Uri artistUri = Artists.buildArtistUri(artist.getId());
1310- int count = mResolver.update(artistUri, values, null, null);
1311- if (count == 0) {
1312- mResolver.insert(Artists.CONTENT_URI, values);
1313- }
1314- // Insert artist albums.
1315- ArrayList<ContentValues> albumsValues = MusicContentValues.albumsFrom(artist);
1316- for (ContentValues albumValues : albumsValues) {
1317- Uri artistAlbumUri = Artists.buildAlbumUri(
1318- artist.getId(), albumValues.getAsString(Albums.ALBUM_ID));
1319- artistAlbumCount++;
1320- int count2 = mResolver.update(artistAlbumUri, albumValues, null, null);
1321- if (count2 == 0) {
1322- mResolver.insert(artistAlbumUri, albumValues);
1323- }
1324+ if (DIRECT_SQL) {
1325+ artistDao.updateOrInsert(db, artist);
1326+ } else {
1327+ artistDao.updateOrInsert(mResolver, artist);
1328 }
1329 mReceiver.send(SYNC_PROGRESS, progressBundle);
1330 }
1331
1332 @Override
1333 public void onFailure(Failure failure) {
1334- LOGE(TAG, String.format("Failed to get artists: %d -- %s",
1335+ this.failure = failure;
1336+ Log.e(TAG, String.format("Failed to get artists: %d -- %s",
1337 failure.getStatusCode(), failure.getMessage()));
1338 }
1339
1340 @Override
1341 public void onFinish() {
1342- LOGD(TAG, String.format("Finished syncing artists " +
1343- "(got %d artists, %d artist albums).", artistCount, artistAlbumCount));
1344+ if (DIRECT_SQL) {
1345+ if (failure == null) db.setTransactionSuccessful();
1346+ db.endTransaction();
1347+ db.close();
1348+ }
1349+ Log.d(TAG, String.format("Finished syncing artists " +
1350+ "(got %d artists).", artistCount));
1351 }
1352 };
1353
1354 private U1AlbumListener mAlbumListener = new U1AlbumListener() {
1355+ private SQLiteDatabase db;
1356+ private AlbumDao albumDao = new AlbumDao();
1357+ private Bundle progressBundle = new Bundle();
1358+ private Failure failure = null;
1359 private int albumCount = 0;
1360
1361- private Bundle progressBundle = new Bundle();
1362-
1363 @Override
1364 public void onStart() {
1365- LOGD(TAG, "Syncing albums...");
1366+ Log.d(TAG, "Syncing albums...");
1367+ if (DIRECT_SQL) {
1368+ db = new MusicDatabase(SyncService.this).getWritableDatabase();
1369+ db.beginTransaction();
1370+ }
1371 progressBundle.putInt(EXTRA_LOADER_ID, R.id.album_loader_id);
1372 }
1373
1374 @Override
1375 public void onSuccess(U1Album album) {
1376 albumCount++;
1377- ContentValues values = MusicContentValues.from(album);
1378- Uri albumUri = Albums.buildAlbumUri(album.getId());
1379- int count = mResolver.update(albumUri, values, null, null);
1380- if (count == 0) {
1381- mResolver.insert(Albums.CONTENT_URI, values);
1382+ if (DIRECT_SQL) {
1383+ albumDao.updateOrInsert(db, album);
1384+ } else {
1385+ albumDao.updateOrInsert(mResolver, album);
1386 }
1387 mReceiver.send(SYNC_PROGRESS, progressBundle);
1388 }
1389
1390 @Override
1391 public void onFailure(Failure failure) {
1392- super.onFailure(failure);
1393- LOGE(TAG, String.format("Failed to get albums: %d -- %s",
1394+ this.failure = failure;
1395+ Log.e(TAG, String.format("Failed to get albums: %d -- %s",
1396 failure.getStatusCode(), failure.getMessage()));
1397 }
1398
1399 @Override
1400 public void onFinish() {
1401- LOGD(TAG, String.format("Finished syncing albums (got %s albums).",
1402+ if (DIRECT_SQL) {
1403+ if (failure == null) db.setTransactionSuccessful();
1404+ db.endTransaction();
1405+ db.close();
1406+ }
1407+ Log.d(TAG, String.format("Finished syncing albums (got %s albums).",
1408 albumCount));
1409 }
1410 };
1411
1412 private U1SongListener mSongListener = new U1SongListener() {
1413+ private SQLiteDatabase db;
1414+ private SongDao songDao = new SongDao();
1415+ private GenreDao genreDao = new GenreDao();
1416+ private Bundle progressBundle = new Bundle();
1417+ private Failure failure = null;
1418 private int songCount = 0;
1419
1420- private Bundle progressBundle = new Bundle();
1421-
1422 @Override
1423 public void onStart() {
1424- LOGD(TAG, "Syncing songs...");
1425+ Log.d(TAG, "Syncing songs...");
1426+ if (DIRECT_SQL) {
1427+ db = new MusicDatabase(SyncService.this).getWritableDatabase();
1428+ db.beginTransaction();
1429+ }
1430 progressBundle.putInt(EXTRA_LOADER_ID, R.id.song_loader_id);
1431 }
1432
1433 @Override
1434 public void onSuccess(U1Song song) {
1435 songCount++;
1436- ContentValues values = MusicContentValues.from(song);
1437- Uri songUri = Songs.buildSongUri(song.getId());
1438- int count = mResolver.update(songUri, values, null, null);
1439- if (count == 0) {
1440- mResolver.insert(Songs.CONTENT_URI, values);
1441+ if (DIRECT_SQL) {
1442+ if (songDao.updateOrInsert(db, song)) {
1443+ genreDao.updateOrInsert(db, song.getGenre());
1444+ }
1445+ } else {
1446+ songDao.updateOrInsert(mResolver, song);
1447 }
1448 mReceiver.send(SYNC_PROGRESS, progressBundle);
1449 }
1450
1451 @Override
1452 public void onFailure(Failure failure) {
1453- super.onFailure(failure);
1454- LOGE(TAG, String.format("Failed to get songs: %d -- %s",
1455+ this.failure = failure;
1456+ Log.e(TAG, String.format("Failed to get songs: %d -- %s",
1457 failure.getStatusCode(), failure.getMessage()));
1458 }
1459
1460 @Override
1461 public void onFinish() {
1462- LOGD(TAG, String.format("Finished syncing songs (got %d songs).",
1463+ if (DIRECT_SQL) {
1464+ if (failure == null) db.setTransactionSuccessful();
1465+ db.endTransaction();
1466+ db.close();
1467+ }
1468+ Log.d(TAG, String.format("Finished syncing songs (got %d songs).",
1469 songCount));
1470 }
1471 };
1472
1473 private U1PlaylistListener mPlaylistListener = new U1PlaylistListener() {
1474+ private SQLiteDatabase db;
1475+ private PlaylistDao playlistDao = new PlaylistDao();
1476+ private Bundle progressBundle = new Bundle();
1477+ private Failure failure = null;
1478 private int playlistCount = 0;
1479
1480- private Bundle progressBundle = new Bundle();
1481-
1482 @Override
1483 public void onStart() {
1484- LOGD(TAG, "Syncing playlists...");
1485+ Log.d(TAG, "Syncing playlists...");
1486+ if (DIRECT_SQL) {
1487+ db = new MusicDatabase(SyncService.this).getWritableDatabase();
1488+ db.beginTransaction();
1489+ }
1490 progressBundle.putInt(EXTRA_LOADER_ID, R.id.playlist_loader_id);
1491 }
1492
1493 @Override
1494 public void onSuccess(U1Playlist playlist) {
1495 playlistCount++;
1496- ContentValues values = MusicContentValues.from(playlist);
1497- Uri playlistUri = Playlists.buildPlaylistUri(playlist.getId());
1498- int count = mResolver.update(playlistUri, values, null, null);
1499- if (count == 0) {
1500- mResolver.insert(Playlists.CONTENT_URI, values);
1501+ if (DIRECT_SQL) {
1502+ playlistDao.updateOrInsert(db, playlist);
1503+ } else {
1504+ playlistDao.updateOrInsert(mResolver, playlist);
1505 }
1506 mReceiver.send(SYNC_PROGRESS, progressBundle);
1507 }
1508
1509 @Override
1510 public void onFailure(Failure failure) {
1511- super.onFailure(failure);
1512- LOGE(TAG, String.format("Failed to get playlists: %d -- %s",
1513+ this.failure = failure;
1514+ Log.e(TAG, String.format("Failed to get playlists: %d -- %s",
1515 failure.getStatusCode(), failure.getMessage()));
1516 }
1517
1518 @Override
1519 public void onFinish() {
1520- LOGD(TAG, String.format("Finished syncing playlists (got %d playlists).",
1521+ if (DIRECT_SQL) {
1522+ if (failure == null) db.setTransactionSuccessful();
1523+ db.endTransaction();
1524+ db.close();
1525+ }
1526+ Log.d(TAG, String.format("Finished syncing playlists (got %d playlists).",
1527 playlistCount));
1528 }
1529 };
1530@@ -330,35 +377,46 @@
1531 }
1532
1533 private PlaylistSongListener mPlaylistSongListener = new PlaylistSongListener() {
1534+ private SQLiteDatabase db;
1535+ private PlaylistSongDao playlistSongDao = new PlaylistSongDao();
1536+ private Failure failure = null;
1537 private int playlistSongCount = 0;
1538
1539 @Override
1540 public void onStart() {
1541 playlistSongCount = 0; // This listener is reused, so reset.
1542- LOGD(TAG, "Syncing playlist songs...");
1543+ Log.d(TAG, "Syncing playlist songs...");
1544+ if (DIRECT_SQL) {
1545+ db = new MusicDatabase(SyncService.this).getWritableDatabase();
1546+ db.beginTransaction();
1547+ }
1548 }
1549
1550 @Override
1551 public void onSuccess(U1Song song) {
1552 playlistSongCount++;
1553- ContentValues values = MusicContentValues.from(mPlaylistId, song.getId());
1554- Uri playlistSongsUri = Playlists.buildPlaylistSongUri(mPlaylistId, song.getId());
1555- int count = mResolver.update(playlistSongsUri, values, null, null);
1556- if (count == 0) {
1557- mResolver.insert(playlistSongsUri, values);
1558+ if (DIRECT_SQL) {
1559+ playlistSongDao.updateOrInsert(db, mPlaylistId, song.getId());
1560+ } else {
1561+ playlistSongDao.updateOrInsert(mResolver, mPlaylistId, song);
1562 }
1563 }
1564
1565 @Override
1566 public void onFailure(Failure failure) {
1567- super.onFailure(failure);
1568- LOGE(TAG, String.format("Failed to get playlist songs: %d -- %s",
1569+ this.failure = failure;
1570+ Log.e(TAG, String.format("Failed to get playlist songs: %d -- %s",
1571 failure.getStatusCode(), failure.getMessage()));
1572 }
1573
1574 @Override
1575 public void onFinish() {
1576- LOGD(TAG, String.format("Finished syncing playlist songs (got %s playlist songs).",
1577+ if (DIRECT_SQL) {
1578+ if (failure == null) db.setTransactionSuccessful();
1579+ db.endTransaction();
1580+ db.close();
1581+ }
1582+ Log.d(TAG, String.format("Finished syncing playlist songs (got %s playlist songs).",
1583 playlistSongCount));
1584 }
1585 };
1586
1587=== modified file 'src/com/ubuntuone/android/music/ui/HomeActivity.java'
1588--- src/com/ubuntuone/android/music/ui/HomeActivity.java 2012-11-08 14:14:54 +0000
1589+++ src/com/ubuntuone/android/music/ui/HomeActivity.java 2012-11-21 17:34:22 +0000
1590@@ -192,7 +192,7 @@
1591 mService.register(HomeActivity.this);
1592 }
1593 };
1594- if (UbuntuOneMusic.DEBUG_SHOULD_BIND) {
1595+ if (UbuntuOneMusic.SHOULD_BIND) {
1596 bindService(service, mConn, BIND_AUTO_CREATE | BIND_IMPORTANT);
1597 }
1598
1599
1600=== added file 'test/src/com/ubuntuone/android/music/UbuntuOneMusicTest.java'
1601--- test/src/com/ubuntuone/android/music/UbuntuOneMusicTest.java 1970-01-01 00:00:00 +0000
1602+++ test/src/com/ubuntuone/android/music/UbuntuOneMusicTest.java 2012-11-21 17:34:22 +0000
1603@@ -0,0 +1,10 @@
1604+package com.ubuntuone.android.music;
1605+
1606+import junit.framework.TestCase;
1607+
1608+public class UbuntuOneMusicTest extends TestCase
1609+{
1610+ public void testIsReleaseVersion() {
1611+ assertTrue("NOT a release version!", UbuntuOneMusic.IS_RELEASE);
1612+ }
1613+}
1614
1615=== modified file 'test/src/com/ubuntuone/android/music/provider/MusicContentValuesTest.java'
1616--- test/src/com/ubuntuone/android/music/provider/MusicContentValuesTest.java 2012-11-13 13:58:31 +0000
1617+++ test/src/com/ubuntuone/android/music/provider/MusicContentValuesTest.java 2012-11-21 17:34:22 +0000
1618@@ -39,7 +39,7 @@
1619
1620 final U1Artist u1Artist = new U1Artist(id, artistUrl, artist,
1621 artistArtUrl, albumList, songCount);
1622- final ContentValues cv = MusicContentValues.from(u1Artist);
1623+ final ContentValues cv = MusicContentValues.forArtist(u1Artist);
1624
1625 assertEquals(id, cv.getAsString(Artists.ARTIST_ID));
1626 assertEquals(artist, cv.getAsString(Artists.ARTIST_NAME));
1627@@ -63,7 +63,7 @@
1628
1629 final U1Album u1Album = new U1Album(id, albumUrl, artist, artistId,
1630 title, dateAdded, albumArtUrl, year);
1631- final ContentValues cv = MusicContentValues.from(u1Album);
1632+ final ContentValues cv = MusicContentValues.forAlbum(u1Album);
1633
1634 assertEquals(id, cv.getAsString(Albums.ALBUM_ID));
1635 assertEquals(title, cv.getAsString(Albums.ALBUM_TITLE));
1636@@ -84,7 +84,7 @@
1637 final String albumId = HashUtils.md5(title+artist);
1638 final String artistId = HashUtils.md5(artist);
1639 final String genre = "Dubstep";
1640- final String genreIds = HashUtils.md5(genre.toUpperCase());
1641+ final String genreIds = MusicContentValues.getGenreId(genre);
1642 final Integer year = 2012;
1643 final Integer discNumber = 1;
1644 final Integer track = 9;
1645@@ -105,7 +105,7 @@
1646 album, songArtUrl, genre, year, discNumber, track,
1647 duration, size, bitRate, artist, artistId, title, suffix,
1648 contentType, songStreamUrl, path);
1649- final ContentValues cv = MusicContentValues.from(u1Song);
1650+ final ContentValues cv = MusicContentValues.forSong(u1Song);
1651
1652 assertEquals(id, cv.getAsString(Songs.SONG_ID));
1653 assertEquals(title, cv.getAsString(Songs.SONG_TITLE));
1654@@ -141,7 +141,7 @@
1655
1656 final U1Playlist u1Playlist = new U1Playlist(
1657 id, playlistUrl, name, songCount);
1658- final ContentValues cv = MusicContentValues.from(u1Playlist);
1659+ final ContentValues cv = MusicContentValues.forPlaylist(u1Playlist);
1660
1661 assertEquals(id, cv.getAsString(Playlists.PLAYLIST_ID));
1662 assertEquals(name, cv.getAsString(Playlists.PLAYLIST_NAME));
1663@@ -153,7 +153,7 @@
1664 final String playlistId = "bc54b75b-0632-4438-b6a3-c90b83362562";
1665 final String songId ="i6aVaQDYSS6Pal0GbO4MAw";
1666
1667- final ContentValues cv = MusicContentValues.from(playlistId, songId);
1668+ final ContentValues cv = MusicContentValues.forPlaylistSong(playlistId, songId);
1669
1670 assertEquals(playlistId, cv.getAsString(PlaylistSongs.PLAYLIST_ID));
1671 assertEquals(songId, cv.getAsString(PlaylistSongs.SONG_ID));
1672@@ -161,9 +161,9 @@
1673
1674 public void testFromGenre() {
1675 final String genre = "Drum'n'Base";
1676- final String genreId = HashUtils.md5(genre.toUpperCase());
1677+ final String genreId = MusicContentValues.getGenreId(genre);
1678
1679- final ContentValues cv = MusicContentValues.fromGenre(genre);
1680+ final ContentValues cv = MusicContentValues.forGenre(genre);
1681
1682 assertEquals(genreId, cv.getAsString(Genres.GENRE_ID));
1683 assertEquals(genre, cv.getAsString(Genres.GENRE_TITLE));
1684
1685=== modified file 'test/src/com/ubuntuone/android/music/provider/MusicProviderInsertTest.java'
1686--- test/src/com/ubuntuone/android/music/provider/MusicProviderInsertTest.java 2012-11-13 13:58:31 +0000
1687+++ test/src/com/ubuntuone/android/music/provider/MusicProviderInsertTest.java 2012-11-21 17:34:22 +0000
1688@@ -4,6 +4,7 @@
1689
1690 import android.content.ContentValues;
1691 import android.database.Cursor;
1692+import android.database.sqlite.SQLiteDatabase;
1693 import android.net.Uri;
1694
1695 import com.ubuntuone.android.music.provider.MusicContract.Albums;
1696@@ -13,6 +14,12 @@
1697 import com.ubuntuone.android.music.provider.MusicContract.Playlists;
1698 import com.ubuntuone.android.music.provider.MusicContract.Songs;
1699 import com.ubuntuone.android.music.provider.MusicContract.SongsColumns;
1700+import com.ubuntuone.android.music.provider.dao.AlbumDao;
1701+import com.ubuntuone.android.music.provider.dao.ArtistDao;
1702+import com.ubuntuone.android.music.provider.dao.GenreDao;
1703+import com.ubuntuone.android.music.provider.dao.PlaylistDao;
1704+import com.ubuntuone.android.music.provider.dao.PlaylistSongDao;
1705+import com.ubuntuone.android.music.provider.dao.SongDao;
1706 import com.ubuntuone.android.music.util.HashUtils;
1707 import com.ubuntuone.android.music.util.Lists;
1708 import com.ubuntuone.api.music.model.U1Album;
1709@@ -32,7 +39,7 @@
1710 albumList.add("album6-album_id");
1711 U1Artist artist = new U1Artist("artist3-artist_id", "artist3-artist_url",
1712 "artist3-artist_name", "artist3-artist_art_url", albumList, 42);
1713- ContentValues cv = MusicContentValues.from(artist);
1714+ ContentValues cv = MusicContentValues.forArtist(artist);
1715
1716 Uri uri = mResolver.insert(Artists.CONTENT_URI, cv);
1717
1718@@ -42,13 +49,42 @@
1719 assertEquals("Wrong artist row count returned.", 1, cursor.getCount());
1720 assertTrue("Cursor missing rows.", cursor.moveToNext());
1721
1722- assertEquals("Wrong artist id.", "artist3-artist_id",
1723- cursor.getString(cursor.getColumnIndexOrThrow(Artists.ARTIST_ID)));
1724- assertEquals("Wrong artist name.", "artist3-artist_name",
1725- cursor.getString(cursor.getColumnIndexOrThrow(Artists.ARTIST_NAME)));
1726- assertEquals("Wrong artist album.", "album5-album_id,album6-album_id",
1727- cursor.getString(cursor.getColumnIndexOrThrow(Artists.ALBUM_LIST)));
1728- assertEquals("Wrong artist song count.", 42,
1729+ assertEquals("Wrong artist id.", artist.getId(),
1730+ cursor.getString(cursor.getColumnIndexOrThrow(Artists.ARTIST_ID)));
1731+ assertEquals("Wrong artist name.", artist.getArtist(),
1732+ cursor.getString(cursor.getColumnIndexOrThrow(Artists.ARTIST_NAME)));
1733+ assertEquals("Wrong artist album.", MusicContentValues.getAlbumList(artist),
1734+ cursor.getString(cursor.getColumnIndexOrThrow(Artists.ALBUM_LIST)));
1735+ assertEquals("Wrong artist song count.", (int) artist.getSongCount(),
1736+ cursor.getInt(cursor.getColumnIndexOrThrow(Artists.SONG_COUNT)));
1737+
1738+ cursor.close();
1739+ }
1740+
1741+ public void testArtistDaoInsert() {
1742+ ArrayList<String> albumList = Lists.newArrayList();
1743+ albumList.add("album5-album_id");
1744+ albumList.add("album6-album_id");
1745+ U1Artist artist = new U1Artist("artist3-artist_id", "artist3-artist_url",
1746+ "artist3-artist_name", "artist3-artist_art_url", albumList, 42);
1747+ ArtistDao artistDao = new ArtistDao();
1748+ SQLiteDatabase db = new MusicDatabase(getMockContext()).getWritableDatabase();
1749+ artistDao.updateOrInsert(db, artist);
1750+ db.close();
1751+
1752+ Uri uri = Artists.buildArtistUri(artist.getId());
1753+
1754+ Cursor cursor = mResolver.query(uri, Artists.DEFAULT_PROJECTION, null, null, null);
1755+ assertEquals("Wrong artist row count returned.", 1, cursor.getCount());
1756+ assertTrue("Cursor missing rows.", cursor.moveToNext());
1757+
1758+ assertEquals("Wrong artist id.", artist.getId(),
1759+ cursor.getString(cursor.getColumnIndexOrThrow(Artists.ARTIST_ID)));
1760+ assertEquals("Wrong artist name.", artist.getArtist(),
1761+ cursor.getString(cursor.getColumnIndexOrThrow(Artists.ARTIST_NAME)));
1762+ assertEquals("Wrong artist album.", MusicContentValues.getAlbumList(artist),
1763+ cursor.getString(cursor.getColumnIndexOrThrow(Artists.ALBUM_LIST)));
1764+ assertEquals("Wrong artist song count.", (int) artist.getSongCount(),
1765 cursor.getInt(cursor.getColumnIndexOrThrow(Artists.SONG_COUNT)));
1766
1767 cursor.close();
1768@@ -57,7 +93,7 @@
1769 public void testAlbumsInsert() {
1770 U1Album album = new U1Album("album5-album_id", "album5-album_url", "artist1-artist_name",
1771 "artist1-artist_id", "album5-album_title", 1345345345L, "album5-art-url", 2012);
1772- ContentValues cv = MusicContentValues.from(album);
1773+ ContentValues cv = MusicContentValues.forAlbum(album);
1774
1775 Uri uri = mResolver.insert(Albums.CONTENT_URI, cv);
1776
1777@@ -67,18 +103,47 @@
1778 assertEquals("Wrong album row count returned.", 1, cursor.getCount());
1779 assertTrue("Cursor missing rows.", cursor.moveToNext());
1780
1781- assertEquals("Wrong album id.", "album5-album_id",
1782- cursor.getString(cursor.getColumnIndexOrThrow(Albums.ALBUM_ID)));
1783- assertEquals("Wrong album title.", "album5-album_title",
1784- cursor.getString(cursor.getColumnIndexOrThrow(Albums.ALBUM_TITLE)));
1785- assertEquals("Wrong album artist name.", "artist1-artist_name",
1786- cursor.getString(cursor.getColumnIndexOrThrow(Albums.ALBUM_ARTIST)));
1787- assertEquals("Wrong album artist id.",
1788- HashUtils.md5("artist1-artist_name"),
1789- cursor.getString(cursor.getColumnIndexOrThrow(Albums.ALBUM_ARTIST_ID)));
1790- assertEquals("Wrong album year.", 2012,
1791- cursor.getInt(cursor.getColumnIndexOrThrow(Albums.ALBUM_YEAR)));
1792- assertEquals("Wrong album date added.", 1345345345L,
1793+ assertEquals("Wrong album id.", album.getId(),
1794+ cursor.getString(cursor.getColumnIndexOrThrow(Albums.ALBUM_ID)));
1795+ assertEquals("Wrong album title.", album.getTitle(),
1796+ cursor.getString(cursor.getColumnIndexOrThrow(Albums.ALBUM_TITLE)));
1797+ assertEquals("Wrong album artist name.", album.getArtist(),
1798+ cursor.getString(cursor.getColumnIndexOrThrow(Albums.ALBUM_ARTIST)));
1799+ assertEquals("Wrong album artist id.", album.getArtistId(),
1800+ cursor.getString(cursor.getColumnIndexOrThrow(Albums.ALBUM_ARTIST_ID)));
1801+ assertEquals("Wrong album year.", (int) album.getYear(),
1802+ cursor.getInt(cursor.getColumnIndexOrThrow(Albums.ALBUM_YEAR)));
1803+ assertEquals("Wrong album date added.", (long) album.getParsedDate(),
1804+ cursor.getLong(cursor.getColumnIndexOrThrow(Albums.ALBUM_DATE_ADDED)));
1805+
1806+ cursor.close();
1807+ }
1808+
1809+ public void testAlbumDaoInsert() {
1810+ U1Album album = new U1Album("album5-album_id", "album5-album_url", "artist1-artist_name",
1811+ "artist1-artist_id", "album5-album_title", 1345345345L, "album5-art-url", 2012);
1812+ AlbumDao albumDao = new AlbumDao();
1813+ SQLiteDatabase db = new MusicDatabase(getMockContext()).getWritableDatabase();
1814+ albumDao.updateOrInsert(db, album);
1815+ db.close();
1816+
1817+ Uri uri = Albums.buildAlbumUri(album.getId());
1818+
1819+ Cursor cursor = mResolver.query(uri, Albums.DEFAULT_PROJECTION, null, null, null);
1820+ assertEquals("Wrong album row count returned.", 1, cursor.getCount());
1821+ assertTrue("Cursor missing rows.", cursor.moveToNext());
1822+
1823+ assertEquals("Wrong album id.", album.getId(),
1824+ cursor.getString(cursor.getColumnIndexOrThrow(Albums.ALBUM_ID)));
1825+ assertEquals("Wrong album title.", album.getTitle(),
1826+ cursor.getString(cursor.getColumnIndexOrThrow(Albums.ALBUM_TITLE)));
1827+ assertEquals("Wrong album artist name.", album.getArtist(),
1828+ cursor.getString(cursor.getColumnIndexOrThrow(Albums.ALBUM_ARTIST)));
1829+ assertEquals("Wrong album artist id.", album.getArtistId(),
1830+ cursor.getString(cursor.getColumnIndexOrThrow(Albums.ALBUM_ARTIST_ID)));
1831+ assertEquals("Wrong album year.", (int) album.getYear(),
1832+ cursor.getInt(cursor.getColumnIndexOrThrow(Albums.ALBUM_YEAR)));
1833+ assertEquals("Wrong album date added.", (long) album.getParsedDate(),
1834 cursor.getLong(cursor.getColumnIndexOrThrow(Albums.ALBUM_DATE_ADDED)));
1835
1836 cursor.close();
1837@@ -88,9 +153,9 @@
1838 U1Song song = new U1Song("song5-song_id", "song5-song_url",
1839 HashUtils.md5("album1-album_titleartist1-artist_name"), "song5-album_artist",
1840 "album1-album_title", "song5-song_art_url", "genre2", 2009, 3, 2, 315,
1841- 1024 * 1024 * 2, 256, "artist1-artist_name", "aritst1-artist_id",
1842+ 1024 * 1024 * 2, 256, "artist1-artist_name", HashUtils.md5("artist1-artist_name"),
1843 "song5-song_title", "mp3", "audio/mpeg", "song5-song_stream", null);
1844- ContentValues cv = MusicContentValues.from(song);
1845+ ContentValues cv = MusicContentValues.forSong(song);
1846
1847 Uri uri = mResolver.insert(Songs.CONTENT_URI, cv);
1848
1849@@ -100,40 +165,96 @@
1850 assertEquals("Wrong song row count returned.", 1, cursor.getCount());
1851 assertTrue("Cursor missing rows.", cursor.moveToNext());
1852
1853- assertEquals("Wrong song id.", "song5-song_id",
1854- cursor.getString(cursor.getColumnIndexOrThrow(Songs.SONG_ID)));
1855- assertEquals("Wrong song title.", "song5-song_title",
1856- cursor.getString(cursor.getColumnIndexOrThrow(Songs.SONG_TITLE)));
1857- assertEquals("Wrong song album.", "album1-album_title",
1858- cursor.getString(cursor.getColumnIndexOrThrow(Songs.SONG_ALBUM)));
1859- assertEquals("Wrong song album id.",
1860- HashUtils.md5("album1-album_titleartist1-artist_name"),
1861- cursor.getString(cursor.getColumnIndexOrThrow(Songs.SONG_ALBUM_ID)));
1862- assertEquals("Wrong song album artist.", "song5-album_artist",
1863- cursor.getString(cursor.getColumnIndexOrThrow(Songs.SONG_ALBUM_ARTIST)));
1864- assertEquals("Wrong song artist.", "artist1-artist_name",
1865- cursor.getString(cursor.getColumnIndexOrThrow(Songs.SONG_ARTIST)));
1866- assertEquals("Wrong song artist id.", HashUtils.md5("artist1-artist_name"),
1867- cursor.getString(cursor.getColumnIndexOrThrow(Songs.SONG_ARTIST_ID)));
1868- assertEquals("Wrong song genre.", "genre2",
1869- cursor.getString(cursor.getColumnIndexOrThrow(Songs.SONG_GENRE)));
1870- assertEquals("Wrong song genre ids.", HashUtils.md5("genre2".toUpperCase()),
1871- cursor.getString(cursor.getColumnIndexOrThrow(Songs.SONG_GENRE_ID)));
1872- assertEquals("Wrong song year.", 2009,
1873- cursor.getInt(cursor.getColumnIndexOrThrow(Songs.SONG_YEAR)));
1874- assertEquals("Wrong song disc number.", 3,
1875- cursor.getInt(cursor.getColumnIndexOrThrow(Songs.SONG_DISC_NUMBER)));
1876- assertEquals("Wrong song track.", 2,
1877- cursor.getInt(cursor.getColumnIndexOrThrow(Songs.SONG_TRACK)));
1878- assertEquals("Wrong song duration.", 315,
1879- cursor.getInt(cursor.getColumnIndexOrThrow(Songs.SONG_DURATION)));
1880- assertEquals("Wrong song size.", 1024 * 1024 * 2,
1881- cursor.getInt(cursor.getColumnIndexOrThrow(Songs.SONG_SIZE)));
1882- assertEquals("Wrong song bit rate.", 256,
1883- cursor.getInt(cursor.getColumnIndexOrThrow(Songs.SONG_BIT_RATE)));
1884- assertEquals("Wrong song suffix.", "mp3",
1885- cursor.getString(cursor.getColumnIndexOrThrow(Songs.SONG_SUFFIX)));
1886- assertEquals("Wrong song content type.", "audio/mpeg",
1887+ assertEquals("Wrong song id.", song.getId(),
1888+ cursor.getString(cursor.getColumnIndexOrThrow(Songs.SONG_ID)));
1889+ assertEquals("Wrong song title.", song.getTitle(),
1890+ cursor.getString(cursor.getColumnIndexOrThrow(Songs.SONG_TITLE)));
1891+ assertEquals("Wrong song album.", song.getAlbum(),
1892+ cursor.getString(cursor.getColumnIndexOrThrow(Songs.SONG_ALBUM)));
1893+ assertEquals("Wrong song album id.", song.getAlbumId(),
1894+ cursor.getString(cursor.getColumnIndexOrThrow(Songs.SONG_ALBUM_ID)));
1895+ assertEquals("Wrong song album artist.", song.getAlbumArtist(),
1896+ cursor.getString(cursor.getColumnIndexOrThrow(Songs.SONG_ALBUM_ARTIST)));
1897+ assertEquals("Wrong song artist.", song.getArtist(),
1898+ cursor.getString(cursor.getColumnIndexOrThrow(Songs.SONG_ARTIST)));
1899+ assertEquals("Wrong song artist id.", song.getArtistId(),
1900+ cursor.getString(cursor.getColumnIndexOrThrow(Songs.SONG_ARTIST_ID)));
1901+ assertEquals("Wrong song genre.", song.getGenre(),
1902+ cursor.getString(cursor.getColumnIndexOrThrow(Songs.SONG_GENRE)));
1903+ assertEquals("Wrong song genre ids.", MusicContentValues.getGenreId(song.getGenre()),
1904+ cursor.getString(cursor.getColumnIndexOrThrow(Songs.SONG_GENRE_ID)));
1905+ assertEquals("Wrong song year.", (int) song.getYear(),
1906+ cursor.getInt(cursor.getColumnIndexOrThrow(Songs.SONG_YEAR)));
1907+ assertEquals("Wrong song disc number.", (int) song.getDiscNumber(),
1908+ cursor.getInt(cursor.getColumnIndexOrThrow(Songs.SONG_DISC_NUMBER)));
1909+ assertEquals("Wrong song track.", (int) song.getTrack(),
1910+ cursor.getInt(cursor.getColumnIndexOrThrow(Songs.SONG_TRACK)));
1911+ assertEquals("Wrong song duration.", (int) song.getDuration(),
1912+ cursor.getInt(cursor.getColumnIndexOrThrow(Songs.SONG_DURATION)));
1913+ assertEquals("Wrong song size.", (int) song.getSize(),
1914+ cursor.getInt(cursor.getColumnIndexOrThrow(Songs.SONG_SIZE)));
1915+ assertEquals("Wrong song bit rate.", (int) song.getBitRate(),
1916+ cursor.getInt(cursor.getColumnIndexOrThrow(Songs.SONG_BIT_RATE)));
1917+ assertEquals("Wrong song suffix.", song.getSuffix(),
1918+ cursor.getString(cursor.getColumnIndexOrThrow(Songs.SONG_SUFFIX)));
1919+ assertEquals("Wrong song content type.", song.getContentType(),
1920+ cursor.getString(cursor.getColumnIndexOrThrow(Songs.SONG_CONTENT_TYPE)));
1921+ assertEquals("Wrong song last played at.", 0L,
1922+ cursor.getLong(cursor.getColumnIndexOrThrow(Songs.SONG_LAST_PLAYED_AT)));
1923+
1924+ cursor.close();
1925+ }
1926+
1927+ public void testSongDaoInsert() {
1928+ U1Song song = new U1Song("song5-song_id", "song5-song_url",
1929+ HashUtils.md5("album1-album_titleartist1-artist_name"), "song5-album_artist",
1930+ "album1-album_title", "song5-song_art_url", "genre2", 2009, 3, 2, 315,
1931+ 1024 * 1024 * 2, 256, "artist1-artist_name", HashUtils.md5("artist1-artist_name"),
1932+ "song5-song_title", "mp3", "audio/mpeg", "song5-song_stream", null);
1933+ SongDao songDao = new SongDao();
1934+ SQLiteDatabase db = new MusicDatabase(getMockContext()).getWritableDatabase();
1935+ songDao.updateOrInsert(db, song);
1936+ db.close();
1937+
1938+ Uri uri = Songs.buildSongUri(song.getId());
1939+
1940+ Cursor cursor = mResolver.query(uri, Songs.DEFAULT_PROJECTION, null, null, null);
1941+ assertEquals("Wrong song row count returned.", 1, cursor.getCount());
1942+ assertTrue("Cursor missing rows.", cursor.moveToNext());
1943+
1944+ assertEquals("Wrong song id.", song.getId(),
1945+ cursor.getString(cursor.getColumnIndexOrThrow(Songs.SONG_ID)));
1946+ assertEquals("Wrong song title.", song.getTitle(),
1947+ cursor.getString(cursor.getColumnIndexOrThrow(Songs.SONG_TITLE)));
1948+ assertEquals("Wrong song album.", song.getAlbum(),
1949+ cursor.getString(cursor.getColumnIndexOrThrow(Songs.SONG_ALBUM)));
1950+ assertEquals("Wrong song album id.", song.getAlbumId(),
1951+ cursor.getString(cursor.getColumnIndexOrThrow(Songs.SONG_ALBUM_ID)));
1952+ assertEquals("Wrong song album artist.", song.getAlbumArtist(),
1953+ cursor.getString(cursor.getColumnIndexOrThrow(Songs.SONG_ALBUM_ARTIST)));
1954+ assertEquals("Wrong song artist.", song.getArtist(),
1955+ cursor.getString(cursor.getColumnIndexOrThrow(Songs.SONG_ARTIST)));
1956+ assertEquals("Wrong song artist id.", song.getArtistId(),
1957+ cursor.getString(cursor.getColumnIndexOrThrow(Songs.SONG_ARTIST_ID)));
1958+ assertEquals("Wrong song genre.", song.getGenre(),
1959+ cursor.getString(cursor.getColumnIndexOrThrow(Songs.SONG_GENRE)));
1960+ assertEquals("Wrong song genre ids.", MusicContentValues.getGenreId(song.getGenre()),
1961+ cursor.getString(cursor.getColumnIndexOrThrow(Songs.SONG_GENRE_ID)));
1962+ assertEquals("Wrong song year.", (int) song.getYear(),
1963+ cursor.getInt(cursor.getColumnIndexOrThrow(Songs.SONG_YEAR)));
1964+ assertEquals("Wrong song disc number.", (int) song.getDiscNumber(),
1965+ cursor.getInt(cursor.getColumnIndexOrThrow(Songs.SONG_DISC_NUMBER)));
1966+ assertEquals("Wrong song track.", (int) song.getTrack(),
1967+ cursor.getInt(cursor.getColumnIndexOrThrow(Songs.SONG_TRACK)));
1968+ assertEquals("Wrong song duration.", (int) song.getDuration(),
1969+ cursor.getInt(cursor.getColumnIndexOrThrow(Songs.SONG_DURATION)));
1970+ assertEquals("Wrong song size.", (int) song.getSize(),
1971+ cursor.getInt(cursor.getColumnIndexOrThrow(Songs.SONG_SIZE)));
1972+ assertEquals("Wrong song bit rate.", (int) song.getBitRate(),
1973+ cursor.getInt(cursor.getColumnIndexOrThrow(Songs.SONG_BIT_RATE)));
1974+ assertEquals("Wrong song suffix.", song.getSuffix(),
1975+ cursor.getString(cursor.getColumnIndexOrThrow(Songs.SONG_SUFFIX)));
1976+ assertEquals("Wrong song content type.", song.getContentType(),
1977 cursor.getString(cursor.getColumnIndexOrThrow(Songs.SONG_CONTENT_TYPE)));
1978 assertEquals("Wrong song last played at.", 0L,
1979 cursor.getLong(cursor.getColumnIndexOrThrow(Songs.SONG_LAST_PLAYED_AT)));
1980@@ -144,7 +265,7 @@
1981 public void testPlaylistsInsert() {
1982 U1Playlist playlist = new U1Playlist("playlist3-playlist_id", "playlist3-playlist_url",
1983 "playlist3-playlist_name", 10);
1984- ContentValues cv = MusicContentValues.from(playlist);
1985+ ContentValues cv = MusicContentValues.forPlaylist(playlist);
1986
1987 Uri uri = mResolver.insert(Playlists.CONTENT_URI, cv);
1988
1989@@ -154,18 +275,44 @@
1990 assertEquals("Wrong playlist row count returned.", 1, cursor.getCount());
1991 assertTrue("Cursor missing rows.", cursor.moveToNext());
1992
1993- assertEquals("Wrong playlist id.", "playlist3-playlist_id",
1994- cursor.getString(cursor.getColumnIndexOrThrow(Playlists.PLAYLIST_ID)));
1995- assertEquals("Wrong playlist name.", "playlist3-playlist_name",
1996- cursor.getString(cursor.getColumnIndexOrThrow(Playlists.PLAYLIST_NAME)));
1997- assertEquals("Wrong playlist song count.", 10,
1998+ assertEquals("Wrong playlist id.", playlist.getId(),
1999+ cursor.getString(cursor.getColumnIndexOrThrow(Playlists.PLAYLIST_ID)));
2000+ assertEquals("Wrong playlist name.", playlist.getName(),
2001+ cursor.getString(cursor.getColumnIndexOrThrow(Playlists.PLAYLIST_NAME)));
2002+ assertEquals("Wrong playlist song count.", (int) playlist.getSongCount(),
2003+ cursor.getInt(cursor.getColumnIndexOrThrow(Playlists.PLAYLIST_SONG_COUNT)));
2004+
2005+ cursor.close();
2006+ }
2007+
2008+ public void testPlaylistDaoInsert() {
2009+ U1Playlist playlist = new U1Playlist("playlist3-playlist_id", "playlist3-playlist_url",
2010+ "playlist3-playlist_name", 10);
2011+ PlaylistDao playlistDao = new PlaylistDao();
2012+ SQLiteDatabase db = new MusicDatabase(getMockContext()).getWritableDatabase();
2013+ playlistDao.updateOrInsert(db, playlist);
2014+ db.close();
2015+
2016+ Uri uri = Playlists.buildPlaylistUri(playlist.getId());
2017+
2018+ Cursor cursor = mResolver.query(uri, Playlists.DEFAULT_PROJECTION, null, null, null);
2019+ assertEquals("Wrong playlist row count returned.", 1, cursor.getCount());
2020+ assertTrue("Cursor missing rows.", cursor.moveToNext());
2021+
2022+ assertEquals("Wrong playlist id.", playlist.getId(),
2023+ cursor.getString(cursor.getColumnIndexOrThrow(Playlists.PLAYLIST_ID)));
2024+ assertEquals("Wrong playlist name.", playlist.getName(),
2025+ cursor.getString(cursor.getColumnIndexOrThrow(Playlists.PLAYLIST_NAME)));
2026+ assertEquals("Wrong playlist song count.", (int) playlist.getSongCount(),
2027 cursor.getInt(cursor.getColumnIndexOrThrow(Playlists.PLAYLIST_SONG_COUNT)));
2028
2029 cursor.close();
2030 }
2031
2032 public void testPlaylistSongsInsert() {
2033- Uri playlistSongsUri = Playlists.buildPlaylistSongsUri("playlist1-playlist_id");
2034+ final String playlistId = "playlist1-playlist_id";
2035+ final String songId = "song3-song_id";
2036+ Uri playlistSongsUri = Playlists.buildPlaylistSongsUri(playlistId);
2037
2038 { // Check preconditions.
2039 Cursor cursor = mResolver.query(playlistSongsUri, PlaylistSongs.DEFAULT_PROJECTION,
2040@@ -175,7 +322,7 @@
2041 }
2042
2043 // Insert new song.
2044- ContentValues cv = MusicContentValues.from("playlist1-playlist_id", "song3-song_id");
2045+ ContentValues cv = MusicContentValues.forPlaylistSong(playlistId, songId);
2046 Uri uri = mResolver.insert(playlistSongsUri, cv);
2047
2048 assertNotNull("Inserted playlist song uri is null.", uri);
2049@@ -186,9 +333,41 @@
2050
2051 assertTrue("Cursor missing rows.", cursor.moveToPosition(2)); // move to third song
2052
2053- assertEquals("Wrong playlist id.", "playlist1-playlist_id",
2054- cursor.getString(cursor.getColumnIndexOrThrow(PlaylistSongs.PLAYLIST_ID)));
2055- assertEquals("Wrong playlist song id.", "song3-song_id",
2056+ assertEquals("Wrong playlist id.", playlistId,
2057+ cursor.getString(cursor.getColumnIndexOrThrow(PlaylistSongs.PLAYLIST_ID)));
2058+ assertEquals("Wrong playlist song id.", songId,
2059+ cursor.getString(cursor.getColumnIndexOrThrow(SongsColumns.SONG_ID)));
2060+
2061+ cursor.close();
2062+ }
2063+
2064+ public void testPlaylistSongDaoInsert() {
2065+ final String playlistId = "playlist1-playlist_id";
2066+ final String songId = "song3-song_id";
2067+ Uri playlistSongsUri = Playlists.buildPlaylistSongsUri(playlistId);
2068+
2069+ { // Check preconditions.
2070+ Cursor cursor = mResolver.query(playlistSongsUri, PlaylistSongs.DEFAULT_PROJECTION,
2071+ null, null, PlaylistSongs.DEFAULT_SORT);
2072+ assertEquals("Wrong playlist song row count returned.", 2, cursor.getCount());
2073+ cursor.close();
2074+ }
2075+
2076+ // Insert new song.
2077+ PlaylistSongDao playlistSongDao = new PlaylistSongDao();
2078+ SQLiteDatabase db = new MusicDatabase(getMockContext()).getWritableDatabase();
2079+ playlistSongDao.updateOrInsert(db, playlistId, songId);
2080+ db.close();
2081+
2082+ Cursor cursor = mResolver.query(playlistSongsUri, PlaylistSongs.DEFAULT_PROJECTION,
2083+ null, null, PlaylistSongs.DEFAULT_SORT);
2084+ assertEquals("Wrong playlist song row count returned.", 3, cursor.getCount());
2085+
2086+ assertTrue("Cursor missing rows.", cursor.moveToPosition(2)); // move to third song
2087+
2088+ assertEquals("Wrong playlist id.", playlistId,
2089+ cursor.getString(cursor.getColumnIndexOrThrow(PlaylistSongs.PLAYLIST_ID)));
2090+ assertEquals("Wrong playlist song id.", songId,
2091 cursor.getString(cursor.getColumnIndexOrThrow(SongsColumns.SONG_ID)));
2092
2093 cursor.close();
2094@@ -199,11 +378,11 @@
2095 String genre1 = "acid jazz";
2096 String genre2 = "Acid JAZZ";
2097
2098- ContentValues cv1 = MusicContentValues.fromGenre(genre1);
2099+ ContentValues cv1 = MusicContentValues.forGenre(genre1);
2100 Uri uri = mResolver.insert(Genres.CONTENT_URI, cv1);
2101 assertNotNull("Inserted genre uri is null.", uri);
2102
2103- ContentValues cv2 = MusicContentValues.fromGenre(genre2);
2104+ ContentValues cv2 = MusicContentValues.forGenre(genre2);
2105 Uri uri2 = mResolver.insert(Genres.CONTENT_URI, cv2);
2106 assertNotNull("Inserted genre uri is null.", uri2);
2107
2108@@ -213,7 +392,28 @@
2109 assertEquals("Wrong genre row count returned.", 1, cursor.getCount());
2110 assertTrue("Cursor missing rows.", cursor.moveToNext());
2111
2112- assertEquals("Wrong genre name.", "acid jazz",
2113+ assertEquals("Wrong genre name.", genre1,
2114+ cursor.getString(cursor.getColumnIndexOrThrow(Genres.GENRE_TITLE)));
2115+ }
2116+
2117+ public void testGenreDaoInsert() {
2118+ // These genres are treated as same: md5(genre.toUpperCase())
2119+ String genre1 = "acid jazz";
2120+ String genre2 = "Acid JAZZ";
2121+
2122+ GenreDao genreDao = new GenreDao();
2123+ SQLiteDatabase db = new MusicDatabase(getMockContext()).getWritableDatabase();
2124+ genreDao.updateOrInsert(db, genre1);
2125+ genreDao.updateOrInsert(db, genre2);
2126+ db.close();
2127+
2128+ Cursor cursor = mResolver.query(Genres.CONTENT_URI,
2129+ Genres.DEFAULT_PROJECTION, null, null, null);
2130+
2131+ assertEquals("Wrong genre row count returned.", 1, cursor.getCount());
2132+ assertTrue("Cursor missing rows.", cursor.moveToNext());
2133+
2134+ assertEquals("Wrong genre name.", genre1,
2135 cursor.getString(cursor.getColumnIndexOrThrow(Genres.GENRE_TITLE)));
2136 }
2137 }

Subscribers

People subscribed via source and target branches