private void traverseDelete() { RowType[] rowsThatWillDelete = all(); if (rowsThatWillDelete == null || rowsThatWillDelete.length == 0) return; List<Field> fields = ClassRowConverter.getAllFields(mRowClass); for (RowType row : rowsThatWillDelete) { for (Field fld : fields) { ForeignKey fkAnn = fld.getAnnotation(ForeignKey.class); if (fkAnn != null) { try { Field rowIdField = mInquiry.getIdField(mRowClass); if (rowIdField == null) throw new IllegalStateException("No _id column field found in " + mRowClass); Class<?> listGenericType = Utils.getGenericTypeOfField(fld); long rowId = rowIdField.getLong(row); Inquiry fkInstance = Inquiry.copy( mInquiry, "[@fk]:" + fkAnn.tableName() + "//" + fkAnn.foreignColumnName(), false); fkInstance .deleteFrom(fkAnn.tableName(), listGenericType) .where(fkAnn.foreignColumnName() + " = ?", rowId) .run(); fkInstance.destroyInstance(); } catch (Throwable t) { Utils.wrapInReIfNeccessary(t); } } } } }
private void postRun(boolean updateMode, Object row, Field fld) { try { ForeignKey fkAnn = fld.getAnnotation(ForeignKey.class); Object fldVal = fld.get(row); if (updateMode && Utils.classExtendsLazyLoader(fld.getType())) { LazyLoaderList lazyLoader = (LazyLoaderList) fldVal; if (!lazyLoader.didLazyLoad()) { // Lazy loading didn't happen, nothing was populated, so nothing changed return; } } Class<?> listGenericType = Utils.getGenericTypeOfField(fld); Field idField = mInquiry.getIdField(row.getClass()); Field fkIdField = mInquiry.getIdField(listGenericType); Field fkField = ClassRowConverter.getField( ClassRowConverter.getAllFields(listGenericType), fkAnn.foreignColumnName(), Long.class, long.class); if (idField == null) throw new IllegalStateException( "You cannot use the @ForeignKey annotation on a field within a class that doesn't have an _id column."); if (fkIdField == null) throw new IllegalStateException( "The @ForeignKey annotation can only be used on fields which contain class objects that have an _id column, " + listGenericType + " does not."); if (fkField == null) throw new IllegalStateException( "The @ForeignKey annotation on " + fld.getName() + " references a non-existent column (or a column which can't hold an Int64 ID): " + fkAnn.foreignColumnName()); long rowId = idField.getLong(row); if (rowId <= 0) throw new IllegalStateException( "The current row's ID is 0, you cannot insert/update @ForeignKey fields if the parent class has no ID."); List list = null; Object[] array = null; if (fldVal != null) { if (fld.getType().isArray()) array = (Object[]) fldVal; else if (Utils.classImplementsList(fld.getType())) list = (List) fldVal; else array = new Object[] {fldVal}; } Inquiry fkInstance = Inquiry.copy( mInquiry, "[@fk]:" + fkAnn.tableName() + "//" + fkAnn.foreignColumnName(), false); if ((array != null && array.length > 0) || (list != null && list.size() > 0)) { // Update foreign row columns with this row's ID if (array != null) { for (Object child : array) ClassRowConverter.setIdField(child, fkField, rowId); } else { for (int i = 0; i < list.size(); i++) ClassRowConverter.setIdField(list.get(i), fkField, rowId); } if (updateMode) { // Delete any rows in the foreign table which reference this row fkInstance .deleteFrom(fkAnn.tableName(), listGenericType) .where(fkAnn.foreignColumnName() + " = ?", rowId) .run(); } // Insert rows from this field into the foreign table if (array != null) { fkInstance.insertInto(fkAnn.tableName(), listGenericType).valuesArray(array).run(); } else { fkInstance.insertInto(fkAnn.tableName(), listGenericType).values(list).run(); } } else { // Delete any rows in the foreign table which reference this row fkInstance .deleteFrom(fkAnn.tableName(), listGenericType) .where(fkAnn.foreignColumnName() + " = ?", rowId) .run(); } fkInstance.destroyInstance(); } catch (Throwable t) { Utils.wrapInReIfNeccessary(t); } }
@SuppressLint("SwitchIntDef") @SuppressWarnings("unchecked") public RunReturn run() { if (mQueryType != DELETE && (mValues == null || mValues.length == 0)) throw new IllegalStateException("No values were provided for this query to run."); else if (mInquiry.mContext == null) { try { return (RunReturn) (Integer) 0; } catch (Throwable t) { return (RunReturn) (Long) 0L; } } final ContentResolver cr = mInquiry.mContext.getContentResolver(); final List<Field> clsFields = ClassRowConverter.getAllFields(mRowClass); if (mTableName == null) throw new IllegalStateException("The table name cannot be null."); Field rowIdField = mInquiry.getIdField(mRowClass); try { switch (mQueryType) { case INSERT: Long[] insertedIds = new Long[mValues.length]; if (mInquiry.getDatabase() != null) { for (int i = 0; i < mValues.length; i++) { final RowType row = mValues[i]; if (row == null) continue; insertedIds[i] = mInquiry .getDatabase() .insert( mTableName, ClassRowConverter.clsToVals(this, row, null, clsFields, false)); ClassRowConverter.setIdField(row, rowIdField, insertedIds[i]); } } else if (mContentUri != null) { for (int i = 0; i < mValues.length; i++) { final RowType row = mValues[i]; if (row == null) continue; final Uri uri = cr.insert( mContentUri, ClassRowConverter.clsToVals(this, row, null, clsFields, false)); if (uri == null) return (RunReturn) (Long) (-1L); insertedIds[i] = Long.parseLong(uri.getLastPathSegment()); ClassRowConverter.setIdField(row, rowIdField, insertedIds[i]); } } else throw new IllegalStateException("Database helper was null."); postRun(false); return (RunReturn) insertedIds; case UPDATE: { boolean allHaveIds = rowIdField != null; if (rowIdField != null && mValues != null) { for (RowType mValue : mValues) { if (mValue == null) continue; long id = ClassRowConverter.getRowId(mValue, rowIdField); if (id <= 0) { allHaveIds = false; break; } } } if (allHaveIds) { // We want to update each object as themselves if (getWhere() != null && !getWhere().trim().isEmpty()) { throw new IllegalStateException( "You want to update rows which have IDs, but specified a where statement."); } int updatedCount = 0; for (RowType row : mValues) { if (row == null) continue; long rowId = ClassRowConverter.getRowId(row, rowIdField); ContentValues values = ClassRowConverter.clsToVals(this, row, mProjection, clsFields, true); if (mInquiry.getDatabase() != null) { updatedCount += mInquiry .getDatabase() .update(mTableName, values, "_id = ?", new String[] {rowId + ""}); } else if (mContentUri != null) { updatedCount += cr.update(mContentUri, values, "_id = ?", new String[] {rowId + ""}); } else throw new IllegalStateException("Database helper was null."); } postRun(true); return (RunReturn) (Integer) updatedCount; } RowType firstNotNull = mValues[mValues.length - 1]; if (firstNotNull == null) { for (int i = mValues.length - 2; i >= 0; i--) { firstNotNull = mValues[i]; if (firstNotNull != null) break; } } if (firstNotNull == null) throw new IllegalStateException("No non-null values specified to update."); ContentValues values = ClassRowConverter.clsToVals(this, firstNotNull, mProjection, clsFields, true); if (mInquiry.getDatabase() != null) { RunReturn value = (RunReturn) (Integer) mInquiry .getDatabase() .update(mTableName, values, getWhere(), getWhereArgs()); postRun(true); return value; } else if (mContentUri != null) return (RunReturn) (Integer) cr.update(mContentUri, values, getWhere(), getWhereArgs()); else throw new IllegalStateException("Database helper was null."); } case DELETE: { Long[] idsToDelete = null; if (rowIdField != null && mValues != null) { int nonNullFound = 0; idsToDelete = new Long[mValues.length]; for (int i = 0; i < mValues.length; i++) { if (mValues[i] == null) continue; nonNullFound++; long id = ClassRowConverter.getRowId(mValues[i], rowIdField); idsToDelete[i] = id; if (id <= 0) { idsToDelete = null; break; } } if (nonNullFound == 0) idsToDelete = null; } if (idsToDelete != null) { // We want to update each object as themselves if (getWhere() != null && !getWhere().trim().isEmpty()) { throw new IllegalStateException( "You want to delete rows which have IDs, but specified a where statement."); } //noinspection CheckResult,ConfusingArgumentToVarargsMethod whereIn("_id", idsToDelete); } if (mInquiry.getDatabase() != null) { RunReturn value = (RunReturn) (Integer) mInquiry.getDatabase().delete(mTableName, getWhere(), getWhereArgs()); traverseDelete(); return value; } else if (mContentUri != null) return (RunReturn) (Integer) cr.delete(mContentUri, getWhere(), getWhereArgs()); else throw new IllegalStateException("Database helper was null."); } } } catch (Throwable t) { Utils.wrapInReIfNeccessary(t); } return null; }