12eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski/*
22eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski * Copyright (C) 2013 The Android Open Source Project
32eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski *
42eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski * Licensed under the Apache License, Version 2.0 (the "License");
52eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski * you may not use this file except in compliance with the License.
62eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski * You may obtain a copy of the License at
72eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski *
82eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski *      http://www.apache.org/licenses/LICENSE-2.0
92eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski *
102eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski * Unless required by applicable law or agreed to in writing, software
112eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski * distributed under the License is distributed on an "AS IS" BASIS,
122eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
132eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski * See the License for the specific language governing permissions and
142eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski * limitations under the License.
152eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski */
162eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski
172eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowskipackage com.android.deskclock.provider;
182eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski
192eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowskiimport android.content.ContentResolver;
202eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowskiimport android.content.ContentUris;
212eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowskiimport android.content.ContentValues;
222eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowskiimport android.database.Cursor;
232eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowskiimport android.net.Uri;
242eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski
252eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowskiimport java.util.Calendar;
262eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowskiimport java.util.LinkedList;
272eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowskiimport java.util.List;
282eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski
292eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowskipublic final class City implements ClockContract.CitiesColumns {
302eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski    private static final String[] QUERY_COLUMNS = {
312eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski            CITY_ID,
322eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski            CITY_NAME,
332eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski            TIMEZONE_NAME,
342eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski            TIMEZONE_OFFSET
352eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski    };
362eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski
372eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski    /**
382eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski     * These save calls to cursor.getColumnIndexOrThrow()
392eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski     * THEY MUST BE KEPT IN SYNC WITH ABOVE QUERY COLUMNS
402eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski     */
412eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski    private static final int CITY_ID_INDEX = 0;
422eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski    private static final int CITY_NAME_INDEX = 1;
432eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski    private static final int TIMEZONE_NAME_INDEX = 2;
442eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski    private static final int TIMEZONE_OFFSET_INDEX = 3;
452eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski
462eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski    private static final int COLUMN_COUNT = TIMEZONE_OFFSET_INDEX + 1;
472eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski
482eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski    public static ContentValues createContentValues(City city) {
492eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski        ContentValues values = new ContentValues(COLUMN_COUNT);
502eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski        values.put(CITY_ID, city.mCityId);
512eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski        values.put(CITY_NAME, city.mCityName);
522eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski        values.put(TIMEZONE_NAME, city.mTimezoneName);
532eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski        values.put(TIMEZONE_OFFSET, city.mTimezoneOffset);
542eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski        return values;
552eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski    }
562eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski
571c7788b33dd4516dae81e6bcab043addc45fc1a1Paul Sliwowski    public static String getCityId(Uri contentUri) {
581c7788b33dd4516dae81e6bcab043addc45fc1a1Paul Sliwowski        return contentUri.getLastPathSegment();
592eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski    }
602eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski
612eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski    /**
622eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski     * Return content uri for specific city id.
632eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski     *
642eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski     * @param cityId to append to content uri
652eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski     *
662eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski     * @return a new city content uri with the given ID appended to the end of the path
672eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski     */
682eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski    public static Uri getContentUriForId(String cityId) {
692eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski        return CONTENT_URI.buildUpon().appendEncodedPath(cityId).build();
702eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski    }
712eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski
722eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski
732eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski    /**
742eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski     * Get city from cityId.
752eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski     *
762eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski     * @param contentResolver to perform the query on.
772eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski     * @param cityId for the desired city.
782eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski     * @return city if found, null otherwise
792eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski     */
802eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski    public static City getCity(ContentResolver contentResolver, String cityId) {
812eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski        Cursor cursor = contentResolver.query(getContentUriForId(cityId),
822eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski                QUERY_COLUMNS, null, null, null);
832eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski        City result = null;
842eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski        if (cursor == null) {
852eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski            return result;
862eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski        }
872eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski
882eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski        try {
892eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski            if (cursor.moveToFirst()) {
902eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski                result = new City(cursor);
912eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski            }
922eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski        } finally {
932eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski            cursor.close();
942eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski        }
952eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski
962eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski        return result;
972eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski    }
982eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski
992eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski    /**
1002eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski     * Get a list of cities given selection.
1012eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski     *
1022eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski     * @param contentResolver to perform the query on.
1032eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski     * @param selection A filter declaring which rows to return, formatted as an
1042eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski     *         SQL WHERE clause (excluding the WHERE itself). Passing null will
1052eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski     *         return all rows for the given URI.
1062eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski     * @param selectionArgs You may include ?s in selection, which will be
1072eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski     *         replaced by the values from selectionArgs, in the order that they
1082eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski     *         appear in the selection. The values will be bound as Strings.
1092eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski     * @return list of alarms matching where clause or empty list if none found.
1102eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski     */
1112eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski    public static List<City> getCities(ContentResolver contentResolver,
1122eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski            String selection, String... selectionArgs) {
1132eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski        Cursor cursor  = contentResolver.query(CONTENT_URI, QUERY_COLUMNS,
1142eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski                selection, selectionArgs, null);
1152eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski        List<City> result = new LinkedList<City>();
1162eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski        if (cursor == null) {
1172eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski            return result;
1182eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski        }
1192eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski
1202eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski        try {
1212eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski            if (cursor.moveToFirst()) {
1222eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski                do {
1232eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski                    result.add(new City(cursor));
1242eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski                } while (cursor.moveToNext());
1252eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski            }
1262eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski        } finally {
1272eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski            cursor.close();
1282eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski        }
1292eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski
1302eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski        return result;
1312eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski    }
1322eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski
1331c7788b33dd4516dae81e6bcab043addc45fc1a1Paul Sliwowski    public static City addCity(ContentResolver contentResolver, City city) {
1341c7788b33dd4516dae81e6bcab043addc45fc1a1Paul Sliwowski        ContentValues values = createContentValues(city);
1351c7788b33dd4516dae81e6bcab043addc45fc1a1Paul Sliwowski        Uri uri = contentResolver.insert(CONTENT_URI, values);
1361c7788b33dd4516dae81e6bcab043addc45fc1a1Paul Sliwowski        city.mCityId = getCityId(uri);
1371c7788b33dd4516dae81e6bcab043addc45fc1a1Paul Sliwowski        return city;
1381c7788b33dd4516dae81e6bcab043addc45fc1a1Paul Sliwowski    }
1391c7788b33dd4516dae81e6bcab043addc45fc1a1Paul Sliwowski
1401c7788b33dd4516dae81e6bcab043addc45fc1a1Paul Sliwowski    public static boolean updateCity(ContentResolver contentResolver, City city) {
1411c7788b33dd4516dae81e6bcab043addc45fc1a1Paul Sliwowski        ContentValues values = createContentValues(city);
1421c7788b33dd4516dae81e6bcab043addc45fc1a1Paul Sliwowski        Uri updateUri = getContentUriForId(city.mCityId);
1431c7788b33dd4516dae81e6bcab043addc45fc1a1Paul Sliwowski        long rowsUpdated = contentResolver.update(updateUri, values, null, null);
1441c7788b33dd4516dae81e6bcab043addc45fc1a1Paul Sliwowski        return rowsUpdated == 1;
1451c7788b33dd4516dae81e6bcab043addc45fc1a1Paul Sliwowski    }
1461c7788b33dd4516dae81e6bcab043addc45fc1a1Paul Sliwowski
1471c7788b33dd4516dae81e6bcab043addc45fc1a1Paul Sliwowski    public static boolean deleteCity(ContentResolver contentResolver, String cityId) {
1481c7788b33dd4516dae81e6bcab043addc45fc1a1Paul Sliwowski        Uri uri = getContentUriForId(cityId);
1491c7788b33dd4516dae81e6bcab043addc45fc1a1Paul Sliwowski        int deletedRows = contentResolver.delete(uri, "", null);
1501c7788b33dd4516dae81e6bcab043addc45fc1a1Paul Sliwowski        return deletedRows == 1;
1511c7788b33dd4516dae81e6bcab043addc45fc1a1Paul Sliwowski    }
1521c7788b33dd4516dae81e6bcab043addc45fc1a1Paul Sliwowski
1532eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski    // Public fields
1542eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski    public String mCityId;
1552eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski    public String mCityName;
1562eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski    public String mTimezoneName;
1572eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski    public int mTimezoneOffset;
1582eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski
1592eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski    public City(String cityId, String cityName, String timezoneName, int timezoneOffset) {
1602eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski        mCityId = cityId;
1612eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski        mCityName = cityName;
1622eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski        mTimezoneName = timezoneName;
1632eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski        mTimezoneOffset = timezoneOffset;
1642eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski    }
1652eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski
1662eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski    public City(Cursor c) {
1672eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski        mCityId = c.getString(CITY_ID_INDEX);
1682eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski        mCityName = c.getString(CITY_NAME_INDEX);
1692eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski        mTimezoneName = c.getString(TIMEZONE_NAME_INDEX);
1702eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski        mTimezoneOffset = c.getInt(TIMEZONE_OFFSET_INDEX);
1712eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski    }
1722eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski
1732eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski    @Override
1742eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski    public boolean equals(Object o) {
1752eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski        if (!(o instanceof City)) return false;
1762eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski        final City other = (City) o;
1772eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski        return mCityId.equals(other.mCityId);
1782eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski    }
1792eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski
1802eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski    @Override
1812eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski    public int hashCode() {
1822eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski        return mCityId.hashCode();
1832eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski    }
1842eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski
1852eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski    @Override
1862eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski    public String toString() {
1872eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski        return "Instance{" +
1882eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski                "mCityId=" + mCityId +
1892eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski                ", mCityName=" + mCityName +
1902eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski                ", mTimezoneName=" + mTimezoneName +
1912eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski                ", mTimezoneOffset=" + mTimezoneOffset +
1922eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski                '}';
1932eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski    }
1942eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski}
195