Example usage for android.net Uri getLastPathSegment

List of usage examples for android.net Uri getLastPathSegment

Introduction

In this page you can find the example usage for android.net Uri getLastPathSegment.

Prototype

@Nullable
public abstract String getLastPathSegment();

Source Link

Document

Gets the decoded last segment in the path.

Usage

From source file:com.ichi2.anki.provider.CardContentProvider.java

@Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
    Timber.d("CardContentProvider.query");
    Collection col = CollectionHelper.getInstance().getCol(getContext());
    if (col == null) {
        return null;
    }//from   w w w .j  av a 2s  . com

    // Find out what data the user is requesting
    int match = sUriMatcher.match(uri);

    switch (match) {
    case NOTES: {
        /* Search for notes
         */
        // TODO: Allow sort order, then also update description in FlashCardContract
        String columnsStr = proj2str(projection);
        String query = (selection != null) ? selection : "";
        List<Long> noteIds = col.findNotes(query);
        if ((noteIds != null) && (!noteIds.isEmpty())) {
            String selectedIds = "id in " + Utils.ids2str(noteIds);
            Cursor cur;
            try {
                cur = col.getDb().getDatabase()
                        .rawQuery("select " + columnsStr + " from notes where " + selectedIds, null);
            } catch (SQLException e) {
                throw new IllegalArgumentException("Not possible to query for data for IDs " + selectedIds, e);
            }
            return cur;
        } else {
            return null;
        }
    }
    case NOTES_ID: {
        /* Direct access note
         */
        long noteId;
        noteId = Long.parseLong(uri.getPathSegments().get(1));
        String columnsStr = proj2str(projection);
        String selectedIds = "id = " + noteId;
        Cursor cur;
        try {
            cur = col.getDb().getDatabase()
                    .rawQuery("select " + columnsStr + " from notes where " + selectedIds, null);
        } catch (SQLException e) {
            throw new IllegalArgumentException("Not possible to query for data for ID \"" + noteId + "\"", e);
        }
        return cur;
    }

    case NOTES_ID_CARDS: {
        Note currentNote = getNoteFromUri(uri, col);
        String[] columns = ((projection != null) ? projection : FlashCardsContract.Card.DEFAULT_PROJECTION);
        MatrixCursor rv = new MatrixCursor(columns, 1);
        for (Card currentCard : currentNote.cards()) {
            addCardToCursor(currentCard, rv, col, columns);
        }
        return rv;
    }
    case NOTES_ID_CARDS_ORD: {
        Card currentCard = getCardFromUri(uri, col);
        String[] columns = ((projection != null) ? projection : FlashCardsContract.Card.DEFAULT_PROJECTION);
        MatrixCursor rv = new MatrixCursor(columns, 1);
        addCardToCursor(currentCard, rv, col, columns);
        return rv;
    }
    case MODELS: {
        HashMap<Long, JSONObject> models = col.getModels().getModels();
        String[] columns = ((projection != null) ? projection : FlashCardsContract.Model.DEFAULT_PROJECTION);
        MatrixCursor rv = new MatrixCursor(columns, 1);
        for (Long modelId : models.keySet()) {
            addModelToCursor(modelId, models, rv, columns);
        }
        return rv;
    }
    case MODELS_ID: {
        long modelId = getModelIdFromUri(uri, col);
        String[] columns = ((projection != null) ? projection : FlashCardsContract.Model.DEFAULT_PROJECTION);
        MatrixCursor rv = new MatrixCursor(columns, 1);
        HashMap<Long, JSONObject> models = col.getModels().getModels();
        addModelToCursor(modelId, models, rv, columns);
        return rv;
    }
    case MODELS_ID_TEMPLATES: {
        /* Direct access model templates
         */
        JSONObject currentModel = col.getModels().get(getModelIdFromUri(uri, col));
        String[] columns = ((projection != null) ? projection : CardTemplate.DEFAULT_PROJECTION);
        MatrixCursor rv = new MatrixCursor(columns, 1);
        try {
            JSONArray templates = currentModel.getJSONArray("tmpls");
            for (int idx = 0; idx < templates.length(); idx++) {
                JSONObject template = templates.getJSONObject(idx);
                addTemplateToCursor(template, currentModel, idx + 1, rv, columns);
            }
        } catch (JSONException e) {
            throw new IllegalArgumentException("Model is malformed", e);
        }
        return rv;
    }
    case MODELS_ID_TEMPLATES_ID: {
        /* Direct access model template with specific ID
         */
        int ord = Integer.parseInt(uri.getLastPathSegment());
        JSONObject currentModel = col.getModels().get(getModelIdFromUri(uri, col));
        String[] columns = ((projection != null) ? projection : CardTemplate.DEFAULT_PROJECTION);
        MatrixCursor rv = new MatrixCursor(columns, 1);
        try {
            JSONObject template = getTemplateFromUri(uri, col);
            addTemplateToCursor(template, currentModel, ord + 1, rv, columns);
        } catch (JSONException e) {
            throw new IllegalArgumentException("Model is malformed", e);
        }
        return rv;
    }

    case SCHEDULE: {
        String[] columns = ((projection != null) ? projection
                : FlashCardsContract.ReviewInfo.DEFAULT_PROJECTION);
        MatrixCursor rv = new MatrixCursor(columns, 1);
        long selectedDeckBeforeQuery = col.getDecks().selected();
        long deckIdOfTemporarilySelectedDeck = -1;
        int limit = 1; //the number of scheduled cards to return
        int selectionArgIndex = 0;

        //parsing the selection arguments
        if (selection != null) {
            String[] args = selection.split(","); //split selection to get arguments like "limit=?"
            for (String arg : args) {
                String[] keyAndValue = arg.split("="); //split arguments into key ("limit") and value ("?")
                try {
                    //check if value is a placeholder ("?"), if so replace with the next value of selectionArgs
                    String value = keyAndValue[1].trim().equals("?") ? selectionArgs[selectionArgIndex++]
                            : keyAndValue[1];
                    if (keyAndValue[0].trim().equals("limit")) {
                        limit = Integer.valueOf(value);
                    } else if (keyAndValue[0].trim().equals("deckID")) {
                        deckIdOfTemporarilySelectedDeck = Long.valueOf(value);
                        if (!selectDeckWithCheck(col, deckIdOfTemporarilySelectedDeck)) {
                            return rv; //if the provided deckID is wrong, return empty cursor.
                        }
                    }
                } catch (NumberFormatException nfe) {
                    nfe.printStackTrace();
                }
            }
        }

        //retrieve the number of cards provided by the selection parameter "limit"
        col.getSched().reset();
        for (int k = 0; k < limit; k++) {
            Card currentCard = col.getSched().getCard();

            if (currentCard != null) {
                int buttonCount = col.getSched().answerButtons(currentCard);
                JSONArray buttonTexts = new JSONArray();
                for (int i = 0; i < buttonCount; i++) {
                    buttonTexts.put(col.getSched().nextIvlStr(getContext(), currentCard, i + 1));
                }
                addReviewInfoToCursor(currentCard, buttonTexts, buttonCount, rv, col, columns);
            } else {
                break;
            }
        }

        if (deckIdOfTemporarilySelectedDeck != -1) {//if the selected deck was changed
            //change the selected deck back to the one it was before the query
            col.getDecks().select(selectedDeckBeforeQuery);
        }
        return rv;
    }
    case DECKS: {
        List<Sched.DeckDueTreeNode> allDecks = col.getSched().deckDueList();
        String[] columns = ((projection != null) ? projection : FlashCardsContract.Deck.DEFAULT_PROJECTION);
        MatrixCursor rv = new MatrixCursor(columns, allDecks.size());
        for (Sched.DeckDueTreeNode deck : allDecks) {
            long id = deck.did;
            String name = deck.names[0];

            addDeckToCursor(id, name, getDeckCountsFromDueTreeNode(deck), rv, col, columns);
        }
        return rv;
    }
    case DECKS_ID: {
        /* Direct access deck
         */
        String[] columns = ((projection != null) ? projection : FlashCardsContract.Deck.DEFAULT_PROJECTION);
        MatrixCursor rv = new MatrixCursor(columns, 1);
        List<Sched.DeckDueTreeNode> allDecks = col.getSched().deckDueList();
        long deckId;
        deckId = Long.parseLong(uri.getPathSegments().get(1));
        for (Sched.DeckDueTreeNode deck : allDecks) {
            if (deck.did == deckId) {
                addDeckToCursor(deckId, deck.names[0], getDeckCountsFromDueTreeNode(deck), rv, col, columns);
                return rv;
            }
        }

        return rv;
    }
    case DECK_SELECTED: {

        long id = col.getDecks().selected();
        String name = col.getDecks().name(id);
        String[] columns = ((projection != null) ? projection : FlashCardsContract.Deck.DEFAULT_PROJECTION);
        MatrixCursor rv = new MatrixCursor(columns, 1);
        JSONArray counts = new JSONArray(Arrays.asList(col.getSched().counts()));
        addDeckToCursor(id, name, counts, rv, col, columns);
        return rv;
    }
    default:
        // Unknown URI type
        throw new IllegalArgumentException("uri " + uri + " is not supported");
    }
}

From source file:com.irccloud.android.activity.MainActivity.java

private boolean open_uri(Uri uri) {
    if (uri != null && conn != null && conn.ready) {
        launchURI = null;// www. java2 s  .  c  o m
        ServersDataSource.Server s = null;
        try {
            if (uri.getHost().equals("cid")) {
                s = ServersDataSource.getInstance().getServer(Integer.parseInt(uri.getPathSegments().get(0)));
            }
        } catch (NumberFormatException e) {

        }
        if (s == null) {
            if (uri.getPort() > 0)
                s = ServersDataSource.getInstance().getServer(uri.getHost(), uri.getPort());
            else if (uri.getScheme() != null && uri.getScheme().equalsIgnoreCase("ircs"))
                s = ServersDataSource.getInstance().getServer(uri.getHost(), true);
            else
                s = ServersDataSource.getInstance().getServer(uri.getHost());
        }

        if (s != null) {
            if (uri.getPath() != null && uri.getPath().length() > 1) {
                String key = null;
                String channel = uri.getLastPathSegment();
                if (channel.contains(",")) {
                    key = channel.substring(channel.indexOf(",") + 1);
                    channel = channel.substring(0, channel.indexOf(","));
                }
                BuffersDataSource.Buffer b = BuffersDataSource.getInstance().getBufferByName(s.cid, channel);
                if (b != null) {
                    server = null;
                    return open_bid(b.bid);
                } else {
                    onBufferSelected(-1);
                    title.setText(channel);
                    getSupportActionBar().setTitle(channel);
                    bufferToOpen = channel;
                    conn.join(s.cid, channel, key);
                }
                return true;
            } else {
                BuffersDataSource.Buffer b = BuffersDataSource.getInstance().getBufferByName(s.cid, "*");
                if (b != null)
                    return open_bid(b.bid);
            }
        } else {
            if (!getResources().getBoolean(R.bool.isTablet)) {
                Intent i = new Intent(this, EditConnectionActivity.class);
                i.putExtra("hostname", uri.getHost());
                if (uri.getPort() > 0)
                    i.putExtra("port", uri.getPort());
                else if (uri.getScheme().equalsIgnoreCase("ircs"))
                    i.putExtra("port", 6697);
                if (uri.getPath() != null && uri.getPath().length() > 1)
                    i.putExtra("channels", uri.getPath().substring(1).replace(",", " "));
                startActivity(i);
            } else {
                EditConnectionFragment connFragment = new EditConnectionFragment();
                connFragment.default_hostname = uri.getHost();
                if (uri.getPort() > 0)
                    connFragment.default_port = uri.getPort();
                else if (uri.getScheme().equalsIgnoreCase("ircs"))
                    connFragment.default_port = 6697;
                if (uri.getPath() != null && uri.getPath().length() > 1)
                    connFragment.default_channels = uri.getPath().substring(1).replace(",", " ");
                connFragment.show(getSupportFragmentManager(), "addnetwork");
            }
            return true;
        }
    }
    return false;
}

From source file:org.kde.kdeconnect.Plugins.SharePlugin.SharePlugin.java

@Override
public boolean onPackageReceived(NetworkPackage np) {

    try {//from   ww w. j  a va 2s  .  co  m
        if (np.hasPayload()) {

            Log.i("SharePlugin", "hasPayload");

            final InputStream input = np.getPayload();
            final long fileLength = np.getPayloadSize();
            final String originalFilename = np.getString("filename", Long.toString(System.currentTimeMillis()));

            //We need to check for already existing files only when storing in the default path.
            //User-defined paths use the new Storage Access Framework that already handles this.
            final boolean customDestination = ShareSettingsActivity.isCustomDestinationEnabled(context);
            final String defaultPath = ShareSettingsActivity.getDefaultDestinationDirectory().getAbsolutePath();
            final String filename = customDestination ? originalFilename
                    : FilesHelper.findNonExistingNameForNewFile(defaultPath, originalFilename);

            String displayName = FilesHelper.getFileNameWithoutExt(filename);
            final String mimeType = FilesHelper.getMimeTypeFromFile(filename);

            if ("*/*".equals(mimeType)) {
                displayName = filename;
            }

            final DocumentFile destinationFolderDocument = ShareSettingsActivity
                    .getDestinationDirectory(context);
            final DocumentFile destinationDocument = destinationFolderDocument.createFile(mimeType,
                    displayName);
            final OutputStream destinationOutput = context.getContentResolver()
                    .openOutputStream(destinationDocument.getUri());
            final Uri destinationUri = destinationDocument.getUri();

            final int notificationId = (int) System.currentTimeMillis();
            Resources res = context.getResources();
            final NotificationCompat.Builder builder = new NotificationCompat.Builder(context)
                    .setContentTitle(res.getString(R.string.incoming_file_title, device.getName()))
                    .setContentText(res.getString(R.string.incoming_file_text, filename))
                    .setTicker(res.getString(R.string.incoming_file_title, device.getName()))
                    .setSmallIcon(android.R.drawable.stat_sys_download).setAutoCancel(true).setOngoing(true)
                    .setProgress(100, 0, true);

            final NotificationManager notificationManager = (NotificationManager) context
                    .getSystemService(Context.NOTIFICATION_SERVICE);
            NotificationHelper.notifyCompat(notificationManager, notificationId, builder.build());

            new Thread(new Runnable() {
                @Override
                public void run() {
                    boolean successful = true;
                    try {
                        byte data[] = new byte[1024];
                        long progress = 0, prevProgressPercentage = 0;
                        int count;
                        while ((count = input.read(data)) >= 0) {
                            progress += count;
                            destinationOutput.write(data, 0, count);
                            if (fileLength > 0) {
                                if (progress >= fileLength)
                                    break;
                                long progressPercentage = (progress * 100 / fileLength);
                                if (progressPercentage != prevProgressPercentage) {
                                    prevProgressPercentage = progressPercentage;
                                    builder.setProgress(100, (int) progressPercentage, false);
                                    NotificationHelper.notifyCompat(notificationManager, notificationId,
                                            builder.build());
                                }
                            }
                            //else Log.e("SharePlugin", "Infinite loop? :D");
                        }

                        destinationOutput.flush();

                    } catch (Exception e) {
                        successful = false;
                        Log.e("SharePlugin", "Receiver thread exception");
                        e.printStackTrace();
                    } finally {
                        try {
                            destinationOutput.close();
                        } catch (Exception e) {
                        }
                        try {
                            input.close();
                        } catch (Exception e) {
                        }
                    }

                    try {
                        Log.i("SharePlugin", "Transfer finished: " + destinationUri.getPath());

                        //Update the notification and allow to open the file from it
                        Resources res = context.getResources();
                        String message = successful
                                ? res.getString(R.string.received_file_title, device.getName())
                                : res.getString(R.string.received_file_fail_title, device.getName());
                        NotificationCompat.Builder builder = new NotificationCompat.Builder(context)
                                .setContentTitle(message).setTicker(message)
                                .setSmallIcon(android.R.drawable.stat_sys_download_done).setAutoCancel(true);
                        if (successful) {
                            Intent intent = new Intent(Intent.ACTION_VIEW);
                            intent.setDataAndType(destinationUri, mimeType);
                            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                            TaskStackBuilder stackBuilder = TaskStackBuilder.create(context);
                            stackBuilder.addNextIntent(intent);
                            PendingIntent resultPendingIntent = stackBuilder.getPendingIntent(0,
                                    PendingIntent.FLAG_UPDATE_CURRENT);
                            builder.setContentText(
                                    res.getString(R.string.received_file_text, destinationDocument.getName()))
                                    .setContentIntent(resultPendingIntent);
                        }
                        SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
                        if (prefs.getBoolean("share_notification_preference", true)) {
                            builder.setDefaults(Notification.DEFAULT_ALL);
                        }
                        NotificationHelper.notifyCompat(notificationManager, notificationId, builder.build());

                        if (successful) {
                            if (!customDestination && Build.VERSION.SDK_INT >= 12) {
                                Log.i("SharePlugin", "Adding to downloads");
                                DownloadManager manager = (DownloadManager) context
                                        .getSystemService(Context.DOWNLOAD_SERVICE);
                                manager.addCompletedDownload(destinationUri.getLastPathSegment(),
                                        device.getName(), true, mimeType, destinationUri.getPath(), fileLength,
                                        false);
                            } else {
                                //Make sure it is added to the Android Gallery anyway
                                MediaStoreHelper.indexFile(context, destinationUri);
                            }
                        }

                    } catch (Exception e) {
                        Log.e("SharePlugin", "Receiver thread exception");
                        e.printStackTrace();
                    }
                }
            }).start();

        } else if (np.has("text")) {
            Log.i("SharePlugin", "hasText");

            String text = np.getString("text");
            if (Build.VERSION.SDK_INT >= 11) {
                ClipboardManager cm = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
                cm.setText(text);
            } else {
                android.text.ClipboardManager clipboard = (android.text.ClipboardManager) context
                        .getSystemService(Context.CLIPBOARD_SERVICE);
                clipboard.setText(text);
            }
            Toast.makeText(context, R.string.shareplugin_text_saved, Toast.LENGTH_LONG).show();
        } else if (np.has("url")) {

            String url = np.getString("url");

            Log.i("SharePlugin", "hasUrl: " + url);

            Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
            browserIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

            if (openUrlsDirectly) {
                context.startActivity(browserIntent);
            } else {
                Resources res = context.getResources();
                TaskStackBuilder stackBuilder = TaskStackBuilder.create(context);
                stackBuilder.addNextIntent(browserIntent);
                PendingIntent resultPendingIntent = stackBuilder.getPendingIntent(0,
                        PendingIntent.FLAG_UPDATE_CURRENT);

                Notification noti = new NotificationCompat.Builder(context)
                        .setContentTitle(res.getString(R.string.received_url_title, device.getName()))
                        .setContentText(res.getString(R.string.received_url_text, url))
                        .setContentIntent(resultPendingIntent)
                        .setTicker(res.getString(R.string.received_url_title, device.getName()))
                        .setSmallIcon(R.drawable.ic_notification).setAutoCancel(true)
                        .setDefaults(Notification.DEFAULT_ALL).build();

                NotificationManager notificationManager = (NotificationManager) context
                        .getSystemService(Context.NOTIFICATION_SERVICE);
                NotificationHelper.notifyCompat(notificationManager, (int) System.currentTimeMillis(), noti);
            }
        } else {
            Log.e("SharePlugin", "Error: Nothing attached!");
        }

    } catch (Exception e) {
        Log.e("SharePlugin", "Exception");
        e.printStackTrace();
    }

    return true;
}

From source file:com.ichi2.anki.provider.CardContentProvider.java

@Override
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
    Timber.d("CardContentProvider.update");
    Collection col = CollectionHelper.getInstance().getCol(getContext());
    if (col == null) {
        return 0;
    }//from  w ww .j  a  va 2  s .c  om

    // Find out what data the user is requesting
    int match = sUriMatcher.match(uri);

    int updated = 0; // Number of updated entries (return value)
    switch (match) {
    case NOTES:
        throw new IllegalArgumentException("Not possible to update notes directly (only through data URI)");
    case NOTES_ID: {
        /* Direct access note details
         */
        Note currentNote = getNoteFromUri(uri, col);
        // the key of the ContentValues contains the column name
        // the value of the ContentValues contains the row value.
        Set<Map.Entry<String, Object>> valueSet = values.valueSet();
        for (Map.Entry<String, Object> entry : valueSet) {
            String key = entry.getKey();
            if (key.equals(FlashCardsContract.Note.FLDS)) {
                // Update FLDS
                Timber.d("CardContentProvider: flds update...");
                String newFldsEncoded = (String) entry.getValue();
                String[] flds = Utils.splitFields(newFldsEncoded);
                // Check that correct number of flds specified
                if (flds.length != currentNote.getFields().length) {
                    throw new IllegalArgumentException("Incorrect flds argument : " + newFldsEncoded);
                }
                // Update the note
                for (int idx = 0; idx < flds.length; idx++) {
                    currentNote.setField(idx, flds[idx]);
                }
                updated++;
            } else if (key.equals(FlashCardsContract.Note.TAGS)) {
                // Update tags
                Timber.d("CardContentProvider: tags update...");
                currentNote.setTagsFromStr((String) entry.getValue());
                updated++;
            } else {
                // Unsupported column
                throw new IllegalArgumentException("Unsupported column: " + key);
            }
        }
        Timber.d("CardContentProvider: Saving note...");
        currentNote.flush();
        break;
    }
    case NOTES_ID_CARDS:
        // TODO: To be implemented
        throw new UnsupportedOperationException("Not yet implemented");
        //                break;
    case NOTES_ID_CARDS_ORD: {
        Card currentCard = getCardFromUri(uri, col);
        boolean isDeckUpdate = false;
        long did = -1;
        // the key of the ContentValues contains the column name
        // the value of the ContentValues contains the row value.
        Set<Map.Entry<String, Object>> valueSet = values.valueSet();
        for (Map.Entry<String, Object> entry : valueSet) {
            // Only updates on deck id is supported
            String key = entry.getKey();
            isDeckUpdate = key.equals(FlashCardsContract.Card.DECK_ID);
            did = values.getAsLong(key);
        }

        /* now update the card
         */
        if ((isDeckUpdate) && (did >= 0)) {
            Timber.d("CardContentProvider: Moving card to other deck...");
            col.getDecks().flush();
            currentCard.setDid(did);
            currentCard.flush();
            updated++;
        } else {
            // User tries an operation that is not (yet?) supported.
            throw new IllegalArgumentException("Currently only updates of decks are supported");
        }
        break;
    }
    case MODELS:
        throw new IllegalArgumentException("Cannot update models in bulk");
    case MODELS_ID:
        // Get the input parameters
        String newModelName = values.getAsString(FlashCardsContract.Model.NAME);
        String newCss = values.getAsString(FlashCardsContract.Model.CSS);
        String newDid = values.getAsString(FlashCardsContract.Model.DECK_ID);
        String newFieldList = values.getAsString(FlashCardsContract.Model.FIELD_NAMES);
        if (newFieldList != null) {
            // Changing the field names would require a full-sync
            throw new IllegalArgumentException("Field names cannot be changed via provider");
        }
        // Get the original note JSON
        JSONObject model = col.getModels().get(getModelIdFromUri(uri, col));
        try {
            // Update model name and/or css
            if (newModelName != null) {
                model.put("name", newModelName);
                updated++;
            }
            if (newCss != null) {
                model.put("css", newCss);
                updated++;
            }
            if (newDid != null) {
                model.put("did", newDid);
                updated++;
            }
            col.getModels().save(model);
        } catch (JSONException e) {
            Timber.e(e, "JSONException updating model");
        }
        break;
    case MODELS_ID_TEMPLATES:
        throw new IllegalArgumentException("Cannot update templates in bulk");
    case MODELS_ID_TEMPLATES_ID:
        Long mid = values.getAsLong(CardTemplate.MODEL_ID);
        Integer ord = values.getAsInteger(CardTemplate.ORD);
        String name = values.getAsString(CardTemplate.NAME);
        String qfmt = values.getAsString(CardTemplate.QUESTION_FORMAT);
        String afmt = values.getAsString(CardTemplate.ANSWER_FORMAT);
        String bqfmt = values.getAsString(CardTemplate.BROWSER_QUESTION_FORMAT);
        String bafmt = values.getAsString(CardTemplate.BROWSER_ANSWER_FORMAT);
        // Throw exception if read-only fields are included
        if (mid != null || ord != null) {
            throw new IllegalArgumentException("Can update mid or ord");
        }
        // Update the model
        try {
            Integer templateOrd = Integer.parseInt(uri.getLastPathSegment());
            JSONObject existingModel = col.getModels().get(getModelIdFromUri(uri, col));
            JSONArray templates = existingModel.getJSONArray("tmpls");
            JSONObject template = templates.getJSONObject(templateOrd);
            if (name != null) {
                template.put("name", name);
                updated++;
            }
            if (qfmt != null) {
                template.put("qfmt", qfmt);
                updated++;
            }
            if (afmt != null) {
                template.put("afmt", afmt);
                updated++;
            }
            if (bqfmt != null) {
                template.put("bqfmt", bqfmt);
                updated++;
            }
            if (bafmt != null) {
                template.put("bafmt", bafmt);
                updated++;
            }
            // Save the model
            templates.put(templateOrd, template);
            existingModel.put("tmpls", templates);
            col.getModels().save(existingModel, true);
        } catch (JSONException e) {
            throw new IllegalArgumentException("Model is malformed", e);
        }
        break;
    case SCHEDULE: {
        Set<Map.Entry<String, Object>> valueSet = values.valueSet();
        int cardOrd = -1;
        long noteID = -1;
        int ease = -1;
        long timeTaken = -1;
        for (Map.Entry<String, Object> entry : valueSet) {
            String key = entry.getKey();

            if (key.equals(FlashCardsContract.ReviewInfo.NOTE_ID)) {
                noteID = values.getAsLong(key);
            } else if (key.equals(FlashCardsContract.ReviewInfo.CARD_ORD)) {
                cardOrd = values.getAsInteger(key);
            } else if (key.equals(FlashCardsContract.ReviewInfo.EASE)) {
                ease = values.getAsInteger(key);
            } else if (key.equals(FlashCardsContract.ReviewInfo.TIME_TAKEN)) {
                timeTaken = values.getAsLong(key);
            }
        }
        if (cardOrd != -1 && noteID != -1) {
            Card cardToAnswer = getCard(noteID, cardOrd, col);
            if (cardToAnswer != null) {
                answerCard(col, col.getSched(), cardToAnswer, ease, timeTaken);
                updated++;
            } else {
                Timber.e(
                        "Requested card with noteId %d and cardOrd %d was not found. Either the provided "
                                + "noteId/cardOrd were wrong or the card has been deleted in the meantime.",
                        noteID, cardOrd);
            }
        }
        break;
    }
    case DECKS:
        throw new IllegalArgumentException("Can't update decks in bulk");
    case DECKS_ID:
        throw new UnsupportedOperationException("Not yet implemented");
    case DECK_SELECTED: {
        Set<Map.Entry<String, Object>> valueSet = values.valueSet();
        for (Map.Entry<String, Object> entry : valueSet) {
            String key = entry.getKey();
            if (key.equals(FlashCardsContract.Deck.DECK_ID)) {
                long deckId = values.getAsLong(key);
                if (selectDeckWithCheck(col, deckId)) {
                    updated++;
                }
            }
        }
        break;
    }
    default:
        // Unknown URI type
        throw new IllegalArgumentException("uri " + uri + " is not supported");
    }
    return updated;
}