1 /*
2  * Copyright (C) 2013 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 
17 package com.android.deskclock.provider;
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 
25 import java.util.Calendar;
26 import java.util.LinkedList;
27 import java.util.List;
28 
29 public final class City implements ClockContract.CitiesColumns {
30     private static final String[] QUERY_COLUMNS = {
31             CITY_ID,
32             CITY_NAME,
33             TIMEZONE_NAME,
34             TIMEZONE_OFFSET
35     };
36 
37     /**
38      * These save calls to cursor.getColumnIndexOrThrow()
39      * THEY MUST BE KEPT IN SYNC WITH ABOVE QUERY COLUMNS
40      */
41     private static final int CITY_ID_INDEX = 0;
42     private static final int CITY_NAME_INDEX = 1;
43     private static final int TIMEZONE_NAME_INDEX = 2;
44     private static final int TIMEZONE_OFFSET_INDEX = 3;
45 
46     private static final int COLUMN_COUNT = TIMEZONE_OFFSET_INDEX + 1;
47 
createContentValues(City city)48     public static ContentValues createContentValues(City city) {
49         ContentValues values = new ContentValues(COLUMN_COUNT);
50         values.put(CITY_ID, city.mCityId);
51         values.put(CITY_NAME, city.mCityName);
52         values.put(TIMEZONE_NAME, city.mTimezoneName);
53         values.put(TIMEZONE_OFFSET, city.mTimezoneOffset);
54         return values;
55     }
56 
getCityId(Uri contentUri)57     public static String getCityId(Uri contentUri) {
58         return contentUri.getLastPathSegment();
59     }
60 
61     /**
62      * Return content uri for specific city id.
63      *
64      * @param cityId to append to content uri
65      *
66      * @return a new city content uri with the given ID appended to the end of the path
67      */
getContentUriForId(String cityId)68     public static Uri getContentUriForId(String cityId) {
69         return CONTENT_URI.buildUpon().appendEncodedPath(cityId).build();
70     }
71 
72 
73     /**
74      * Get city from cityId.
75      *
76      * @param contentResolver to perform the query on.
77      * @param cityId for the desired city.
78      * @return city if found, null otherwise
79      */
getCity(ContentResolver contentResolver, String cityId)80     public static City getCity(ContentResolver contentResolver, String cityId) {
81         Cursor cursor = contentResolver.query(getContentUriForId(cityId),
82                 QUERY_COLUMNS, null, null, null);
83         City result = null;
84         if (cursor == null) {
85             return result;
86         }
87 
88         try {
89             if (cursor.moveToFirst()) {
90                 result = new City(cursor);
91             }
92         } finally {
93             cursor.close();
94         }
95 
96         return result;
97     }
98 
99     /**
100      * Get a list of cities given selection.
101      *
102      * @param contentResolver to perform the query on.
103      * @param selection A filter declaring which rows to return, formatted as an
104      *         SQL WHERE clause (excluding the WHERE itself). Passing null will
105      *         return all rows for the given URI.
106      * @param selectionArgs You may include ?s in selection, which will be
107      *         replaced by the values from selectionArgs, in the order that they
108      *         appear in the selection. The values will be bound as Strings.
109      * @return list of alarms matching where clause or empty list if none found.
110      */
getCities(ContentResolver contentResolver, String selection, String... selectionArgs)111     public static List<City> getCities(ContentResolver contentResolver,
112             String selection, String... selectionArgs) {
113         Cursor cursor  = contentResolver.query(CONTENT_URI, QUERY_COLUMNS,
114                 selection, selectionArgs, null);
115         List<City> result = new LinkedList<City>();
116         if (cursor == null) {
117             return result;
118         }
119 
120         try {
121             if (cursor.moveToFirst()) {
122                 do {
123                     result.add(new City(cursor));
124                 } while (cursor.moveToNext());
125             }
126         } finally {
127             cursor.close();
128         }
129 
130         return result;
131     }
132 
addCity(ContentResolver contentResolver, City city)133     public static City addCity(ContentResolver contentResolver, City city) {
134         ContentValues values = createContentValues(city);
135         Uri uri = contentResolver.insert(CONTENT_URI, values);
136         city.mCityId = getCityId(uri);
137         return city;
138     }
139 
updateCity(ContentResolver contentResolver, City city)140     public static boolean updateCity(ContentResolver contentResolver, City city) {
141         ContentValues values = createContentValues(city);
142         Uri updateUri = getContentUriForId(city.mCityId);
143         long rowsUpdated = contentResolver.update(updateUri, values, null, null);
144         return rowsUpdated == 1;
145     }
146 
deleteCity(ContentResolver contentResolver, String cityId)147     public static boolean deleteCity(ContentResolver contentResolver, String cityId) {
148         Uri uri = getContentUriForId(cityId);
149         int deletedRows = contentResolver.delete(uri, "", null);
150         return deletedRows == 1;
151     }
152 
153     // Public fields
154     public String mCityId;
155     public String mCityName;
156     public String mTimezoneName;
157     public int mTimezoneOffset;
158 
City(String cityId, String cityName, String timezoneName, int timezoneOffset)159     public City(String cityId, String cityName, String timezoneName, int timezoneOffset) {
160         mCityId = cityId;
161         mCityName = cityName;
162         mTimezoneName = timezoneName;
163         mTimezoneOffset = timezoneOffset;
164     }
165 
City(Cursor c)166     public City(Cursor c) {
167         mCityId = c.getString(CITY_ID_INDEX);
168         mCityName = c.getString(CITY_NAME_INDEX);
169         mTimezoneName = c.getString(TIMEZONE_NAME_INDEX);
170         mTimezoneOffset = c.getInt(TIMEZONE_OFFSET_INDEX);
171     }
172 
173     @Override
equals(Object o)174     public boolean equals(Object o) {
175         if (!(o instanceof City)) return false;
176         final City other = (City) o;
177         return mCityId.equals(other.mCityId);
178     }
179 
180     @Override
hashCode()181     public int hashCode() {
182         return mCityId.hashCode();
183     }
184 
185     @Override
toString()186     public String toString() {
187         return "Instance{" +
188                 "mCityId=" + mCityId +
189                 ", mCityName=" + mCityName +
190                 ", mTimezoneName=" + mTimezoneName +
191                 ", mTimezoneOffset=" + mTimezoneOffset +
192                 '}';
193     }
194 }
195