private void writeRemoveWith(Table table, Field field) throws IOException { ArrayList<String> params = new ArrayList<String>(); params.add(SqlUtil.getJavaTypeFor(field.type)); params.add(field.name); // remove with UNIQUE writer.emitEmptyLine(); writer.beginMethod( "void", "remove" + Util.capitalize(table.name) + "With" + Util.capitalize(field.name), EnumSet.of(Modifier.PUBLIC), params.toArray(new String[params.size()])); writer.emitStatement( "ContentProviderOperation.Builder operationBuilder = ContentProviderOperation.newDelete(" + mModel.getContentProviderName() + "." + SqlUtil.URI(table) + ")"); writer.emitStatement( "operationBuilder.withSelection(" + mModel.getDbClassName() + "." + SqlUtil.ROW_COLUMN(table, field) + " + \"=?\", new String[]{String.valueOf(" + field.name + ")})"); insertAddOpBlock(); writer.endMethod(); }
private void emitURIs() throws IOException { writer.emitEmptyLine(); for (Table table : mModel.getTables()) { writer.emitField( "Uri", SqlUtil.URI(table), EnumSet.of(Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL), "Uri.parse(\"content://" + mModel.getContentAuthority() + "/" + table.name.toLowerCase() + "\")"); } for (View view : mModel.getViews()) { writer.emitField( "Uri", SqlUtil.URI(view), EnumSet.of(Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL), "Uri.parse(\"content://" + mModel.getContentAuthority() + "/" + view.name.toLowerCase() + "\")"); } writer.emitEmptyLine(); }
private void emitTableConstants() throws IOException { int index = 1; for (Table table : mModel.getTables()) { writer.emitSingleLineComment(table.name + " constants"); writer.emitField( "String", SqlUtil.IDENTIFIER(table), EnumSet.of(Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL), "\"" + table.name + "\""); writer.emitField( "int", table.getAllName(), EnumSet.of(Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL), "" + index); index++; writer.emitField( "int", table.getSingleName(), EnumSet.of(Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL), "" + index); index++; } writer.emitEmptyLine(); writer.emitSingleLineComment("views constants"); for (View view : mModel.getViews()) { writer.emitField( "String", view.name, EnumSet.of(Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL), "\"" + view.name + "\""); writer.emitField( "int", SqlUtil.IDENTIFIER(view), EnumSet.of(Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL), "" + index); index++; } }
private void emitURIMatcher() throws IOException { writer.emitEmptyLine(); writer.emitField( "UriMatcher", "uriMatcher", EnumSet.of(Modifier.PRIVATE, Modifier.STATIC, Modifier.FINAL)); writer.beginInitializer(true); writer.emitStatement("uriMatcher = new UriMatcher(UriMatcher.NO_MATCH)"); for (Table table : mModel.getTables()) { writer.emitStatement( "uriMatcher.addURI(\"" + mModel.getContentAuthority() + "\", \"" + table.name.toLowerCase() + "\", " + table.getAllName() + ")"); writer.emitStatement( "uriMatcher.addURI(\"" + mModel.getContentAuthority() + "\", \"" + table.name.toLowerCase() + "/#\", " + table.getSingleName() + ")"); } for (View view : mModel.getViews()) { writer.emitStatement( "uriMatcher.addURI(\"" + mModel.getContentAuthority() + "\", \"" + view.name.toLowerCase() + "\", " + SqlUtil.IDENTIFIER(view) + ")"); } writer.endInitializer(); }
private void emitTableCRUD(Table table) throws Exception { // Default array params for all rows ArrayList<String> params = new ArrayList<String>(); for (Field row : table.fields) { params.add(SqlUtil.getJavaTypeFor(row.type)); params.add(row.name); } ArrayList<String> paramsWithUnique = new ArrayList<String>(); paramsWithUnique.add(SqlUtil.getJavaTypeFor(table.getPrimaryKey().type)); paramsWithUnique.add(table.getPrimaryKey().name); ArrayList<String> updateParams = new ArrayList<String>(); // TODO : add unique id updateParams.addAll(params); Iterator<Constraint> constraintiter; writer.emitEmptyLine(); writer.emitJavadoc( table.name + " OPERATIONS\nall operations require this client to first run start"); writer.emitEmptyLine(); // Add through ContentProviderOperation writer.beginMethod( "void", "add" + Util.capitalize(table.name), EnumSet.of(Modifier.PUBLIC), params.toArray(new String[params.size()])); writer.emitStatement( "ContentProviderOperation.Builder operationBuilder = ContentProviderOperation.newInsert(" + mModel.getContentProviderName() + "." + SqlUtil.URI(table) + ")"); for (Field row : table.fields) { writer.emitStatement( "operationBuilder.withValue(" + mModel.getDbClassName() + "." + SqlUtil.ROW_COLUMN(table, row) + "," + row.name + ")"); } insertAddOpBlock(); writer.endMethod(); // Removes writeRemoveWith(table, table.getPrimaryKey()); constraintiter = table.constraints.iterator(); while (constraintiter.hasNext()) { Constraint constraint = constraintiter.next(); if (constraint.type.equals(Constraint.Type.UNIQUE)) { final String[] fields = SqlUtil.getFieldsFromConstraint(constraint); for (int i = 0; i < fields.length; i++) { writeRemoveWith(table, table.getFieldByName(fields[i])); } } } // Remove All results writer.emitEmptyLine(); writer.beginMethod( "void", "removeAll" + Util.capitalize(table.name), EnumSet.of(Modifier.PUBLIC)); writer.emitStatement( "ContentProviderOperation.Builder operationBuilder = ContentProviderOperation.newDelete(" + mModel.getContentProviderName() + "." + SqlUtil.URI(table) + ")"); insertAddOpBlock(); writer.endMethod(); // Update through ContentProviderOperation writer.emitEmptyLine(); writer.beginMethod( "void", "update" + Util.capitalize(table.name), EnumSet.of(Modifier.PUBLIC), updateParams.toArray(new String[updateParams.size()])); writer.emitStatement( "ContentProviderOperation.Builder operationBuilder = ContentProviderOperation.newUpdate(" + mModel.getContentProviderName() + "." + SqlUtil.URI(table) + ")"); for (Field row : table.fields) { writer.emitStatement( "operationBuilder.withValue(" + mModel.getDbClassName() + "." + SqlUtil.ROW_COLUMN(table, row) + "," + row.name + ")"); } insertAddOpBlock(); writer.endMethod(); }
private void emitMethods() throws IOException { writer.emitEmptyLine(); writer.emitAnnotation("Override"); writer.beginMethod("boolean", "onCreate", EnumSet.of(Modifier.PUBLIC)); writer.emitStatement("mLocalDatabase = new " + mModel.getDbClassName() + " (getContext())"); writer.emitStatement("return true"); writer.endMethod(); writer.emitEmptyLine(); writer.beginMethod("String", "getTableNameFromUri", EnumSet.of(Modifier.PRIVATE), "Uri", "uri"); writer.beginControlFlow("switch(uriMatcher.match(uri))"); for (Table table : mModel.getTables()) { writer.emitStatement( "\tcase " + table.getAllName() + ":\ncase " + table.getSingleName() + ":\n\treturn " + SqlUtil.IDENTIFIER(table)); } for (View view : mModel.getViews()) { writer.emitStatement("\tcase " + SqlUtil.IDENTIFIER(view) + ":\n\treturn " + view.name); } writer.emitStatement("default: break"); writer.endControlFlow(); writer.emitEmptyLine(); writer.emitStatement("return null"); writer.endMethod(); writer.emitEmptyLine(); writer.beginMethod("String", "getUniqueKey", EnumSet.of(Modifier.PRIVATE), "Uri", "uri"); writer.emitSingleLineComment("Only for actual tables"); writer.beginControlFlow("switch(uriMatcher.match(uri))"); for (Table table : mModel.getTables()) { writer.emitStatement( "\tcase " + table.getAllName() + ":\ncase " + table.getSingleName() + ":\n\treturn \"" + table.UNIQUEROWID().snd + "\""); } writer.emitStatement("default: break"); writer.endControlFlow(); writer.emitEmptyLine(); writer.emitStatement("return null"); writer.endMethod(); writer.emitEmptyLine(); writer.beginMethod( "boolean", "containsUnique", EnumSet.of(Modifier.PRIVATE), "Uri", "uri", "ContentValues", "contentvalues"); writer.emitStatement("String unique = getUniqueKey(uri)"); writer.beginControlFlow("for (String key : contentvalues.keySet())"); writer.beginControlFlow("if (key.equals(unique))"); writer.emitStatement("return true"); writer.endControlFlow(); writer.endControlFlow(); writer.emitStatement("return false"); writer.endMethod(); writer.emitEmptyLine(); writer.beginMethod("Uri", "getContentUriFromUri", EnumSet.of(Modifier.PRIVATE), "Uri", "uri"); writer.emitSingleLineComment("Only for actual tables"); writer.beginControlFlow("switch(uriMatcher.match(uri))"); for (Table table : mModel.getTables()) { writer.emitStatement( "\tcase " + table.getAllName() + ":\ncase " + table.getSingleName() + ":\n\treturn " + SqlUtil.URI(table)); } writer.emitStatement("default: break"); writer.endControlFlow(); writer.emitEmptyLine(); writer.emitStatement("return null"); writer.endMethod(); writer.emitEmptyLine(); writer.beginMethod( "ArrayList<Uri>", "getAssociatedViewUris", EnumSet.of(Modifier.PRIVATE), "Uri", "uri"); writer.emitSingleLineComment("Only for actual views"); writer.emitStatement("ArrayList<Uri> viewUris = null"); writer.beginControlFlow("switch(uriMatcher.match(uri))"); for (Table table : mModel.getTables()) { String statement = "\tcase " + table.getAllName() + ":\ncase " + table.getSingleName() + ":\n\t"; ArrayList<String> associatedviews = new ArrayList<String>(); for (View view : mModel.getViews()) { if (view.getFromtables().contains(table.name)) { associatedviews.add(SqlUtil.URI(view)); } } if (!associatedviews.isEmpty()) { statement += "viewUris = new ArrayList<Uri>();\n\t"; } for (String string : associatedviews) { statement += "viewUris.add(" + string + ");\n\t"; } statement += "break"; writer.emitStatement(statement); } writer.emitStatement("default: break"); writer.endControlFlow(); writer.emitEmptyLine(); writer.emitStatement("return viewUris"); writer.endMethod(); writer.emitEmptyLine(); writer.emitAnnotation("Override"); writer.beginMethod("String", "getType", EnumSet.of(Modifier.PUBLIC), "Uri", "uri"); writer.emitSingleLineComment( "Return a string that identifies the MIME type for a Content Provider URI"); writer.beginControlFlow("switch(uriMatcher.match(uri))"); for (Table table : mModel.getTables()) { writer.emitStatement( "\tcase " + table.getAllName() + ":\n\treturn \"vnd.android.cursor.dir/vnd." + mModel.getClassPackage() + "." + table.name.toLowerCase() + "\""); writer.emitStatement( "\tcase " + table.getSingleName() + ":\n\treturn \"vnd.android.cursor.dir/vnd." + mModel.getClassPackage() + "." + table.name.toLowerCase() + "\""); } for (View view : mModel.getViews()) { writer.emitStatement( "\tcase " + SqlUtil.IDENTIFIER(view) + ":\n\treturn \"vnd.android.cursor.dir/vnd." + mModel.getClassPackage() + "." + view.name.toLowerCase() + "\""); } writer.emitStatement( "default:\n throw new IllegalArgumentException(\"Unsupported URI: \" + uri)"); writer.endControlFlow(); writer.endMethod(); writer.emitEmptyLine(); writer.emitAnnotation("Override"); writer.beginMethod( "Cursor", "query", EnumSet.of(Modifier.PUBLIC), "Uri", "uri", "String[]", "projection", "String", "selection", "String[]", "selectionArgs", "String", "sortOrder"); writer.emitSingleLineComment("Open database"); writer.emitStatement("SQLiteDatabase db"); writer.beginControlFlow("try"); writer.emitStatement("db = mLocalDatabase.getWritableDatabase()"); writer.nextControlFlow("catch (SQLiteException ex)"); writer.emitStatement("db = mLocalDatabase.getReadableDatabase()"); writer.endControlFlow(); writer.emitSingleLineComment("Replace these with valid SQL statements if necessary."); writer.emitStatement("String groupBy = null"); writer.emitStatement("String having = null"); writer.emitStatement("SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder()"); writer.emitSingleLineComment( "If this is a row query, limit the result set to the passed in row."); writer.emitStatement("String rowID"); writer.beginControlFlow("switch(uriMatcher.match(uri))"); for (Table table : mModel.getTables()) { writer.emitStatement( "case " + table.getSingleName() + ":\n\trowID = uri.getPathSegments().get(1);\n\tqueryBuilder.appendWhere(ROW_ID + \"=\" + rowID);\n\tbreak"); } writer.emitStatement("default: break"); writer.endControlFlow(); writer.emitSingleLineComment( "Specify the table on which to perform the query. This can be a specific table or a join as required."); writer.emitStatement("queryBuilder.setTables(getTableNameFromUri(uri))"); writer.emitEmptyLine(); writer.emitSingleLineComment("Execute..."); writer.emitStatement( "Cursor cursor = queryBuilder.query(db, projection, selection, selectionArgs, groupBy, having, sortOrder)"); writer.emitStatement("cursor.setNotificationUri(getContext().getContentResolver(), uri)"); writer.emitStatement("return cursor"); writer.endMethod(); ArrayList<String> throwTypes = new ArrayList<String>(); throwTypes.add("OperationApplicationException"); ArrayList<String> parameters = new ArrayList<String>(); parameters.add("ArrayList <ContentProviderOperation>"); parameters.add("operations"); writer.emitAnnotation("Override"); writer.beginMethod( "ContentProviderResult[]", "applyBatch", EnumSet.of(Modifier.PUBLIC), parameters, throwTypes); writer.emitStatement("SQLiteDatabase db = mLocalDatabase.getWritableDatabase()"); writer.emitStatement("db.beginTransaction()"); writer.emitStatement("final int numOperations = operations.size()"); writer.emitStatement( "final ContentProviderResult[] results = new ContentProviderResult[numOperations]"); writer.emitStatement("Log.i(TAG, \"Applying a batch of \" + numOperations + \" operations.\")"); writer.beginControlFlow("try"); writer.beginControlFlow("for (int i = 0; i < numOperations; i++)"); writer.emitStatement("results[i] = operations.get(i).apply(this, results, i)"); writer.endControlFlow(); writer.emitStatement("db.setTransactionSuccessful()"); writer.nextControlFlow("finally"); writer.emitStatement("db.endTransaction()"); writer.endControlFlow(); writer.emitStatement("return results"); writer.endMethod(); writer.emitEmptyLine(); writer.emitAnnotation("Override"); writer.beginMethod( "int", "delete", EnumSet.of(Modifier.PUBLIC), "Uri", "uri", "String", "selection", "String[]", "selectionArgs"); writer.emitSingleLineComment("Open database"); writer.emitStatement("SQLiteDatabase db = mLocalDatabase.getWritableDatabase()"); writer.emitStatement("String rowID"); writer.emitStatement("String UNIQUEID"); writer.beginControlFlow("switch(uriMatcher.match(uri))"); for (Table table : mModel.getTables()) { writer.emitStatement( "\tcase " + table.getSingleName() + ":" + "\n\tUNIQUEID = \"" + table.UNIQUEROWID().snd + "\";\n\trowID = uri.getPathSegments().get(1);\n\tselection = UNIQUEID + \"=\" + rowID + (!TextUtils.isEmpty(selection) ? \" AND (\" + selection + ')' : \"\")"); } writer.emitStatement("default: break"); writer.endControlFlow(); writer.emitEmptyLine(); writer.beginControlFlow("if (selection == null)"); writer.emitStatement("selection = \"1\""); writer.endControlFlow(); writer.emitEmptyLine(); writer.emitStatement( "int deleteCount = db.delete(getTableNameFromUri(uri), selection, selectionArgs)"); insertNotifyBlock(); writer.emitEmptyLine(); writer.emitStatement("return deleteCount"); writer.endMethod(); writer.emitEmptyLine(); writer.emitAnnotation("Override"); writer.beginMethod( "Uri", "insert", EnumSet.of(Modifier.PUBLIC), "Uri", "uri", "ContentValues", "values"); writer.emitSingleLineComment("Open database"); writer.emitStatement("SQLiteDatabase db = mLocalDatabase.getWritableDatabase()"); writer.emitSingleLineComment("Try to do an insert as per usual"); writer.emitStatement("String nullColumnHack = null"); writer.emitStatement("long id = db.insert(getTableNameFromUri(uri), nullColumnHack, values)"); if (mModel.getConflictStrategy().equals("UPSERT")) { writer.emitEmptyLine(); writer.beginControlFlow("if (id == -1)"); writer.emitSingleLineComment("There was an error inserting, try upsert!"); writer.beginControlFlow("if (containsUnique(uri, values))"); writer.emitStatement("ContentValues withoutUnique = new ContentValues(values)"); writer.emitStatement("String unique = getUniqueKey(uri)"); writer.emitStatement("withoutUnique.remove(unique)"); writer.emitStatement("String selection = unique + \"=?\""); writer.emitStatement( "String[] selectionArgs = new String[]{String.valueOf(values.get(unique))}"); writer.emitStatement( "int updated = db.update(getTableNameFromUri(uri), withoutUnique, selection, selectionArgs)"); writer.beginControlFlow("if (updated > 0)"); writer.emitSingleLineComment( "If any row was updated, we'll get the row id from that row so we can pass it along below."); writer.emitStatement("SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder()"); writer.emitStatement("queryBuilder.setTables(getTableNameFromUri(uri))"); writer.emitStatement( "Cursor c = queryBuilder.query(db, new String[]{\"_id\"}, selection, selectionArgs, null, null, null)"); writer.emitStatement("c.moveToNext()"); writer.emitStatement("id = c.getLong(0)"); writer.emitStatement("c.close()"); writer.endControlFlow(); writer.endControlFlow(); writer.endControlFlow(); } writer.emitEmptyLine(); writer.beginControlFlow("if (id > -1)"); writer.emitSingleLineComment("the insert was successful"); writer.emitStatement( "Uri insertedId = ContentUris.withAppendedId(getContentUriFromUri(uri), id)"); insertNotifyBlock(); writer.emitEmptyLine(); writer.emitStatement("return insertedId"); writer.endControlFlow(); writer.emitStatement("return null"); writer.endMethod(); writer.emitEmptyLine(); writer.emitAnnotation("Override"); writer.beginMethod( "int", "update", EnumSet.of(Modifier.PUBLIC), "Uri", "uri", "ContentValues", "values", "String", "selection", "String[]", "selectionArgs"); writer.emitSingleLineComment("Open database"); writer.emitStatement("SQLiteDatabase db = mLocalDatabase.getWritableDatabase()"); writer.emitSingleLineComment("If this is a row URI, limit the deletion to the specified row."); writer.emitStatement("String rowID"); writer.emitStatement("String UNIQUEID"); writer.beginControlFlow("switch(uriMatcher.match(uri))"); for (Table table : mModel.getTables()) { writer.emitStatement( "\tcase " + table.getSingleName() + ":" + "\n\tUNIQUEID = \"" + table.UNIQUEROWID().snd + "\";\n\trowID = uri.getPathSegments().get(1);\n\tselection = UNIQUEID + \"=\" + rowID + (!TextUtils.isEmpty(selection) ? \" AND (\" + selection + ')' : \"\")"); } writer.emitStatement("default: break"); writer.endControlFlow(); writer.emitSingleLineComment("Perform update"); writer.emitStatement( "int updateCount = db.update(getTableNameFromUri(uri), values, selection, selectionArgs)"); insertNotifyBlock(); writer.emitEmptyLine(); writer.emitStatement("return updateCount"); writer.endMethod(); }