List of usage examples for android.content ContentValues getAsBoolean
public Boolean getAsBoolean(String key)
From source file:com.akop.bach.parser.XboxLiveParser.java
private void parseAccountSummary(XboxLiveAccount account) throws ParserException, IOException { ContentValues cv = parseSummaryData(account); ContentResolver cr = mContext.getContentResolver(); long accountId = account.getId(); boolean newRecord = true; long started = System.currentTimeMillis(); Cursor c = cr.query(Profiles.CONTENT_URI, new String[] { Profiles._ID }, Profiles.ACCOUNT_ID + "=" + accountId, null, null); if (c != null) { if (c.moveToFirst()) newRecord = false;/* w w w . jav a 2s . co m*/ c.close(); } if (newRecord) { cv.put(Profiles.ACCOUNT_ID, account.getId()); cv.put(Profiles.UUID, account.getUuid()); cr.insert(Profiles.CONTENT_URI, cv); } else { cr.update(Profiles.CONTENT_URI, cv, Profiles.ACCOUNT_ID + "=" + accountId, null); } cr.notifyChange(Profiles.CONTENT_URI, null); if (App.getConfig().logToConsole()) displayTimeTaken("Summary update", started); account.refresh(Preferences.get(mContext)); account.setGamertag(cv.getAsString(Profiles.GAMERTAG)); account.setIconUrl(cv.getAsString(Profiles.ICON_URL)); account.setGoldStatus(cv.getAsBoolean(Profiles.IS_GOLD)); account.setLastSummaryUpdate(System.currentTimeMillis()); account.save(Preferences.get(mContext)); }
From source file:org.opendatakit.services.database.utlities.ODKDatabaseImplUtils.java
/** * Delete any prior server conflict row. * Examine database and incoming server values to determine how to apply the * server values to the database. This might delete the existing row, update * it, or create a conflict row.//from w ww .j a v a 2s.c om * * @param db * @param tableId * @param orderedColumns * @param serverValues field values for this row coming from server. * All fields must have values. The SyncState field * (a local field that does not come from the server) * should be "changed" or "deleted" * @param rowId * @param activeUser * @param rolesList passed in to determine if the current user is a privileged user * @param locale */ public void privilegedPerhapsPlaceRowIntoConflictWithId(OdkConnectionInterface db, String tableId, OrderedColumns orderedColumns, ContentValues serverValues, String rowId, String activeUser, String rolesList, String locale) { AccessContext accessContext = getAccessContext(db, tableId, activeUser, rolesList); // The rolesList of the activeUser does not impact the execution of this action. boolean dbWithinTransaction = db.inTransaction(); try { if (!dbWithinTransaction) { db.beginTransactionNonExclusive(); } // delete any existing server conflict row this.deleteServerConflictRowWithId(db, tableId, rowId); // fetch the current local (possibly-in-conflict) row BaseTable baseTable = this.privilegedGetRowsWithId(db, tableId, rowId, activeUser); if (baseTable.getNumberOfRows() == 0) { throw new IllegalArgumentException("no matching row found for server conflict"); } else if (baseTable.getNumberOfRows() != 1) { throw new IllegalArgumentException("row has checkpoints or database is corrupt"); } Row localRow = baseTable.getRowAtIndex(0); if (localRow.getDataByKey(DataTableColumns.SAVEPOINT_TYPE) == null) { throw new IllegalArgumentException("row has checkpoints"); } String strSyncState = localRow.getDataByKey(DataTableColumns.SYNC_STATE); SyncState state = SyncState.valueOf(strSyncState); int localRowConflictTypeBeforeSync = -1; if (state == SyncState.in_conflict) { // we need to remove the in_conflict records that refer to the // prior state of the server String localRowConflictTypeBeforeSyncStr = localRow.getDataByKey(DataTableColumns.CONFLICT_TYPE); if (localRowConflictTypeBeforeSyncStr == null) { // this row is in conflict. It MUST have a non-null conflict type. throw new IllegalStateException("conflict type is null on an in-conflict row"); } localRowConflictTypeBeforeSync = Integer.parseInt(localRowConflictTypeBeforeSyncStr); if (localRowConflictTypeBeforeSync == ConflictType.SERVER_DELETED_OLD_VALUES || localRowConflictTypeBeforeSync == ConflictType.SERVER_UPDATED_UPDATED_VALUES) { // should be impossible throw new IllegalStateException("only the local conflict record should remain"); } } boolean isServerRowDeleted = serverValues.getAsString(DataTableColumns.SYNC_STATE) .equals(SyncState.deleted.name()); boolean executeDropThrough = false; if (isServerRowDeleted) { if (state == SyncState.synced) { // the server's change should be applied locally. this.privilegedDeleteRowWithId(db, tableId, rowId, activeUser); } else if (state == SyncState.synced_pending_files) { // sync logic may want to UPLOAD local files up to server before calling this routine. // this would prevent loss of attachments that have not yet been pushed to server. // the server's change should be applied locally. this.privilegedDeleteRowWithId(db, tableId, rowId, activeUser); } else if ((state == SyncState.deleted) || ((state == SyncState.in_conflict) && (localRowConflictTypeBeforeSync == ConflictType.LOCAL_DELETED_OLD_VALUES))) { // this occurs if // (1) a delete request was never ACKed but it was performed // on the server. // (2) if there is an unresolved conflict held locally with the // local action being to delete the record, and the prior server // state being a value change, but the newly sync'd state now // reflects a deletion by another party. // // the server's change should be applied locally. this.privilegedDeleteRowWithId(db, tableId, rowId, activeUser); } else { // need to resolve a conflict situation... executeDropThrough = true; } } else if (state == SyncState.synced || state == SyncState.synced_pending_files) { // When a prior sync ends with conflicts, we will not update the table's "lastDataETag" // and when we next sync, we will pull the same server row updates as when the // conflicts were raised (elsewhere in the table). // // Therefore, we can expect many server row updates to have already been locally // applied (for the rows were not in conflict). Detect and ignore these already- // processed changes by testing for the server and device having identical field values. // boolean isDifferent = false; for (int i = 0; i < baseTable.getWidth(); ++i) { String colName = baseTable.getElementKey(i); if (DataTableColumns.ID.equals(colName) || DataTableColumns.CONFLICT_TYPE.equals(colName) || DataTableColumns.EFFECTIVE_ACCESS.equals(colName) || DataTableColumns.SYNC_STATE.equals(colName)) { // these values are ignored during comparisons continue; } String localValue = localRow.getDataByKey(colName); String serverValue = serverValues.containsKey(colName) ? serverValues.getAsString(colName) : null; ElementDataType dt = ElementDataType.string; try { ColumnDefinition cd = orderedColumns.find(colName); dt = cd.getType().getDataType(); } catch (IllegalArgumentException e) { // ignore } if (!identicalValue(localValue, serverValue, dt)) { isDifferent = true; break; } } if (isDifferent) { // Local row needs to be updated with server values. // // detect and handle file attachment column changes and sync state // (need to change serverRow value of this) boolean hasNonNullAttachments = false; for (ColumnDefinition cd : orderedColumns.getColumnDefinitions()) { // todo: does not handle array containing (types containing) rowpath elements if (cd.isUnitOfRetention() && cd.getType().getDataType().equals(ElementDataType.rowpath)) { String uriFragment = serverValues.getAsString(cd.getElementKey()); String localUriFragment = localRow.getDataByKey(cd.getElementKey()); if (uriFragment != null) { if (localUriFragment == null || !localUriFragment.equals(uriFragment)) { hasNonNullAttachments = true; break; } } } } // update the row from the changes on the server ContentValues values = new ContentValues(serverValues); values.put(DataTableColumns.SYNC_STATE, (hasNonNullAttachments || (state == SyncState.synced_pending_files)) ? SyncState.synced_pending_files.name() : SyncState.synced.name()); values.putNull(DataTableColumns.CONFLICT_TYPE); this.privilegedUpdateRowWithId(db, tableId, orderedColumns, values, rowId, activeUser, locale, false); } // and don't execute the drop-through in this case. } else { executeDropThrough = true; } if (executeDropThrough) { // SyncState.deleted and server is not deleting // SyncState.new_row and record exists on server // SyncState.changed and new change (or delete) on server // SyncState.in_conflict and new change (or delete) on server // ALSO: this case can occur when our prior sync attempt pulled down changes that // placed local row(s) in conflict -- which we have since resolved -- and we are now // issuing a sync to push those changes up to the server. // // This is because we do not update our local table's "lastDataETag" until we have // sync'd and applied all changes from the server and have no local conflicts or // checkpoints on the table. Because of this, when we issue a sync after resolving // a conflict, we will get the set of server row changes that include the row(s) // that were previously in conflict. This will appear as one of: // changed | changed // changed | deleted // deleted | changed // deleted | deleted // // BUT, this time, however, the local records will have the same rowETag as the // server record, indicating that they are valid changes (or deletions) on top of // the server's current version of this same row. // // If this is the case (the rowETags match), then we should not place the row into // conflict, but should instead ignore the reported content from the server and push // the local row's change or delete up to the server in the next section. // // If not, when we reach this point in the code, the rowETag of the server row // should **not match** our local row -- indicating that the server has a change from // another source, and that we should place the row into conflict. // String localRowETag = localRow.getDataByKey(DataTableColumns.ROW_ETAG); String serverRowETag = serverValues.getAsString(DataTableColumns.ROW_ETAG); boolean isDifferentRowETag = (localRowETag == null) || !localRowETag.equals(serverRowETag); if (!isDifferentRowETag) { // ignore the server record. // This is an update we will push to the server. // todo: make sure local row is not in_conflict at this point. if (state == SyncState.in_conflict) { // don't think this is logically possible at this point, but we should // transition record to changed or deleted state. ContentValues values = new ContentValues(); for (int i = 0; i < baseTable.getWidth(); ++i) { String colName = baseTable.getElementKey(i); if (DataTableColumns.EFFECTIVE_ACCESS.equals(colName)) { continue; } if (localRow.getDataByIndex(i) == null) { values.putNull(colName); } else { values.put(colName, localRow.getDataByIndex(i)); } } values.put(DataTableColumns.ID, rowId); values.putNull(DataTableColumns.CONFLICT_TYPE); values.put(DataTableColumns.SYNC_STATE, (localRowConflictTypeBeforeSync == ConflictType.LOCAL_DELETED_OLD_VALUES) ? SyncState.deleted.name() : SyncState.changed.name()); this.privilegedUpdateRowWithId(db, tableId, orderedColumns, values, rowId, activeUser, locale, false); } } else { // figure out what the localRow conflict type should be... int localRowConflictType; if (state == SyncState.changed) { // SyncState.changed and new change on server localRowConflictType = ConflictType.LOCAL_UPDATED_UPDATED_VALUES; } else if (state == SyncState.new_row) { // SyncState.new_row and record exists on server // The 'new_row' case occurs if an insert is never ACKed but // completes successfully on the server. localRowConflictType = ConflictType.LOCAL_UPDATED_UPDATED_VALUES; } else if (state == SyncState.deleted) { // SyncState.deleted and server is not deleting localRowConflictType = ConflictType.LOCAL_DELETED_OLD_VALUES; } else if (state == SyncState.in_conflict) { // SyncState.in_conflict and new change on server // leave the local conflict type unchanged (retrieve it and // use it). localRowConflictType = localRowConflictTypeBeforeSync; } else { throw new IllegalStateException("Unexpected state encountered"); } boolean isDifferentPrivilegedFields = false; { String[] privilegedColumns = new String[] { DataTableColumns.FILTER_TYPE, DataTableColumns.FILTER_VALUE }; for (int i = 0; i < privilegedColumns.length; ++i) { String colName = privilegedColumns[i]; String localValue = localRow.getDataByKey(colName); String serverValue = serverValues.containsKey(colName) ? serverValues.getAsString(colName) : null; ElementDataType dt = ElementDataType.string; try { ColumnDefinition cd = orderedColumns.find(colName); dt = cd.getType().getDataType(); } catch (IllegalArgumentException e) { // ignore } boolean sameValue = identicalValue(localValue, serverValue, dt); if (!sameValue) { isDifferentPrivilegedFields = true; break; } } } boolean isDifferentExcludingPrivilegedFields = false; for (int i = 0; i < baseTable.getWidth(); ++i) { String colName = baseTable.getElementKey(i); if (DataTableColumns.ID.equals(colName) || DataTableColumns.CONFLICT_TYPE.equals(colName) || DataTableColumns.EFFECTIVE_ACCESS.equals(colName) || DataTableColumns.SYNC_STATE.equals(colName) || DataTableColumns.ROW_ETAG.equals(colName) || DataTableColumns.FILTER_TYPE.equals(colName) || DataTableColumns.FILTER_VALUE.equals(colName)) { // these values are ignored during this comparison continue; } String localValue = localRow.getDataByKey(colName); String serverValue = serverValues.containsKey(colName) ? serverValues.getAsString(colName) : null; ElementDataType dt = ElementDataType.string; try { ColumnDefinition cd = orderedColumns.find(colName); dt = cd.getType().getDataType(); } catch (IllegalArgumentException e) { // ignore } if (serverValue != null && dt == ElementDataType.bool) { serverValue = Integer .toString(DataHelper.boolToInt(serverValues.getAsBoolean(colName))); } boolean sameValue = identicalValue(localValue, serverValue, dt); if (!sameValue) { isDifferentExcludingPrivilegedFields = true; break; } } boolean hasNonNullDifferingServerAttachments = false; if (isDifferentExcludingPrivilegedFields || (state != SyncState.synced)) { for (ColumnDefinition cd : orderedColumns.getColumnDefinitions()) { // todo: does not handle array containing (types containing) rowpath elements if (cd.isUnitOfRetention() && cd.getType().getDataType().equals(ElementDataType.rowpath)) { String uriFragment = serverValues.getAsString(cd.getElementKey()); String localUriFragment = localRow.getDataByKey(cd.getElementKey()); if (uriFragment != null) { if (localUriFragment == null || !localUriFragment.equals(uriFragment)) { hasNonNullDifferingServerAttachments = true; } } } } } ContentValues values = new ContentValues(serverValues); if (isDifferentExcludingPrivilegedFields || isDifferentPrivilegedFields || isDifferentRowETag || isServerRowDeleted) { if (isDifferentExcludingPrivilegedFields || isServerRowDeleted || (localRowConflictType == ConflictType.LOCAL_DELETED_OLD_VALUES) || (accessContext.isPrivilegedUser && isDifferentPrivilegedFields)) { this.placeRowIntoConflict(db, tableId, rowId, localRowConflictType); serverValues.put(DataTableColumns.SYNC_STATE, SyncState.in_conflict.name()); serverValues.put(DataTableColumns.CONFLICT_TYPE, (isServerRowDeleted ? ConflictType.SERVER_DELETED_OLD_VALUES : ConflictType.SERVER_UPDATED_UPDATED_VALUES)); this.privilegedInsertRowWithId(db, tableId, orderedColumns, serverValues, rowId, activeUser, locale, false); } else { // just apply the server RowETag and filterScope to the local row values.put(DataTableColumns.SYNC_STATE, hasNonNullDifferingServerAttachments ? SyncState.synced_pending_files.name() : SyncState.synced.name()); values.putNull(DataTableColumns.CONFLICT_TYPE); // move the local conflict back into the normal non-conflict (null) state // set the sync state to "changed" temporarily (otherwise we can't update) this.restoreRowFromConflict(db, tableId, rowId, SyncState.changed, localRowConflictTypeBeforeSync); this.privilegedUpdateRowWithId(db, tableId, orderedColumns, values, rowId, activeUser, locale, false); } } else { // data matches -- update row to adjust sync state and conflict type // if needed. SyncState destState = (hasNonNullDifferingServerAttachments || (state == SyncState.synced_pending_files)) ? SyncState.synced_pending_files : SyncState.synced; if ((state != destState) || isDifferentRowETag || (localRow.getDataByKey(DataTableColumns.CONFLICT_TYPE) != null)) { // todo: handle case where local row was in conflict // server has now matched the local row's state. i.e., // update rowEtag, clear conflictType and adjust syncState on row. values.put(DataTableColumns.SYNC_STATE, destState.name()); values.putNull(DataTableColumns.CONFLICT_TYPE); // move the local conflict back into the normal non-conflict (null) state // set the sync state to "changed" temporarily (otherwise we can't update) this.restoreRowFromConflict(db, tableId, rowId, SyncState.changed, localRowConflictTypeBeforeSync); this.privilegedUpdateRowWithId(db, tableId, orderedColumns, values, rowId, activeUser, locale, false); WebLogger.getLogger(db.getAppName()).w(t, "identical rows returned from server -- " + "SHOULDN'T THESE NOT HAPPEN?"); } } } } if (!dbWithinTransaction) { db.setTransactionSuccessful(); } } finally { if (!dbWithinTransaction) { db.endTransaction(); } } }