/**
   * Synchronize raw contacts
   *
   * @param context The context of Authenticator Activity
   * @param account The username for the account
   * @param users The list of users
   */
  public static synchronized void syncContacts(Context context, String account, List<User> users) {
    String userName;
    long rawContactId = 0;
    final ContentResolver resolver = context.getContentResolver();

    List<Long> currentContacts = lookupAllContacts(resolver);

    final BatchOperation batchOperation = new BatchOperation(context, resolver);
    Log.d(TAG, "In SyncContacts");
    for (final User user : users) {
      userName = user.getUserName();
      // Check to see if the contact needs to be inserted or updated
      rawContactId = lookupRawContact(resolver, userName);
      if (rawContactId == 0) {
        // add new contact
        Log.d(TAG, "In addContact");
        addContact(context, account, user, batchOperation);
      } else {
        currentContacts.remove(rawContactId);
      }
      // A sync adapter should batch operations on multiple contacts,
      // because it will make a dramatic performance difference.
      if (batchOperation.size() >= 50) {
        batchOperation.execute();
      }
    }

    for (final Long l : currentContacts) {
      Log.d(TAG, "Deleting contact");
      deleteContact(context, l, batchOperation);
    }

    batchOperation.execute();
  }
  public static void main(String[] args) throws Throwable {
    Configuration conf = HBaseConfiguration.create();
    conf.set("hbase.zookeeper.quorum", "localhost");
    conf.set("hbase.zookeeper.property.clientPort", "2181");
    conf.set("zookeeper.session.timeout", "100000");

    HTableInterface hTable = new HTable(conf, "test");

    System.out.println("Putting");
    long t0 = System.currentTimeMillis();
    //    for (int i = 0; i < 100000; i++) {
    //      Put put = new Put(Bytes.toBytes("test" + i));
    //      put.add(Bytes.toBytes("family1"), Bytes.toBytes("qual" + i), Bytes.toBytes("value" +
    // i));
    //      if(i % 10 ==0){
    //        put.add(Bytes.toBytes("family1"), Bytes.toBytes("filterqual"),
    // Bytes.toBytes("filter"));
    //      }
    //      hTable.put(put);
    //    }
    //    System.out.println("Issued puts in " + (System.currentTimeMillis() - t0));

    System.out.println("Executing Protocol call");
    t0 = System.currentTimeMillis();

    Scan scan = new Scan();
    //  SingleColumnValueFilter filter= new SingleColumnValueFilter(Bytes.toBytes("family1"),
    // Bytes.toBytes("filterqual"),CompareOp.EQUAL, Bytes.toBytes("filter"));
    //    filter.setFilterIfMissing(true);
    //    scan.setFilter(filter);
    final BatchOperation operation = new BatchOperation(scan);
    operation.addValue(
        Bytes.toBytes("family1"), Bytes.toBytes("first"), Bytes.toBytes("first val"));
    operation.addValue(
        Bytes.toBytes("family1"), Bytes.toBytes("second"), Bytes.toBytes("second val"));
    Map<byte[], BatchOperationResult> results =
        hTable.coprocessorExec(
            BatchOperationsProtocol.class,
            null,
            null,
            new Batch.Call<BatchOperationsProtocol, BatchOperationResult>() {

              @Override
              public BatchOperationResult call(BatchOperationsProtocol instance)
                  throws IOException {
                return instance.batchUpdate(operation);
              }
            });
    System.out.println("Executed protocol in " + (System.currentTimeMillis() - t0));

    for (Map.Entry<byte[], BatchOperationResult> entry : results.entrySet()) {
      System.out.println(entry.getValue().getRecords() + " " + entry.getValue().getTime());
    }
  }
 /**
  * Deletes a contact from the platform contacts provider.
  *
  * @param context the Authenticator Activity context
  * @param rawContactId the unique Id for this rawContact in contacts provider
  */
 private static void deleteContact(
     Context context, long rawContactId, BatchOperation batchOperation) {
   batchOperation.add(
       ContactOperations.newDeleteCpo(
               ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId), true)
           .build());
 }
  /**
   * Add a list of status messages to the contacts provider.
   *
   * @param context the context to use
   * @param accountName the username of the logged in user
   * @param statuses the list of statuses to store
   */
  public static void insertStatuses(Context context, String username, List<User.Status> list) {
    final ContentValues values = new ContentValues();
    final ContentResolver resolver = context.getContentResolver();

    final ArrayList<String> processedUsers = new ArrayList<String>();

    final BatchOperation batchOperation = new BatchOperation(context, resolver);
    for (final User.Status status : list) {
      // Look up the user's sample SyncAdapter data row
      final String userName = status.getUserName();

      if (!processedUsers.contains(userName)) {
        final long profileId = lookupProfile(resolver, userName);

        // Insert the activity into the stream
        if (profileId > 0) {
          values.put(StatusUpdates.DATA_ID, profileId);
          values.put(StatusUpdates.STATUS, status.getStatus());
          values.put(StatusUpdates.PROTOCOL, Im.PROTOCOL_CUSTOM);
          values.put(StatusUpdates.CUSTOM_PROTOCOL, CUSTOM_IM_PROTOCOL);
          values.put(StatusUpdates.IM_ACCOUNT, username);
          values.put(StatusUpdates.IM_HANDLE, status.getUserName());
          values.put(StatusUpdates.STATUS_TIMESTAMP, status.getTimeStamp().getTime());
          values.put(StatusUpdates.STATUS_RES_PACKAGE, context.getPackageName());
          values.put(StatusUpdates.STATUS_ICON, R.drawable.ic_main);
          values.put(StatusUpdates.STATUS_LABEL, R.string.label);

          batchOperation.add(
              ContactOperations.newInsertCpo(StatusUpdates.CONTENT_URI, true)
                  .withValues(values)
                  .build());
          // A sync adapter should batch operations on multiple contacts,
          // because it will make a dramatic performance difference.
          if (batchOperation.size() >= 50) {
            batchOperation.execute();
          }
        }

        processedUsers.add(userName);
      }
    }
    batchOperation.execute();
  }
  /**
   * Add a list of status messages to the contacts provider.
   *
   * @param context the context to use
   * @param accountName the username of the logged in user
   * @param statuses the list of statuses to store
   */
  @TargetApi(15)
  public static void insertStreamStatuses(Context context, String username) {
    final ContentValues values = new ContentValues();
    final ContentResolver resolver = context.getContentResolver();
    final BatchOperation batchOperation = new BatchOperation(context, resolver);
    List<Long> currentContacts = lookupAllContacts(resolver);

    for (long id : currentContacts) {

      String friendUsername = lookupUsername(resolver, id);
      long watermark = lookupHighWatermark(resolver, id);
      long newWatermark = watermark;

      try {
        List<Status> statuses = DeliciousFeed.fetchFriendStatuses(friendUsername);

        for (Status status : statuses) {

          if (status.getTimeStamp().getTime() > watermark) {

            if (status.getTimeStamp().getTime() > newWatermark)
              newWatermark = status.getTimeStamp().getTime();

            values.clear();
            values.put(StreamItems.RAW_CONTACT_ID, id);
            values.put(StreamItems.TEXT, status.getStatus());
            values.put(StreamItems.TIMESTAMP, status.getTimeStamp().getTime());
            values.put(StreamItems.ACCOUNT_NAME, username);
            values.put(StreamItems.ACCOUNT_TYPE, Constants.ACCOUNT_TYPE);
            values.put(StreamItems.RES_ICON, R.drawable.ic_main);
            values.put(StreamItems.RES_PACKAGE, context.getPackageName());
            values.put(StreamItems.RES_LABEL, R.string.label);

            batchOperation.add(
                ContactOperations.newInsertCpo(StreamItems.CONTENT_URI, false)
                    .withValues(values)
                    .build());
            // A sync adapter should batch operations on multiple contacts,
            // because it will make a dramatic performance difference.
            if (batchOperation.size() >= 50) {
              batchOperation.execute();
            }
          }
        }

        values.clear();
        values.put(RawContacts.SYNC1, Long.toString(newWatermark));
        batchOperation.add(
            ContactOperations.newUpdateCpo(RawContacts.CONTENT_URI, false)
                .withValues(values)
                .withSelection(RawContacts._ID + "=?", new String[] {Long.toString(id)})
                .build());

        batchOperation.execute();

      } catch (AuthenticationException e) {
        e.printStackTrace();
      } catch (JSONException e) {
        e.printStackTrace();
      } catch (IOException e) {
        e.printStackTrace();
      }
    }
  }