Tue, 10 Feb 2015 22:40:00 +0100
Merge https://github.com/gggard/AndroidCaldavSyncAdapater/pull/206/
michael@0 | 1 | /** |
michael@0 | 2 | * Copyright (c) 2012-2013, Gerald Garcia, Timo Berger |
michael@8 | 3 | * |
michael@0 | 4 | * This file is part of Andoid Caldav Sync Adapter Free. |
michael@0 | 5 | * |
michael@0 | 6 | * Andoid Caldav Sync Adapter Free is free software: you can redistribute |
michael@0 | 7 | * it and/or modify it under the terms of the GNU General Public License |
michael@0 | 8 | * as published by the Free Software Foundation, either version 3 of the |
michael@0 | 9 | * License, or at your option any later version. |
michael@0 | 10 | * |
michael@0 | 11 | * Andoid Caldav Sync Adapter Free is distributed in the hope that |
michael@0 | 12 | * it will be useful, but WITHOUT ANY WARRANTY; without even the implied |
michael@0 | 13 | * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
michael@0 | 14 | * GNU General Public License for more details. |
michael@0 | 15 | * |
michael@0 | 16 | * You should have received a copy of the GNU General Public License |
michael@0 | 17 | * along with Andoid Caldav Sync Adapter Free. |
michael@0 | 18 | * If not, see <http://www.gnu.org/licenses/>. |
michael@8 | 19 | * |
michael@0 | 20 | */ |
michael@0 | 21 | |
michael@0 | 22 | package org.gege.caldavsyncadapter.caldav.entities; |
michael@0 | 23 | |
michael@0 | 24 | import android.accounts.Account; |
michael@0 | 25 | import android.content.ContentProviderClient; |
michael@0 | 26 | import android.content.ContentUris; |
michael@0 | 27 | import android.content.ContentValues; |
michael@0 | 28 | import android.content.SyncStats; |
michael@0 | 29 | import android.database.Cursor; |
michael@0 | 30 | import android.net.Uri; |
michael@0 | 31 | import android.os.RemoteException; |
michael@0 | 32 | import android.provider.CalendarContract.Calendars; |
michael@0 | 33 | import android.provider.CalendarContract.Events; |
michael@0 | 34 | import android.util.Log; |
michael@0 | 35 | |
michael@8 | 36 | import org.apache.http.client.ClientProtocolException; |
michael@8 | 37 | import org.gege.caldavsyncadapter.CalendarColors; |
michael@8 | 38 | import org.gege.caldavsyncadapter.Event; |
michael@8 | 39 | import org.gege.caldavsyncadapter.android.entities.AndroidEvent; |
michael@8 | 40 | import org.gege.caldavsyncadapter.caldav.CaldavFacade; |
michael@8 | 41 | import org.gege.caldavsyncadapter.syncadapter.SyncAdapter; |
michael@8 | 42 | import org.gege.caldavsyncadapter.syncadapter.notifications.NotificationsHelper; |
michael@8 | 43 | import org.xml.sax.SAXException; |
michael@8 | 44 | |
michael@8 | 45 | import java.io.IOException; |
michael@8 | 46 | import java.net.URI; |
michael@8 | 47 | import java.net.URISyntaxException; |
michael@8 | 48 | import java.util.ArrayList; |
michael@8 | 49 | import java.util.regex.Matcher; |
michael@8 | 50 | import java.util.regex.Pattern; |
michael@8 | 51 | |
michael@8 | 52 | import javax.xml.parsers.ParserConfigurationException; |
michael@8 | 53 | |
michael@0 | 54 | public class DavCalendar { |
michael@8 | 55 | public enum CalendarSource { |
michael@8 | 56 | undefined, Android, CalDAV |
michael@8 | 57 | } |
michael@0 | 58 | |
michael@8 | 59 | private static final String TAG = "Calendar"; |
michael@0 | 60 | |
michael@8 | 61 | /** |
michael@8 | 62 | * stores the CTAG of a calendar |
michael@8 | 63 | */ |
michael@8 | 64 | public static String CTAG = Calendars.CAL_SYNC1; |
michael@0 | 65 | |
michael@8 | 66 | /** |
michael@8 | 67 | * stores the URI of a calendar |
michael@8 | 68 | * example: http://caldav.example.com/calendarserver.php/calendars/username/calendarname |
michael@8 | 69 | */ |
michael@8 | 70 | public static String URI = Calendars._SYNC_ID; |
michael@0 | 71 | |
michael@8 | 72 | public static String SERVERURL = Calendars.CAL_SYNC2; |
michael@0 | 73 | |
michael@8 | 74 | private String strCalendarColor = ""; |
michael@0 | 75 | |
michael@8 | 76 | private ArrayList<Uri> mNotifyList = new ArrayList<Uri>(); |
michael@0 | 77 | |
michael@8 | 78 | /** |
michael@8 | 79 | * the event transformed into ContentValues |
michael@8 | 80 | */ |
michael@8 | 81 | public ContentValues ContentValues = new ContentValues(); |
michael@0 | 82 | |
michael@8 | 83 | private Account mAccount = null; |
michael@8 | 84 | private ContentProviderClient mProvider = null; |
michael@0 | 85 | |
michael@8 | 86 | public boolean foundServerSide = false; |
michael@8 | 87 | public boolean foundClientSide = false; |
michael@8 | 88 | public CalendarSource Source = CalendarSource.undefined; |
michael@0 | 89 | |
michael@8 | 90 | public String ServerUrl = ""; |
michael@0 | 91 | |
michael@8 | 92 | private ArrayList<CalendarEvent> mCalendarEvents = new ArrayList<CalendarEvent>(); |
michael@0 | 93 | |
michael@8 | 94 | private int mTagCounter = 1; |
michael@0 | 95 | |
michael@8 | 96 | /** |
michael@8 | 97 | * example: http://caldav.example.com/calendarserver.php/calendars/username/calendarname |
michael@8 | 98 | */ |
michael@8 | 99 | public URI getURI() { |
michael@8 | 100 | String strUri = this.getContentValueAsString(DavCalendar.URI); |
michael@8 | 101 | URI result = null; |
michael@8 | 102 | try { |
michael@8 | 103 | result = new URI(strUri); |
michael@8 | 104 | } catch (URISyntaxException e) { |
michael@8 | 105 | e.printStackTrace(); |
michael@8 | 106 | } |
michael@8 | 107 | return result; |
michael@8 | 108 | } |
michael@0 | 109 | |
michael@8 | 110 | /** |
michael@8 | 111 | * example: http://caldav.example.com/calendarserver.php/calendars/username/calendarname |
michael@8 | 112 | */ |
michael@8 | 113 | public void setURI(URI uri) { |
michael@8 | 114 | this.setContentValueAsString(DavCalendar.URI, uri.toString()); |
michael@8 | 115 | } |
michael@0 | 116 | |
michael@8 | 117 | /** |
michael@8 | 118 | * example: Cleartext Display Name |
michael@8 | 119 | */ |
michael@8 | 120 | public String getCalendarDisplayName() { |
michael@8 | 121 | return this.getContentValueAsString(Calendars.CALENDAR_DISPLAY_NAME); |
michael@8 | 122 | } |
michael@0 | 123 | |
michael@8 | 124 | /** |
michael@8 | 125 | * example: Cleartext Display Name |
michael@8 | 126 | */ |
michael@8 | 127 | public void setCalendarDisplayName(String displayName) { |
michael@8 | 128 | this.setContentValueAsString(Calendars.CALENDAR_DISPLAY_NAME, displayName); |
michael@8 | 129 | } |
michael@0 | 130 | |
michael@0 | 131 | |
michael@8 | 132 | /** |
michael@8 | 133 | * example: 1143 |
michael@8 | 134 | */ |
michael@8 | 135 | public void setCTag(String cTag, boolean Update) { |
michael@8 | 136 | this.setContentValueAsString(DavCalendar.CTAG, cTag); |
michael@8 | 137 | if (Update) { |
michael@8 | 138 | //serverCalendar.updateAndroidCalendar(androidCalendarUri, Calendar.CTAG, serverCalendar.getcTag()); |
michael@8 | 139 | try { |
michael@8 | 140 | this.updateAndroidCalendar(this.getAndroidCalendarUri(), CTAG, cTag); |
michael@8 | 141 | } catch (RemoteException e) { |
michael@8 | 142 | e.printStackTrace(); |
michael@8 | 143 | } |
michael@8 | 144 | } |
michael@8 | 145 | } |
michael@0 | 146 | |
michael@8 | 147 | /** |
michael@8 | 148 | * example: 1143 |
michael@8 | 149 | */ |
michael@8 | 150 | public String getcTag() { |
michael@8 | 151 | return this.getContentValueAsString(DavCalendar.CTAG); |
michael@8 | 152 | } |
michael@0 | 153 | |
michael@8 | 154 | /** |
michael@8 | 155 | * example: #FFCCAA |
michael@8 | 156 | */ |
michael@8 | 157 | public void setCalendarColorAsString(String color) { |
michael@8 | 158 | int maxlen = 6; |
michael@0 | 159 | |
michael@8 | 160 | this.strCalendarColor = color; |
michael@8 | 161 | if (!color.equals("")) { |
michael@8 | 162 | String strColor = color.replace("#", ""); |
michael@8 | 163 | if (strColor.length() > maxlen) |
michael@8 | 164 | strColor = strColor.substring(0, maxlen); |
michael@8 | 165 | int intColor = Integer.parseInt(strColor, 16); |
michael@8 | 166 | this.setContentValueAsInt(Calendars.CALENDAR_COLOR, intColor); |
michael@8 | 167 | } |
michael@8 | 168 | } |
michael@0 | 169 | |
michael@8 | 170 | /** |
michael@8 | 171 | * example: #FFCCAA |
michael@8 | 172 | */ |
michael@8 | 173 | public String getCalendarColorAsString() { |
michael@8 | 174 | return this.strCalendarColor; |
michael@8 | 175 | } |
michael@0 | 176 | |
michael@8 | 177 | /** |
michael@8 | 178 | * example 12345 |
michael@8 | 179 | */ |
michael@8 | 180 | public int getCalendarColor() { |
michael@8 | 181 | return this.getContentValueAsInt(Calendars.CALENDAR_COLOR); |
michael@8 | 182 | } |
michael@8 | 183 | |
michael@8 | 184 | /** |
michael@8 | 185 | * example 12345 |
michael@8 | 186 | */ |
michael@8 | 187 | public void setCalendarColor(int color) { |
michael@8 | 188 | this.setContentValueAsInt(Calendars.CALENDAR_COLOR, color); |
michael@8 | 189 | } |
michael@8 | 190 | |
michael@8 | 191 | /** |
michael@8 | 192 | * example: |
michael@8 | 193 | * should be: calendarname |
michael@8 | 194 | * but is: http://caldav.example.com/calendarserver.php/calendars/username/calendarname/ |
michael@8 | 195 | */ |
michael@8 | 196 | public String getCalendarName() { |
michael@8 | 197 | return this.getContentValueAsString(Calendars.NAME); |
michael@8 | 198 | } |
michael@8 | 199 | |
michael@8 | 200 | /** |
michael@8 | 201 | * example: |
michael@8 | 202 | * should be: calendarname |
michael@8 | 203 | * but is: http://caldav.example.com/calendarserver.php/calendars/username/calendarname/ |
michael@8 | 204 | */ |
michael@8 | 205 | public void setCalendarName(String calendarName) { |
michael@8 | 206 | this.setContentValueAsString(Calendars.NAME, calendarName); |
michael@8 | 207 | } |
michael@8 | 208 | |
michael@8 | 209 | /** |
michael@8 | 210 | * example: 8 |
michael@8 | 211 | */ |
michael@8 | 212 | public int getAndroidCalendarId() { |
michael@8 | 213 | return this.getContentValueAsInt(Calendars._ID); |
michael@8 | 214 | } |
michael@8 | 215 | |
michael@8 | 216 | /** |
michael@8 | 217 | * example: 8 |
michael@8 | 218 | */ |
michael@8 | 219 | public void setAndroidCalendarId(int androidCalendarId) { |
michael@8 | 220 | this.setContentValueAsInt(Calendars._ID, androidCalendarId); |
michael@8 | 221 | } |
michael@8 | 222 | |
michael@8 | 223 | /** |
michael@8 | 224 | * example: content://com.android.calendar/calendars/8 |
michael@8 | 225 | */ |
michael@8 | 226 | public Uri getAndroidCalendarUri() { |
michael@8 | 227 | return ContentUris.withAppendedId(Calendars.CONTENT_URI, this.getAndroidCalendarId()); |
michael@8 | 228 | } |
michael@8 | 229 | |
michael@8 | 230 | /** |
michael@8 | 231 | * empty constructor |
michael@8 | 232 | */ |
michael@8 | 233 | public DavCalendar(CalendarSource source) { |
michael@8 | 234 | this.Source = source; |
michael@8 | 235 | } |
michael@8 | 236 | |
michael@8 | 237 | /** |
michael@8 | 238 | * creates an new instance from a cursor |
michael@8 | 239 | * |
michael@8 | 240 | * @param cur must be a cursor from "ContentProviderClient" with Uri Calendars.CONTENT_URI |
michael@8 | 241 | */ |
michael@8 | 242 | public DavCalendar(Account account, ContentProviderClient provider, Cursor cur, CalendarSource source, String serverUrl) { |
michael@8 | 243 | this.mAccount = account; |
michael@8 | 244 | this.mProvider = provider; |
michael@8 | 245 | this.foundClientSide = true; |
michael@8 | 246 | this.Source = source; |
michael@8 | 247 | this.ServerUrl = serverUrl; |
michael@8 | 248 | |
michael@8 | 249 | String strSyncID = cur.getString(cur.getColumnIndex(Calendars._SYNC_ID)); |
michael@8 | 250 | String strName = cur.getString(cur.getColumnIndex(Calendars.NAME)); |
michael@8 | 251 | String strDisplayName = cur.getString(cur.getColumnIndex(Calendars.CALENDAR_DISPLAY_NAME)); |
michael@8 | 252 | String strCTAG = cur.getString(cur.getColumnIndex(DavCalendar.CTAG)); |
michael@8 | 253 | String strServerUrl = cur.getString(cur.getColumnIndex(DavCalendar.SERVERURL)); |
michael@8 | 254 | String strCalendarColor = cur.getString(cur.getColumnIndex(Calendars.CALENDAR_COLOR)); |
michael@8 | 255 | int intAndroidCalendarId = cur.getInt(cur.getColumnIndex(Calendars._ID)); |
michael@8 | 256 | |
michael@8 | 257 | this.setCalendarName(strName); |
michael@8 | 258 | this.setCalendarDisplayName(strDisplayName); |
michael@8 | 259 | this.setCTag(strCTAG, false); |
michael@8 | 260 | this.setAndroidCalendarId(intAndroidCalendarId); |
michael@8 | 261 | this.setCalendarColor(Integer.parseInt(strCalendarColor)); |
michael@8 | 262 | |
michael@8 | 263 | if (strSyncID == null) { |
michael@8 | 264 | this.correctSyncID(strName); |
michael@8 | 265 | strSyncID = strName; |
michael@8 | 266 | } |
michael@8 | 267 | if (strServerUrl == null) { |
michael@8 | 268 | this.correctServerUrl(serverUrl); |
michael@8 | 269 | } |
michael@8 | 270 | URI uri = null; |
michael@8 | 271 | try { |
michael@8 | 272 | uri = new URI(strSyncID); |
michael@8 | 273 | } catch (URISyntaxException e) { |
michael@8 | 274 | e.printStackTrace(); |
michael@8 | 275 | } |
michael@8 | 276 | this.setURI(uri); |
michael@8 | 277 | } |
michael@8 | 278 | |
michael@8 | 279 | /** |
michael@8 | 280 | * checks a given list of android calendars for a specific android calendar. |
michael@8 | 281 | * this calendar should be a server calendar as it is searched for. |
michael@8 | 282 | * if the calendar is not found, it will be created. |
michael@8 | 283 | * |
michael@8 | 284 | * @param androidCalList the list of android calendars |
michael@8 | 285 | * @param context |
michael@8 | 286 | * @return the found android calendar or null of fails |
michael@8 | 287 | * @throws RemoteException |
michael@8 | 288 | */ |
michael@8 | 289 | public Uri checkAndroidCalendarList(CalendarList androidCalList, android.content.Context context) throws RemoteException { |
michael@8 | 290 | Uri androidCalendarUri = null; |
michael@8 | 291 | boolean isCalendarExist = false; |
michael@8 | 292 | |
michael@8 | 293 | DavCalendar androidCalendar = androidCalList.getCalendarByURI(this.getURI()); |
michael@8 | 294 | if (androidCalendar != null) { |
michael@8 | 295 | isCalendarExist = true; |
michael@8 | 296 | androidCalendar.foundServerSide = true; |
michael@8 | 297 | } |
michael@8 | 298 | |
michael@8 | 299 | |
michael@8 | 300 | if (!isCalendarExist) { |
michael@8 | 301 | DavCalendar newCal = this.createNewAndroidCalendar(this, androidCalList.getCalendarList() |
michael@8 | 302 | .size(), context); |
michael@8 | 303 | if (newCal != null) { |
michael@8 | 304 | androidCalList.addCalendar(newCal); |
michael@8 | 305 | androidCalendarUri = newCal.getAndroidCalendarUri(); |
michael@8 | 306 | } |
michael@8 | 307 | } else { |
michael@8 | 308 | androidCalendarUri = androidCalendar.getAndroidCalendarUri(); |
michael@8 | 309 | if (!this.getCalendarColorAsString().equals("")) { |
michael@8 | 310 | this.updateAndroidCalendar(androidCalendarUri, Calendars.CALENDAR_COLOR, getColorAsHex(this.getCalendarColorAsString())); |
michael@8 | 311 | } |
michael@8 | 312 | if ((this.ContentValues.containsKey(Calendars.CALENDAR_DISPLAY_NAME)) && |
michael@8 | 313 | (androidCalendar.ContentValues.containsKey(Calendars.CALENDAR_DISPLAY_NAME))) { |
michael@8 | 314 | String serverDisplayName = this.ContentValues.getAsString(Calendars.CALENDAR_DISPLAY_NAME); |
michael@8 | 315 | String clientDisplayName = androidCalendar.ContentValues.getAsString(Calendars.CALENDAR_DISPLAY_NAME); |
michael@8 | 316 | if (!serverDisplayName.equals(clientDisplayName)) |
michael@8 | 317 | this.updateAndroidCalendar(androidCalendarUri, Calendars.CALENDAR_DISPLAY_NAME, serverDisplayName); |
michael@8 | 318 | } |
michael@8 | 319 | } |
michael@8 | 320 | |
michael@8 | 321 | return androidCalendarUri; |
michael@8 | 322 | } |
michael@8 | 323 | |
michael@8 | 324 | /** |
michael@8 | 325 | * COMPAT: the calendar Uri was stored as calendar Name. this function updates the URI (_SYNC_ID) |
michael@8 | 326 | * |
michael@8 | 327 | * @param calendarUri the real calendarUri |
michael@8 | 328 | * @return success of this function |
michael@8 | 329 | */ |
michael@8 | 330 | private boolean correctSyncID(String calendarUri) { |
michael@8 | 331 | boolean Result = false; |
michael@8 | 332 | Log.v(TAG, "correcting SyncID for calendar:" + this.getContentValueAsString(Calendars.CALENDAR_DISPLAY_NAME)); |
michael@8 | 333 | |
michael@8 | 334 | ContentValues mUpdateValues = new ContentValues(); |
michael@8 | 335 | mUpdateValues.put(DavCalendar.URI, calendarUri); |
michael@8 | 336 | |
michael@8 | 337 | try { |
michael@8 | 338 | mProvider.update(this.SyncAdapterCalendar(), mUpdateValues, null, null); |
michael@8 | 339 | Result = true; |
michael@8 | 340 | } catch (RemoteException e) { |
michael@8 | 341 | e.printStackTrace(); |
michael@8 | 342 | } |
michael@8 | 343 | |
michael@8 | 344 | return Result; |
michael@8 | 345 | } |
michael@8 | 346 | |
michael@8 | 347 | /** |
michael@8 | 348 | * COMPAT: the serverurl (CAL_SYNC2) was not sored within a calendar. this fixes it. (see #98) |
michael@8 | 349 | * |
michael@8 | 350 | * @param serverUrl the current serverurl |
michael@8 | 351 | * @return success of this function |
michael@8 | 352 | */ |
michael@8 | 353 | private boolean correctServerUrl(String serverUrl) { |
michael@8 | 354 | boolean Result = false; |
michael@8 | 355 | Log.v(TAG, "correcting ServerUrl for calendar:" + this.getContentValueAsString(Calendars.CALENDAR_DISPLAY_NAME)); |
michael@8 | 356 | |
michael@8 | 357 | ContentValues mUpdateValues = new ContentValues(); |
michael@8 | 358 | mUpdateValues.put(DavCalendar.SERVERURL, serverUrl); |
michael@8 | 359 | |
michael@8 | 360 | try { |
michael@8 | 361 | mProvider.update(this.SyncAdapterCalendar(), mUpdateValues, null, null); |
michael@8 | 362 | Result = true; |
michael@8 | 363 | } catch (RemoteException e) { |
michael@8 | 364 | e.printStackTrace(); |
michael@8 | 365 | } |
michael@8 | 366 | |
michael@8 | 367 | return Result; |
michael@8 | 368 | } |
michael@8 | 369 | |
michael@8 | 370 | /** |
michael@8 | 371 | * creates a new androidCalendar |
michael@8 | 372 | * |
michael@8 | 373 | * @param serverCalendar |
michael@8 | 374 | * @param index |
michael@8 | 375 | * @param context |
michael@8 | 376 | * @return the new androidCalendar or null if fails |
michael@8 | 377 | */ |
michael@8 | 378 | private DavCalendar createNewAndroidCalendar(DavCalendar serverCalendar, int index, android.content.Context context) { |
michael@8 | 379 | Uri newUri = null; |
michael@8 | 380 | DavCalendar Result = null; |
michael@8 | 381 | |
michael@8 | 382 | final ContentValues contentValues = new ContentValues(); |
michael@8 | 383 | contentValues.put(DavCalendar.URI, serverCalendar.getURI().toString()); |
michael@8 | 384 | contentValues.put(DavCalendar.SERVERURL, this.ServerUrl); |
michael@8 | 385 | |
michael@8 | 386 | contentValues.put(Calendars.VISIBLE, 1); |
michael@8 | 387 | contentValues.put(Calendars.CALENDAR_DISPLAY_NAME, serverCalendar.getCalendarDisplayName()); |
michael@8 | 388 | contentValues.put(Calendars.ACCOUNT_NAME, mAccount.name); |
michael@8 | 389 | contentValues.put(Calendars.ACCOUNT_TYPE, mAccount.type); |
michael@8 | 390 | contentValues.put(Calendars.OWNER_ACCOUNT, mAccount.name); |
michael@8 | 391 | contentValues.put(Calendars.SYNC_EVENTS, 1); |
michael@8 | 392 | contentValues.put(Calendars.CALENDAR_ACCESS_LEVEL, Calendars.CAL_ACCESS_OWNER); |
michael@8 | 393 | |
michael@8 | 394 | String calendarColorAsString = serverCalendar.getCalendarColorAsString(); |
michael@8 | 395 | if (!calendarColorAsString.isEmpty()) { |
michael@8 | 396 | int color = getColorAsHex(calendarColorAsString); |
michael@8 | 397 | contentValues.put(Calendars.CALENDAR_COLOR, color); |
michael@8 | 398 | } else { |
michael@8 | 399 | // find a color |
michael@8 | 400 | //int index = mList.size(); |
michael@8 | 401 | index = index % CalendarColors.colors.length; |
michael@8 | 402 | contentValues.put(Calendars.CALENDAR_COLOR, CalendarColors.colors[2]); |
michael@8 | 403 | } |
michael@8 | 404 | |
michael@8 | 405 | try { |
michael@8 | 406 | newUri = mProvider.insert(asSyncAdapter(Calendars.CONTENT_URI, mAccount.name, mAccount.type), contentValues); |
michael@8 | 407 | } catch (RemoteException e) { |
michael@8 | 408 | e.printStackTrace(); |
michael@8 | 409 | } |
michael@8 | 410 | |
michael@8 | 411 | // it is possible that this calendar already exists but the provider failed to find it within isCalendarExist() |
michael@8 | 412 | // the adapter would try to create a new calendar but the provider fails again to create a new calendar. |
michael@8 | 413 | if (newUri != null) { |
michael@8 | 414 | long newCalendarId = ContentUris.parseId(newUri); |
michael@8 | 415 | |
michael@8 | 416 | Cursor cur = null; |
michael@8 | 417 | Uri uri = Calendars.CONTENT_URI; |
michael@8 | 418 | String selection = "(" + Calendars._ID + " = ?)"; |
michael@8 | 419 | String[] selectionArgs = new String[]{String.valueOf(newCalendarId)}; |
michael@8 | 420 | |
michael@8 | 421 | // Submit the query and get a Cursor object back. |
michael@8 | 422 | try { |
michael@8 | 423 | cur = mProvider.query(uri, null, selection, selectionArgs, null); |
michael@8 | 424 | } catch (RemoteException e) { |
michael@8 | 425 | e.printStackTrace(); |
michael@8 | 426 | } |
michael@8 | 427 | |
michael@8 | 428 | if (cur != null) { |
michael@8 | 429 | while (cur.moveToNext()) { |
michael@8 | 430 | Result = new DavCalendar(mAccount, mProvider, cur, this.Source, this.ServerUrl); |
michael@8 | 431 | Result.foundServerSide = true; |
michael@8 | 432 | } |
michael@8 | 433 | cur.close(); |
michael@8 | 434 | //if (Result != null) |
michael@8 | 435 | // this.mList.add(Result); |
michael@8 | 436 | } |
michael@8 | 437 | Log.i(TAG, "New calendar created : URI=" + Result.getAndroidCalendarUri()); |
michael@8 | 438 | NotificationsHelper.signalSyncErrors(context, "CalDAV Sync Adapter", "new calendar found: " + Result |
michael@8 | 439 | .getCalendarDisplayName()); |
michael@8 | 440 | mNotifyList.add(Result.getAndroidCalendarUri()); |
michael@8 | 441 | } |
michael@8 | 442 | |
michael@8 | 443 | return Result; |
michael@8 | 444 | } |
michael@8 | 445 | |
michael@8 | 446 | private int getColorAsHex(String calendarColorAsString) { |
michael@8 | 447 | int color = 0x0000FF00; |
michael@8 | 448 | Pattern p = Pattern.compile("#?(\\p{XDigit}{6})(\\p{XDigit}{2})?"); |
michael@8 | 449 | Matcher m = p.matcher(calendarColorAsString); |
michael@8 | 450 | if (m.find()) { |
michael@8 | 451 | int color_rgb = Integer.parseInt(m.group(1), 16); |
michael@8 | 452 | int color_alpha = m.group(2) != null ? (Integer.parseInt(m.group(2), 16) & 0xFF) : 0xFF; |
michael@8 | 453 | color = (color_alpha << 24) | color_rgb; |
michael@8 | 454 | } |
michael@8 | 455 | return color; |
michael@8 | 456 | } |
michael@8 | 457 | |
michael@8 | 458 | /** |
michael@8 | 459 | * there is no corresponding calendar on server side. time to delete this calendar on android side. |
michael@8 | 460 | * |
michael@8 | 461 | * @return |
michael@8 | 462 | */ |
michael@8 | 463 | public boolean deleteAndroidCalendar() { |
michael@8 | 464 | boolean Result = false; |
michael@8 | 465 | |
michael@8 | 466 | String mSelectionClause = "(" + Calendars._ID + " = ?)"; |
michael@8 | 467 | int calendarId = this.getAndroidCalendarId(); |
michael@8 | 468 | String[] mSelectionArgs = {Long.toString(calendarId)}; |
michael@8 | 469 | |
michael@8 | 470 | int CountDeleted = 0; |
michael@8 | 471 | try { |
michael@8 | 472 | CountDeleted = mProvider.delete(this.SyncAdapter(), mSelectionClause, mSelectionArgs); |
michael@8 | 473 | Log.i(TAG, "Calendar deleted: " + String.valueOf(calendarId)); |
michael@8 | 474 | this.mNotifyList.add(this.getAndroidCalendarUri()); |
michael@8 | 475 | Result = true; |
michael@8 | 476 | } catch (RemoteException e) { |
michael@8 | 477 | e.printStackTrace(); |
michael@8 | 478 | } |
michael@8 | 479 | Log.d(TAG, "Android Calendars deleted: " + Integer.toString(CountDeleted)); |
michael@8 | 480 | |
michael@8 | 481 | return Result; |
michael@8 | 482 | } |
michael@8 | 483 | |
michael@8 | 484 | /** |
michael@8 | 485 | * updates the android calendar |
michael@8 | 486 | * |
michael@8 | 487 | * @param calendarUri the uri of the androidCalendar |
michael@8 | 488 | * @param target must be from android.provider.CalendarContract.Calendars |
michael@8 | 489 | * @param value the new value for the target |
michael@8 | 490 | * @throws RemoteException |
michael@8 | 491 | */ |
michael@8 | 492 | private void updateAndroidCalendar(Uri calendarUri, String target, int value) throws RemoteException { |
michael@8 | 493 | ContentValues mUpdateValues = new ContentValues(); |
michael@8 | 494 | mUpdateValues.put(target, value); |
michael@8 | 495 | |
michael@8 | 496 | mProvider.update(asSyncAdapter(calendarUri, mAccount.name, mAccount.type), mUpdateValues, null, null); |
michael@8 | 497 | } |
michael@8 | 498 | |
michael@8 | 499 | /** |
michael@8 | 500 | * updates the android calendar |
michael@8 | 501 | * |
michael@8 | 502 | * @param calendarUri the uri of the androidCalendar |
michael@8 | 503 | * @param target must be from android.provider.CalendarContract.Calendars |
michael@8 | 504 | * @param value the new value for the target |
michael@8 | 505 | * @throws RemoteException |
michael@8 | 506 | */ |
michael@8 | 507 | private void updateAndroidCalendar(Uri calendarUri, String target, String value) throws RemoteException { |
michael@8 | 508 | ContentValues mUpdateValues = new ContentValues(); |
michael@8 | 509 | mUpdateValues.put(target, value); |
michael@8 | 510 | |
michael@8 | 511 | mProvider.update(asSyncAdapter(calendarUri, mAccount.name, mAccount.type), mUpdateValues, null, null); |
michael@8 | 512 | } |
michael@8 | 513 | |
michael@8 | 514 | /** |
michael@8 | 515 | * marks the android event as already handled |
michael@8 | 516 | * |
michael@8 | 517 | * @return |
michael@8 | 518 | * @throws RemoteException |
michael@8 | 519 | * @see AndroidEvent#cInternalTag |
michael@8 | 520 | * @see SyncAdapter#synchroniseEvents(CaldavFacade, Account, ContentProviderClient, Uri, DavCalendar, SyncStats) |
michael@8 | 521 | */ |
michael@8 | 522 | public boolean tagAndroidEvent(AndroidEvent androidEvent) throws RemoteException { |
michael@8 | 523 | boolean Result = false; |
michael@8 | 524 | |
michael@8 | 525 | ContentValues values = new ContentValues(); |
michael@8 | 526 | //values.put(Event.INTERNALTAG, 1); |
michael@8 | 527 | values.put(Event.INTERNALTAG, mTagCounter); |
michael@8 | 528 | //values.put(Event.INTERNALTAG, String.valueOf(mTagCounter)); |
michael@8 | 529 | |
michael@8 | 530 | int RowCount = this.mProvider.update(asSyncAdapter(androidEvent.getUri(), this.mAccount.name, this.mAccount.type), values, null, null); |
michael@8 | 531 | //Log.v(TAG,"event tag nr: " + String.valueOf(mTagCounter)); |
michael@8 | 532 | //Log.v(TAG,"Rows updated: " + String.valueOf(RowCount)); |
michael@8 | 533 | |
michael@8 | 534 | if (RowCount == 1) { |
michael@8 | 535 | Result = true; |
michael@8 | 536 | mTagCounter += 1; |
michael@8 | 537 | } else { |
michael@8 | 538 | Log.v(TAG, "EVENT NOT TAGGED!"); |
michael@8 | 539 | } |
michael@8 | 540 | |
michael@8 | 541 | return Result; |
michael@8 | 542 | } |
michael@8 | 543 | |
michael@8 | 544 | /** |
michael@8 | 545 | * removes the tag of all android events |
michael@8 | 546 | * |
michael@8 | 547 | * @return |
michael@8 | 548 | * @throws RemoteException |
michael@8 | 549 | * @see AndroidEvent#cInternalTag |
michael@8 | 550 | * @see SyncAdapter#synchroniseEvents(CaldavFacade, Account, ContentProviderClient, Uri, DavCalendar, SyncStats) |
michael@8 | 551 | */ |
michael@8 | 552 | public int untagAndroidEvents() throws RemoteException { |
michael@8 | 553 | int RowCount = 0; |
michael@8 | 554 | int Steps = 100; |
michael@8 | 555 | ContentValues values = new ContentValues(); |
michael@8 | 556 | values.put(Event.INTERNALTAG, 0); |
michael@8 | 557 | |
michael@8 | 558 | for (int i = 1; i < this.mTagCounter; i = i + Steps) { |
michael@8 | 559 | String mSelectionClause = "(CAST(" + Event.INTERNALTAG + " AS INT) >= ?) AND (CAST(" + Event.INTERNALTAG + " AS INT) < ?) AND (" + Events.CALENDAR_ID + " = ?)"; |
michael@8 | 560 | String[] mSelectionArgs = {String.valueOf(i), String.valueOf(i + Steps), Long.toString(ContentUris |
michael@8 | 561 | .parseId(this.getAndroidCalendarUri()))}; |
michael@8 | 562 | RowCount += this.mProvider.update(asSyncAdapter(Events.CONTENT_URI, this.mAccount.name, this.mAccount.type), values, mSelectionClause, mSelectionArgs); |
michael@8 | 563 | } |
michael@8 | 564 | /*String mSelectionClause = "(" + Event.INTERNALTAG + " > ?) AND (" + Events.CALENDAR_ID + " = ?)"; |
michael@8 | 565 | String[] mSelectionArgs = {"0", Long.toString(ContentUris.parseId(this.getAndroidCalendarUri()))}; |
michael@0 | 566 | RowCount += this.mProvider.update(asSyncAdapter(Events.CONTENT_URI, this.mAccount.name, this.mAccount.type), values, mSelectionClause, mSelectionArgs);*/ |
michael@0 | 567 | |
michael@8 | 568 | //Log.d(TAG, "Rows reseted: " + RowCount.toString()); |
michael@8 | 569 | return RowCount; |
michael@8 | 570 | } |
michael@8 | 571 | |
michael@8 | 572 | /** |
michael@8 | 573 | * Events not being tagged are for deletion |
michael@8 | 574 | * |
michael@8 | 575 | * @return |
michael@8 | 576 | * @throws RemoteException |
michael@8 | 577 | * @see AndroidEvent#cInternalTag |
michael@8 | 578 | * @see SyncAdapter#synchroniseEvents(CaldavFacade, Account, ContentProviderClient, Uri, DavCalendar, SyncStats) |
michael@8 | 579 | */ |
michael@8 | 580 | public int deleteUntaggedEvents() throws RemoteException { |
michael@8 | 581 | String mSelectionClause = "(" + Event.INTERNALTAG + " < ?) AND (" + Events.CALENDAR_ID + " = ?)"; |
michael@8 | 582 | String[] mSelectionArgs = {"1", Long.toString(ContentUris.parseId(this.getAndroidCalendarUri()))}; |
michael@8 | 583 | |
michael@8 | 584 | int CountDeleted = this.mProvider.delete(asSyncAdapter(Events.CONTENT_URI, this.mAccount.name, this.mAccount.type), mSelectionClause, mSelectionArgs); |
michael@8 | 585 | //Log.d(TAG, "Rows deleted: " + CountDeleted.toString()); |
michael@8 | 586 | return CountDeleted; |
michael@8 | 587 | } |
michael@8 | 588 | |
michael@8 | 589 | private Uri SyncAdapterCalendar() { |
michael@8 | 590 | return asSyncAdapter(this.getAndroidCalendarUri(), mAccount.name, mAccount.type); |
michael@8 | 591 | } |
michael@8 | 592 | |
michael@8 | 593 | private Uri SyncAdapter() { |
michael@8 | 594 | return asSyncAdapter(Calendars.CONTENT_URI, mAccount.name, mAccount.type); |
michael@8 | 595 | } |
michael@8 | 596 | |
michael@8 | 597 | private static Uri asSyncAdapter(Uri uri, String account, String accountType) { |
michael@8 | 598 | return uri.buildUpon() |
michael@8 | 599 | .appendQueryParameter(android.provider.CalendarContract.CALLER_IS_SYNCADAPTER, "true") |
michael@8 | 600 | .appendQueryParameter(Calendars.ACCOUNT_NAME, account) |
michael@8 | 601 | .appendQueryParameter(Calendars.ACCOUNT_TYPE, accountType).build(); |
michael@8 | 602 | } |
michael@8 | 603 | |
michael@8 | 604 | public void setAccount(Account account) { |
michael@8 | 605 | this.mAccount = account; |
michael@8 | 606 | } |
michael@8 | 607 | |
michael@8 | 608 | public void setProvider(ContentProviderClient provider) { |
michael@8 | 609 | this.mProvider = provider; |
michael@8 | 610 | } |
michael@8 | 611 | |
michael@8 | 612 | /** |
michael@8 | 613 | * general access function to ContentValues |
michael@8 | 614 | * |
michael@8 | 615 | * @param Item the item name from Calendars.* |
michael@8 | 616 | * @return the value for the item |
michael@8 | 617 | */ |
michael@8 | 618 | private String getContentValueAsString(String Item) { |
michael@8 | 619 | String Result = ""; |
michael@8 | 620 | if (this.ContentValues.containsKey(Item)) |
michael@8 | 621 | Result = this.ContentValues.getAsString(Item); |
michael@8 | 622 | return Result; |
michael@8 | 623 | } |
michael@8 | 624 | |
michael@8 | 625 | /** |
michael@8 | 626 | * general access function to ContentValues |
michael@8 | 627 | * |
michael@8 | 628 | * @param Item the item name from Calendars.* |
michael@8 | 629 | * @return the value for the item |
michael@8 | 630 | */ |
michael@8 | 631 | private int getContentValueAsInt(String Item) { |
michael@8 | 632 | int Result = 0; |
michael@8 | 633 | if (this.ContentValues.containsKey(Item)) |
michael@8 | 634 | Result = this.ContentValues.getAsInteger(Item); |
michael@8 | 635 | return Result; |
michael@8 | 636 | } |
michael@8 | 637 | |
michael@8 | 638 | /** |
michael@8 | 639 | * general access function to ContentValues |
michael@8 | 640 | * |
michael@8 | 641 | * @param Item the item name from Calendars.* |
michael@8 | 642 | * @param Value the value for the item |
michael@8 | 643 | * @return success of this function |
michael@8 | 644 | */ |
michael@8 | 645 | private boolean setContentValueAsString(String Item, String Value) { |
michael@8 | 646 | boolean Result = false; |
michael@8 | 647 | |
michael@8 | 648 | if (this.ContentValues.containsKey(Item)) |
michael@8 | 649 | this.ContentValues.remove(Item); |
michael@8 | 650 | this.ContentValues.put(Item, Value); |
michael@8 | 651 | |
michael@8 | 652 | return Result; |
michael@8 | 653 | } |
michael@8 | 654 | |
michael@8 | 655 | /** |
michael@8 | 656 | * general access function to ContentValues |
michael@8 | 657 | * |
michael@8 | 658 | * @param Item the item name from Calendars.* |
michael@8 | 659 | * @param Value the value for the item |
michael@8 | 660 | * @return success of this function |
michael@8 | 661 | */ |
michael@8 | 662 | private boolean setContentValueAsInt(String Item, int Value) { |
michael@8 | 663 | boolean Result = false; |
michael@8 | 664 | |
michael@8 | 665 | if (this.ContentValues.containsKey(Item)) |
michael@8 | 666 | this.ContentValues.remove(Item); |
michael@8 | 667 | this.ContentValues.put(Item, Value); |
michael@8 | 668 | |
michael@8 | 669 | return Result; |
michael@8 | 670 | } |
michael@8 | 671 | |
michael@8 | 672 | public ArrayList<Uri> getNotifyList() { |
michael@8 | 673 | return this.mNotifyList; |
michael@8 | 674 | } |
michael@8 | 675 | |
michael@8 | 676 | public ArrayList<CalendarEvent> getCalendarEvents() { |
michael@8 | 677 | return this.mCalendarEvents; |
michael@8 | 678 | } |
michael@8 | 679 | |
michael@8 | 680 | public boolean readCalendarEvents(CaldavFacade facade) { |
michael@8 | 681 | boolean Result = false; |
michael@8 | 682 | |
michael@8 | 683 | try { |
michael@8 | 684 | this.mCalendarEvents = facade.getCalendarEvents(this); |
michael@8 | 685 | Result = true; |
michael@8 | 686 | } catch (ClientProtocolException e) { |
michael@8 | 687 | e.printStackTrace(); |
michael@8 | 688 | Result = false; |
michael@8 | 689 | } catch (URISyntaxException e) { |
michael@8 | 690 | e.printStackTrace(); |
michael@8 | 691 | Result = false; |
michael@8 | 692 | } catch (IOException e) { |
michael@8 | 693 | e.printStackTrace(); |
michael@8 | 694 | Result = false; |
michael@8 | 695 | } catch (ParserConfigurationException e) { |
michael@8 | 696 | e.printStackTrace(); |
michael@8 | 697 | Result = false; |
michael@8 | 698 | } catch (SAXException e) { |
michael@8 | 699 | e.printStackTrace(); |
michael@8 | 700 | Result = false; |
michael@8 | 701 | } |
michael@8 | 702 | |
michael@8 | 703 | return Result; |
michael@8 | 704 | } |
michael@8 | 705 | |
michael@0 | 706 | } |