/* (non-Javadoc) * @see org.eclipse.team.core.synchronize.FastSyncInfoFilter#select(org.eclipse.team.core.synchronize.SyncInfo) */ public boolean select(SyncInfo info) { int syncKind = info.getKind(); for (int i = 0; i < directionFilters.length; i++) { int filter = directionFilters[i]; if ((syncKind & SyncInfo.DIRECTION_MASK) == filter) return true; } return false; }
/* (non-Javadoc) * @see org.eclipse.team.core.synchronize.FastSyncInfoFilter#select(org.eclipse.team.core.synchronize.SyncInfo) */ public boolean select(SyncInfo info) { int syncKind = info.getKind(); for (int i = 0; i < changeFilters.length; i++) { int filter = changeFilters[i]; if ((syncKind & SyncInfo.CHANGE_MASK) == filter) return true; } return false; }
public void updateProvider( Feed feed, Long syncLocalId, Entry entry, ContentProvider provider, Object info) throws ParseException { SyncInfo syncInfo = (SyncInfo) info; EventEntry event = (EventEntry) entry; ContentValues map = new ContentValues(); // use the calendar's timezone, if provided in the feed. // this overwrites whatever was in the db. if ((feed != null) && (feed instanceof EventsFeed)) { EventsFeed eventsFeed = (EventsFeed) feed; syncInfo.calendarTimezone = eventsFeed.getTimezone(); } if (entry.isDeleted()) { deletedEntryToContentValues(syncLocalId, event, map); if (Config.LOGV) { Log.v(TAG, "Deleting entry: " + map); } provider.insert(Events.DELETED_CONTENT_URI, map); return; } int entryState = entryToContentValues(event, syncLocalId, map, syncInfo); if (entryState == ENTRY_DELETED) { if (Config.LOGV) { Log.v(TAG, "Got deleted entry from server: " + map); } provider.insert(Events.DELETED_CONTENT_URI, map); } else if (entryState == ENTRY_OK) { if (Config.LOGV) { Log.v(TAG, "Got entry from server: " + map); } Uri result = provider.insert(Events.CONTENT_URI, map); long rowId = ContentUris.parseId(result); // handle the reminders for the event Integer hasAlarm = map.getAsInteger(Events.HAS_ALARM); if (hasAlarm != null && hasAlarm == 1) { // reminders should not be null Vector alarms = event.getReminders(); if (alarms == null) { Log.e(TAG, "Have an alarm but do not have any reminders " + "-- should not happen."); throw new IllegalStateException("Have an alarm but do not have any reminders"); } Enumeration reminders = alarms.elements(); while (reminders.hasMoreElements()) { ContentValues reminderValues = new ContentValues(); reminderValues.put(Calendar.Reminders.EVENT_ID, rowId); Reminder reminder = (Reminder) reminders.nextElement(); byte method = reminder.getMethod(); switch (method) { case Reminder.METHOD_DEFAULT: reminderValues.put(Calendar.Reminders.METHOD, Calendar.Reminders.METHOD_DEFAULT); break; case Reminder.METHOD_ALERT: reminderValues.put(Calendar.Reminders.METHOD, Calendar.Reminders.METHOD_ALERT); break; case Reminder.METHOD_EMAIL: reminderValues.put(Calendar.Reminders.METHOD, Calendar.Reminders.METHOD_EMAIL); break; case Reminder.METHOD_SMS: reminderValues.put(Calendar.Reminders.METHOD, Calendar.Reminders.METHOD_SMS); break; default: // should not happen. return false? we'd have to // roll back the event. Log.e(TAG, "Unknown reminder method: " + method + " should not happen!"); } int minutes = reminder.getMinutes(); reminderValues.put( Calendar.Reminders.MINUTES, minutes == Reminder.MINUTES_DEFAULT ? Calendar.Reminders.MINUTES_DEFAULT : minutes); if (provider.insert(Calendar.Reminders.CONTENT_URI, reminderValues) == null) { throw new ParseException("Unable to insert reminders."); } } } // handle attendees for the event Vector attendees = event.getAttendees(); Enumeration attendeesEnum = attendees.elements(); while (attendeesEnum.hasMoreElements()) { Who who = (Who) attendeesEnum.nextElement(); ContentValues attendeesValues = new ContentValues(); attendeesValues.put(Calendar.Attendees.EVENT_ID, rowId); attendeesValues.put(Calendar.Attendees.ATTENDEE_NAME, who.getValue()); attendeesValues.put(Calendar.Attendees.ATTENDEE_EMAIL, who.getEmail()); byte status; switch (who.getStatus()) { case Who.STATUS_NONE: status = Calendar.Attendees.ATTENDEE_STATUS_NONE; break; case Who.STATUS_INVITED: status = Calendar.Attendees.ATTENDEE_STATUS_INVITED; break; case Who.STATUS_ACCEPTED: status = Calendar.Attendees.ATTENDEE_STATUS_ACCEPTED; break; case Who.STATUS_TENTATIVE: status = Calendar.Attendees.ATTENDEE_STATUS_TENTATIVE; break; case Who.STATUS_DECLINED: status = Calendar.Attendees.ATTENDEE_STATUS_DECLINED; break; default: Log.w(TAG, "Unknown attendee status " + who.getStatus()); status = Calendar.Attendees.ATTENDEE_STATUS_NONE; } attendeesValues.put(Calendar.Attendees.ATTENDEE_STATUS, status); byte rel; switch (who.getRelationship()) { case Who.RELATIONSHIP_NONE: rel = Calendar.Attendees.RELATIONSHIP_NONE; break; case Who.RELATIONSHIP_ORGANIZER: rel = Calendar.Attendees.RELATIONSHIP_ORGANIZER; break; case Who.RELATIONSHIP_ATTENDEE: rel = Calendar.Attendees.RELATIONSHIP_ATTENDEE; break; case Who.RELATIONSHIP_PERFORMER: rel = Calendar.Attendees.RELATIONSHIP_PERFORMER; break; case Who.RELATIONSHIP_SPEAKER: rel = Calendar.Attendees.RELATIONSHIP_SPEAKER; break; default: Log.w(TAG, "Unknown attendee relationship " + who.getRelationship()); rel = Calendar.Attendees.RELATIONSHIP_NONE; } attendeesValues.put(Calendar.Attendees.ATTENDEE_RELATIONSHIP, rel); byte type; switch (who.getType()) { case Who.TYPE_NONE: type = Calendar.Attendees.TYPE_NONE; break; case Who.TYPE_REQUIRED: type = Calendar.Attendees.TYPE_REQUIRED; break; case Who.TYPE_OPTIONAL: type = Calendar.Attendees.TYPE_OPTIONAL; break; default: Log.w(TAG, "Unknown attendee type " + who.getType()); type = Calendar.Attendees.TYPE_NONE; } attendeesValues.put(Calendar.Attendees.ATTENDEE_TYPE, type); if (provider.insert(Calendar.Attendees.CONTENT_URI, attendeesValues) == null) { throw new ParseException("Unable to insert attendees."); } } // handle the extended properties for the event Integer hasExtendedProperties = map.getAsInteger(Events.HAS_EXTENDED_PROPERTIES); if (hasExtendedProperties != null && hasExtendedProperties.intValue() != 0) { // extended properties should not be null // TODO: make the extended properties a bit more OO? Hashtable extendedProperties = event.getExtendedProperties(); if (extendedProperties == null) { Log.e( TAG, "Have extendedProperties but do not have any properties" + "-- should not happen."); throw new IllegalStateException("Have extendedProperties but do not have any properties"); } Enumeration propertyNames = extendedProperties.keys(); while (propertyNames.hasMoreElements()) { String propertyName = (String) propertyNames.nextElement(); String propertyValue = (String) extendedProperties.get(propertyName); ContentValues extendedPropertyValues = new ContentValues(); extendedPropertyValues.put(Calendar.ExtendedProperties.EVENT_ID, rowId); extendedPropertyValues.put(Calendar.ExtendedProperties.NAME, propertyName); extendedPropertyValues.put(Calendar.ExtendedProperties.VALUE, propertyValue); if (provider.insert(Calendar.ExtendedProperties.CONTENT_URI, extendedPropertyValues) == null) { throw new ParseException("Unable to insert extended properties."); } } } } else { // If the DTSTART == -1, then the date was out of range. We don't // need to throw a ParseException because the user can create // dates on the web that we can't handle on the phone. For // example, events with dates before Dec 13, 1901 can be created // on the web but cannot be handled on the phone. Long dtstart = map.getAsLong(Events.DTSTART); if (dtstart != null && dtstart == -1) { return; } if (Config.LOGV) { Log.v(TAG, "Got invalid entry from server: " + map); } throw new ParseException("Got invalid entry from server: " + map); } }
@Override protected String cursorToEntry(SyncContext context, Cursor c, Entry entry, Object info) throws ParseException { EventEntry event = (EventEntry) entry; SyncInfo syncInfo = (SyncInfo) info; String feedUrl = c.getString(c.getColumnIndex(Calendars.URL)); // update the sync info. this will be used later when we update the // provider with the results of sending this entry to the calendar // server. syncInfo.calendarId = c.getLong(c.getColumnIndex(Events.CALENDAR_ID)); syncInfo.calendarTimezone = c.getString(c.getColumnIndex(Events.EVENT_TIMEZONE)); if (TextUtils.isEmpty(syncInfo.calendarTimezone)) { // if the event timezone is not set -- e.g., when we're creating an // event on the device -- we will use the timezone for the calendar. syncInfo.calendarTimezone = c.getString(c.getColumnIndex(Events.TIMEZONE)); } // id event.setId(c.getString(c.getColumnIndex(Events._SYNC_ID))); event.setEditUri(c.getString(c.getColumnIndex(Events._SYNC_VERSION))); // status byte status; int localStatus = c.getInt(c.getColumnIndex(Events.STATUS)); switch (localStatus) { case Events.STATUS_CANCELED: status = EventEntry.STATUS_CANCELED; break; case Events.STATUS_CONFIRMED: status = EventEntry.STATUS_CONFIRMED; break; case Events.STATUS_TENTATIVE: status = EventEntry.STATUS_TENTATIVE; break; default: // should not happen status = EventEntry.STATUS_TENTATIVE; break; } event.setStatus(status); // visibility byte visibility; int localVisibility = c.getInt(c.getColumnIndex(Events.VISIBILITY)); switch (localVisibility) { case Events.VISIBILITY_DEFAULT: visibility = EventEntry.VISIBILITY_DEFAULT; break; case Events.VISIBILITY_CONFIDENTIAL: visibility = EventEntry.VISIBILITY_CONFIDENTIAL; break; case Events.VISIBILITY_PRIVATE: visibility = EventEntry.VISIBILITY_PRIVATE; break; case Events.VISIBILITY_PUBLIC: visibility = EventEntry.VISIBILITY_PUBLIC; break; default: // should not happen Log.e( TAG, "Unexpected value for visibility: " + localVisibility + "; using default visibility."); visibility = EventEntry.VISIBILITY_DEFAULT; break; } event.setVisibility(visibility); byte transparency; int localTransparency = c.getInt(c.getColumnIndex(Events.TRANSPARENCY)); switch (localTransparency) { case Events.TRANSPARENCY_OPAQUE: transparency = EventEntry.TRANSPARENCY_OPAQUE; break; case Events.TRANSPARENCY_TRANSPARENT: transparency = EventEntry.TRANSPARENCY_TRANSPARENT; break; default: // should not happen Log.e( TAG, "Unexpected value for transparency: " + localTransparency + "; using opaque transparency."); transparency = EventEntry.TRANSPARENCY_OPAQUE; break; } event.setTransparency(transparency); // could set the html uri, but there's no need to, since it should not be edited. // title event.setTitle(c.getString(c.getColumnIndex(Events.TITLE))); // description event.setContent(c.getString(c.getColumnIndex(Events.DESCRIPTION))); // where event.setWhere(c.getString(c.getColumnIndex(Events.EVENT_LOCATION))); // attendees long eventId = c.getInt(c.getColumnIndex(Events._SYNC_LOCAL_ID)); addAttendeesToEntry(eventId, event); // comment uri event.setCommentsUri(c.getString(c.getColumnIndexOrThrow(Events.COMMENTS_URI))); Time utc = new Time(Time.TIMEZONE_UTC); boolean allDay = c.getInt(c.getColumnIndex(Events.ALL_DAY)) != 0; String startTime = null; String endTime = null; // start time int dtstartColumn = c.getColumnIndex(Events.DTSTART); if (!c.isNull(dtstartColumn)) { long dtstart = c.getLong(dtstartColumn); utc.set(dtstart); startTime = utc.format3339(allDay); } // end time int dtendColumn = c.getColumnIndex(Events.DTEND); if (!c.isNull(dtendColumn)) { long dtend = c.getLong(dtendColumn); utc.set(dtend); endTime = utc.format3339(allDay); } When when = new When(startTime, endTime); event.addWhen(when); // reminders Integer hasReminder = c.getInt(c.getColumnIndex(Events.HAS_ALARM)); if (hasReminder != null && hasReminder.intValue() != 0) { addRemindersToEntry(eventId, event); } // extendedProperties Integer hasExtendedProperties = c.getInt(c.getColumnIndex(Events.HAS_EXTENDED_PROPERTIES)); if (hasExtendedProperties != null && hasExtendedProperties.intValue() != 0) { addExtendedPropertiesToEntry(eventId, event); } long originalStartTime = -1; String originalId = c.getString(c.getColumnIndex(Events.ORIGINAL_EVENT)); int originalStartTimeIndex = c.getColumnIndex(Events.ORIGINAL_INSTANCE_TIME); if (!c.isNull(originalStartTimeIndex)) { originalStartTime = c.getLong(originalStartTimeIndex); } if ((originalStartTime != -1) && !TextUtils.isEmpty(originalId)) { // We need to use the "originalAllDay" field for the original event // in order to format the "originalStartTime" correctly. boolean originalAllDay = c.getInt(c.getColumnIndex(Events.ORIGINAL_ALL_DAY)) != 0; Time originalTime = new Time(c.getString(c.getColumnIndex(Events.EVENT_TIMEZONE))); originalTime.set(originalStartTime); utc.set(originalStartTime); event.setOriginalEventStartTime(utc.format3339(originalAllDay)); event.setOriginalEventId(originalId); } // recurrences. ICalendar.Component component = new ICalendar.Component("DUMMY", null /* parent */); if (RecurrenceSet.populateComponent(c, component)) { addRecurrenceToEntry(component, event); } // if this is a new entry, return the feed url. otherwise, return null; the edit url is // already in the entry. if (event.getEditUri() == null) { return feedUrl; } else { return null; } }
private void getServerDiffsForFeed( SyncContext context, SyncData baseSyncData, SyncableContentProvider tempProvider, String feed, Object baseSyncInfo, SyncResult syncResult) { final SyncInfo syncInfo = (SyncInfo) baseSyncInfo; final GDataSyncData syncData = (GDataSyncData) baseSyncData; Cursor cursor = getContext() .getContentResolver() .query( Calendar.Calendars.CONTENT_URI, CALENDARS_PROJECTION, SELECT_BY_ACCOUNT_AND_FEED, new String[] {getAccount(), feed}, null /* sort order */); ContentValues map = new ContentValues(); int maxResults = getMaxEntriesPerSync(); try { if (!cursor.moveToFirst()) { return; } // TODO: refactor all of this, so we don't have to rely on // member variables getting updated here in order for the // base class hooks to work. syncInfo.calendarId = cursor.getLong(0); boolean syncEvents = (cursor.getInt(6) == 1); long syncTime = cursor.getLong(2); String feedUrl = cursor.getString(3); String name = cursor.getString(4); String origCalendarTimezone = syncInfo.calendarTimezone = cursor.getString(5); if (!syncEvents) { // should not happen. non-syncable feeds should not be scheduled for syncs nor // should they get tickled. if (Log.isLoggable(TAG, Log.VERBOSE)) { Log.v(TAG, "Ignoring sync request for non-syncable feed."); } return; } context.setStatusText("Syncing " + name); // call the superclass implementation to sync the current // calendar from the server. getServerDiffsImpl( context, tempProvider, getFeedEntryClass(), feedUrl, syncInfo, maxResults, syncData, syncResult); if (mSyncCanceled || syncResult.hasError()) { return; } // update the timezone for this calendar if it changed if (!TextUtils.equals(syncInfo.calendarTimezone, origCalendarTimezone)) { map.clear(); map.put(Calendars.TIMEZONE, syncInfo.calendarTimezone); mContentResolver.update( ContentUris.withAppendedId(Calendars.CONTENT_URI, syncInfo.calendarId), map, null, null); } } finally { cursor.close(); } }
/* (non-Javadoc) * @see org.eclipse.team.core.synchronize.FastSyncInfoFilter#select(org.eclipse.team.core.synchronize.SyncInfo) */ public boolean select(SyncInfo info) { return info.getKind() != 0 && (info.getKind() & SyncInfo.PSEUDO_CONFLICT) == 0; }
/* (non-Javadoc) * @see org.eclipse.team.core.synchronize.FastSyncInfoFilter#select(org.eclipse.team.core.synchronize.SyncInfo) */ public boolean select(SyncInfo info) { return (info.getKind() & SyncInfo.AUTOMERGE_CONFLICT) != 0; }
/** * Return whether the provided <code>SyncInfo</code> matches the filter. The default behavior it * to include resources whose syncKind is non-zero. * * @param info the <code>SyncInfo</code> being tested * @return <code>true</code> if the <code>SyncInfo</code> matches the filter */ public boolean select(SyncInfo info) { return info.getKind() != 0; }