Skip to content

Commit 31e5805

Browse files
committed
Adding event persistence with content providers
1 parent 354c032 commit 31e5805

File tree

4 files changed

+355
-4
lines changed

4 files changed

+355
-4
lines changed

AndroidManifest.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,10 @@
2525
android:name=".persistence.database.TaskProvider"
2626
android:authorities="com.nullpointerengineering.android.pomodoro.provider.task">
2727
</provider>
28+
<provider
29+
android:name=".persistence.database.EventProvider"
30+
android:authorities="com.nullpointerengineering.android.pomodoro.provider.event">
31+
</provider>
2832
<activity
2933
android:name=".view.activities.PreferencesEditor"
3034
android:label="Select Preferences"/>
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
/*
2+
* Copyright (c) 2013 Efstratios Xakoustos.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.nullpointerengineering.android.pomodoro.persistence.database;
18+
19+
import android.content.ContentResolver;
20+
import android.content.ContentUris;
21+
import android.content.ContentValues;
22+
import android.database.Cursor;
23+
import android.net.Uri;
24+
import android.test.AndroidTestCase;
25+
26+
import static com.nullpointerengineering.android.pomodoro.persistence.database.DatabaseConstants.*;
27+
28+
/**
29+
* Created with IntelliJ IDEA.
30+
* User: Stratos
31+
* Date: 13/03/13
32+
* Time: 10:38 PM
33+
* Event provider test cases.
34+
*/
35+
public class EventProviderTests extends AndroidTestCase {
36+
37+
private final static int KEY_ID_INDEX = 0;
38+
private final static int TYPE_INDEX = 1;
39+
private final static int TIME_FINISHED_INDEX = 2;
40+
private final static int DURATION_INDEX = 3;
41+
private final static int COMPLETE_INDEX = 4;
42+
private final static String[] PROJECTION;
43+
static {
44+
PROJECTION = new String[5];
45+
PROJECTION[KEY_ID_INDEX] = EVENT_KEY_ID;
46+
PROJECTION[TYPE_INDEX] = EVENT_TYPE;
47+
PROJECTION[TIME_FINISHED_INDEX] = EVENT_TIME_FINISHED;
48+
PROJECTION[DURATION_INDEX] = EVENT_DURATION;
49+
PROJECTION[COMPLETE_INDEX] = EVENT_COMPLETE;
50+
}
51+
52+
private ContentResolver resolver;
53+
private long id;
54+
55+
@Override
56+
protected void setUp(){
57+
resolver = getContext().getContentResolver();
58+
id = createTestEvent();
59+
}
60+
61+
@Override
62+
protected void tearDown() {
63+
resolver.delete(EventProvider.CONTENT_URI, null, null);
64+
}
65+
66+
private long createTestEvent() {
67+
ContentValues eventValues = new ContentValues();
68+
eventValues.put(DatabaseConstants.EVENT_TYPE, "pomodoro");
69+
eventValues.put(DatabaseConstants.EVENT_TIME_FINISHED, System.currentTimeMillis());
70+
eventValues.put(DatabaseConstants.EVENT_COMPLETE, 1);
71+
eventValues.put(DatabaseConstants.EVENT_DURATION, 25 * 60 );
72+
Uri uri = resolver.insert(EventProvider.CONTENT_URI, eventValues);
73+
return Long.parseLong(uri.getPathSegments().get(EventProvider.EVENT_ID_PATH_POSITION));
74+
}
75+
76+
//POST
77+
public void testCreateEvent() {
78+
assertNotSame(0, id);
79+
}
80+
81+
//GET
82+
public void testFindEventById() {
83+
Uri eventUri = EventProvider.CONTENT_ID_URI_BASE;
84+
Cursor cursor = resolver.query( eventUri, PROJECTION, EVENT_KEY_ID +"="+ id, null, null);
85+
assertEquals(1, cursor.getCount());
86+
cursor.moveToFirst();
87+
assertEquals(id, cursor.getLong(KEY_ID_INDEX));
88+
}
89+
90+
public void testFindAllEvents() {
91+
createTestEvent();
92+
Uri eventUri = EventProvider.CONTENT_URI;
93+
Cursor cursor = resolver.query( eventUri, PROJECTION, null, null, null);
94+
assertEquals(2, cursor.getCount());
95+
}
96+
97+
//PUT
98+
public void testUpdateEvent() {
99+
Uri eventUri = ContentUris.withAppendedId(EventProvider.CONTENT_ID_URI_BASE, id);
100+
ContentValues eventValues = new ContentValues();
101+
eventValues.put(DatabaseConstants.EVENT_TYPE, "break");
102+
resolver.update(eventUri,eventValues, null, null );
103+
104+
Cursor cursor = resolver.query(eventUri, PROJECTION, null, null, null);
105+
cursor.moveToFirst();
106+
assertEquals("Value that should be updated didn't","break", cursor.getString(TYPE_INDEX));
107+
assertEquals("Value that shouldn't be updated did", 25 * 60 , cursor.getInt(DURATION_INDEX));
108+
}
109+
110+
//DELETE
111+
public void testDeleteEvent() {
112+
Uri eventUri = ContentUris.withAppendedId(EventProvider.CONTENT_ID_URI_BASE, id);
113+
int count = resolver.delete(eventUri, null, null);
114+
assertEquals(1 , count);
115+
}
116+
}

src/com/nullpointerengineering/android/pomodoro/persistence/database/DatabaseHelper.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ public void onCreate(SQLiteDatabase db) {
4343
Log.v( this.getClass().toString(), "Creating the tables");
4444
Log.v(this.getClass().toString(), CREATE_TASKS_TABLE);
4545
db.execSQL(CREATE_TASKS_TABLE);
46-
db.execSQL(CREATE_POMODOROS_TABLE);
46+
db.execSQL(CREATE_EVENTS_TABLE);
4747
}
4848

4949
@Override
@@ -65,10 +65,10 @@ public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
6565
TASK_DONE_DATE + " INTEGER" +
6666
");";
6767

68-
private static final String CREATE_POMODOROS_TABLE = "create table " + TABLE_EVENTS +" ("+
69-
EVENT_KEY_ID + " INTEGER primary key autoincrement" + ", " +
68+
private static final String CREATE_EVENTS_TABLE = "create table " + TABLE_EVENTS +" ("+
69+
EVENT_KEY_ID + " INTEGER primary key autoincrement, " +
7070
EVENT_DURATION + " INTEGER, " +
71-
EVENT_TYPE + " TEXT not null" +
71+
EVENT_TYPE + " TEXT not null, " +
7272
EVENT_TIME_FINISHED + " INTEGER default 0, " +
7373
EVENT_COMPLETE + " INTEGER default 0" +
7474
");";
Lines changed: 231 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,231 @@
1+
/*
2+
* Copyright (c) 2013 Efstratios Xakoustos.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.nullpointerengineering.android.pomodoro.persistence.database;
18+
19+
import android.content.ContentProvider;
20+
import android.content.ContentUris;
21+
import android.content.ContentValues;
22+
import android.content.UriMatcher;
23+
import android.database.Cursor;
24+
import android.database.SQLException;
25+
import android.database.sqlite.SQLiteDatabase;
26+
import android.database.sqlite.SQLiteQueryBuilder;
27+
import android.net.Uri;
28+
import android.text.TextUtils;
29+
30+
import java.util.HashMap;
31+
32+
import static com.nullpointerengineering.android.pomodoro.persistence.database.DatabaseConstants.*;
33+
34+
/**
35+
* Created with IntelliJ IDEA.
36+
* User: Stratos
37+
* Date: 13/03/13
38+
* Time: 10:27 PM
39+
* Provides access to the event database.
40+
*/
41+
public class EventProvider extends ContentProvider {
42+
43+
private DatabaseHelper databaseHelper;
44+
45+
@Override
46+
public boolean onCreate() {
47+
databaseHelper = new DatabaseHelper(getContext());
48+
return true;
49+
}
50+
51+
@Override
52+
public Cursor query(Uri uri, String[] projection, String selection,
53+
String[] selectionArgs, String sortOrder) {
54+
SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder();
55+
queryBuilder.setTables(TABLE_EVENTS);
56+
57+
switch (uriMatcher.match(uri)){
58+
case EVENTS:
59+
queryBuilder.setProjectionMap(eventsProjectionMap);
60+
break;
61+
case EVENT_ID:
62+
queryBuilder.setProjectionMap(eventsProjectionMap);
63+
queryBuilder.appendWhere(
64+
EVENT_KEY_ID +
65+
"=" +
66+
uri.getPathSegments().get(EVENT_ID_PATH_POSITION));
67+
break;
68+
default:
69+
throw new IllegalArgumentException("Unknown URI " + uri);
70+
}
71+
72+
String orderBy;
73+
if (TextUtils.isEmpty(sortOrder)){
74+
orderBy = DEFAULT_SORT_ORDER;
75+
} else orderBy = sortOrder;
76+
77+
SQLiteDatabase db = databaseHelper.getReadableDatabase();
78+
Cursor cursor = queryBuilder.query(
79+
db, projection, selection, selectionArgs, null, null, orderBy );
80+
cursor.setNotificationUri(getContext().getContentResolver(), uri);
81+
return cursor;
82+
}
83+
84+
@Override
85+
public String getType(Uri uri) {
86+
switch (uriMatcher.match(uri)){
87+
case EVENTS:
88+
return CONTENT_TYPE;
89+
case EVENT_ID:
90+
return CONTENT_ITEM_TYPE;
91+
default:
92+
throw new IllegalArgumentException("Unknown URI " + uri);
93+
} }
94+
95+
@Override
96+
public Uri insert(Uri uri, ContentValues values) {
97+
if (uriMatcher.match(uri) != EVENTS) {
98+
throw new IllegalArgumentException("Unknown URI" + uri);
99+
}
100+
101+
if (values == null) {
102+
values = new ContentValues();
103+
}
104+
105+
if (!values.containsKey(EVENT_TYPE)) {
106+
values.put(EVENT_TYPE, "pomodoro");
107+
}
108+
109+
if (!values.containsKey(EVENT_DURATION)) {
110+
values.put(EVENT_DURATION, 0);
111+
}
112+
113+
if (!values.containsKey(EVENT_TIME_FINISHED)) {
114+
values.put(EVENT_TIME_FINISHED, 0);
115+
}
116+
117+
if (!values.containsKey(EVENT_COMPLETE)) {
118+
values.put(EVENT_COMPLETE, 0);
119+
}
120+
121+
SQLiteDatabase db = databaseHelper.getWritableDatabase();
122+
123+
long rowId = db.insert(TABLE_EVENTS, null, values);
124+
125+
if (rowId > 0 ) {
126+
Uri eventUri = ContentUris.withAppendedId(CONTENT_ID_URI_BASE, rowId);
127+
getContext().getContentResolver().notifyChange(eventUri, null);
128+
return eventUri;
129+
}
130+
throw new SQLException("Failed to insert row into " + uri);
131+
}
132+
133+
@Override
134+
public int delete(Uri uri, String where, String[] whereArgs) {
135+
SQLiteDatabase db = databaseHelper.getWritableDatabase();
136+
String finalWhere;
137+
int count;
138+
139+
switch (uriMatcher.match(uri)) {
140+
case EVENTS:
141+
count = db.delete(TABLE_EVENTS, where, whereArgs);
142+
break;
143+
case EVENT_ID:
144+
finalWhere = EVENT_KEY_ID + " = " + uri.getPathSegments().get(EVENT_ID_PATH_POSITION);
145+
if (where != null) {
146+
finalWhere = finalWhere + " AND " + where;
147+
}
148+
149+
count = db.delete( TABLE_EVENTS, finalWhere, whereArgs );
150+
break;
151+
default:
152+
throw new IllegalArgumentException("Unknown URI " + uri);
153+
}
154+
getContext().getContentResolver().notifyChange(uri, null);
155+
return count;
156+
}
157+
158+
@Override
159+
public int update(Uri uri, ContentValues values, String where, String[] whereArgs) {
160+
SQLiteDatabase db = databaseHelper.getWritableDatabase();
161+
int count;
162+
String finalWhere;
163+
164+
switch (uriMatcher.match(uri)) {
165+
case EVENTS:
166+
count = db.update( TABLE_EVENTS, values, where, whereArgs);
167+
break;
168+
case EVENT_ID:
169+
finalWhere =EVENT_KEY_ID + " = " + uri.getPathSegments().get(EVENT_ID_PATH_POSITION);
170+
171+
if (where !=null) {
172+
finalWhere = finalWhere + " AND " + where;
173+
}
174+
175+
count = db.update( TABLE_EVENTS, values, finalWhere, whereArgs );
176+
break;
177+
default:
178+
throw new IllegalArgumentException("Unknown URI " + uri);
179+
}
180+
getContext().getContentResolver().notifyChange(uri, null);
181+
return count;
182+
}
183+
184+
public static final String AUTHORITY = "com.nullpointerengineering.android.pomodoro.provider.event";
185+
186+
private static final String SCHEME = "content://";
187+
188+
private static final String PATH_EVENTS = "/events";
189+
190+
private static final String PATH_EVENT_ID = "/events/";
191+
192+
public static final Uri CONTENT_URI = Uri.parse(SCHEME + AUTHORITY + PATH_EVENTS);
193+
194+
public static final Uri CONTENT_ID_URI_BASE = Uri.parse(SCHEME + AUTHORITY + PATH_EVENT_ID);
195+
196+
@SuppressWarnings("UnusedDeclaration")
197+
public static final Uri CONTENT_ID_URI_PATTERN = Uri.parse(SCHEME + AUTHORITY + PATH_EVENT_ID + "/#");
198+
199+
public static final int EVENT_ID_PATH_POSITION = 1;
200+
201+
/*
202+
* MIME type definitions
203+
*/
204+
205+
public static final String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.nullpointerengineering.event";
206+
207+
public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/vnd.nullpointerengineering.event";
208+
209+
public static final String DEFAULT_SORT_ORDER = EVENT_TIME_FINISHED + " DESC";
210+
211+
private static HashMap<String, String> eventsProjectionMap;
212+
213+
private static final int EVENTS= 1;
214+
215+
private static final int EVENT_ID = 2;
216+
217+
private static final UriMatcher uriMatcher;
218+
219+
static {
220+
uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
221+
uriMatcher.addURI(AUTHORITY, "events", EVENTS);
222+
uriMatcher.addURI(AUTHORITY, "events/#", EVENT_ID);
223+
224+
eventsProjectionMap = new HashMap<String, String>();
225+
eventsProjectionMap.put(EVENT_KEY_ID, EVENT_KEY_ID);
226+
eventsProjectionMap.put(EVENT_DURATION, EVENT_DURATION);
227+
eventsProjectionMap.put(EVENT_TYPE, EVENT_TYPE);
228+
eventsProjectionMap.put(EVENT_TIME_FINISHED, EVENT_TIME_FINISHED);
229+
eventsProjectionMap.put(EVENT_COMPLETE, EVENT_COMPLETE);
230+
}
231+
}

0 commit comments

Comments
 (0)