/* * * * Copyright (C) 2014 Open Whisper Systems * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. * / */ package org.anhonesteffort.flock.sync.calendar; import android.accounts.Account; import android.content.ContentProviderClient; import android.content.ContentValues; import android.content.Context; import android.database.Cursor; import android.net.Uri; import android.os.RemoteException; import android.provider.CalendarContract; import android.util.Log; import org.anhonesteffort.flock.util.guava.Optional; import org.anhonesteffort.flock.auth.DavAccount; import org.anhonesteffort.flock.sync.LocalComponentStore; import java.util.LinkedList; import java.util.List; /** * Programmer: rhodey */ public class LocalCalendarStore implements LocalComponentStore<LocalEventCollection> { private static final String TAG = "org.anhonesteffort.flock.sync.calendar.LocalCalendarStore"; public static final int MAXIMUM_COLLECTIONS = 100; // is this reasonable? private ContentProviderClient client; private Account account; public LocalCalendarStore(ContentProviderClient client, Account account) { this.client = client; this.account = account; } public LocalCalendarStore(Context context, Account account) { this.account = account; client = context.getContentResolver().acquireContentProviderClient (CalendarsSyncScheduler.CONTENT_AUTHORITY); } @Override public Optional<LocalEventCollection> getCollection(String remotePath) throws RemoteException { final String[] PROJECTION = new String[]{CalendarContract.Calendars._ID, CalendarContract.Calendars.NAME}; final String SELECTION = CalendarContract.Calendars.DELETED + "=0 " + "AND " + CalendarContract.Calendars.SYNC_EVENTS + "=1 " + "AND " + CalendarContract.Calendars.NAME + "=?"; final String[] SELECTION_ARGS = new String[]{remotePath}; Cursor cursor = client.query(LocalEventCollection.getCollectionsUri(account), PROJECTION, SELECTION, SELECTION_ARGS, null); if (cursor == null) throw new RemoteException("Content provider client gave us a null cursor!"); List<LocalEventCollection> collections = new LinkedList<LocalEventCollection>(); if (cursor.moveToNext()) collections.add(new LocalEventCollection(client, account, cursor.getLong(0), cursor.getString(1))); cursor.close(); if (collections.size() > 0) return Optional.of(collections.get(0)); return Optional.absent(); } @Override public void addCollection(String remotePath) throws RemoteException { addCollection(remotePath, "UNKNOWN", 0xffffffff); } @Override public void addCollection(String remotePath, String displayName) throws RemoteException { addCollection(remotePath, displayName, 0xffffffff); } public void addCollection(String remotePath, String displayName, int color) throws RemoteException { if (getCollection(remotePath).isPresent()) { Log.w(TAG, "attempted to create duplicate collection at " + remotePath); throw new RemoteException("Collection already exists!"); } ContentValues values = new ContentValues(); values.put(CalendarContract.Calendars.ACCOUNT_NAME, account.name); values.put(CalendarContract.Calendars.ACCOUNT_TYPE, account.type); values.put(LocalEventCollection.COLUMN_NAME_COLLECTION_COPIED, 0); values.put(CalendarContract.Calendars.NAME, remotePath); values.put(CalendarContract.Calendars.CALENDAR_DISPLAY_NAME, displayName); values.put(CalendarContract.Calendars.CALENDAR_COLOR, color); values.put(CalendarContract.Calendars.OWNER_ACCOUNT, account.name); values.put(CalendarContract.Calendars.CALENDAR_ACCESS_LEVEL, CalendarContract.Calendars.CAL_ACCESS_OWNER); values.put(CalendarContract.Calendars.ALLOWED_REMINDERS, CalendarContract.Reminders.METHOD_ALERT); values.put(CalendarContract.Calendars.ALLOWED_AVAILABILITY, CalendarContract.Events.AVAILABILITY_BUSY + "," + CalendarContract.Events.AVAILABILITY_FREE); values.put(CalendarContract.Calendars.ALLOWED_ATTENDEE_TYPES, CalendarContract.Attendees.TYPE_NONE + "," + CalendarContract.Attendees.TYPE_OPTIONAL + "," + CalendarContract.Attendees.TYPE_REQUIRED + "," + CalendarContract.Attendees.TYPE_RESOURCE); values.put(CalendarContract.Calendars.CAN_ORGANIZER_RESPOND, 0); values.put(CalendarContract.Calendars.CAN_MODIFY_TIME_ZONE, 1); values.put(CalendarContract.Calendars.SYNC_EVENTS, 1); values.put(CalendarContract.Calendars.VISIBLE, 1); client.insert(LocalEventCollection.getCollectionsUri(account), values); } @Override public void removeCollection(String remotePath) throws RemoteException{ final String SELECTION = CalendarContract.Calendars.NAME + "=?"; final String[] SELECTION_ARGS = new String[]{remotePath}; client.delete(LocalEventCollection.getCollectionsUri(account), SELECTION, SELECTION_ARGS); } public void setCollectionCopied(Long localId, boolean isCopied) throws RemoteException { final String COLLECTION_SELECTION = CalendarContract.Calendars._ID + "=?"; final String[] COLLECTION_SELECTION_ARGS = new String[] {localId.toString()}; final Uri COLLECTION_URI = LocalEventCollection.getCollectionsUri(account); ContentValues updateValues = new ContentValues(); updateValues.put(LocalEventCollection.COLUMN_NAME_COLLECTION_COPIED, isCopied ? 1 : 0); client.update(COLLECTION_URI, updateValues, COLLECTION_SELECTION, COLLECTION_SELECTION_ARGS); } public void setCollectionPath(Long localId, String path) throws RemoteException { final String COLLECTION_SELECTION = CalendarContract.Calendars._ID + "=?"; final String[] COLLECTION_SELECTION_ARGS = new String[] {localId.toString()}; final Uri COLLECTION_URI = LocalEventCollection.getCollectionsUri(account); ContentValues updateValues = new ContentValues(); updateValues.put(CalendarContract.Calendars.NAME, path); client.update(COLLECTION_URI, updateValues, COLLECTION_SELECTION, COLLECTION_SELECTION_ARGS); } @Override public List<LocalEventCollection> getCollections() throws RemoteException { final String[] PROJECTION = new String[]{CalendarContract.Calendars._ID, CalendarContract.Calendars.NAME}; String SELECTION = CalendarContract.Calendars.DELETED + "=0 AND " + CalendarContract.Calendars.SYNC_EVENTS + "=1"; if (account.type.equals(DavAccount.SYNC_ACCOUNT_TYPE)) SELECTION += " AND " + LocalEventCollection.COLUMN_NAME_COLLECTION_COPIED + "=0"; Cursor cursor = client.query(LocalEventCollection.getCollectionsUri(account), PROJECTION, SELECTION, null, null); if (cursor == null) throw new RemoteException("Content provider client gave us a null cursor!"); List<LocalEventCollection> collections = new LinkedList<LocalEventCollection>(); while (cursor.moveToNext()) collections.add(new LocalEventCollection(client, account, cursor.getLong(0), cursor.getString(1))); cursor.close(); return collections; } public List<LocalEventCollection> getCollectionsIgnoreSync() throws RemoteException { final String[] PROJECTION = new String[]{CalendarContract.Calendars._ID, CalendarContract.Calendars.NAME}; String SELECTION = CalendarContract.Calendars.DELETED + "=0"; if (account.type.equals(DavAccount.SYNC_ACCOUNT_TYPE)) SELECTION += " AND " + LocalEventCollection.COLUMN_NAME_COLLECTION_COPIED + "=0"; Cursor cursor = client.query(LocalEventCollection.getCollectionsUri(account), PROJECTION, SELECTION, null, null); if (cursor == null) throw new RemoteException("Content provider client gave us a null cursor!"); List<LocalEventCollection> collections = new LinkedList<LocalEventCollection>(); while (cursor.moveToNext()) collections.add(new LocalEventCollection(client, account, cursor.getLong(0), cursor.getString(1))); cursor.close(); return collections; } public List<LocalEventCollection> getCopiedCollections() throws RemoteException { final String[] PROJECTION = new String[]{CalendarContract.Calendars._ID, CalendarContract.Calendars.NAME}; final String SELECTION = LocalEventCollection.COLUMN_NAME_COLLECTION_COPIED + "=1 AND " + CalendarContract.Calendars.DELETED + "=0 AND " + CalendarContract.Calendars.SYNC_EVENTS + "=1"; if (!account.type.equals(DavAccount.SYNC_ACCOUNT_TYPE)) throw new RemoteException("Unable to determine which collections are copied!"); Cursor cursor = client.query(LocalEventCollection.getCollectionsUri(account), PROJECTION, SELECTION, null, null); if (cursor == null) throw new RemoteException("Content provider client gave us a null cursor!"); List<LocalEventCollection> collections = new LinkedList<LocalEventCollection>(); while (cursor.moveToNext()) collections.add(new LocalEventCollection(client, account, cursor.getLong(0), cursor.getString(1))); cursor.close(); return collections; } }