PhotoProvider.java revision b2a646658c87378b681d85a130db705a39d07171
1c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount/*
2c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount * Copyright (C) 2013 The Android Open Source Project
3c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount *
4c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount * Licensed under the Apache License, Version 2.0 (the "License");
5c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount * you may not use this file except in compliance with the License.
6c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount * You may obtain a copy of the License at
7c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount *
8c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount *      http://www.apache.org/licenses/LICENSE-2.0
9c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount *
10c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount * Unless required by applicable law or agreed to in writing, software
11c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount * distributed under the License is distributed on an "AS IS" BASIS,
12c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount * See the License for the specific language governing permissions and
14c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount * limitations under the License.
15c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount */
16c8419b4e5e3302f2efc7ea629891041a14219aa7George Mountpackage com.android.photos.data;
17c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount
185139ee00d28c3f694df74f0ccf13cec402707aeaGeorge Mountimport android.content.ContentResolver;
19aebb3b012aef838001c5f9e6adfa4bbcc7bb6569George Mountimport android.content.ContentUris;
20c8419b4e5e3302f2efc7ea629891041a14219aa7George Mountimport android.content.ContentValues;
215139ee00d28c3f694df74f0ccf13cec402707aeaGeorge Mountimport android.content.Context;
22c8419b4e5e3302f2efc7ea629891041a14219aa7George Mountimport android.content.UriMatcher;
23c8419b4e5e3302f2efc7ea629891041a14219aa7George Mountimport android.database.Cursor;
24c8419b4e5e3302f2efc7ea629891041a14219aa7George Mountimport android.database.DatabaseUtils;
25c8419b4e5e3302f2efc7ea629891041a14219aa7George Mountimport android.database.sqlite.SQLiteDatabase;
26c8419b4e5e3302f2efc7ea629891041a14219aa7George Mountimport android.database.sqlite.SQLiteOpenHelper;
27135c2e576f3dfea954ba628942c55adcb35a7cf6George Mountimport android.database.sqlite.SQLiteQueryBuilder;
282f5a064980ad79e88616ba124268e4d7298c68a5George Mountimport android.media.ExifInterface;
29c8419b4e5e3302f2efc7ea629891041a14219aa7George Mountimport android.net.Uri;
30c8419b4e5e3302f2efc7ea629891041a14219aa7George Mountimport android.os.CancellationSignal;
31c8419b4e5e3302f2efc7ea629891041a14219aa7George Mountimport android.provider.BaseColumns;
32c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount
33091314b7ea73e774ce96c981bd7007c94ad80e30George Mountimport com.android.gallery3d.common.ApiHelper;
34091314b7ea73e774ce96c981bd7007c94ad80e30George Mount
35c8419b4e5e3302f2efc7ea629891041a14219aa7George Mountimport java.util.List;
36c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount
37c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount/**
38c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount * A provider that gives access to photo and video information for media stored
39c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount * on the server. Only media that is or will be put on the server will be
40c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount * accessed by this provider. Use Photos.CONTENT_URI to query all photos and
41c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount * videos. Use Albums.CONTENT_URI to query all albums. Use Metadata.CONTENT_URI
42c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount * to query metadata about a photo or video, based on the ID of the media. Use
43c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount * ImageCache.THUMBNAIL_CONTENT_URI, ImageCache.PREVIEW_CONTENT_URI, or
44c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount * ImageCache.ORIGINAL_CONTENT_URI to query the path of the thumbnail, preview,
45c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount * or original-sized image respectfully. <br/>
46c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount * To add or update metadata, use the update function rather than insert. All
47c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount * values for the metadata must be in the ContentValues, even if they are also
48c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount * in the selection. The selection and selectionArgs are not used when updating
49c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount * metadata. If the metadata values are null, the row will be deleted.
50c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount */
515139ee00d28c3f694df74f0ccf13cec402707aeaGeorge Mountpublic class PhotoProvider extends SQLiteContentProvider {
52c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    @SuppressWarnings("unused")
53c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    private static final String TAG = PhotoProvider.class.getSimpleName();
54135c2e576f3dfea954ba628942c55adcb35a7cf6George Mount
55135c2e576f3dfea954ba628942c55adcb35a7cf6George Mount    protected static final String DB_NAME = "photo.db";
56135c2e576f3dfea954ba628942c55adcb35a7cf6George Mount    public static final String AUTHORITY = PhotoProviderAuthority.AUTHORITY;
57c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    static final Uri BASE_CONTENT_URI = new Uri.Builder().scheme("content").authority(AUTHORITY)
58c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount            .build();
59c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount
60135c2e576f3dfea954ba628942c55adcb35a7cf6George Mount    // Used to allow mocking out the change notification because
61135c2e576f3dfea954ba628942c55adcb35a7cf6George Mount    // MockContextResolver disallows system-wide notification.
62135c2e576f3dfea954ba628942c55adcb35a7cf6George Mount    public static interface ChangeNotification {
635139ee00d28c3f694df74f0ccf13cec402707aeaGeorge Mount        void notifyChange(Uri uri, boolean syncToNetwork);
64135c2e576f3dfea954ba628942c55adcb35a7cf6George Mount    }
65135c2e576f3dfea954ba628942c55adcb35a7cf6George Mount
66c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    /**
672f5a064980ad79e88616ba124268e4d7298c68a5George Mount     * Contains columns that can be accessed via Accounts.CONTENT_URI
68c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount     */
692f5a064980ad79e88616ba124268e4d7298c68a5George Mount    public static interface Accounts extends BaseColumns {
70c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        /**
712f5a064980ad79e88616ba124268e4d7298c68a5George Mount         * Internal database table used for account information
72c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount         */
732f5a064980ad79e88616ba124268e4d7298c68a5George Mount        public static final String TABLE = "accounts";
74c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        /**
752f5a064980ad79e88616ba124268e4d7298c68a5George Mount         * Content URI for account information
76c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount         */
77c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        public static final Uri CONTENT_URI = Uri.withAppendedPath(BASE_CONTENT_URI, TABLE);
78c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        /**
792f5a064980ad79e88616ba124268e4d7298c68a5George Mount         * User name for this account.
80c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount         */
812f5a064980ad79e88616ba124268e4d7298c68a5George Mount        public static final String ACCOUNT_NAME = "name";
822f5a064980ad79e88616ba124268e4d7298c68a5George Mount    }
832f5a064980ad79e88616ba124268e4d7298c68a5George Mount
842f5a064980ad79e88616ba124268e4d7298c68a5George Mount    /**
852f5a064980ad79e88616ba124268e4d7298c68a5George Mount     * Contains columns that can be accessed via Photos.CONTENT_URI.
862f5a064980ad79e88616ba124268e4d7298c68a5George Mount     */
872f5a064980ad79e88616ba124268e4d7298c68a5George Mount    public static interface Photos extends BaseColumns {
882f5a064980ad79e88616ba124268e4d7298c68a5George Mount        /** Internal database table used for basic photo information. */
89693a5b7a18066d4757d49a44214356a3dd9f61a0Mangesh Ghiware        public static final String TABLE = "photos";
902f5a064980ad79e88616ba124268e4d7298c68a5George Mount        /** Content URI for basic photo and video information. */
912f5a064980ad79e88616ba124268e4d7298c68a5George Mount        public static final Uri CONTENT_URI = Uri.withAppendedPath(BASE_CONTENT_URI, TABLE);
922f5a064980ad79e88616ba124268e4d7298c68a5George Mount
932f5a064980ad79e88616ba124268e4d7298c68a5George Mount        /** Long foreign key to Accounts._ID */
942f5a064980ad79e88616ba124268e4d7298c68a5George Mount        public static final String ACCOUNT_ID = "account_id";
952f5a064980ad79e88616ba124268e4d7298c68a5George Mount        /** Column name for the width of the original image. Integer value. */
96c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        public static final String WIDTH = "width";
972f5a064980ad79e88616ba124268e4d7298c68a5George Mount        /** Column name for the height of the original image. Integer value. */
98c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        public static final String HEIGHT = "height";
99c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        /**
100c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount         * Column name for the date that the original image was taken. Long
101c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount         * value indicating the milliseconds since epoch in the GMT time zone.
102c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount         */
103c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        public static final String DATE_TAKEN = "date_taken";
104c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        /**
105c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount         * Column name indicating the long value of the album id that this image
106c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount         * resides in. Will be NULL if it it has not been uploaded to the
107c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount         * server.
108c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount         */
109c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        public static final String ALBUM_ID = "album_id";
1102f5a064980ad79e88616ba124268e4d7298c68a5George Mount        /** The column name for the mime-type String. */
1112f5a064980ad79e88616ba124268e4d7298c68a5George Mount        public static final String MIME_TYPE = "mime_type";
1122f5a064980ad79e88616ba124268e4d7298c68a5George Mount        /** The title of the photo. String value. */
1132f5a064980ad79e88616ba124268e4d7298c68a5George Mount        public static final String TITLE = "title";
1142f5a064980ad79e88616ba124268e4d7298c68a5George Mount        /** The date the photo entry was last updated. Long value. */
1152f5a064980ad79e88616ba124268e4d7298c68a5George Mount        public static final String DATE_MODIFIED = "date_modified";
116c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        /**
1172f5a064980ad79e88616ba124268e4d7298c68a5George Mount         * The rotation of the photo in degrees, if rotation has not already
1182f5a064980ad79e88616ba124268e4d7298c68a5George Mount         * been applied. Integer value.
119c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount         */
1202f5a064980ad79e88616ba124268e4d7298c68a5George Mount        public static final String ROTATION = "rotation";
121c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    }
122c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount
123c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    /**
124c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount     * Contains columns and Uri for accessing album information.
125c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount     */
126c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    public static interface Albums extends BaseColumns {
1272f5a064980ad79e88616ba124268e4d7298c68a5George Mount        /** Internal database table used album information. */
128693a5b7a18066d4757d49a44214356a3dd9f61a0Mangesh Ghiware        public static final String TABLE = "albums";
1292f5a064980ad79e88616ba124268e4d7298c68a5George Mount        /** Content URI for album information. */
130c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        public static final Uri CONTENT_URI = Uri.withAppendedPath(BASE_CONTENT_URI, TABLE);
1312f5a064980ad79e88616ba124268e4d7298c68a5George Mount
1322f5a064980ad79e88616ba124268e4d7298c68a5George Mount        /** Long foreign key to Accounts._ID */
1332f5a064980ad79e88616ba124268e4d7298c68a5George Mount        public static final String ACCOUNT_ID = "account_id";
1342f5a064980ad79e88616ba124268e4d7298c68a5George Mount        /** Parent directory or null if this is in the root. */
1352f5a064980ad79e88616ba124268e4d7298c68a5George Mount        public static final String PARENT_ID = "parent_id";
136b2a646658c87378b681d85a130db705a39d07171Mangesh Ghiware        /** The type of album. Non-null, if album is auto-generated. String value. */
137b2a646658c87378b681d85a130db705a39d07171Mangesh Ghiware        public static final String ALBUM_TYPE = "album_type";
138c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        /**
139c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount         * Column name for the visibility level of the album. Can be any of the
140c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount         * VISIBILITY_* values.
141c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount         */
142c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        public static final String VISIBILITY = "visibility";
1432f5a064980ad79e88616ba124268e4d7298c68a5George Mount        /** The user-specified location associated with the album. String value. */
1442f5a064980ad79e88616ba124268e4d7298c68a5George Mount        public static final String LOCATION_STRING = "location_string";
1452f5a064980ad79e88616ba124268e4d7298c68a5George Mount        /** The title of the album. String value. */
1462f5a064980ad79e88616ba124268e4d7298c68a5George Mount        public static final String TITLE = "title";
1472f5a064980ad79e88616ba124268e4d7298c68a5George Mount        /** A short summary of the contents of the album. String value. */
1482f5a064980ad79e88616ba124268e4d7298c68a5George Mount        public static final String SUMMARY = "summary";
1492f5a064980ad79e88616ba124268e4d7298c68a5George Mount        /** The date the album was created. Long value */
1502f5a064980ad79e88616ba124268e4d7298c68a5George Mount        public static final String DATE_PUBLISHED = "date_published";
1512f5a064980ad79e88616ba124268e4d7298c68a5George Mount        /** The date the album entry was last updated. Long value. */
1522f5a064980ad79e88616ba124268e4d7298c68a5George Mount        public static final String DATE_MODIFIED = "date_modified";
153c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount
154c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        // Privacy values for Albums.VISIBILITY
155c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        public static final int VISIBILITY_PRIVATE = 1;
156c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        public static final int VISIBILITY_SHARED = 2;
157c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        public static final int VISIBILITY_PUBLIC = 3;
158c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    }
159c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount
160c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    /**
161c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount     * Contains columns and Uri for accessing photo and video metadata
162c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount     */
163c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    public static interface Metadata extends BaseColumns {
1642f5a064980ad79e88616ba124268e4d7298c68a5George Mount        /** Internal database table used metadata information. */
165c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        public static final String TABLE = "metadata";
1662f5a064980ad79e88616ba124268e4d7298c68a5George Mount        /** Content URI for photo and video metadata. */
167c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        public static final Uri CONTENT_URI = Uri.withAppendedPath(BASE_CONTENT_URI, TABLE);
1682f5a064980ad79e88616ba124268e4d7298c68a5George Mount        /** Foreign key to photo_id. Long value. */
169c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        public static final String PHOTO_ID = "photo_id";
1702f5a064980ad79e88616ba124268e4d7298c68a5George Mount        /** Metadata key. String value */
171c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        public static final String KEY = "key";
172c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        /**
173c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount         * Metadata value. Type is based on key.
174c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount         */
175c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        public static final String VALUE = "value";
1762f5a064980ad79e88616ba124268e4d7298c68a5George Mount
1772f5a064980ad79e88616ba124268e4d7298c68a5George Mount        /** A short summary of the photo. String value. */
1782f5a064980ad79e88616ba124268e4d7298c68a5George Mount        public static final String KEY_SUMMARY = "summary";
1792f5a064980ad79e88616ba124268e4d7298c68a5George Mount        /** The date the photo was added. Long value. */
1802f5a064980ad79e88616ba124268e4d7298c68a5George Mount        public static final String KEY_PUBLISHED = "date_published";
1812f5a064980ad79e88616ba124268e4d7298c68a5George Mount        /** The date the photo was last updated. Long value. */
1822f5a064980ad79e88616ba124268e4d7298c68a5George Mount        public static final String KEY_DATE_UPDATED = "date_updated";
1832f5a064980ad79e88616ba124268e4d7298c68a5George Mount        /** The size of the photo is bytes. Integer value. */
1842f5a064980ad79e88616ba124268e4d7298c68a5George Mount        public static final String KEY_SIZE_IN_BTYES = "size";
1852f5a064980ad79e88616ba124268e4d7298c68a5George Mount        /** The latitude associated with the photo. Double value. */
1862f5a064980ad79e88616ba124268e4d7298c68a5George Mount        public static final String KEY_LATITUDE = "latitude";
1872f5a064980ad79e88616ba124268e4d7298c68a5George Mount        /** The longitude associated with the photo. Double value. */
1882f5a064980ad79e88616ba124268e4d7298c68a5George Mount        public static final String KEY_LONGITUDE = "longitude";
1892f5a064980ad79e88616ba124268e4d7298c68a5George Mount
1902f5a064980ad79e88616ba124268e4d7298c68a5George Mount        /** The make of the camera used. String value. */
1912f5a064980ad79e88616ba124268e4d7298c68a5George Mount        public static final String KEY_EXIF_MAKE = ExifInterface.TAG_MAKE;
1922f5a064980ad79e88616ba124268e4d7298c68a5George Mount        /** The model of the camera used. String value. */
1932f5a064980ad79e88616ba124268e4d7298c68a5George Mount        public static final String KEY_EXIF_MODEL = ExifInterface.TAG_MODEL;;
1942f5a064980ad79e88616ba124268e4d7298c68a5George Mount        /** The exposure time used. Float value. */
1952f5a064980ad79e88616ba124268e4d7298c68a5George Mount        public static final String KEY_EXIF_EXPOSURE = ExifInterface.TAG_EXPOSURE_TIME;
1962f5a064980ad79e88616ba124268e4d7298c68a5George Mount        /** Whether the flash was used. Boolean value. */
1972f5a064980ad79e88616ba124268e4d7298c68a5George Mount        public static final String KEY_EXIF_FLASH = ExifInterface.TAG_FLASH;
1982f5a064980ad79e88616ba124268e4d7298c68a5George Mount        /** The focal length used. Float value. */
1992f5a064980ad79e88616ba124268e4d7298c68a5George Mount        public static final String KEY_EXIF_FOCAL_LENGTH = ExifInterface.TAG_FOCAL_LENGTH;
2002f5a064980ad79e88616ba124268e4d7298c68a5George Mount        /** The fstop value used. Float value. */
2012f5a064980ad79e88616ba124268e4d7298c68a5George Mount        public static final String KEY_EXIF_FSTOP = ExifInterface.TAG_APERTURE;
2022f5a064980ad79e88616ba124268e4d7298c68a5George Mount        /** The ISO equivalent value used. Integer value. */
2032f5a064980ad79e88616ba124268e4d7298c68a5George Mount        public static final String KEY_EXIF_ISO = ExifInterface.TAG_ISO;
204c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    }
205c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount
206c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    /**
207c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount     * Contains columns and Uri for maintaining the image cache.
208c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount     */
209c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    public static interface ImageCache extends BaseColumns {
2102f5a064980ad79e88616ba124268e4d7298c68a5George Mount        /** Internal database table used for the image cache */
211c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        public static final String TABLE = "image_cache";
212c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount
213c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        /**
214c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount         * The image_type query parameter required for accessing a specific
215c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount         * image
216c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount         */
217c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        public static final String IMAGE_TYPE_QUERY_PARAMETER = "image_type";
218c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount
219c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        // ImageCache.IMAGE_TYPE values
220cb8c486b85267f81511d71f89a4c13d8e1dcfc19George Mount        public static final int IMAGE_TYPE_ALBUM_COVER = 1;
221cb8c486b85267f81511d71f89a4c13d8e1dcfc19George Mount        public static final int IMAGE_TYPE_THUMBNAIL = 2;
222cb8c486b85267f81511d71f89a4c13d8e1dcfc19George Mount        public static final int IMAGE_TYPE_PREVIEW = 3;
223cb8c486b85267f81511d71f89a4c13d8e1dcfc19George Mount        public static final int IMAGE_TYPE_ORIGINAL = 4;
224c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount
225c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        /**
226c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount         * Content URI for retrieving image paths. The
227c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount         * IMAGE_TYPE_QUERY_PARAMETER must be used in queries.
228c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount         */
229c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        public static final Uri CONTENT_URI = Uri.withAppendedPath(BASE_CONTENT_URI, TABLE);
230c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount
231cb8c486b85267f81511d71f89a4c13d8e1dcfc19George Mount        /**
232cb8c486b85267f81511d71f89a4c13d8e1dcfc19George Mount         * Content URI for retrieving the album cover art. The album ID must be
233cb8c486b85267f81511d71f89a4c13d8e1dcfc19George Mount         * appended to the URI.
234cb8c486b85267f81511d71f89a4c13d8e1dcfc19George Mount         */
235cb8c486b85267f81511d71f89a4c13d8e1dcfc19George Mount        public static final Uri ALBUM_COVER_CONTENT_URI = Uri.withAppendedPath(CONTENT_URI,
236cb8c486b85267f81511d71f89a4c13d8e1dcfc19George Mount                Albums.TABLE);
237cb8c486b85267f81511d71f89a4c13d8e1dcfc19George Mount
238cb8c486b85267f81511d71f89a4c13d8e1dcfc19George Mount        /**
239cb8c486b85267f81511d71f89a4c13d8e1dcfc19George Mount         * An _ID from Albums or Photos, depending on whether IMAGE_TYPE is
240cb8c486b85267f81511d71f89a4c13d8e1dcfc19George Mount         * IMAGE_TYPE_ALBUM or not. Long value.
241cb8c486b85267f81511d71f89a4c13d8e1dcfc19George Mount         */
242cb8c486b85267f81511d71f89a4c13d8e1dcfc19George Mount        public static final String REMOTE_ID = "remote_id";
2432f5a064980ad79e88616ba124268e4d7298c68a5George Mount        /** One of IMAGE_TYPE_* values. */
244c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        public static final String IMAGE_TYPE = "image_type";
2452f5a064980ad79e88616ba124268e4d7298c68a5George Mount        /** The String path to the image. */
246c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        public static final String PATH = "path";
247c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    };
248c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount
249c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    // SQL used within this class.
250c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    protected static final String WHERE_ID = BaseColumns._ID + " = ?";
251c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    protected static final String WHERE_METADATA_ID = Metadata.PHOTO_ID + " = ? AND "
252c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount            + Metadata.KEY + " = ?";
253c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount
254c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    protected static final String SELECT_ALBUM_ID = "SELECT " + Albums._ID + " FROM "
255c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount            + Albums.TABLE;
256c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    protected static final String SELECT_PHOTO_ID = "SELECT " + Photos._ID + " FROM "
257c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount            + Photos.TABLE;
258c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    protected static final String SELECT_PHOTO_COUNT = "SELECT COUNT(*) FROM " + Photos.TABLE;
259c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    protected static final String DELETE_PHOTOS = "DELETE FROM " + Photos.TABLE;
260c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    protected static final String DELETE_METADATA = "DELETE FROM " + Metadata.TABLE;
261c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    protected static final String SELECT_METADATA_COUNT = "SELECT COUNT(*) FROM " + Metadata.TABLE;
262c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    protected static final String WHERE = " WHERE ";
263c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    protected static final String IN = " IN ";
264c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    protected static final String NESTED_SELECT_START = "(";
265c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    protected static final String NESTED_SELECT_END = ")";
266c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount
267c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    /**
268c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount     * For selecting the mime-type for an image.
269c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount     */
270c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    private static final String[] PROJECTION_MIME_TYPE = {
271c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        Photos.MIME_TYPE,
272c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    };
273c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount
27409bfc1d566621498d08903559ae707161a701571George Mount    protected static final String[] BASE_COLUMNS_ID = {
275135c2e576f3dfea954ba628942c55adcb35a7cf6George Mount        BaseColumns._ID,
276135c2e576f3dfea954ba628942c55adcb35a7cf6George Mount    };
277135c2e576f3dfea954ba628942c55adcb35a7cf6George Mount
278135c2e576f3dfea954ba628942c55adcb35a7cf6George Mount    protected ChangeNotification mNotifier = null;
279c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    protected static final UriMatcher sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
280c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount
281c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    protected static final int MATCH_PHOTO = 1;
282c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    protected static final int MATCH_PHOTO_ID = 2;
283c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    protected static final int MATCH_ALBUM = 3;
284c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    protected static final int MATCH_ALBUM_ID = 4;
285c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    protected static final int MATCH_METADATA = 5;
286c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    protected static final int MATCH_METADATA_ID = 6;
287c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    protected static final int MATCH_IMAGE = 7;
288cb8c486b85267f81511d71f89a4c13d8e1dcfc19George Mount    protected static final int MATCH_ALBUM_COVER = 8;
289dc32aaf95fd6925796474688c24704b3265a1ae7Mangesh Ghiware    protected static final int MATCH_ACCOUNT = 9;
290dc32aaf95fd6925796474688c24704b3265a1ae7Mangesh Ghiware    protected static final int MATCH_ACCOUNT_ID = 10;
291c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount
292c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    static {
293c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        sUriMatcher.addURI(AUTHORITY, Photos.TABLE, MATCH_PHOTO);
294c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        // match against Photos._ID
295c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        sUriMatcher.addURI(AUTHORITY, Photos.TABLE + "/#", MATCH_PHOTO_ID);
296c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        sUriMatcher.addURI(AUTHORITY, Albums.TABLE, MATCH_ALBUM);
297c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        // match against Albums._ID
298c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        sUriMatcher.addURI(AUTHORITY, Albums.TABLE + "/#", MATCH_ALBUM_ID);
299c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        sUriMatcher.addURI(AUTHORITY, Metadata.TABLE, MATCH_METADATA);
300c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        // match against metadata/<Metadata._ID>
301c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        sUriMatcher.addURI(AUTHORITY, Metadata.TABLE + "/#", MATCH_METADATA_ID);
302c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        // match against image_cache/<ImageCache.PHOTO_ID>
303c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        sUriMatcher.addURI(AUTHORITY, ImageCache.TABLE + "/#", MATCH_IMAGE);
304cb8c486b85267f81511d71f89a4c13d8e1dcfc19George Mount        // match against image_cache/album/<Albums._ID>
305cb8c486b85267f81511d71f89a4c13d8e1dcfc19George Mount        sUriMatcher.addURI(AUTHORITY, ImageCache.TABLE + "/" + Albums.TABLE + "/#",
306cb8c486b85267f81511d71f89a4c13d8e1dcfc19George Mount                MATCH_ALBUM_COVER);
307dc32aaf95fd6925796474688c24704b3265a1ae7Mangesh Ghiware        sUriMatcher.addURI(AUTHORITY, Accounts.TABLE, MATCH_ACCOUNT);
308dc32aaf95fd6925796474688c24704b3265a1ae7Mangesh Ghiware        // match against Accounts._ID
309dc32aaf95fd6925796474688c24704b3265a1ae7Mangesh Ghiware        sUriMatcher.addURI(AUTHORITY, Accounts.TABLE + "/#", MATCH_ACCOUNT_ID);
310c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    }
311c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount
312c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    @Override
3135139ee00d28c3f694df74f0ccf13cec402707aeaGeorge Mount    public int deleteInTransaction(Uri uri, String selection, String[] selectionArgs,
3145139ee00d28c3f694df74f0ccf13cec402707aeaGeorge Mount            boolean callerIsSyncAdapter) {
315c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        int match = matchUri(uri);
316c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        selection = addIdToSelection(match, selection);
317c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        selectionArgs = addIdToSelectionArgs(match, uri, selectionArgs);
3188324b3355817e8f6d08ac0b1f7349926df8a9bc7George Mount        return deleteCascade(uri, match, selection, selectionArgs);
319c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    }
320c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount
321c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    @Override
322c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    public String getType(Uri uri) {
323c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        Cursor cursor = query(uri, PROJECTION_MIME_TYPE, null, null, null);
324c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        String mimeType = null;
325c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        if (cursor.moveToNext()) {
326c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount            mimeType = cursor.getString(0);
327c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        }
328c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        cursor.close();
329c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        return mimeType;
330c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    }
331c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount
332c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    @Override
3335139ee00d28c3f694df74f0ccf13cec402707aeaGeorge Mount    public Uri insertInTransaction(Uri uri, ContentValues values, boolean callerIsSyncAdapter) {
334aebb3b012aef838001c5f9e6adfa4bbcc7bb6569George Mount        int match = matchUri(uri);
335aebb3b012aef838001c5f9e6adfa4bbcc7bb6569George Mount        validateMatchTable(match);
336aebb3b012aef838001c5f9e6adfa4bbcc7bb6569George Mount        String table = getTableFromMatch(match, uri);
3375139ee00d28c3f694df74f0ccf13cec402707aeaGeorge Mount        SQLiteDatabase db = getDatabaseHelper().getWritableDatabase();
338aebb3b012aef838001c5f9e6adfa4bbcc7bb6569George Mount        Uri insertedUri = null;
3395139ee00d28c3f694df74f0ccf13cec402707aeaGeorge Mount        long id = db.insert(table, null, values);
3405139ee00d28c3f694df74f0ccf13cec402707aeaGeorge Mount        if (id != -1) {
3415139ee00d28c3f694df74f0ccf13cec402707aeaGeorge Mount            // uri already matches the table.
3425139ee00d28c3f694df74f0ccf13cec402707aeaGeorge Mount            insertedUri = ContentUris.withAppendedId(uri, id);
3435139ee00d28c3f694df74f0ccf13cec402707aeaGeorge Mount            postNotifyUri(insertedUri);
344aebb3b012aef838001c5f9e6adfa4bbcc7bb6569George Mount        }
345aebb3b012aef838001c5f9e6adfa4bbcc7bb6569George Mount        return insertedUri;
346c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    }
347c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount
348c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    @Override
349c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
350c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount            String sortOrder) {
351c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        return query(uri, projection, selection, selectionArgs, sortOrder, null);
352c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    }
353c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount
354c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    @Override
355c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
356c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount            String sortOrder, CancellationSignal cancellationSignal) {
357c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        int match = matchUri(uri);
358c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        selection = addIdToSelection(match, selection);
359c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        selectionArgs = addIdToSelectionArgs(match, uri, selectionArgs);
360c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        String table = getTableFromMatch(match, uri);
361835a0d50318e9cd61bbbd834e36ddda4cff9c59dJohn Reck        Cursor c = query(table, projection, selection, selectionArgs, sortOrder, cancellationSignal);
362835a0d50318e9cd61bbbd834e36ddda4cff9c59dJohn Reck        if (c != null) {
363835a0d50318e9cd61bbbd834e36ddda4cff9c59dJohn Reck            c.setNotificationUri(getContext().getContentResolver(), uri);
364835a0d50318e9cd61bbbd834e36ddda4cff9c59dJohn Reck        }
365835a0d50318e9cd61bbbd834e36ddda4cff9c59dJohn Reck        return c;
366c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    }
367c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount
368c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    @Override
3695139ee00d28c3f694df74f0ccf13cec402707aeaGeorge Mount    public int updateInTransaction(Uri uri, ContentValues values, String selection,
3705139ee00d28c3f694df74f0ccf13cec402707aeaGeorge Mount            String[] selectionArgs, boolean callerIsSyncAdapter) {
371c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        int match = matchUri(uri);
372c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        int rowsUpdated = 0;
3735139ee00d28c3f694df74f0ccf13cec402707aeaGeorge Mount        SQLiteDatabase db = getDatabaseHelper().getWritableDatabase();
3745139ee00d28c3f694df74f0ccf13cec402707aeaGeorge Mount        if (match == MATCH_METADATA) {
3755139ee00d28c3f694df74f0ccf13cec402707aeaGeorge Mount            rowsUpdated = modifyMetadata(db, values);
3765139ee00d28c3f694df74f0ccf13cec402707aeaGeorge Mount        } else {
3775139ee00d28c3f694df74f0ccf13cec402707aeaGeorge Mount            selection = addIdToSelection(match, selection);
3785139ee00d28c3f694df74f0ccf13cec402707aeaGeorge Mount            selectionArgs = addIdToSelectionArgs(match, uri, selectionArgs);
3795139ee00d28c3f694df74f0ccf13cec402707aeaGeorge Mount            String table = getTableFromMatch(match, uri);
3805139ee00d28c3f694df74f0ccf13cec402707aeaGeorge Mount            rowsUpdated = db.update(table, values, selection, selectionArgs);
381c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        }
3825139ee00d28c3f694df74f0ccf13cec402707aeaGeorge Mount        postNotifyUri(uri);
383c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        return rowsUpdated;
384c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    }
385c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount
386135c2e576f3dfea954ba628942c55adcb35a7cf6George Mount    public void setMockNotification(ChangeNotification notification) {
387135c2e576f3dfea954ba628942c55adcb35a7cf6George Mount        mNotifier = notification;
388135c2e576f3dfea954ba628942c55adcb35a7cf6George Mount    }
389135c2e576f3dfea954ba628942c55adcb35a7cf6George Mount
390c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    protected static String addIdToSelection(int match, String selection) {
391c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        String where;
392c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        switch (match) {
393c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount            case MATCH_PHOTO_ID:
394c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount            case MATCH_ALBUM_ID:
395c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount            case MATCH_METADATA_ID:
396c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount                where = WHERE_ID;
397c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount                break;
398c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount            default:
399c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount                return selection;
400c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        }
401c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        return DatabaseUtils.concatenateWhere(selection, where);
402c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    }
403c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount
404c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    protected static String[] addIdToSelectionArgs(int match, Uri uri, String[] selectionArgs) {
405c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        String[] whereArgs;
406c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        switch (match) {
407c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount            case MATCH_PHOTO_ID:
408c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount            case MATCH_ALBUM_ID:
409c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount            case MATCH_METADATA_ID:
410c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount                whereArgs = new String[] {
411c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount                    uri.getPathSegments().get(1),
412c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount                };
413c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount                break;
414c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount            default:
415c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount                return selectionArgs;
416c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        }
417c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        return DatabaseUtils.appendSelectionArgs(selectionArgs, whereArgs);
418c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    }
419c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount
420c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    protected static String[] addMetadataKeysToSelectionArgs(String[] selectionArgs, Uri uri) {
421c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        List<String> segments = uri.getPathSegments();
422c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        String[] additionalArgs = {
423c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount                segments.get(1),
424c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount                segments.get(2),
425c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        };
426c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount
427c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        return DatabaseUtils.appendSelectionArgs(selectionArgs, additionalArgs);
428c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    }
429c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount
430c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    protected static String getTableFromMatch(int match, Uri uri) {
431c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        String table;
432c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        switch (match) {
433c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount            case MATCH_PHOTO:
434c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount            case MATCH_PHOTO_ID:
435c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount                table = Photos.TABLE;
436c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount                break;
437c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount            case MATCH_ALBUM:
438c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount            case MATCH_ALBUM_ID:
439c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount                table = Albums.TABLE;
440c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount                break;
441c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount            case MATCH_METADATA:
442c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount            case MATCH_METADATA_ID:
443c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount                table = Metadata.TABLE;
444c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount                break;
445dc32aaf95fd6925796474688c24704b3265a1ae7Mangesh Ghiware            case MATCH_ACCOUNT:
446dc32aaf95fd6925796474688c24704b3265a1ae7Mangesh Ghiware            case MATCH_ACCOUNT_ID:
447dc32aaf95fd6925796474688c24704b3265a1ae7Mangesh Ghiware                table = Accounts.TABLE;
448dc32aaf95fd6925796474688c24704b3265a1ae7Mangesh Ghiware                break;
449c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount            default:
450c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount                throw unknownUri(uri);
451c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        }
452c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        return table;
453c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    }
454c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount
4555139ee00d28c3f694df74f0ccf13cec402707aeaGeorge Mount    @Override
4565139ee00d28c3f694df74f0ccf13cec402707aeaGeorge Mount    public SQLiteOpenHelper getDatabaseHelper(Context context) {
4575139ee00d28c3f694df74f0ccf13cec402707aeaGeorge Mount        return new PhotoDatabase(context, DB_NAME);
458c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    }
459c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount
460c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    private int modifyMetadata(SQLiteDatabase db, ContentValues values) {
461c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        int rowCount;
462c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        if (values.get(Metadata.VALUE) == null) {
463aebb3b012aef838001c5f9e6adfa4bbcc7bb6569George Mount            String[] selectionArgs = {
464aebb3b012aef838001c5f9e6adfa4bbcc7bb6569George Mount                    values.getAsString(Metadata.PHOTO_ID), values.getAsString(Metadata.KEY),
465aebb3b012aef838001c5f9e6adfa4bbcc7bb6569George Mount            };
466c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount            rowCount = db.delete(Metadata.TABLE, WHERE_METADATA_ID, selectionArgs);
467c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        } else {
468aebb3b012aef838001c5f9e6adfa4bbcc7bb6569George Mount            long rowId = db.replace(Metadata.TABLE, null, values);
469aebb3b012aef838001c5f9e6adfa4bbcc7bb6569George Mount            rowCount = (rowId == -1) ? 0 : 1;
470c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        }
471c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        return rowCount;
472c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    }
473c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount
474c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    private int matchUri(Uri uri) {
475c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        int match = sUriMatcher.match(uri);
476c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        if (match == UriMatcher.NO_MATCH) {
477c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount            throw unknownUri(uri);
478c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        }
479aebb3b012aef838001c5f9e6adfa4bbcc7bb6569George Mount        if (match == MATCH_IMAGE || match == MATCH_ALBUM_COVER) {
480aebb3b012aef838001c5f9e6adfa4bbcc7bb6569George Mount            throw new IllegalArgumentException("Operation not allowed on image cache database");
481aebb3b012aef838001c5f9e6adfa4bbcc7bb6569George Mount        }
482c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        return match;
483c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    }
484c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount
4855139ee00d28c3f694df74f0ccf13cec402707aeaGeorge Mount    @Override
4865139ee00d28c3f694df74f0ccf13cec402707aeaGeorge Mount    protected void notifyChange(ContentResolver resolver, Uri uri, boolean syncToNetwork) {
487135c2e576f3dfea954ba628942c55adcb35a7cf6George Mount        if (mNotifier != null) {
4885139ee00d28c3f694df74f0ccf13cec402707aeaGeorge Mount            mNotifier.notifyChange(uri, syncToNetwork);
489135c2e576f3dfea954ba628942c55adcb35a7cf6George Mount        } else {
490835a0d50318e9cd61bbbd834e36ddda4cff9c59dJohn Reck            super.notifyChange(resolver, uri, syncToNetwork);
491135c2e576f3dfea954ba628942c55adcb35a7cf6George Mount        }
492c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    }
493c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount
494c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    protected static IllegalArgumentException unknownUri(Uri uri) {
495c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        return new IllegalArgumentException("Unknown Uri format: " + uri);
496c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    }
497c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount
498135c2e576f3dfea954ba628942c55adcb35a7cf6George Mount    protected static String nestWhere(String matchColumn, String table, String nestedWhere) {
499135c2e576f3dfea954ba628942c55adcb35a7cf6George Mount        String query = SQLiteQueryBuilder.buildQueryString(false, table, BASE_COLUMNS_ID,
500135c2e576f3dfea954ba628942c55adcb35a7cf6George Mount                nestedWhere, null, null, null, null);
501135c2e576f3dfea954ba628942c55adcb35a7cf6George Mount        return matchColumn + IN + NESTED_SELECT_START + query + NESTED_SELECT_END;
502c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    }
503c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount
5048324b3355817e8f6d08ac0b1f7349926df8a9bc7George Mount    protected static String metadataSelectionFromPhotos(String where) {
5058324b3355817e8f6d08ac0b1f7349926df8a9bc7George Mount        return nestWhere(Metadata.PHOTO_ID, Photos.TABLE, where);
5068324b3355817e8f6d08ac0b1f7349926df8a9bc7George Mount    }
5078324b3355817e8f6d08ac0b1f7349926df8a9bc7George Mount
5088324b3355817e8f6d08ac0b1f7349926df8a9bc7George Mount    protected static String photoSelectionFromAlbums(String where) {
5098324b3355817e8f6d08ac0b1f7349926df8a9bc7George Mount        return nestWhere(Photos.ALBUM_ID, Albums.TABLE, where);
5108324b3355817e8f6d08ac0b1f7349926df8a9bc7George Mount    }
5118324b3355817e8f6d08ac0b1f7349926df8a9bc7George Mount
5128324b3355817e8f6d08ac0b1f7349926df8a9bc7George Mount    protected static String photoSelectionFromAccounts(String where) {
5138324b3355817e8f6d08ac0b1f7349926df8a9bc7George Mount        return nestWhere(Photos.ACCOUNT_ID, Accounts.TABLE, where);
5148324b3355817e8f6d08ac0b1f7349926df8a9bc7George Mount    }
5158324b3355817e8f6d08ac0b1f7349926df8a9bc7George Mount
5168324b3355817e8f6d08ac0b1f7349926df8a9bc7George Mount    protected static String albumSelectionFromAccounts(String where) {
5178324b3355817e8f6d08ac0b1f7349926df8a9bc7George Mount        return nestWhere(Albums.ACCOUNT_ID, Accounts.TABLE, where);
5188324b3355817e8f6d08ac0b1f7349926df8a9bc7George Mount    }
5198324b3355817e8f6d08ac0b1f7349926df8a9bc7George Mount
5208324b3355817e8f6d08ac0b1f7349926df8a9bc7George Mount    protected int deleteCascade(Uri uri, int match, String selection, String[] selectionArgs) {
521c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        switch (match) {
522c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount            case MATCH_PHOTO:
52356c42ad3265ceac0674e6a4c00800336101a230cGeorge Mount            case MATCH_PHOTO_ID:
5248324b3355817e8f6d08ac0b1f7349926df8a9bc7George Mount                deleteCascade(Metadata.CONTENT_URI, MATCH_METADATA,
5258324b3355817e8f6d08ac0b1f7349926df8a9bc7George Mount                        metadataSelectionFromPhotos(selection), selectionArgs);
526c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount                break;
527c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount            case MATCH_ALBUM:
52856c42ad3265ceac0674e6a4c00800336101a230cGeorge Mount            case MATCH_ALBUM_ID:
5298324b3355817e8f6d08ac0b1f7349926df8a9bc7George Mount                deleteCascade(Photos.CONTENT_URI, MATCH_PHOTO,
5308324b3355817e8f6d08ac0b1f7349926df8a9bc7George Mount                        photoSelectionFromAlbums(selection), selectionArgs);
531c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount                break;
53256c42ad3265ceac0674e6a4c00800336101a230cGeorge Mount            case MATCH_ACCOUNT:
53356c42ad3265ceac0674e6a4c00800336101a230cGeorge Mount            case MATCH_ACCOUNT_ID:
5348324b3355817e8f6d08ac0b1f7349926df8a9bc7George Mount                deleteCascade(Photos.CONTENT_URI, MATCH_PHOTO,
5358324b3355817e8f6d08ac0b1f7349926df8a9bc7George Mount                        photoSelectionFromAccounts(selection), selectionArgs);
5368324b3355817e8f6d08ac0b1f7349926df8a9bc7George Mount                deleteCascade(Albums.CONTENT_URI, MATCH_ALBUM,
5378324b3355817e8f6d08ac0b1f7349926df8a9bc7George Mount                        albumSelectionFromAccounts(selection), selectionArgs);
53856c42ad3265ceac0674e6a4c00800336101a230cGeorge Mount                break;
539c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        }
5408324b3355817e8f6d08ac0b1f7349926df8a9bc7George Mount        SQLiteDatabase db = getDatabaseHelper().getWritableDatabase();
541c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        String table = getTableFromMatch(match, uri);
542135c2e576f3dfea954ba628942c55adcb35a7cf6George Mount        int deleted = db.delete(table, selection, selectionArgs);
543135c2e576f3dfea954ba628942c55adcb35a7cf6George Mount        if (deleted > 0) {
5445139ee00d28c3f694df74f0ccf13cec402707aeaGeorge Mount            postNotifyUri(uri);
545c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount        }
546135c2e576f3dfea954ba628942c55adcb35a7cf6George Mount        return deleted;
547c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount    }
548c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount
549aebb3b012aef838001c5f9e6adfa4bbcc7bb6569George Mount    private static void validateMatchTable(int match) {
550aebb3b012aef838001c5f9e6adfa4bbcc7bb6569George Mount        switch (match) {
551aebb3b012aef838001c5f9e6adfa4bbcc7bb6569George Mount            case MATCH_PHOTO:
552aebb3b012aef838001c5f9e6adfa4bbcc7bb6569George Mount            case MATCH_ALBUM:
553aebb3b012aef838001c5f9e6adfa4bbcc7bb6569George Mount            case MATCH_METADATA:
554dc32aaf95fd6925796474688c24704b3265a1ae7Mangesh Ghiware            case MATCH_ACCOUNT:
555aebb3b012aef838001c5f9e6adfa4bbcc7bb6569George Mount                break;
556aebb3b012aef838001c5f9e6adfa4bbcc7bb6569George Mount            default:
557aebb3b012aef838001c5f9e6adfa4bbcc7bb6569George Mount                throw new IllegalArgumentException("Operation not allowed on an existing row.");
558aebb3b012aef838001c5f9e6adfa4bbcc7bb6569George Mount        }
559aebb3b012aef838001c5f9e6adfa4bbcc7bb6569George Mount    }
560091314b7ea73e774ce96c981bd7007c94ad80e30George Mount
561091314b7ea73e774ce96c981bd7007c94ad80e30George Mount    protected Cursor query(String table, String[] columns, String selection,
562091314b7ea73e774ce96c981bd7007c94ad80e30George Mount            String[] selectionArgs, String orderBy, CancellationSignal cancellationSignal) {
563091314b7ea73e774ce96c981bd7007c94ad80e30George Mount        SQLiteDatabase db = getDatabaseHelper().getReadableDatabase();
564091314b7ea73e774ce96c981bd7007c94ad80e30George Mount        if (ApiHelper.HAS_CANCELLATION_SIGNAL) {
565091314b7ea73e774ce96c981bd7007c94ad80e30George Mount            return db.query(false, table, columns, selection, selectionArgs, null, null,
566091314b7ea73e774ce96c981bd7007c94ad80e30George Mount                    orderBy, null, cancellationSignal);
567091314b7ea73e774ce96c981bd7007c94ad80e30George Mount        } else {
568091314b7ea73e774ce96c981bd7007c94ad80e30George Mount            return db.query(table, columns, selection, selectionArgs, null, null, orderBy);
569091314b7ea73e774ce96c981bd7007c94ad80e30George Mount        }
570091314b7ea73e774ce96c981bd7007c94ad80e30George Mount    }
571c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount}
572