Example usage for android.content ContentProviderOperation newInsert

List of usage examples for android.content ContentProviderOperation newInsert

Introduction

In this page you can find the example usage for android.content ContentProviderOperation newInsert.

Prototype

public static Builder newInsert(Uri uri) 

Source Link

Document

Create a Builder suitable for building an insert ContentProviderOperation .

Usage

From source file:com.weimed.app.sync.SyncAdapter.java

/**
 * Read JSON from an input stream, storing it into the content provider.
 *
 * <p>This is where incoming data is persisted, committing the results of a sync. In order to
 * minimize (expensive) disk operations, we compare incoming data with what's already in our
 * database, and compute a merge. Only changes (insert/update/delete) will result in a database
 * write./*ww  w .jav a 2 s . co  m*/
 *
 * <p>As an additional optimization, we use a batch operation to perform all database writes at
 * once.
 *
 * <p>Merge strategy:
 * 1. Get cursor to all items in feed<br/>
 * 2. For each item, check if it's in the incoming data.<br/>
 *    a. YES: Remove from "incoming" list. Check if data has mutated, if so, perform
 *            database UPDATE.<br/>
 *    b. NO: Schedule DELETE from database.<br/>
 * (At this point, incoming database only contains missing items.)<br/>
 * 3. For any items remaining in incoming list, ADD to database.
 */
public void updateLocalJSONData(final InputStream stream, final SyncResult syncResult)
        throws IOException, JSONException, RemoteException, OperationApplicationException, ParseException {
    final JSONParser JSONParser = new JSONParser();
    final ContentResolver contentResolver = getContext().getContentResolver();

    Log.i(TAG, "Parsing stream as JSON Array");
    final JSONObject json = JSONParser.parseJSONObject(stream);
    Log.i(TAG, "Parsing complete. Found " + json.getInt("total_rows") + " entries");

    ArrayList<ContentProviderOperation> batch = new ArrayList<ContentProviderOperation>();

    // Build hash table of incoming entries
    HashMap<String, JSONObject> entryMap = new HashMap<String, JSONObject>();
    final JSONArray entries = json.getJSONArray("rows");
    for (int i = 0; i < json.getInt("total_rows"); i++) {
        JSONObject e = entries.getJSONObject(i).getJSONObject("value");
        entryMap.put(e.getString("_id"), e);
    }

    // Get list of all items
    Log.i(TAG, "Fetching local entries for merge");
    Uri uri = NewsContract.Entry.CONTENT_URI; // Get all entries
    Cursor c = contentResolver.query(uri, PROJECTION, null, null, null);
    assert c != null;
    Log.i(TAG, "Found " + c.getCount() + " local entries. Computing merge solution...");

    // Find stale data
    int id;
    String entryId;
    String title;
    String content;
    String publisher;
    String picurl;
    String originalurl;
    String createdat;
    String updatedat;
    String publishedat;

    while (c.moveToNext()) {
        syncResult.stats.numEntries++;
        id = c.getInt(COLUMN_ID);
        entryId = c.getString(COLUMN_ENTRY_ID);
        title = c.getString(COLUMN_TITLE);
        content = c.getString(COLUMN_CONTENT);
        publisher = c.getString(COLUMN_PUBLISHER);
        picurl = c.getString(COLUMN_PICURL);
        originalurl = c.getString(COLUMN_ORIGINALURL);
        createdat = c.getString(COLUMN_CREATEDAT);
        updatedat = c.getString(COLUMN_UPDATEDAT);
        publishedat = c.getString(COLUMN_PUBLISHEDAT);
        JSONObject match = entryMap.get(entryId);
        //            if (match != null) {
        // Entry exists. Remove from entry map to prevent insert later.
        //                entryMap.remove(entryId);
        // Check to see if the entry needs to be updated
        // How to know update local or remote? updatedAt! which is newer, update another.
        //                Uri existingUri = NewsContract.Entry.CONTENT_URI.buildUpon()
        //                                              .appendPath(Integer.toString(id)).build();
        //                if ((match.getString("title") != null && !match.getString("title").equals(title)) ||
        //                    (match.getString("content") != null && !match.getString("content").equals(content)) ||
        //                    (match.getString("publisher") != null && !match.getString("publisher").equals(publisher)) ||
        //                    (match.getString("picurl") != null && !match.getString("picurl").equals(picurl)) ||
        //                    (match.getString("originalurl") != null && !match.getString("originalurl").equals(originalurl)) ||
        //                    (match.getString("createdat") != null && !match.getString("createdat").equals(createdat)) ||
        //                    (match.getString("updatedat") != null && !match.getString("updatedat").equals(updatedat)) ||
        //                    (match.getString("publishedat") != null && !match.getString("publishedat").equals(publishedat))
        //                   ) {
        //                    // Update existing record
        //                    Log.i(TAG, "Scheduling update: " + existingUri);
        //                    batch.add(ContentProviderOperation.newUpdate(existingUri)
        //                         .withValue(NewsContract.Entry.COLUMN_TITLE, title)
        //                         .withValue(NewsContract.Entry.COLUMN_CONTENT, content)
        //                         .withValue(NewsContract.Entry.COLUMN_PUBLISHER, publisher)
        //                         .withValue(NewsContract.Entry.COLUMN_PICURL, picurl)
        //                         .withValue(NewsContract.Entry.COLUMN_ORIGINALURL, originalurl)
        //                         .withValue(NewsContract.Entry.COLUMN_CREATEDAT, createdat)
        //                         .withValue(NewsContract.Entry.COLUMN_UPDATEDAT, updatedat)
        //                         .withValue(NewsContract.Entry.COLUMN_PUBLISHEDAT, publishedat)
        //                         .build());
        //                    syncResult.stats.numUpdates++;
        //                } else {
        //                    Log.i(TAG, "No action: " + existingUri);
        //                }
        //            } else {
        // Entry doesn't exist. Remove it from the database.
        Uri deleteUri = NewsContract.Entry.CONTENT_URI.buildUpon().appendPath(Integer.toString(id)).build();
        Log.i(TAG, "Scheduling delete: " + deleteUri);
        batch.add(ContentProviderOperation.newDelete(deleteUri).build());
        syncResult.stats.numDeletes++;
        //            }
    }
    c.close();

    // Add new items
    for (JSONObject e : entryMap.values()) {
        Log.i(TAG, "Scheduling insert: entry_id=" + e.getString("_id"));
        batch.add(ContentProviderOperation.newInsert(NewsContract.Entry.CONTENT_URI)
                .withValue(NewsContract.Entry.COLUMN_ENTRY_ID, e.getString("_id"))
                .withValue(NewsContract.Entry.COLUMN_TITLE, e.getString("title"))
                .withValue(NewsContract.Entry.COLUMN_CONTENT,
                        fetchTextFileToString(NEWS_URL_BASE + '/' + e.getString("_id") + "/content.md"))
                .withValue(NewsContract.Entry.COLUMN_PUBLISHER, e.getString("publisher"))
                .withValue(NewsContract.Entry.COLUMN_PICURL, e.has("pic_link") ? e.getString("pic_link") : null)
                .withValue(NewsContract.Entry.COLUMN_ORIGINALURL, e.getString("origin_link"))
                .withValue(NewsContract.Entry.COLUMN_CREATEDAT, e.getString("created_at"))
                .withValue(NewsContract.Entry.COLUMN_UPDATEDAT, e.getString("updated_at"))
                .withValue(NewsContract.Entry.COLUMN_PUBLISHEDAT, e.getString("publish_at")).build());
        syncResult.stats.numInserts++;
    }
    Log.i(TAG, "Merge solution ready. Applying batch update");
    mContentResolver.applyBatch(NewsContract.CONTENT_AUTHORITY, batch);
    mContentResolver.notifyChange(NewsContract.Entry.CONTENT_URI, // URI where data was modified
            null, // No local observer
            false); // IMPORTANT: Do not sync to network
    // This sample doesn't support uploads, but if *your* code does, make sure you set
    // syncToNetwork=false in the line above to prevent duplicate syncs.
}

From source file:at.bitfire.ical4android.AndroidEvent.java

protected int add(BatchOperation batch) {
    Builder builder = ContentProviderOperation.newInsert(calendar.syncAdapterURI(eventsSyncURI()));

    final int idxEvent = batch.nextBackrefIdx();
    buildEvent(null, builder);/* w ww. j  a va  2 s.  c om*/
    batch.enqueue(builder.build());

    // add reminders
    for (VAlarm alarm : event.getAlarms())
        insertReminder(batch, idxEvent, alarm);

    // add attendees
    for (Attendee attendee : event.getAttendees())
        insertAttendee(batch, idxEvent, attendee);

    // add exceptions
    for (Event exception : event.getExceptions()) {
        /* I guess exceptions should be inserted using Events.CONTENT_EXCEPTION_URI so that we could
           benefit from some provider logic (for recurring exceptions e.g.). However, this method
           has some caveats:
           - For instance, only Events.SYNC_DATA1, SYNC_DATA3 and SYNC_DATA7 can be used
           in exception events (that's hardcoded in the CalendarProvider, don't ask me why).
           - Also, CONTENT_EXCEPTIONS_URI doesn't deal with exceptions for recurring events defined by RDATE
           (it checks for RRULE and aborts if no RRULE is found).
           So I have chosen the method of inserting the exception event manually.
                
           It's also noteworthy that the link between the "master event" and the exception is not
           between ID and ORIGINAL_ID (as one could assume), but between _SYNC_ID and ORIGINAL_SYNC_ID.
           So, if you don't set _SYNC_ID in the master event and ORIGINAL_SYNC_ID in the exception,
           the exception will appear additionally (and not *instead* of the instance).
         */

        builder = ContentProviderOperation.newInsert(calendar.syncAdapterURI(eventsSyncURI()));
        buildEvent(exception, builder);

        Date date = exception.recurrenceId.getDate();
        if (event.isAllDay() && date instanceof DateTime) { // correct VALUE=DATE-TIME RECURRENCE-IDs to VALUE=DATE for all-day events
            final DateFormat dateFormatDate = new SimpleDateFormat("yyyyMMdd", Locale.US);
            final String dateString = dateFormatDate.format(exception.recurrenceId.getDate());
            try {
                date = new Date(dateString);
            } catch (ParseException e) {
                Log.e(TAG, "Couldn't parse DATE part of DATE-TIME RECURRENCE-ID", e);
            }
        }
        builder.withValueBackReference(Events.ORIGINAL_ID, idxEvent)
                .withValue(Events.ORIGINAL_ALL_DAY, event.isAllDay() ? 1 : 0)
                .withValue(Events.ORIGINAL_INSTANCE_TIME, date.getTime());

        int idxException = batch.nextBackrefIdx();
        batch.enqueue(builder.build());

        // add exception reminders
        for (VAlarm alarm : exception.getAlarms())
            insertReminder(batch, idxException, alarm);

        // add exception attendees
        for (Attendee attendee : exception.getAttendees())
            insertAttendee(batch, idxException, attendee);
    }

    return idxEvent;
}

From source file:com.google.samples.apps.iosched.io.SessionsHandler.java

private void buildTagsMapping(Session session, ArrayList<ContentProviderOperation> list) {
    final Uri uri = ScheduleContractHelper
            .setUriAsCalledFromSyncAdapter(ScheduleContract.Sessions.buildTagsDirUri(session.id));

    // delete any existing mappings
    list.add(ContentProviderOperation.newDelete(uri).build());

    // add a mapping (a session+tag tuple) for each tag in the session
    if (session.tags != null) {
        for (String tag : session.tags) {
            list.add(ContentProviderOperation.newInsert(uri)
                    .withValue(ScheduleDatabase.SessionsTags.SESSION_ID, session.id)
                    .withValue(ScheduleDatabase.SessionsTags.TAG_ID, tag).build());
        }/*ww  w .j a  v a  2s  .c o m*/
    }
}

From source file:pl.epodreczniki.service.MetadataService.java

private ContentProviderOperation toInsertOperation(JSONBook book) {
    if (book == null) {
        return null;
    }/* w  w  w. j a va  2  s  .  c  o  m*/

    int longerEdge = Util.getLongerEdge(this);
    StringBuilder authorsStringBuilder = new StringBuilder();
    String mainAuthor = null;
    if (book.getMdAuthors() != null) {
        final JSONAuthor.JSONAuthorComparator cmp = new JSONAuthor.JSONAuthorComparator();
        Map<String, List<JSONAuthor>> byRoles = authorsByRoles(book.getMdAuthors());
        for (Map.Entry<String, List<JSONAuthor>> entry : byRoles.entrySet()) {
            final String roleName = entry.getKey();
            if (!roleName.equals(KEY_ROLELESS)) {
                authorsStringBuilder.append("<b>").append(roleName).append("</b><br />");
            } else {
                authorsStringBuilder.append("<b>").append("Autorzy").append("</b><br />");
            }
            Collections.sort(entry.getValue(), cmp);
            for (JSONAuthor auth : entry.getValue()) {
                final String fullName = TextUtils.isEmpty(auth.getMdFullName()) ? auth.getFullName()
                        : auth.getMdFullName();
                if (!TextUtils.isEmpty(fullName)) {
                    authorsStringBuilder.append(fullName);
                    authorsStringBuilder.append(", ");
                    if (mainAuthor == null) {
                        mainAuthor = fullName;
                    }
                }
            }
            if (authorsStringBuilder.toString().endsWith(", ")) {
                authorsStringBuilder.replace(authorsStringBuilder.length() - 2, authorsStringBuilder.length(),
                        "<br />");
            }
        }
    }

    String educationLevel = null;
    Integer epClass = null;
    if (book.getMdSchool() != null) {
        educationLevel = book.getMdSchool().getMdEducationLevel();
        epClass = book.getMdSchool().getEpClass();
    }

    String subject = null;
    if (book.getMdSubject() != null) {
        subject = book.getMdSubject().getMdName();
    }

    String zip = null;
    Long extractedSize = null;
    if (book.getFormats() != null) {
        Map<Integer, UrlAndSize> resolutions = new TreeMap<Integer, UrlAndSize>();
        for (JSONFormat format : book.getFormats()) {
            final String formatStr = format.getFormat();
            if (!TextUtils.isEmpty(formatStr)) {
                if (formatStr.matches(Constants.RE_ZIP)) {
                    final int resolution = Integer.parseInt(formatStr.split("-")[1]);
                    final String url = format.getUrl();
                    final Long size = format.getSize();
                    resolutions.put(resolution, new UrlAndSize(url, size));
                }
            }
        }
        int chosen = 0;
        for (Map.Entry<Integer, UrlAndSize> entry : resolutions.entrySet()) {
            chosen = chosen == 0 ? entry.getKey() : (entry.getKey() <= longerEdge ? entry.getKey() : chosen);
        }
        final UrlAndSize choice = resolutions.get(chosen);
        zip = choice.url;
        extractedSize = choice.size;
    }

    String cover = null;
    if (book.getCovers() != null) {
        Map<Integer, String> resolutions = new TreeMap<Integer, String>();
        for (JSONFormat cvr : book.getCovers()) {
            final String formatStr = cvr.getFormat();
            if (!TextUtils.isEmpty(formatStr)) {
                if (formatStr.matches(Constants.RE_COVER)) {
                    final int resolution = Integer.parseInt(formatStr.split("-")[1]);
                    final String url = cvr.getUrl();
                    resolutions.put(resolution, url);
                }
            }
        }
        int chosen = 0;
        for (Map.Entry<Integer, String> entry : resolutions.entrySet()) {
            chosen = chosen == 0 ? entry.getKey() : (entry.getKey() <= longerEdge ? entry.getKey() : chosen);
        }
        Log.e("MDS", "chosen cover resolution: " + chosen);
        cover = resolutions.get(chosen);
    }

    ContentProviderOperation.Builder res = ContentProviderOperation.newInsert(BooksProvider.BOOKS_URI)
            .withValue(BooksTable.C_MD_CONTENT_ID, book.getMdContentId())
            .withValue(BooksTable.C_MD_TITLE, book.getMdTitle())
            .withValue(BooksTable.C_MD_ABSTRACT, book.getMdAbstract())
            .withValue(BooksTable.C_MD_PUBLISHED,
                    book.getMdPublished() == null ? 0 : book.getMdPublished() ? 1 : 0)
            .withValue(BooksTable.C_MD_VERSION, book.getMdVersion())
            .withValue(BooksTable.C_MD_LANGUAGE, book.getMdLanguage())
            .withValue(BooksTable.C_MD_LICENSE, book.getMdLicense())
            .withValue(BooksTable.C_MD_CREATED, book.getMdCreated())
            .withValue(BooksTable.C_MD_REVISED, book.getMdRevised()).withValue(BooksTable.C_COVER, cover)
            .withValue(BooksTable.C_LINK, book.getLink())
            .withValue(BooksTable.C_MD_SUBTITLE, book.getMdSubtitle())
            .withValue(BooksTable.C_AUTHORS, authorsStringBuilder.toString())
            .withValue(BooksTable.C_MAIN_AUTHOR, mainAuthor)
            .withValue(BooksTable.C_EDUCATION_LEVEL, educationLevel).withValue(BooksTable.C_CLASS, epClass)
            .withValue(BooksTable.C_SUBJECT, subject).withValue(BooksTable.C_ZIP, zip)
            .withValue(BooksTable.C_EXTRACTED_SIZE, extractedSize);
    if (book.getAppVersion() != null) {
        return res.withValue(BooksTable.C_APP_VERSION, book.getAppVersion()).build();
    } else {
        return res.build();
    }
}

From source file:com.rukman.emde.smsgroups.syncadapter.SyncAdapter.java

/**
 * We know that the group exists locally, so we can use the data in the JSON group as gold
 * @param group//from  www.j av a2s  . c  o m
 * @param provider
 * @param authToken
 * @param account
 * @param syncResult
 * @throws JSONException
 * @throws RemoteException
 * @throws OperationApplicationException
 */
private void optimisticallyAddContactsToExistingGroup(JSONObject group, ContentProviderClient provider,
        String authToken, Account account, SyncResult syncResult) throws JSONException, RemoteException {

    if (!group.has(JSONKeys.KEY_MEMBERS)) {
        return;
    }
    String groupCloudId = group.getString(JSONKeys.KEY_ID);
    Cursor groupCursor = provider.query(GMSGroups.CONTENT_URI, new String[] { GMSGroup._ID, GMSGroup.CLOUD_ID },
            GMSGroup.CLOUD_ID + "=?", new String[] { groupCloudId }, null);
    try {
        if (groupCursor == null || 1 != groupCursor.getCount() || !groupCursor.moveToFirst()) {
            syncResult.databaseError = true;
            return;
        }
        long groupId = groupCursor.getLong(0);
        if (groupId < 0L) {
            syncResult.databaseError = true;
            return;
        }
        // Optimistically add the contacts
        JSONArray membersArray = group.getJSONArray(JSONKeys.KEY_MEMBERS);
        for (int j = 0; j < membersArray.length(); ++j) {
            JSONObject member = membersArray.getJSONObject(j);
            ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();
            // If the first operation asserts it means the contact exists already
            // Operation 0
            ContentProviderOperation op = ContentProviderOperation.newAssertQuery(GMSContacts.CONTENT_URI)
                    .withSelection(GMSContact.CLOUD_ID + "=? AND " + GMSContact.GROUP_ID + "=?",
                            new String[] { member.getString(JSONKeys.KEY_ID), String.valueOf(groupId) })
                    .withExpectedCount(0).build();
            ops.add(op);
            op = ContentProviderOperation.newInsert(GMSContacts.CONTENT_URI)
                    .withValues(GMSApplication.getMemberValues(member)).withValue(GMSContact.GROUP_ID, groupId)
                    .withValue(GMSContact.STATUS, GMSContact.STATUS_SYNCED).build();
            ops.add(op);
            try {
                @SuppressWarnings("unused")
                ContentProviderResult[] results = provider.applyBatch(ops);
            } catch (OperationApplicationException e) {
                // The contact already exists, so we'll optionally update it, based on its version
                Cursor contactCursor = null;
                try {
                    contactCursor = provider.query(GMSContacts.CONTENT_URI,
                            new String[] { GMSContact._ID, GMSContact.CLOUD_ID, GMSContact.GROUP_ID },
                            GMSContact.CLOUD_ID + "=? AND " + GMSContact.GROUP_ID + "=?",
                            new String[] { member.getString(JSONKeys.KEY_ID), String.valueOf(groupId) }, null);
                    if (contactCursor == null || !contactCursor.moveToFirst()) {
                        syncResult.databaseError = true;
                        return;
                    }
                    // The member already exists, so optinally update it
                    ops = new ArrayList<ContentProviderOperation>();
                    // Operation 0 - we know it exists. If its the right version, we don't need to do the update
                    // So we assert that we'll find zero records with the current version and if that's right, we'll update our
                    // record, including the version with the new record data
                    op = ContentProviderOperation
                            .newAssertQuery(ContentUris.withAppendedId(GMSContacts.CONTENT_URI,
                                    contactCursor.getLong(0)))
                            .withSelection(GMSContact.VERSION + "=?",
                                    new String[] { member.getString(JSONKeys.KEY_VERSION) })
                            .withExpectedCount(0).build();
                    ops.add(op);
                    op = ContentProviderOperation
                            .newUpdate(ContentUris.withAppendedId(GMSContacts.CONTENT_URI,
                                    contactCursor.getLong(0)))
                            .withValues(GMSApplication.getMemberValues(member))
                            .withValue(GMSContact.STATUS, GMSContact.STATUS_SYNCED).withExpectedCount(1)
                            .build();
                    ops.add(op);
                    provider.applyBatch(ops);
                } catch (OperationApplicationException l) {
                    ops = new ArrayList<ContentProviderOperation>();
                    // Operation 0 - we know it exists and is of the current version, so no update of attributes is needed
                    // We still have to update the status to SYNCED so we don't blow it away later.
                    op = ContentProviderOperation
                            .newUpdate(ContentUris.withAppendedId(GMSContacts.CONTENT_URI,
                                    contactCursor.getLong(0)))
                            .withValue(GMSContact.STATUS, GMSContact.STATUS_SYNCED).withExpectedCount(1)
                            .build();
                    ops.add(op);
                    try {
                        provider.applyBatch(ops);
                    } catch (OperationApplicationException e1) {
                        syncResult.stats.numSkippedEntries++;
                        e1.printStackTrace();
                    }
                } finally {
                    if (contactCursor != null) {
                        contactCursor.close();
                    }
                }
            }
        }
    } finally {
        if (groupCursor != null) {
            groupCursor.close();
        }
    }
}

From source file:net.smartpager.android.activity.MainActivity.java

private void insertQuickResponsesDefaults() {

    String[] strArray = getResources().getStringArray(R.array.quick_resp_defaults);
    List<String> defaultsList = Arrays.asList(strArray);

    ArrayList<ContentProviderOperation> operations = new ArrayList<ContentProviderOperation>();
    Uri uri = SmartPagerContentProvider.CONTENT_QUICK_RESPONSE_URI;

    for (String item : defaultsList) {
        Builder builder = ContentProviderOperation.newInsert(uri);
        builder.withValue(QuickResponseTable.messageText.name(), item);
        operations.add(builder.build());
    }/*  ww  w  . j a  v  a 2s .c o  m*/

    try {
        getContentResolver().applyBatch(SmartPagerContentProvider.AUTHORITY, operations);
    } catch (RemoteException e) {
        e.printStackTrace();
    } catch (OperationApplicationException e) {
        e.printStackTrace();
    }
}

From source file:ch.berta.fabio.popularmovies.data.repositories.MovieRepositoryImpl.java

private void addMovieReviewsOps(@NonNull MovieDetails movieDetails, long movieRowId,
        @NonNull ArrayList<ContentProviderOperation> ops) {
    ops.add(ContentProviderOperation.newDelete(MovieContract.Review.buildReviewsFromMovieUri(movieRowId))
            .build());/*from  w w w. j  a  va 2  s .  c o m*/

    List<Review> reviews = movieDetails.getReviewsPage().getReviews();
    if (!reviews.isEmpty()) {
        for (Review review : reviews) {
            ops.add(ContentProviderOperation.newInsert(MovieContract.Review.CONTENT_URI)
                    .withValue(MovieContract.Review.COLUMN_MOVIE_ID, movieRowId)
                    .withValues(review.getContentValuesEntry()).build());
        }
    }
}

From source file:com.trellmor.berrymotes.sync.SubredditEmoteDownloader.java

public void updateEmotes(List<EmoteImage> emotes)
        throws RemoteException, OperationApplicationException, InterruptedException {
    checkInterrupted();/*from   w w  w  .j a v a2  s. c  o  m*/

    Log.debug("Updating emote database");

    // Build map of entries
    HashMap<String, EmoteImage> emoteHash = new HashMap<String, EmoteImage>();
    for (EmoteImage emote : emotes) {
        emoteHash.put(emote.getHash(), emote);
    }

    checkInterrupted();
    Cursor c = mContentResolver.query(EmotesContract.Emote.CONTENT_URI_DISTINCT,
            new String[] { EmotesContract.Emote._ID, EmotesContract.Emote.COLUMN_NAME,
                    EmotesContract.Emote.COLUMN_HASH },
            EmotesContract.Emote.COLUMN_SUBREDDIT + "=?", new String[] { mSubreddit }, null);
    if (c != null) {
        ArrayList<ContentProviderOperation> batch = new ArrayList<ContentProviderOperation>();

        if (c.moveToFirst()) {
            final int POS_ID = c.getColumnIndex(EmotesContract.Emote._ID);
            final int POS_NAME = c.getColumnIndex(EmotesContract.Emote.COLUMN_NAME);
            final int POS_HASH = c.getColumnIndex(EmotesContract.Emote.COLUMN_HASH);

            do {
                String hash = c.getString(POS_HASH);
                String name = c.getString(POS_NAME);
                EmoteImage emote = emoteHash.get(hash);
                if (emote != null) {
                    if (emote.getNames().contains(name)) {
                        emote.getNames().remove(name);
                        if (emote.getNames().size() == 0) {
                            // Already in db, no need to insert
                            emoteHash.remove(hash);
                            emotes.remove(emote);
                        }
                    } else {
                        Log.debug("Removing " + name + " (" + hash + ") from DB");
                        Uri deleteUri = EmotesContract.Emote.CONTENT_URI.buildUpon()
                                .appendPath(Integer.toString(c.getInt(POS_ID))).build();
                        batch.add(ContentProviderOperation.newDelete(deleteUri).build());
                    }
                }
            } while (c.moveToNext());
        }

        c.close();

        // Delete all emotes that no longer exist
        Log.debug("Removing emotes names from DB");
        checkInterrupted();
        applyBatch(batch);
        mSyncResult.stats.numDeletes += batch.size();
        Log.info("Removed " + Integer.toString(batch.size()) + " emotes names from DB");
    }

    // Generate batch insert
    checkInterrupted();
    ArrayList<ContentProviderOperation> batch = new ArrayList<ContentProviderOperation>();
    String baseDir = mBaseDir.getAbsolutePath() + File.separator;
    for (EmoteImage emote : emotes) {
        for (String name : emote.getNames()) {
            Log.debug("Adding " + name + " to DB");
            batch.add(ContentProviderOperation.newInsert(EmotesContract.Emote.CONTENT_URI)
                    .withValue(EmotesContract.Emote.COLUMN_NAME, name)
                    .withValue(EmotesContract.Emote.COLUMN_NSFW, (emote.isNsfw() ? 1 : 0))
                    .withValue(EmotesContract.Emote.COLUMN_APNG, (emote.isApng() ? 1 : 0))
                    .withValue(EmotesContract.Emote.COLUMN_IMAGE, baseDir + emote.getImage())
                    .withValue(EmotesContract.Emote.COLUMN_HASH, emote.getHash())
                    .withValue(EmotesContract.Emote.COLUMN_INDEX, emote.getIndex())
                    .withValue(EmotesContract.Emote.COLUMN_DELAY, emote.getDelay())
                    .withValue(EmotesContract.Emote.COLUMN_SUBREDDIT, emote.getSubreddit()).build());
        }
    }

    Log.debug("Adding emotes names to DB");
    checkInterrupted();
    applyBatch(batch);
    mSyncResult.stats.numInserts += batch.size();
    Log.info("Added " + Integer.toString(batch.size()) + " emotes names to DB");
}

From source file:com.owncloud.android.datamodel.FileDataStorageManager.java

/**
 * Inserts or updates the list of files contained in a given folder.
 * <p/>/*  ww  w . j av  a  2s . c o m*/
 * CALLER IS THE RESPONSIBLE FOR GRANTING RIGHT UPDATE OF INFORMATION, NOT THIS METHOD.
 * HERE ONLY DATA CONSISTENCY SHOULD BE GRANTED
 *
 * @param folder
 * @param updatedFiles
 * @param filesToRemove
 */
public void saveFolder(OCFile folder, Collection<OCFile> updatedFiles, Collection<OCFile> filesToRemove) {

    Log_OC.d(TAG, "Saving folder " + folder.getRemotePath() + " with " + updatedFiles.size() + " children and "
            + filesToRemove.size() + " files to remove");

    ArrayList<ContentProviderOperation> operations = new ArrayList<ContentProviderOperation>(
            updatedFiles.size());

    // prepare operations to insert or update files to save in the given folder
    for (OCFile file : updatedFiles) {
        ContentValues cv = new ContentValues();
        cv.put(ProviderTableMeta.FILE_MODIFIED, file.getModificationTimestamp());
        cv.put(ProviderTableMeta.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA,
                file.getModificationTimestampAtLastSyncForData());
        cv.put(ProviderTableMeta.FILE_CREATION, file.getCreationTimestamp());
        cv.put(ProviderTableMeta.FILE_CONTENT_LENGTH, file.getFileLength());
        cv.put(ProviderTableMeta.FILE_CONTENT_TYPE, file.getMimetype());
        cv.put(ProviderTableMeta.FILE_NAME, file.getFileName());
        cv.put(ProviderTableMeta.FILE_PARENT, folder.getFileId());
        cv.put(ProviderTableMeta.FILE_PATH, file.getRemotePath());
        if (!file.isFolder()) {
            cv.put(ProviderTableMeta.FILE_STORAGE_PATH, file.getStoragePath());
        }
        cv.put(ProviderTableMeta.FILE_ACCOUNT_OWNER, mAccount.name);
        cv.put(ProviderTableMeta.FILE_LAST_SYNC_DATE, file.getLastSyncDateForProperties());
        cv.put(ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA, file.getLastSyncDateForData());
        cv.put(ProviderTableMeta.FILE_ETAG, file.getEtag());
        cv.put(ProviderTableMeta.FILE_TREE_ETAG, file.getTreeEtag());
        cv.put(ProviderTableMeta.FILE_SHARED_VIA_LINK, file.isSharedViaLink() ? 1 : 0);
        cv.put(ProviderTableMeta.FILE_SHARED_WITH_SHAREE, file.isSharedWithSharee() ? 1 : 0);
        cv.put(ProviderTableMeta.FILE_PERMISSIONS, file.getPermissions());
        cv.put(ProviderTableMeta.FILE_REMOTE_ID, file.getRemoteId());
        cv.put(ProviderTableMeta.FILE_UPDATE_THUMBNAIL, file.needsUpdateThumbnail());
        cv.put(ProviderTableMeta.FILE_IS_DOWNLOADING, file.isDownloading());
        cv.put(ProviderTableMeta.FILE_ETAG_IN_CONFLICT, file.getEtagInConflict());
        cv.put(ProviderTableMeta.FILE_PRIVATE_LINK, file.getPrivateLink());

        boolean existsByPath = fileExists(file.getRemotePath());
        if (existsByPath || fileExists(file.getFileId())) {
            // updating an existing file
            operations.add(ContentProviderOperation.newUpdate(ProviderTableMeta.CONTENT_URI).withValues(cv)
                    .withSelection(ProviderTableMeta._ID + "=?",
                            new String[] { String.valueOf(file.getFileId()) })
                    .build());

        } else {
            // adding a new file
            setInitialAvailableOfflineStatus(file, cv);
            operations.add(
                    ContentProviderOperation.newInsert(ProviderTableMeta.CONTENT_URI).withValues(cv).build());
        }
    }

    // prepare operations to remove files in the given folder
    String where = ProviderTableMeta.FILE_ACCOUNT_OWNER + "=?" + " AND " + ProviderTableMeta.FILE_PATH + "=?";
    String[] whereArgs = null;
    for (OCFile file : filesToRemove) {
        if (file.getParentId() == folder.getFileId()) {
            whereArgs = new String[] { mAccount.name, file.getRemotePath() };
            if (file.isFolder()) {
                operations.add(ContentProviderOperation
                        .newDelete(
                                ContentUris.withAppendedId(ProviderTableMeta.CONTENT_URI_DIR, file.getFileId()))
                        .withSelection(where, whereArgs).build());

                File localFolder = new File(FileStorageUtils.getDefaultSavePathFor(mAccount.name, file));
                if (localFolder.exists()) {
                    removeLocalFolder(localFolder);
                }
            } else {
                operations.add(ContentProviderOperation.newDelete(
                        ContentUris.withAppendedId(ProviderTableMeta.CONTENT_URI_FILE, file.getFileId()))
                        .withSelection(where, whereArgs).build());

                if (file.isDown()) {
                    String path = file.getStoragePath();
                    new File(path).delete();
                    triggerMediaScan(path); // notify MediaScanner about removed file
                }
            }
        }
    }

    // update metadata of folder
    ContentValues cv = new ContentValues();
    cv.put(ProviderTableMeta.FILE_MODIFIED, folder.getModificationTimestamp());
    cv.put(ProviderTableMeta.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA,
            folder.getModificationTimestampAtLastSyncForData());
    cv.put(ProviderTableMeta.FILE_CREATION, folder.getCreationTimestamp());
    cv.put(ProviderTableMeta.FILE_CONTENT_LENGTH, folder.getFileLength());
    cv.put(ProviderTableMeta.FILE_CONTENT_TYPE, folder.getMimetype());
    cv.put(ProviderTableMeta.FILE_NAME, folder.getFileName());
    cv.put(ProviderTableMeta.FILE_PARENT, folder.getParentId());
    cv.put(ProviderTableMeta.FILE_PATH, folder.getRemotePath());
    cv.put(ProviderTableMeta.FILE_ACCOUNT_OWNER, mAccount.name);
    cv.put(ProviderTableMeta.FILE_LAST_SYNC_DATE, folder.getLastSyncDateForProperties());
    cv.put(ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA, folder.getLastSyncDateForData());
    cv.put(ProviderTableMeta.FILE_ETAG, folder.getEtag());
    cv.put(ProviderTableMeta.FILE_TREE_ETAG, folder.getTreeEtag());
    cv.put(ProviderTableMeta.FILE_SHARED_VIA_LINK, folder.isSharedViaLink() ? 1 : 0);
    cv.put(ProviderTableMeta.FILE_SHARED_WITH_SHAREE, folder.isSharedWithSharee() ? 1 : 0);
    cv.put(ProviderTableMeta.FILE_PERMISSIONS, folder.getPermissions());
    cv.put(ProviderTableMeta.FILE_REMOTE_ID, folder.getRemoteId());
    cv.put(ProviderTableMeta.FILE_PRIVATE_LINK, folder.getPrivateLink());

    operations.add(ContentProviderOperation.newUpdate(ProviderTableMeta.CONTENT_URI).withValues(cv)
            .withSelection(ProviderTableMeta._ID + "=?", new String[] { String.valueOf(folder.getFileId()) })
            .build());

    // apply operations in batch
    ContentProviderResult[] results = null;
    Log_OC.d(TAG, "Sending " + operations.size() + " operations to FileContentProvider");
    try {
        if (getContentResolver() != null) {
            results = getContentResolver().applyBatch(MainApp.getAuthority(), operations);

        } else {
            results = getContentProviderClient().applyBatch(operations);
        }

    } catch (OperationApplicationException e) {
        Log_OC.e(TAG, "Exception in batch of operations " + e.getMessage());

    } catch (RemoteException e) {
        Log_OC.e(TAG, "Exception in batch of operations  " + e.getMessage());
    }

    // update new id in file objects for insertions
    if (results != null) {
        long newId;
        Iterator<OCFile> filesIt = updatedFiles.iterator();
        OCFile file = null;
        for (int i = 0; i < results.length; i++) {
            if (filesIt.hasNext()) {
                file = filesIt.next();
            } else {
                file = null;
            }
            if (results[i].uri != null) {
                newId = Long.parseLong(results[i].uri.getPathSegments().get(1));
                //updatedFiles.get(i).setFileId(newId);
                if (file != null) {
                    file.setFileId(newId);
                }
            }
        }
    }

}

From source file:org.pixmob.droidlink.sync.SyncAdapter.java

private void doPerformSync(NetworkClient client, SharedPreferences prefs, ContentProviderClient provider,
        SyncResult syncResult, boolean fullSync) {
    // Prepare the query.
    final String selection = DEVICE_ID + "=? AND " + STATE + "=? OR " + STATE + "=?";
    final String[] selectionArgs = { client.getDeviceId(), String.valueOf(EventsContract.PENDING_UPLOAD_STATE),
            String.valueOf(EventsContract.PENDING_DELETE_STATE) };

    // Get local data to sync.
    final Map<String, JSONObject> eventsToUpload = new HashMap<String, JSONObject>(8);
    final Set<String> eventsToDelete = new HashSet<String>(4);
    Cursor c = null;//from   www .  j  av a2s .c  o m
    try {
        c = provider.query(EventsContract.CONTENT_URI, PROJECTION, selection, selectionArgs, null);

        final int idIdx = c.getColumnIndexOrThrow(_ID);
        final int typeIdx = c.getColumnIndexOrThrow(TYPE);
        final int createdIdx = c.getColumnIndexOrThrow(CREATED);
        final int numberIdx = c.getColumnIndexOrThrow(NUMBER);
        final int nameIdx = c.getColumnIndexOrThrow(NAME);
        final int messageIdx = c.getColumnIndexOrThrow(MESSAGE);
        final int stateIdx = c.getColumnIndexOrThrow(STATE);

        while (c.moveToNext()) {
            final String eventId = c.getString(idIdx);
            final int eventState = c.getInt(stateIdx);

            if (EventsContract.PENDING_UPLOAD_STATE == eventState) {
                // This is a newly created event.
                final JSONObject event = new JSONObject();
                try {
                    event.put("deviceId", client.getDeviceId());
                    event.put("created", c.getLong(createdIdx));
                    event.put("type", c.getInt(typeIdx));
                    event.put("number", c.getString(numberIdx));
                    event.put("name", c.getString(nameIdx));
                    event.put("message", c.getString(messageIdx));
                } catch (JSONException e) {
                    Log.w(TAG, "Invalid event " + eventId + ": cannot sync", e);
                    syncResult.stats.numSkippedEntries++;
                    continue;
                }
                eventsToUpload.put(eventId, event);
            } else if (EventsContract.PENDING_DELETE_STATE == eventState) {
                // The user wants this event to be deleted.
                eventsToDelete.add(eventId);
            }
        }
    } catch (RemoteException e) {
        Log.e(TAG, "Failed to get events: cannot sync", e);
        syncResult.stats.numIoExceptions++;
    } finally {
        if (c != null) {
            c.close();
            c = null;
        }
    }

    final ArrayList<ContentProviderOperation> batch = new ArrayList<ContentProviderOperation>(32);
    final ContentValues values = new ContentValues(8);

    if (eventsToDelete.isEmpty()) {
        Log.i(TAG, "No events to delete");
    } else {
        Log.i(TAG, "Found " + eventsToDelete.size() + " event(s) to delete");
    }

    // Delete events on the remote server.
    for (final String eventId : eventsToDelete) {
        if (DEVELOPER_MODE) {
            Log.d(TAG, "Deleting event: " + eventId);
        }

        try {
            client.delete("/events/" + eventId);

            if (DEVELOPER_MODE) {
                Log.d(TAG, "Deleting event in local database: " + eventId);
            }
            batch.add(ContentProviderOperation
                    .newDelete(Uri.withAppendedPath(EventsContract.CONTENT_URI, eventId)).build());
            syncResult.stats.numDeletes++;
        } catch (IOException e) {
            Log.e(TAG, "Event deletion error: cannot sync", e);
            syncResult.stats.numIoExceptions++;
            return;
        } catch (AppEngineAuthenticationException e) {
            Log.e(TAG, "Authentication error: cannot sync", e);
            syncResult.stats.numAuthExceptions++;
            return;
        }
    }

    try {
        provider.applyBatch(batch);
    } catch (Exception e) {
        Log.w(TAG, "Database error: cannot sync", e);
        syncResult.stats.numIoExceptions++;
        return;
    }
    batch.clear();

    if (fullSync) {
        // Get all events from the remote server.
        final JSONArray events;
        if (DEVELOPER_MODE) {
            Log.d(TAG, "Fetching events from the remote server");
        }
        try {
            events = client.getAsArray("/events");
        } catch (IOException e) {
            Log.e(TAG, "Event listing error: cannot sync", e);
            syncResult.stats.numIoExceptions++;
            return;
        } catch (AppEngineAuthenticationException e) {
            Log.e(TAG, "Authentication error: cannot sync", e);
            syncResult.stats.numAuthExceptions++;
            return;
        }

        final int eventsLen = events != null ? events.length() : 0;
        if (eventsLen == 0) {
            Log.i(TAG, "No events from the remote server");
        } else {
            Log.i(TAG, "Found " + eventsLen + " event(s) from the remote server");
        }

        // Build a collection with local event identifiers.
        // This collection will be used to identify which events have
        // been deleted on the remote server.
        final Set<String> localEventIds;
        try {
            c = provider.query(EventsContract.CONTENT_URI, PROJECTION_ID, STATE + "=?",
                    new String[] { String.valueOf(EventsContract.UPLOADED_STATE) }, null);
            localEventIds = new HashSet<String>(c.getCount());

            final int idIdx = c.getColumnIndexOrThrow(_ID);
            while (c.moveToNext()) {
                final String eventId = c.getString(idIdx);
                localEventIds.add(eventId);
            }
        } catch (RemoteException e) {
            Log.e(TAG, "Failed to get events from local database", e);
            syncResult.stats.numIoExceptions++;
            return;
        } finally {
            if (c != null) {
                c.close();
                c = null;
            }
        }

        String newEventId = null;
        int newEventCount = 0;

        // Reconcile remote events with local events.
        for (int i = 0; i < eventsLen; ++i) {
            String eventId = null;
            try {
                final JSONObject event = events.getJSONObject(i);
                eventId = event.getString("id");

                // Check if this event exists in the local database.
                if (localEventIds.contains(eventId)) {
                    // Found the event: update it.
                    values.clear();
                    values.put(NUMBER, trimToNull(event.getString("number")));
                    values.put(NAME, trimToNull(event.getString("name")));
                    values.put(MESSAGE, trimToNull(event.getString("message")));

                    if (DEVELOPER_MODE) {
                        Log.d(TAG, "Updating event in local database: " + eventId);
                    }
                    batch.add(ContentProviderOperation
                            .newUpdate(Uri.withAppendedPath(EventsContract.CONTENT_URI, eventId))
                            .withExpectedCount(1).withValues(values).build());
                    syncResult.stats.numUpdates++;
                } else {
                    // The event was not found: insert it.
                    values.clear();
                    values.put(_ID, eventId);
                    values.put(DEVICE_ID, event.getString("deviceId"));
                    values.put(CREATED, event.getLong("created"));
                    values.put(TYPE, event.getInt("type"));
                    values.put(NUMBER, trimToNull(event.getString("number")));
                    values.put(NAME, trimToNull(event.getString("name")));
                    values.put(MESSAGE, trimToNull(event.getString("message")));
                    values.put(STATE, EventsContract.UPLOADED_STATE);

                    if (DEVELOPER_MODE) {
                        Log.d(TAG, "Adding event to local database: " + eventId);
                    }
                    batch.add(ContentProviderOperation
                            .newInsert(Uri.withAppendedPath(EventsContract.CONTENT_URI, eventId))
                            .withValues(values).build());
                    syncResult.stats.numInserts++;

                    ++newEventCount;
                    if (newEventId == null) {
                        newEventId = eventId;
                    }
                }

                // This event now exists in the local database:
                // remove its identifier from this collection as we
                // don't want to delete it.
                localEventIds.remove(eventId);
            } catch (JSONException e) {
                Log.w(TAG, "Invalid event at index " + i + ": cannot sync", e);
                syncResult.stats.numSkippedEntries++;
                continue;
            }
        }

        // The remaining event identifiers was removed on the remote
        // server: there are still present in the local database. These
        // events are now being deleted.
        for (final String eventId : localEventIds) {
            if (DEVELOPER_MODE) {
                Log.d(TAG, "Deleting event in local database: " + eventId);
            }
            batch.add(ContentProviderOperation
                    .newDelete(Uri.withAppendedPath(EventsContract.CONTENT_URI, eventId)).build());
            syncResult.stats.numDeletes++;
        }

        try {
            provider.applyBatch(batch);
        } catch (Exception e) {
            Log.e(TAG, "Database error: cannot sync", e);
            syncResult.stats.numIoExceptions++;
            return;
        }
        batch.clear();

        if (newEventCount > 1) {
            newEventId = null;
        }
        if (newEventCount != 0) {
            startSyncNotificationService(newEventCount, newEventId);
        }
    }

    final int numEventsToUpload = eventsToUpload.size();
    if (numEventsToUpload == 0) {
        Log.i(TAG, "No events to upload");
    } else {
        Log.i(TAG, "Found " + numEventsToUpload + " event(s) to upload");
    }

    // Send local events to the remote server.
    for (final Map.Entry<String, JSONObject> entry : eventsToUpload.entrySet()) {
        final String eventId = entry.getKey();

        if (DEVELOPER_MODE) {
            Log.d(TAG, "Uploading event: " + eventId);
        }

        final JSONObject event = entry.getValue();
        try {
            client.put("/events/" + eventId, event);

            if (DEVELOPER_MODE) {
                Log.d(TAG, "Updating event state to UPLOADED: " + eventId);
            }
            values.clear();
            values.put(STATE, EventsContract.UPLOADED_STATE);
            batch.add(ContentProviderOperation
                    .newUpdate(Uri.withAppendedPath(EventsContract.CONTENT_URI, eventId)).withValues(values)
                    .withExpectedCount(1).build());
            syncResult.stats.numUpdates++;

            Log.i(TAG, "Event upload successful: " + eventId);
        } catch (NetworkClientException e) {
            if (e.getStatusCode() == 404) {
                Log.e(TAG, "Device not found: cannot sync", e);
                registerDevice();
            } else {
                Log.e(TAG, "Network error: cannot sync", e);
            }
            syncResult.stats.numIoExceptions++;
            return;
        } catch (IOException e) {
            Log.e(TAG, "Event upload error: cannot sync", e);
            syncResult.stats.numIoExceptions++;
            return;
        } catch (AppEngineAuthenticationException e) {
            Log.e(TAG, "Authentication error: cannot sync", e);
            syncResult.stats.numAuthExceptions++;
            return;
        }
    }

    try {
        provider.applyBatch(batch);
    } catch (Exception e) {
        Log.w(TAG, "Database error: cannot sync", e);
        syncResult.stats.numIoExceptions++;
        return;
    }
    batch.clear();

    final SharedPreferences.Editor prefsEditor = prefs.edit();
    final boolean syncRequired = !eventsToDelete.isEmpty() || !eventsToUpload.isEmpty();
    if (syncRequired) {
        // Generate an unique sync token: the server will send this token to
        // every devices. If this token is received on this device, the sync
        // will not start.
        final String syncToken = UUID.randomUUID().toString();
        prefsEditor.putString(SP_KEY_SYNC_TOKEN, syncToken);
        Features.getFeature(SharedPreferencesSaverFeature.class).save(prefsEditor);

        // Sync user devices.
        try {
            final JSONObject data = new JSONObject();
            data.put("token", syncToken);
            client.post("/devices/" + client.getDeviceId() + "/sync", data);
        } catch (NetworkClientException e) {
            if (e.getStatusCode() == 404) {
                registerDevice();
            }
        } catch (IOException e) {
            Log.e(TAG, "Device sync error: cannot sync", e);
            syncResult.stats.numIoExceptions++;
            return;
        } catch (AppEngineAuthenticationException e) {
            Log.e(TAG, "Authentication error: cannot sync", e);
            syncResult.stats.numAuthExceptions++;
            return;
        } catch (JSONException e) {
            Log.w(TAG, "Invalid sync token " + syncToken + ": cannot sync", e);
            syncResult.stats.numIoExceptions++;
            return;
        }
    }

    // Store sync time.
    prefsEditor.putLong(SP_KEY_LAST_SYNC, System.currentTimeMillis());
    Features.getFeature(SharedPreferencesSaverFeature.class).save(prefsEditor);
}