private static ContentProviderOperation updateEvent(
     long calendar_id, Account account, Event event, long raw_id) {
   ContentProviderOperation.Builder builder;
   if (raw_id != -1) {
     builder =
         ContentProviderOperation.newUpdate(
             Events.CONTENT_URI
                 .buildUpon()
                 .appendQueryParameter(CalendarContract.CALLER_IS_SYNCADAPTER, "true")
                 .appendQueryParameter(Calendars.ACCOUNT_NAME, account.name)
                 .appendQueryParameter(Calendars.ACCOUNT_TYPE, account.type)
                 .build());
     builder.withSelection(Events._ID + " = '" + raw_id + "'", null);
   } else {
     builder =
         ContentProviderOperation.newInsert(
             Events.CONTENT_URI
                 .buildUpon()
                 .appendQueryParameter(CalendarContract.CALLER_IS_SYNCADAPTER, "true")
                 .appendQueryParameter(Calendars.ACCOUNT_NAME, account.name)
                 .appendQueryParameter(Calendars.ACCOUNT_TYPE, account.type)
                 .build());
   }
   long dtstart = event.getStartDate().getTime();
   long dtend = dtstart + (1000 * 60 * 60);
   if (event.getEndDate() != null) dtend = event.getEndDate().getTime();
   builder.withValue(Events.CALENDAR_ID, calendar_id);
   builder.withValue(Events.DTSTART, dtstart);
   builder.withValue(Events.DTEND, dtend);
   builder.withValue(Events.TITLE, event.getTitle());
   builder.withValue(
       Events.EVENT_LOCATION,
       event.getVenue().getName()
           + "\n"
           + event.getVenue().getLocation().getCity()
           + "\n"
           + event.getVenue().getLocation().getCountry());
   if (Integer.valueOf(event.getStatus()) == 1)
     builder.withValue(Events.STATUS, Events.STATUS_TENTATIVE);
   else builder.withValue(Events.STATUS, Events.STATUS_CONFIRMED);
   builder.withValue(Events._SYNC_ID, Long.valueOf(event.getId()));
   return builder.build();
 }
  private static void performSync(
      Context context,
      Account account,
      Bundle extras,
      String authority,
      ContentProviderClient provider,
      SyncResult syncResult)
      throws OperationCanceledException {
    HashMap<Long, SyncEntry> localEvents = new HashMap<Long, SyncEntry>();
    ArrayList<Long> lastfmEvents = new ArrayList<Long>();
    mContentResolver = context.getContentResolver();

    // If our app has requested a full sync, we're going to delete all our local contacts and start
    // over
    boolean is_full_sync =
        PreferenceManager.getDefaultSharedPreferences(LastFMApplication.getInstance())
            .getBoolean("do_full_sync", false);

    // If our schema is out-of-date, do a fresh sync
    if (PreferenceManager.getDefaultSharedPreferences(LastFMApplication.getInstance())
            .getInt("sync_schema", 0)
        < syncSchema) is_full_sync = true;

    long calendar_id = getCalendar(account);
    if (calendar_id == -1) {
      Log.e("CalendarSyncAdapter", "Unable to create Last.fm event calendar");
      return;
    }

    Log.i("CalendarSyncAdapter", "Last.fm events calendar: " + calendar_id);

    // Load the local Last.fm events
    Uri eventsUri =
        Events.CONTENT_URI
            .buildUpon()
            .appendQueryParameter(Events.CALENDAR_ID, String.valueOf(calendar_id))
            .build();
    Cursor c1 =
        mContentResolver.query(
            eventsUri, new String[] {Events._ID, Events._SYNC_ID}, null, null, null);
    while (c1 != null && c1.moveToNext()) {
      if (is_full_sync) {
        deleteEvent(context, account, c1.getLong(0));
      } else {
        SyncEntry entry = new SyncEntry();
        entry.raw_id = c1.getLong(0);
        localEvents.put(c1.getLong(1), entry);
      }
    }
    c1.close();

    Editor editor =
        PreferenceManager.getDefaultSharedPreferences(LastFMApplication.getInstance()).edit();
    editor.remove("do_full_sync");
    editor.putInt("sync_schema", syncSchema);
    editor.commit();

    LastFmServer server = AndroidLastFmServerFactory.getServer();
    try {
      Event[] events = server.getUserEvents(account.name);
      ArrayList<ContentProviderOperation> operationList = new ArrayList<ContentProviderOperation>();
      for (Event event : events) {
        lastfmEvents.add(Long.valueOf(event.getId()));

        if (localEvents.containsKey(Long.valueOf(event.getId()))) {
          SyncEntry entry = localEvents.get(Long.valueOf(event.getId()));
          operationList.add(updateEvent(calendar_id, account, event, entry.raw_id));
        } else {
          operationList.add(updateEvent(calendar_id, account, event, -1));
        }

        if (operationList.size() >= 50) {
          try {
            mContentResolver.applyBatch(CalendarContract.AUTHORITY, operationList);
          } catch (Exception e) {
            e.printStackTrace();
          }
          operationList.clear();
        }
      }

      events = server.getPastUserEvents(account.name);
      for (Event event : events) {
        lastfmEvents.add(Long.valueOf(event.getId()));

        if (localEvents.containsKey(Long.valueOf(event.getId()))) {
          SyncEntry entry = localEvents.get(Long.valueOf(event.getId()));
          operationList.add(updateEvent(calendar_id, account, event, entry.raw_id));
        } else {
          operationList.add(updateEvent(calendar_id, account, event, -1));
        }

        if (operationList.size() >= 50) {
          try {
            mContentResolver.applyBatch(CalendarContract.AUTHORITY, operationList);
          } catch (Exception e) {
            e.printStackTrace();
          }
          operationList.clear();
        }
      }

      if (operationList.size() > 0) {
        try {
          mContentResolver.applyBatch(CalendarContract.AUTHORITY, operationList);
        } catch (Exception e) {
          e.printStackTrace();
        }
      }
    } catch (IOException e1) {
      // TODO Auto-generated catch block
      e1.printStackTrace();
    } catch (WSError e1) {
      // TODO Auto-generated catch block
      e1.printStackTrace();
    }

    Iterator<Long> i = localEvents.keySet().iterator();
    while (i.hasNext()) {
      Long event = i.next();
      if (!lastfmEvents.contains(event))
        deleteEvent(context, account, localEvents.get(event).raw_id);
    }
  }
  private static ContentProviderOperation updateEvent(
      long calendar_id, Account account, Event event, long raw_id) {
    ContentProviderOperation.Builder builder;
    if (raw_id != -1) {
      builder =
          ContentProviderOperation.newUpdate(
              Events.CONTENT_URI
                  .buildUpon()
                  .appendQueryParameter(CalendarContract.CALLER_IS_SYNCADAPTER, "true")
                  .appendQueryParameter(Calendars.ACCOUNT_NAME, account.name)
                  .appendQueryParameter(Calendars.ACCOUNT_TYPE, account.type)
                  .build());
      builder.withSelection(Events._ID + " = '" + raw_id + "'", null);
    } else {
      builder =
          ContentProviderOperation.newInsert(
              Events.CONTENT_URI
                  .buildUpon()
                  .appendQueryParameter(CalendarContract.CALLER_IS_SYNCADAPTER, "true")
                  .appendQueryParameter(Calendars.ACCOUNT_NAME, account.name)
                  .appendQueryParameter(Calendars.ACCOUNT_TYPE, account.type)
                  .build());
    }
    long dtstart = event.getStartDate().getTime();
    long dtend = dtstart + (1000 * 60 * 60);
    if (event.getEndDate() != null) dtend = event.getEndDate().getTime();
    builder.withValue(Events.CALENDAR_ID, calendar_id);
    builder.withValue(Events.DTSTART, dtstart);
    builder.withValue(Events.DTEND, dtend);
    builder.withValue(Events.TITLE, event.getTitle());

    String location = "";
    if (event.getVenue().getName().length() > 0) location += event.getVenue().getName() + "\n";
    if (event.getVenue().getLocation().getCity().length() > 0)
      location += event.getVenue().getLocation().getCity() + "\n";
    if (event.getVenue().getLocation().getCountry().length() > 0)
      location += event.getVenue().getLocation().getCountry() + "\n";

    builder.withValue(Events.EVENT_LOCATION, location);

    String description = "http://www.last.fm/event/" + event.getId() + "\n\n";

    if (event.getArtists().length > 0) {
      description += "LINEUP\n";
      for (String artist : event.getArtists()) {
        description += artist + "\n";
      }
      description += "\n";
    }

    if (event.getDescription() != null && event.getDescription().length() > 0) {
      description += "MORE DETAILS\n";
      description += event.getDescription();
    }

    builder.withValue(Events.DESCRIPTION, description);

    if (Integer.valueOf(event.getStatus()) == 1)
      builder.withValue(Events.STATUS, Events.STATUS_TENTATIVE);
    else builder.withValue(Events.STATUS, Events.STATUS_CONFIRMED);
    builder.withValue(Events._SYNC_ID, Long.valueOf(event.getId()));
    return builder.build();
  }