1/*
2 * Copyright (C) 2014 The Android Open Source Project
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
17package com.android.fmradio;
18
19import android.content.ContentProvider;
20import android.content.ContentUris;
21import android.content.ContentValues;
22import android.content.Context;
23import android.content.UriMatcher;
24import android.database.Cursor;
25import android.database.sqlite.SQLiteDatabase;
26import android.database.sqlite.SQLiteOpenHelper;
27import android.database.sqlite.SQLiteQueryBuilder;
28import android.net.Uri;
29import android.text.TextUtils;
30import android.util.Log;
31
32/**
33 * This class provider interface to operator FM database table StationList
34 */
35public class FmProvider extends ContentProvider {
36    private static final String TAG = "FmProvider";
37
38    // database instance use to operate the database
39    private SQLiteDatabase mSqlDb = null;
40    // database helper use to get database instance
41    private DatabaseHelper mDbHelper = null;
42    // database name
43    private static final String DATABASE_NAME = "FmRadio.db";
44    // database version
45    private static final int DATABASE_VERSION = 1;
46    // table name
47    private static final String TABLE_NAME = "StationList";
48
49    // URI match code
50    private static final int STATION_FREQ = 1;
51    // URI match code
52    private static final int STATION_FREQ_ID = 2;
53    // use to match URI
54    private static final UriMatcher URI_MATCHER = new UriMatcher(UriMatcher.NO_MATCH);
55
56    // match URI with station frequency or station frequency id
57    static {
58        URI_MATCHER.addURI(FmStation.AUTHORITY, FmStation.STATION, STATION_FREQ);
59        URI_MATCHER.addURI(FmStation.AUTHORITY, FmStation.STATION + "/#",
60                STATION_FREQ_ID);
61    }
62
63    /**
64     * Helper to operate database
65     */
66    private static class DatabaseHelper extends SQLiteOpenHelper {
67
68        /**
69         * initial database name and database version
70         *
71         * @param context application context
72         */
73        DatabaseHelper(Context context) {
74            super(context, DATABASE_NAME, null, DATABASE_VERSION);
75        }
76
77        /**
78         * Create database table
79         *
80         * @param db The database
81         */
82        @Override
83        public void onCreate(SQLiteDatabase db) {
84            // Create the table
85            Log.d(TAG, "onCreate, create the database");
86            db.execSQL(
87                    "CREATE TABLE " + TABLE_NAME + "("
88                            + FmStation.Station._ID + " INTEGER PRIMARY KEY AUTOINCREMENT,"
89                            + FmStation.Station.FREQUENCY + " INTEGER UNIQUE,"
90                            + FmStation.Station.IS_FAVORITE + " INTEGER DEFAULT 0,"
91                            + FmStation.Station.STATION_NAME + " TEXT,"
92                            + FmStation.Station.PROGRAM_SERVICE + " TEXT,"
93                            + FmStation.Station.RADIO_TEXT + " TEXT"
94                            + ");"
95                    );
96        }
97
98        /**
99         * Upgrade database
100         *
101         * @param db database
102         * @param oldVersion The old database version
103         * @param newVersion The new database version
104         */
105        @Override
106        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
107            // TODO: reimplement this when dB version changes
108            Log.i(TAG, "onUpgrade, upgrading database from version " + oldVersion + " to "
109                    + newVersion + ", which will destroy all old data");
110            db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME);
111            onCreate(db);
112        }
113    }
114
115    /**
116     * Delete database table rows with condition
117     *
118     * @param uri The uri to delete
119     * @param selection The where cause to apply, if null will delete all rows
120     * @param selectionArgs The select value
121     *
122     * @return The rows number has be deleted
123     */
124    @Override
125    public int delete(Uri uri, String selection, String[] selectionArgs) {
126        int rows = 0;
127        mSqlDb = mDbHelper.getWritableDatabase();
128        switch (URI_MATCHER.match(uri)) {
129            case STATION_FREQ:
130                rows = mSqlDb.delete(TABLE_NAME, selection, selectionArgs);
131                getContext().getContentResolver().notifyChange(uri, null);
132                break;
133
134            case STATION_FREQ_ID:
135                String stationID = uri.getPathSegments().get(1);
136                rows = mSqlDb.delete(TABLE_NAME,
137                        FmStation.Station._ID
138                                + "="
139                                + stationID
140                                + (TextUtils.isEmpty(selection) ? "" : " AND (" + selection + ")"),
141                        selectionArgs);
142                getContext().getContentResolver().notifyChange(uri, null);
143                break;
144
145            default:
146                Log.e(TAG, "delete, unkown URI to delete: " + uri);
147                break;
148        }
149        return rows;
150    }
151
152    /**
153     * Insert values to database with uri
154     *
155     * @param uri The insert uri
156     * @param values The insert values
157     *
158     * @return The uri after inserted
159     */
160    @Override
161    public Uri insert(Uri uri, ContentValues values) {
162        Uri rowUri = null;
163        mSqlDb = mDbHelper.getWritableDatabase();
164        ContentValues v = new ContentValues(values);
165
166        long rowId = mSqlDb.insert(TABLE_NAME, null, v);
167        if (rowId <= 0) {
168            Log.e(TAG, "insert, failed to insert row into " + uri);
169        }
170        rowUri = ContentUris.appendId(FmStation.Station.CONTENT_URI.buildUpon(), rowId)
171                .build();
172        getContext().getContentResolver().notifyChange(rowUri, null);
173        return rowUri;
174    }
175
176    /**
177     * Create database helper
178     *
179     * @return true if create database helper success
180     */
181    @Override
182    public boolean onCreate() {
183        mDbHelper = new DatabaseHelper(getContext());
184        return (null == mDbHelper) ? false : true;
185    }
186
187    /**
188     * Query the database with current settings and add information
189     *
190     * @param uri The database uri
191     * @param projection The columns need to query
192     * @param selection The where clause
193     * @param selectionArgs The where value
194     * @param sortOrder The column to sort
195     *
196     * @return The query result cursor
197     */
198    @Override
199    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
200            String sortOrder) {
201        SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
202        SQLiteDatabase db = mDbHelper.getReadableDatabase();
203        qb.setTables(TABLE_NAME);
204
205        int match = URI_MATCHER.match(uri);
206
207        if (STATION_FREQ_ID == match) {
208            qb.appendWhere("_id = " + uri.getPathSegments().get(1));
209        }
210
211        Cursor c = qb.query(db, projection, selection, selectionArgs, null, null, sortOrder);
212        if (null != c) {
213            c.setNotificationUri(getContext().getContentResolver(), uri);
214        }
215        return c;
216    }
217
218    /**
219     * Update the database content use content values with current settings and
220     * add information
221     *
222     * @param uri The database uri
223     * @param values The values need to update
224     * @param selection The where clause
225     * @param selectionArgs The where value
226     *
227     * @return The row numbers have changed
228     */
229    @Override
230    public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
231        int rows = 0;
232        mSqlDb = mDbHelper.getWritableDatabase();
233        switch (URI_MATCHER.match(uri)) {
234            case STATION_FREQ:
235                rows = mSqlDb.update(TABLE_NAME, values, selection, selectionArgs);
236                getContext().getContentResolver().notifyChange(uri, null);
237                break;
238            case STATION_FREQ_ID:
239                String stationID = uri.getPathSegments().get(1);
240                rows = mSqlDb.update(TABLE_NAME,
241                        values,
242                        FmStation.Station._ID
243                                + "="
244                                + stationID
245                                + (TextUtils.isEmpty(selection) ? "" : " AND (" + selection + ")"),
246                        selectionArgs);
247                getContext().getContentResolver().notifyChange(uri, null);
248                break;
249            default:
250                Log.e(TAG, "update, unkown URI to update: " + uri);
251                break;
252        }
253        return rows;
254    }
255
256    /**
257     * Get uri type
258     *
259     * @param uri The the uri
260     *
261     * @return The type
262     */
263    @Override
264    public String getType(Uri uri) {
265        return null;
266    }
267}
268