Example usage for android.content ContentValues get

List of usage examples for android.content ContentValues get

Introduction

In this page you can find the example usage for android.content ContentValues get.

Prototype

public Object get(String key) 

Source Link

Document

Gets a value.

Usage

From source file:org.opendatakit.services.database.utilities.ODKDatabaseImplUtils.java

/**
 * Insert the given rowId with the values in the cvValues. If certain metadata
 * values are not specified in the cvValues, then suitable default values may
 * be supplied for them./*from   w w w  . java 2  s . c o  m*/
 * <p/>
 * If a row with this rowId and certain matching metadata fields is present,
 * then an exception is thrown.
 *
 * @param db
 * @param tableId
 * @param orderedColumns
 * @param cvValues
 * @param rowId
 * @param activeUser
 * @param rolesList
 * @param locale
 */
public void insertRowWithId(OdkConnectionInterface db, String tableId, OrderedColumns orderedColumns,
        ContentValues cvValues, String rowId, String activeUser, String rolesList, String locale)
        throws ActionNotAuthorizedException {

    if (cvValues == null) {
        throw new IllegalArgumentException(t + ": No values to add into table " + tableId);
    }

    HashMap<String, Object> cvDataTableVal = new HashMap<String, Object>();
    cvDataTableVal.put(DataTableColumns.ID, rowId);
    for (String key : cvValues.keySet()) {
        cvDataTableVal.put(key, cvValues.get(key));
    }

    upsertDataIntoExistingTable(db, tableId, orderedColumns, cvDataTableVal, false, false, activeUser,
            rolesList, locale, false);
}

From source file:org.opendatakit.services.database.utilities.ODKDatabaseImplUtils.java

/**
 * Insert the given rowId with the values in the cvValues. All metadata field
 * values must be specified in the cvValues. This is called from Sync for inserting
 * a row verbatim from the server.//from w  w  w .  j  a v  a2s . c  o m
 * <p/>
 * If a row with this rowId is present, then an exception is thrown.
 *
 * @param db
 * @param tableId
 * @param orderedColumns
 * @param cvValues
 * @param rowId
 * @param activeUser
 * @param locale
 * @param asCsvRequestedChange
 */
public void privilegedInsertRowWithId(OdkConnectionInterface db, String tableId, OrderedColumns orderedColumns,
        ContentValues cvValues, String rowId, String activeUser, String locale, boolean asCsvRequestedChange) {

    String rolesList = RoleConsts.ADMIN_ROLES_LIST;

    if (cvValues == null || cvValues.size() <= 0) {
        throw new IllegalArgumentException(t + ": No values to add into table " + tableId);
    }

    HashMap<String, Object> cvDataTableVal = new HashMap<String, Object>();
    cvDataTableVal.put(DataTableColumns.ID, rowId);
    for (String key : cvValues.keySet()) {
        cvDataTableVal.put(key, cvValues.get(key));
    }

    // TODO: verify that all fields are specified
    try {
        upsertDataIntoExistingTable(db, tableId, orderedColumns, cvDataTableVal, false, true, activeUser,
                rolesList, locale, asCsvRequestedChange);
    } catch (ActionNotAuthorizedException e) {
        WebLogger.getLogger(db.getAppName()).printStackTrace(e);
        throw new IllegalStateException(e);
    }
}

From source file:org.opendatakit.services.database.utilities.ODKDatabaseImplUtils.java

/**
 * Update the given rowId with the values in the cvValues. If certain metadata
 * values are not specified in the cvValues, then suitable default values may
 * be supplied for them. Furthermore, if the cvValues do not specify certain
 * metadata fields, then an exception may be thrown if there are more than one
 * row matching this rowId.//ww w  .  j  a v a  2  s. c om
 *
 * @param db
 * @param tableId
 * @param orderedColumns
 * @param cvValues
 * @param rowId
 * @param activeUser
 * @param rolesList
 * @param locale
 */
public void updateRowWithId(OdkConnectionInterface db, String tableId, OrderedColumns orderedColumns,
        ContentValues cvValues, String rowId, String activeUser, String rolesList, String locale)
        throws ActionNotAuthorizedException {

    // TODO: make sure caller passes in the correct roleList for the use case.
    // TODO: for multi-step sync actions, we probably need an internal variant of this.

    if (cvValues.size() <= 0) {
        throw new IllegalArgumentException(t + ": No values to add into table " + tableId);
    }

    HashMap<String, Object> cvDataTableVal = new HashMap<String, Object>();
    cvDataTableVal.put(DataTableColumns.ID, rowId);
    for (String key : cvValues.keySet()) {
        cvDataTableVal.put(key, cvValues.get(key));
    }

    upsertDataIntoExistingTable(db, tableId, orderedColumns, cvDataTableVal, true, false, activeUser, rolesList,
            locale, false);
}

From source file:org.opendatakit.services.database.utilities.ODKDatabaseImplUtils.java

/**
 * Update the given rowId with the values in the cvValues. All field
 * values are specified in the cvValues. This is a server-induced update
 * of the row to match all fields from the server. An error is thrown if
 * there isn't a row matching this rowId or if there are checkpoint or
 * conflict entries for this rowId./*from  www  . j  a  v a2 s  .c  o m*/
 *
 * @param db
 * @param tableId
 * @param orderedColumns
 * @param cvValues
 * @param rowId
 * @param activeUser
 * @param locale
 * @param asCsvRequestedChange
 */
private void privilegedUpdateRowWithId(OdkConnectionInterface db, String tableId, OrderedColumns orderedColumns,
        ContentValues cvValues, String rowId, String activeUser, String locale, boolean asCsvRequestedChange) {

    // TODO: make sure caller passes in the correct roleList for the use case.
    // TODO: for multi-step sync actions, we probably need an internal variant of this.

    String rolesList = RoleConsts.ADMIN_ROLES_LIST;

    if (cvValues.size() <= 0) {
        throw new IllegalArgumentException(t + ": No values to add into table " + tableId);
    }

    HashMap<String, Object> cvDataTableVal = new HashMap<String, Object>();
    cvDataTableVal.put(DataTableColumns.ID, rowId);
    for (String key : cvValues.keySet()) {
        cvDataTableVal.put(key, cvValues.get(key));
    }

    try {
        upsertDataIntoExistingTable(db, tableId, orderedColumns, cvDataTableVal, true, true, activeUser,
                rolesList, locale, asCsvRequestedChange);
    } catch (ActionNotAuthorizedException e) {
        WebLogger.getLogger(db.getAppName()).printStackTrace(e);
        throw new IllegalStateException(e);
    }
}

From source file:org.opendatakit.services.database.utlities.ODKDatabaseImplUtils.java

/**
 * Inserts a checkpoint row for the given rowId in the tableId. Checkpoint
 * rows are created by ODK Survey to hold intermediate values during the
 * filling-in of the form. They act as restore points in the Survey, should
 * the application die./*  www .  java 2s.  c o  m*/
 *
 * @param db
 * @param tableId
 * @param orderedColumns
 * @param cvValues
 * @param rowId
 * @param activeUser
 * @param rolesList
 * @param locale
 */
public void insertCheckpointRowWithId(OdkConnectionInterface db, String tableId, OrderedColumns orderedColumns,
        ContentValues cvValues, String rowId, String activeUser, String rolesList, String locale)
        throws ActionNotAuthorizedException {

    if (cvValues.size() <= 0) {
        throw new IllegalArgumentException(t + ": No values to add into table for checkpoint" + tableId);
    }

    // these are all managed in the database layer...
    // the user should NOT set them...

    if (cvValues.containsKey(DataTableColumns.SAVEPOINT_TIMESTAMP)) {
        throw new IllegalArgumentException(
                t + ": No user supplied savepoint timestamp can be included for a checkpoint");
    }

    if (cvValues.containsKey(DataTableColumns.SAVEPOINT_TYPE)) {
        throw new IllegalArgumentException(
                t + ": No user supplied savepoint type can be included for a checkpoint");
    }

    if (cvValues.containsKey(DataTableColumns.ROW_ETAG)) {
        throw new IllegalArgumentException(t + ": No user supplied row ETag can be included for a checkpoint");
    }

    if (cvValues.containsKey(DataTableColumns.SYNC_STATE)) {
        throw new IllegalArgumentException(
                t + ": No user supplied sync state can be included for a checkpoint");
    }

    if (cvValues.containsKey(DataTableColumns.CONFLICT_TYPE)) {
        throw new IllegalArgumentException(
                t + ": No user supplied conflict type can be included for a checkpoint");
    }

    if (cvValues.containsKey(DataTableColumns.FILTER_VALUE)) {
        throw new IllegalArgumentException(
                t + ": No user supplied filter value can be included for a checkpoint");
    }

    if (cvValues.containsKey(DataTableColumns.FILTER_TYPE)) {
        throw new IllegalArgumentException(
                t + ": No user supplied filter type can be included for a checkpoint");
    }

    // If a rowId is specified, a cursor will be needed to
    // get the current row to create a checkpoint with the relevant data
    Cursor c = null;
    try {
        // Allow the user to pass in no rowId if this is the first
        // checkpoint row that the user is adding
        if (rowId == null) {

            // TODO: is this even valid any more? I think we disallow this in the AIDL flow.

            String rowIdToUse = LocalizationUtils.genUUID();
            HashMap<String, Object> currValues = new HashMap<String, Object>();
            for (String key : cvValues.keySet()) {
                currValues.put(key, cvValues.get(key));
            }
            currValues.put(DataTableColumns._ID, rowIdToUse);
            currValues.put(DataTableColumns.SYNC_STATE, SyncState.new_row.name());
            insertCheckpointIntoExistingTable(db, tableId, orderedColumns, currValues, activeUser, rolesList,
                    locale, true, null, null);
            return;
        }

        StringBuilder b = new StringBuilder();
        b.append(K_DATATABLE_ID_EQUALS_PARAM).append(S_AND).append(DataTableColumns.SAVEPOINT_TIMESTAMP)
                .append(" IN (SELECT MAX(").append(DataTableColumns.SAVEPOINT_TIMESTAMP).append(") FROM ")
                .append(tableId).append(K_WHERE).append(K_DATATABLE_ID_EQUALS_PARAM).append(")");
        c = db.query(tableId, null, b.toString(), new Object[] { rowId, rowId }, null, null, null, null);
        c.moveToFirst();

        if (c.getCount() > 1) {
            throw new IllegalStateException(t + ": More than one checkpoint at a timestamp");
        }

        // Inserting a checkpoint for the first time
        if (c.getCount() <= 0) {
            HashMap<String, Object> currValues = new HashMap<String, Object>();
            for (String key : cvValues.keySet()) {
                currValues.put(key, cvValues.get(key));
            }
            currValues.put(DataTableColumns._ID, rowId);
            currValues.put(DataTableColumns.SYNC_STATE, SyncState.new_row.name());
            insertCheckpointIntoExistingTable(db, tableId, orderedColumns, currValues, activeUser, rolesList,
                    locale, true, null, null);
            return;
        } else {
            // Make sure that the conflict_type of any existing row
            // is null, otherwise throw an exception
            int conflictIndex = c.getColumnIndex(DataTableColumns.CONFLICT_TYPE);
            if (!c.isNull(conflictIndex)) {
                throw new IllegalStateException(
                        t + ":  A checkpoint cannot be added for a row that is in conflict");
            }

            HashMap<String, Object> currValues = new HashMap<String, Object>();
            for (String key : cvValues.keySet()) {
                currValues.put(key, cvValues.get(key));
            }

            // This is unnecessary
            // We should only have one row at this point
            //c.moveToFirst();

            String priorFilterType = null;
            String priorFilterValue = null;

            // Get the number of columns to iterate over and add
            // those values to the content values
            for (int i = 0; i < c.getColumnCount(); i++) {
                String name = c.getColumnName(i);

                if (currValues.containsKey(name)) {
                    continue;
                }

                // omitting savepoint timestamp will generate a new timestamp.
                if (name.equals(DataTableColumns.SAVEPOINT_TIMESTAMP)) {
                    continue;
                }

                // set savepoint type to null to mark this as a checkpoint
                if (name.equals(DataTableColumns.SAVEPOINT_TYPE)) {
                    currValues.put(name, null);
                    continue;
                }

                // sync state (a non-null field) should either remain 'new_row'
                // or be set to 'changed' for all other existing values.
                if (name.equals(DataTableColumns.SYNC_STATE)) {
                    String priorState = c.getString(i);
                    if (priorState.equals(SyncState.new_row.name())) {
                        currValues.put(name, SyncState.new_row.name());
                    } else {
                        currValues.put(name, SyncState.changed.name());
                    }
                    continue;
                }

                if (c.isNull(i)) {
                    currValues.put(name, null);
                    continue;
                }

                // otherwise, just copy the values over...
                Class<?> theClass = CursorUtils.getIndexDataType(c, i);
                Object object = CursorUtils.getIndexAsType(c, theClass, i);
                insertValueIntoContentValues(currValues, theClass, name, object);

                if (name.equals(DataTableColumns.FILTER_TYPE)) {
                    priorFilterType = c.getString(i);
                }

                if (name.equals(DataTableColumns.FILTER_VALUE)) {
                    priorFilterValue = c.getString(i);
                }
            }

            insertCheckpointIntoExistingTable(db, tableId, orderedColumns, currValues, activeUser, rolesList,
                    locale, false, priorFilterType, priorFilterValue);
        }
    } finally {
        if (c != null && !c.isClosed()) {
            c.close();
        }
    }
}

From source file:org.opendatakit.services.database.utilities.ODKDatabaseImplUtils.java

/**
 * Inserts a checkpoint row for the given rowId in the tableId. Checkpoint
 * rows are created by ODK Survey to hold intermediate values during the
 * filling-in of the form. They act as restore points in the Survey, should
 * the application die./*from   w w  w . ja  v  a  2  s.c  om*/
 *
 * @param db
 * @param tableId
 * @param orderedColumns
 * @param cvValues
 * @param rowId
 * @param activeUser
 * @param rolesList
 * @param locale
 */
public void insertCheckpointRowWithId(OdkConnectionInterface db, String tableId, OrderedColumns orderedColumns,
        ContentValues cvValues, String rowId, String activeUser, String rolesList, String locale)
        throws ActionNotAuthorizedException {

    if (cvValues.size() <= 0) {
        throw new IllegalArgumentException(t + ": No values to add into table for checkpoint" + tableId);
    }

    // these are all managed in the database layer...
    // the user should NOT set them...

    if (cvValues.containsKey(DataTableColumns.SAVEPOINT_TIMESTAMP)) {
        throw new IllegalArgumentException(
                t + ": No user supplied savepoint timestamp can be included for a checkpoint");
    }

    if (cvValues.containsKey(DataTableColumns.SAVEPOINT_TYPE)) {
        throw new IllegalArgumentException(
                t + ": No user supplied savepoint type can be included for a checkpoint");
    }

    if (cvValues.containsKey(DataTableColumns.ROW_ETAG)) {
        throw new IllegalArgumentException(t + ": No user supplied row ETag can be included for a checkpoint");
    }

    if (cvValues.containsKey(DataTableColumns.SYNC_STATE)) {
        throw new IllegalArgumentException(
                t + ": No user supplied sync state can be included for a checkpoint");
    }

    if (cvValues.containsKey(DataTableColumns.CONFLICT_TYPE)) {
        throw new IllegalArgumentException(
                t + ": No user supplied conflict type can be included for a checkpoint");
    }

    // If a rowId is specified, a cursor will be needed to
    // get the current row to create a checkpoint with the relevant data
    Cursor c = null;
    try {
        // Allow the user to pass in no rowId if this is the first
        // checkpoint row that the user is adding
        if (rowId == null) {

            // TODO: is this even valid any more? I think we disallow this in the AIDL flow.

            String rowIdToUse = LocalizationUtils.genUUID();
            HashMap<String, Object> currValues = new HashMap<String, Object>();
            for (String key : cvValues.keySet()) {
                currValues.put(key, cvValues.get(key));
            }
            currValues.put(DataTableColumns._ID, rowIdToUse);
            currValues.put(DataTableColumns.SYNC_STATE, SyncState.new_row.name());
            insertCheckpointIntoExistingTable(db, tableId, orderedColumns, currValues, activeUser, rolesList,
                    locale, true, null, null, null, null, null);
            return;
        }

        StringBuilder b = new StringBuilder();
        b.append(K_DATATABLE_ID_EQUALS_PARAM).append(S_AND).append(DataTableColumns.SAVEPOINT_TIMESTAMP)
                .append(" IN (SELECT MAX(").append(DataTableColumns.SAVEPOINT_TIMESTAMP).append(") FROM ")
                .append(tableId).append(K_WHERE).append(K_DATATABLE_ID_EQUALS_PARAM).append(")");
        c = db.query(tableId, null, b.toString(), new Object[] { rowId, rowId }, null, null, null, null);
        c.moveToFirst();

        if (c.getCount() > 1) {
            throw new IllegalStateException(t + ": More than one checkpoint at a timestamp");
        }

        // Inserting a checkpoint for the first time
        if (c.getCount() <= 0) {
            HashMap<String, Object> currValues = new HashMap<String, Object>();
            for (String key : cvValues.keySet()) {
                currValues.put(key, cvValues.get(key));
            }
            currValues.put(DataTableColumns._ID, rowId);
            currValues.put(DataTableColumns.SYNC_STATE, SyncState.new_row.name());
            insertCheckpointIntoExistingTable(db, tableId, orderedColumns, currValues, activeUser, rolesList,
                    locale, true, null, null, null, null, null);
            return;
        } else {
            // Make sure that the conflict_type of any existing row
            // is null, otherwise throw an exception
            int conflictIndex = c.getColumnIndex(DataTableColumns.CONFLICT_TYPE);
            if (!c.isNull(conflictIndex)) {
                throw new IllegalStateException(
                        t + ":  A checkpoint cannot be added for a row that is in conflict");
            }

            // these are all managed in the database layer...
            // the user should NOT set them...

            if (cvValues.containsKey(DataTableColumns.DEFAULT_ACCESS)) {
                throw new IllegalArgumentException(
                        t + ": No user supplied default access can be included for a checkpoint");
            }

            if (cvValues.containsKey(DataTableColumns.ROW_OWNER)) {
                throw new IllegalArgumentException(
                        t + ": No user supplied row owner can be included for a checkpoint");
            }

            if (cvValues.containsKey(DataTableColumns.GROUP_READ_ONLY)) {
                throw new IllegalArgumentException(
                        t + ": No user supplied group read only can be included for a checkpoint");
            }

            if (cvValues.containsKey(DataTableColumns.GROUP_MODIFY)) {
                throw new IllegalArgumentException(
                        t + ": No user supplied group modify can be included for a checkpoint");
            }

            if (cvValues.containsKey(DataTableColumns.GROUP_PRIVILEGED)) {
                throw new IllegalArgumentException(
                        t + ": No user supplied group privileged can be included for a checkpoint");
            }

            HashMap<String, Object> currValues = new HashMap<String, Object>();
            for (String key : cvValues.keySet()) {
                currValues.put(key, cvValues.get(key));
            }

            // This is unnecessary
            // We should only have one row at this point
            //c.moveToFirst();

            String priorDefaultAccess = null;
            String priorOwner = null;
            String priorGroupReadOnly = null;
            String priorGroupModify = null;
            String priorGroupPrivileged = null;

            // Get the number of columns to iterate over and add
            // those values to the content values
            for (int i = 0; i < c.getColumnCount(); i++) {
                String name = c.getColumnName(i);

                if (name.equals(DataTableColumns.DEFAULT_ACCESS)) {
                    priorDefaultAccess = c.getString(i);
                }

                if (name.equals(DataTableColumns.ROW_OWNER)) {
                    priorOwner = c.getString(i);
                }

                if (name.equals(DataTableColumns.GROUP_READ_ONLY)) {
                    priorGroupReadOnly = c.getString(i);
                }

                if (name.equals(DataTableColumns.GROUP_MODIFY)) {
                    priorGroupModify = c.getString(i);
                }

                if (name.equals(DataTableColumns.GROUP_PRIVILEGED)) {
                    priorGroupPrivileged = c.getString(i);
                }

                if (currValues.containsKey(name)) {
                    continue;
                }

                // omitting savepoint timestamp will generate a new timestamp.
                if (name.equals(DataTableColumns.SAVEPOINT_TIMESTAMP)) {
                    continue;
                }

                // set savepoint type to null to mark this as a checkpoint
                if (name.equals(DataTableColumns.SAVEPOINT_TYPE)) {
                    currValues.put(name, null);
                    continue;
                }

                // sync state (a non-null field) should either remain 'new_row'
                // or be set to 'changed' for all other existing values.
                if (name.equals(DataTableColumns.SYNC_STATE)) {
                    String priorState = c.getString(i);
                    if (priorState.equals(SyncState.new_row.name())) {
                        currValues.put(name, SyncState.new_row.name());
                    } else {
                        currValues.put(name, SyncState.changed.name());
                    }
                    continue;
                }

                if (c.isNull(i)) {
                    currValues.put(name, null);
                    continue;
                }

                // otherwise, just copy the values over...
                Class<?> theClass = CursorUtils.getIndexDataType(c, i);
                Object object = CursorUtils.getIndexAsType(c, theClass, i);
                insertValueIntoContentValues(currValues, theClass, name, object);
            }

            insertCheckpointIntoExistingTable(db, tableId, orderedColumns, currValues, activeUser, rolesList,
                    locale, false, priorDefaultAccess, priorOwner, priorGroupReadOnly, priorGroupModify,
                    priorGroupPrivileged);
        }
    } finally {
        if (c != null && !c.isClosed()) {
            c.close();
        }
    }
}

From source file:org.opendatakit.services.database.utlities.ODKDatabaseImplUtils.java

/**
 * Resolve the server conflict by taking the local changes plus a value map
 * of select server field values.  This map should not update any metadata
 * fields -- it should just contain user data fields.
 * <p/>/*  w w w. j a  va  2 s. c  o m*/
 * It is an error to call this if the local change is to delete the row.
 *
 * @param db
 * @param tableId
 * @param cvValues   key-value pairs from the server record that we should incorporate.
 * @param rowId
 * @param activeUser
 * @param rolesList
 * @param locale
 */
public void resolveServerConflictTakeLocalRowPlusServerDeltasWithId(OdkConnectionInterface db, String tableId,
        ContentValues cvValues, String rowId, String activeUser, String rolesList, String locale)
        throws ActionNotAuthorizedException {

    // TODO: if rolesList does not contain RoleConsts.ROLE_SUPER_USER or RoleConsts.ROLE_ADMINISTRATOR
    // TODO: then take the server's rowFilterScope rather than the user's values of those.
    // TODO: and apply the update only if the user roles support that update.

    // I.e., if the user is super-user or higher, we should take local FilterScope.
    // otherwise, we should take server FilterScope. Or should we allow user to select
    // which to take?

    boolean inTransaction = false;
    try {

        inTransaction = db.inTransaction();
        if (!inTransaction) {
            db.beginTransactionNonExclusive();
        }

        OrderedColumns orderedColumns = getUserDefinedColumns(db, tableId);

        AccessContext accessContext = getAccessContext(db, tableId, activeUser, RoleConsts.ADMIN_ROLES_LIST);

        // get both conflict records for this row.
        // the local record is always before the server record (due to conflict_type values)
        BaseTable table = privilegedQuery(db, tableId,
                QueryUtil.buildSqlStatement(tableId,
                        K_DATATABLE_ID_EQUALS_PARAM + S_AND + DataTableColumns.CONFLICT_TYPE + S_IS_NOT_NULL,
                        null, null, new String[] { DataTableColumns.CONFLICT_TYPE }, new String[] { "ASC" }),
                new Object[] { rowId }, null, accessContext);

        if (table.getNumberOfRows() != 2) {
            throw new IllegalStateException(
                    "Did not find a server and local row when resolving conflicts for rowId: " + rowId);
        }
        Row localRow = table.getRowAtIndex(0);
        Row serverRow = table.getRowAtIndex(1);

        int localConflictType = Integer.parseInt(localRow.getDataByKey(DataTableColumns.CONFLICT_TYPE));

        int serverConflictType = Integer.parseInt(serverRow.getDataByKey(DataTableColumns.CONFLICT_TYPE));

        if (localConflictType != ConflictType.LOCAL_UPDATED_UPDATED_VALUES
                && localConflictType != ConflictType.LOCAL_DELETED_OLD_VALUES) {
            throw new IllegalStateException(
                    "Did not find local conflict row when resolving conflicts for rowId: " + rowId);
        }

        if (serverConflictType != ConflictType.SERVER_UPDATED_UPDATED_VALUES
                && serverConflictType != ConflictType.SERVER_DELETED_OLD_VALUES) {
            throw new IllegalStateException(
                    "Did not find server conflict row when resolving conflicts for rowId: " + rowId);
        }

        if (localConflictType == ConflictType.LOCAL_DELETED_OLD_VALUES) {
            throw new IllegalStateException(
                    "Local row is marked for deletion -- blending does not make sense for rowId: " + rowId);
        }

        HashMap<String, Object> updateValues = new HashMap<String, Object>();
        for (String key : cvValues.keySet()) {
            updateValues.put(key, cvValues.get(key));
        }

        // clean up the incoming map of server values to retain
        cleanUpValuesMap(orderedColumns, updateValues);
        updateValues.put(DataTableColumns.ID, rowId);
        updateValues.put(DataTableColumns.ROW_ETAG, serverRow.getDataByKey(DataTableColumns.ROW_ETAG));

        // update what was the local conflict record with the local's changes
        // by the time we apply the update, the local conflict record will be
        // restored to the proper (conflict_type, sync_state) values.
        //
        // No need to specify them here.

        // but take the local's metadata values (i.e., do not change these
        // during the update) ...
        updateValues.put(DataTableColumns.FORM_ID, localRow.getDataByKey(DataTableColumns.FORM_ID));
        updateValues.put(DataTableColumns.LOCALE, localRow.getDataByKey(DataTableColumns.LOCALE));
        updateValues.put(DataTableColumns.SAVEPOINT_TYPE,
                localRow.getDataByKey(DataTableColumns.SAVEPOINT_TYPE));
        updateValues.put(DataTableColumns.SAVEPOINT_TIMESTAMP,
                localRow.getDataByKey(DataTableColumns.SAVEPOINT_TIMESTAMP));
        updateValues.put(DataTableColumns.SAVEPOINT_CREATOR,
                localRow.getDataByKey(DataTableColumns.SAVEPOINT_CREATOR));

        // take the server's filter metadata values ...
        TreeMap<String, Object> privilegedUpdateValues = new TreeMap<String, Object>();
        privilegedUpdateValues.put(DataTableColumns.ID, rowId);
        privilegedUpdateValues.put(DataTableColumns.FILTER_TYPE,
                serverRow.getDataByKey(DataTableColumns.FILTER_TYPE));
        privilegedUpdateValues.put(DataTableColumns.FILTER_VALUE,
                serverRow.getDataByKey(DataTableColumns.FILTER_VALUE));
        privilegedUpdateValues.put(DataTableColumns.SAVEPOINT_TIMESTAMP,
                serverRow.getDataByKey(DataTableColumns.SAVEPOINT_TIMESTAMP));
        privilegedUpdateValues.put(DataTableColumns.SAVEPOINT_CREATOR,
                serverRow.getDataByKey(DataTableColumns.SAVEPOINT_CREATOR));

        // delete the record of the server row
        deleteServerConflictRowWithId(db, tableId, rowId);

        // move the local conflict back into the normal (null) state

        restoreRowFromConflict(db, tableId, rowId, SyncState.changed, localConflictType);

        // update local with server's changes
        updateRowWithId(db, tableId, orderedColumns, updateValues, activeUser, rolesList, locale);

        // update as if user has admin privileges.
        // do this so we can update the filter type and filter value
        updateRowWithId(db, tableId, orderedColumns, privilegedUpdateValues, activeUser,
                RoleConsts.ADMIN_ROLES_LIST, locale);

        if (!inTransaction) {
            db.setTransactionSuccessful();
        }
    } finally {
        if (db != null) {
            if (!inTransaction) {
                db.endTransaction();
            }
        }
    }
}

From source file:org.opendatakit.services.database.utilities.ODKDatabaseImplUtils.java

/**
 * Resolve the server conflict by taking the local changes plus a value map
 * of select server field values.  This map should not update any metadata
 * fields -- it should just contain user data fields.
 * <p/>//w  w w.  ja  v  a  2 s . c om
 * It is an error to call this if the local change is to delete the row.
 *
 * @param db
 * @param tableId
 * @param cvValues   key-value pairs from the server record that we should incorporate.
 * @param rowId
 * @param activeUser
 * @param rolesList
 * @param locale
 */
public void resolveServerConflictTakeLocalRowPlusServerDeltasWithId(OdkConnectionInterface db, String tableId,
        ContentValues cvValues, String rowId, String activeUser, String rolesList, String locale)
        throws ActionNotAuthorizedException {

    // TODO: if rolesList does not contain RoleConsts.ROLE_SUPER_USER or RoleConsts.ROLE_ADMINISTRATOR
    // TODO: then take the server's rowFilterScope rather than the user's values of those.
    // TODO: and apply the update only if the user roles support that update.

    // I.e., if the user is super-user or higher, we should take local FilterScope.
    // otherwise, we should take server FilterScope. Or should we allow user to select
    // which to take?

    boolean inTransaction = false;
    try {

        inTransaction = db.inTransaction();
        if (!inTransaction) {
            db.beginTransactionNonExclusive();
        }

        OrderedColumns orderedColumns = getUserDefinedColumns(db, tableId);

        AccessContext accessContext = getAccessContext(db, tableId, activeUser, RoleConsts.ADMIN_ROLES_LIST);

        // get both conflict records for this row.
        // the local record is always before the server record (due to conflict_type values)
        BaseTable table = privilegedQuery(db, tableId,
                QueryUtil.buildSqlStatement(tableId,
                        K_DATATABLE_ID_EQUALS_PARAM + S_AND + DataTableColumns.CONFLICT_TYPE + S_IS_NOT_NULL,
                        null, null, new String[] { DataTableColumns.CONFLICT_TYPE }, new String[] { "ASC" }),
                new Object[] { rowId }, null, accessContext);

        if (table.getNumberOfRows() != 2) {
            throw new IllegalStateException(
                    "Did not find a server and local row when resolving conflicts for rowId: " + rowId);
        }
        Row localRow = table.getRowAtIndex(0);
        Row serverRow = table.getRowAtIndex(1);

        int localConflictType = Integer.parseInt(localRow.getDataByKey(DataTableColumns.CONFLICT_TYPE));

        int serverConflictType = Integer.parseInt(serverRow.getDataByKey(DataTableColumns.CONFLICT_TYPE));

        if (localConflictType != ConflictType.LOCAL_UPDATED_UPDATED_VALUES
                && localConflictType != ConflictType.LOCAL_DELETED_OLD_VALUES) {
            throw new IllegalStateException(
                    "Did not find local conflict row when resolving conflicts for rowId: " + rowId);
        }

        if (serverConflictType != ConflictType.SERVER_UPDATED_UPDATED_VALUES
                && serverConflictType != ConflictType.SERVER_DELETED_OLD_VALUES) {
            throw new IllegalStateException(
                    "Did not find server conflict row when resolving conflicts for rowId: " + rowId);
        }

        if (localConflictType == ConflictType.LOCAL_DELETED_OLD_VALUES) {
            throw new IllegalStateException(
                    "Local row is marked for deletion -- blending does not make sense for rowId: " + rowId);
        }

        HashMap<String, Object> updateValues = new HashMap<String, Object>();
        for (String key : cvValues.keySet()) {
            updateValues.put(key, cvValues.get(key));
        }

        // clean up the incoming map of server values to retain
        cleanUpValuesMap(orderedColumns, updateValues);
        updateValues.put(DataTableColumns.ID, rowId);
        updateValues.put(DataTableColumns.ROW_ETAG, serverRow.getDataByKey(DataTableColumns.ROW_ETAG));

        // update what was the local conflict record with the local's changes
        // by the time we apply the update, the local conflict record will be
        // restored to the proper (conflict_type, sync_state) values.
        //
        // No need to specify them here.

        // but take the local's metadata values (i.e., do not change these
        // during the update) ...
        updateValues.put(DataTableColumns.FORM_ID, localRow.getDataByKey(DataTableColumns.FORM_ID));
        updateValues.put(DataTableColumns.LOCALE, localRow.getDataByKey(DataTableColumns.LOCALE));
        updateValues.put(DataTableColumns.SAVEPOINT_TYPE,
                localRow.getDataByKey(DataTableColumns.SAVEPOINT_TYPE));
        updateValues.put(DataTableColumns.SAVEPOINT_TIMESTAMP,
                localRow.getDataByKey(DataTableColumns.SAVEPOINT_TIMESTAMP));
        updateValues.put(DataTableColumns.SAVEPOINT_CREATOR,
                localRow.getDataByKey(DataTableColumns.SAVEPOINT_CREATOR));

        // take the server's filter metadata values ...
        TreeMap<String, Object> privilegedUpdateValues = new TreeMap<String, Object>();
        privilegedUpdateValues.put(DataTableColumns.ID, rowId);
        privilegedUpdateValues.put(DataTableColumns.DEFAULT_ACCESS,
                serverRow.getDataByKey(DataTableColumns.DEFAULT_ACCESS));
        privilegedUpdateValues.put(DataTableColumns.ROW_OWNER,
                serverRow.getDataByKey(DataTableColumns.ROW_OWNER));
        privilegedUpdateValues.put(DataTableColumns.GROUP_READ_ONLY,
                serverRow.getDataByKey(DataTableColumns.GROUP_READ_ONLY));
        privilegedUpdateValues.put(DataTableColumns.GROUP_MODIFY,
                serverRow.getDataByKey(DataTableColumns.GROUP_MODIFY));
        privilegedUpdateValues.put(DataTableColumns.GROUP_PRIVILEGED,
                serverRow.getDataByKey(DataTableColumns.GROUP_PRIVILEGED));
        privilegedUpdateValues.put(DataTableColumns.SAVEPOINT_TIMESTAMP,
                serverRow.getDataByKey(DataTableColumns.SAVEPOINT_TIMESTAMP));
        privilegedUpdateValues.put(DataTableColumns.SAVEPOINT_CREATOR,
                serverRow.getDataByKey(DataTableColumns.SAVEPOINT_CREATOR));

        // delete the record of the server row
        deleteServerConflictRowWithId(db, tableId, rowId);

        // move the local conflict back into the normal (null) state

        restoreRowFromConflict(db, tableId, rowId, SyncState.changed, localConflictType);

        // update local with server's changes
        updateRowWithId(db, tableId, orderedColumns, updateValues, activeUser, rolesList, locale);

        // update as if user has admin privileges.
        // do this so we can update the filter type and filter value
        updateRowWithId(db, tableId, orderedColumns, privilegedUpdateValues, activeUser,
                RoleConsts.ADMIN_ROLES_LIST, locale);

        if (!inTransaction) {
            db.setTransactionSuccessful();
        }
    } finally {
        if (db != null) {
            if (!inTransaction) {
                db.endTransaction();
            }
        }
    }
}