Skip to content

Commit

Permalink
Merge branch 'release-0.4.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
AndrewReitz committed Nov 16, 2014
2 parents f2fc6a5 + d9aab1c commit 35cb20d
Show file tree
Hide file tree
Showing 6 changed files with 119 additions and 95 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Change Log

## Version 0.4.0 (11-27-2014)

- Added query builder functionality. Returned from `selectFrom`
- Removed namespacing on tables. All tables MUST have unique names.
- Create statements written out.
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,19 +62,19 @@ jar in your application compile time. You can download the jars
<dependency>
<groupId>com.andrewreitz</groupId>
<artifactId>shillelagh</artifactId>
<version>0.3.0</version>
<version>0.4.0</version>
</dependency>
<dependency>
<groupId>com.andrewreitz</groupId>
<artifactId>shillelagh-processor</artifactId>
<version>0.3.0</version>
<version>0.4.0</version>
<optional>true</optional>
</dependency>
```
## Gradle:
```groovy
compile 'com.andrewreitz:shillelagh:0.3.0'
provided 'com.andrewreitz:shillelagh:0.3.0'
compile 'com.andrewreitz:shillelagh:0.4.0'
provided 'com.andrewreitz:shillelagh:0.4.0'
```

# License
Expand Down
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ buildscript {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:0.14.0'
classpath 'com.android.tools.build:gradle:0.14.1'
classpath 'com.netflix.nebula:gradle-extra-configurations-plugin:1.12.3'
classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:0.6'
classpath 'org.jfrog.buildinfo:build-info-extractor-gradle:3.0.1'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -140,12 +140,13 @@ public final class ShillelaghProcessor extends AbstractProcessor {
Element element = tableObject.getOriginatingElement();

try {
// Write out the create statement.
JavaFileManager.Location location = StandardLocation.SOURCE_OUTPUT;
String path = getPackageName(element);
String file = tableObject.getTableName() + ".sql";
FileObject resource = filer.createResource(location, path, file, element);
Writer writer = resource.openWriter();
writer.write(tableObject.getSchema());
writer.write(tableObject.toString());
writer.flush();
writer.close();
} catch (IOException e) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,23 +49,23 @@

class TableObject {

private static final String SERIALIZE_FUNCTION = "serialize";
private static final String DESERIALIZE_FUNCTION = "deserialize";
private static final String SERIALIZE_FUNCTION = "ShillelaghUtil.serialize";
private static final String DESERIALIZE_FUNCTION = "ShillelaghUtil.deserialize";
private static final String GET_ID_FUNCTION = "getId";
private static final String SELECT_ALL_FUNCTION = "selectAll";
private static final String PARENT_INSERT_FUNCTION = "parentInsert";
private static final String INSERT_ONE_TO_ONE = "insertOneToOne";

/** Used as a template to create a new table */
private static final String CREATE_TABLE_DEFAULT = "CREATE TABLE %s "
+ "(%s INTEGER PRIMARY KEY AUTOINCREMENT, %s);";
private static final String CREATE_TABLE_DEFAULT =
"CREATE TABLE %s " + "(%s INTEGER PRIMARY KEY AUTOINCREMENT, %s);";

/**
* SQL statement to select the id of the last inserted row. Does not end with ; in order to be
* used with SQLiteDatabase#rawQuery(String, String[])
*/
private static final String GET_ID_OF_LAST_INSERTED_ROW_SQL
= "SELECT ROWID FROM %s ORDER BY ROWID DESC LIMIT 1";
private static final String GET_ID_OF_LAST_INSERTED_ROW_SQL =
"SELECT ROWID FROM %s ORDER BY ROWID DESC LIMIT 1";

private final Element element;
private final String classPackage;
Expand Down Expand Up @@ -113,7 +113,7 @@ String getTargetClass() {
}

/** Get table schema */
String getSchema() {
private String getSchema() {
StringBuilder sb = new StringBuilder();
Iterator<TableColumn> iterator = columns.iterator();
while (iterator.hasNext()) {
Expand Down Expand Up @@ -146,14 +146,14 @@ void brewJava(Writer writer) throws IOException {
JavaWriter javaWriter = new JavaWriter(writer);
javaWriter.setCompressingTypes(false);

javaWriter.emitSingleLineComment("Generated code from Shillelagh. Do not modify!")
.emitPackage(classPackage)
/* Knows nothing of android types */
.emitImports("android.content.ContentValues", "android.database.Cursor",
"android.database.DatabaseUtils", "android.database.sqlite.SQLiteDatabase")
.emitImports(ByteArrayInputStream.class, ByteArrayOutputStream.class, IOException.class,
ObjectInputStream.class, ObjectOutputStream.class, LinkedList.class, Date.class,
List.class)
javaWriter.emitSingleLineComment("Generated code from Shillelagh. Do not modify!") //
.emitPackage(classPackage) //
/* Knows nothing of android types, must use strings. */ //
.emitImports("android.content.ContentValues", "android.database.Cursor", //
"android.database.DatabaseUtils", "android.database.sqlite.SQLiteDatabase") //
.emitImports(ShillelaghUtil.class, ByteArrayInputStream.class, ByteArrayOutputStream.class,
IOException.class, ObjectInputStream.class, ObjectOutputStream.class, LinkedList.class,
Date.class, List.class) //
.beginType(className, "class", EnumSet.of(PUBLIC, FINAL));

if (this.isChildTable) {
Expand All @@ -172,33 +172,28 @@ void brewJava(Writer writer) throws IOException {
emitMapCursorToObject(javaWriter);
emitSingleMap(javaWriter);
emitSelectById(javaWriter);
emitByteArraySerialization(javaWriter);
javaWriter.endType();
}

/** Create a way to get an id for foreign keys */
private void emitGetId(JavaWriter javaWriter) throws IOException {
logger.d("emitGetId");
javaWriter.beginMethod(
"long", GET_ID_FUNCTION, EnumSet.of(PUBLIC, STATIC), getTargetClass(), "value")
.emitStatement("return value.%s", idColumnName)
.endMethod();
javaWriter.beginMethod("long", GET_ID_FUNCTION, EnumSet.of(PUBLIC, STATIC), getTargetClass(),
"value").emitStatement("return value.%s", idColumnName).endMethod();
}

/** Creates the function for creating the table */
private void emitCreateTable(JavaWriter javaWriter) throws IOException {
logger.d("emitCreateTable");
javaWriter.beginMethod(
"void", $$CREATE_TABLE_FUNCTION, EnumSet.of(PUBLIC, STATIC), "SQLiteDatabase", "db")
.emitStatement("db.execSQL(\"%s\")", getSchema())
.endMethod();
javaWriter.beginMethod("void", $$CREATE_TABLE_FUNCTION, EnumSet.of(PUBLIC, STATIC),
"SQLiteDatabase", "db").emitStatement("db.execSQL(\"%s\")", getSchema()).endMethod();
}

/** Creates the function dropping the table */
private void emitDropTable(JavaWriter javaWriter) throws IOException {
logger.d("emitDropTable");
javaWriter.beginMethod(
"void", $$DROP_TABLE_FUNCTION, EnumSet.of(PUBLIC, STATIC), "SQLiteDatabase", "db")
javaWriter.beginMethod("void", $$DROP_TABLE_FUNCTION, EnumSet.of(PUBLIC, STATIC),
"SQLiteDatabase", "db")
.emitStatement("db.execSQL(\"DROP TABLE IF EXISTS %s\")", getTableName())
.endMethod();
}
Expand All @@ -217,13 +212,13 @@ private void emitInsert(JavaWriter javaWriter) throws IOException {
javaWriter.emitStatement("values.put(\"%s\", %s(element.%s))", columnName,
SERIALIZE_FUNCTION, columnName);
} else if (column.isOneToOne()) {
javaWriter.emitStatement("%s%s.%s(element.%s, db)", column.getType(),
$$SUFFIX, INSERT_ONE_TO_ONE, column.getColumnName())
.emitStatement("values.put(\"%s\", %s%s.%s(element.%s))", columnName,
column.getType(), $$SUFFIX, GET_ID_FUNCTION, columnName);
javaWriter.emitStatement("%s%s.%s(element.%s, db)", column.getType(), $$SUFFIX,
INSERT_ONE_TO_ONE, column.getColumnName())
.emitStatement("values.put(\"%s\", %s%s.%s(element.%s))", columnName, column.getType(),
$$SUFFIX, GET_ID_FUNCTION, columnName);
} else if (column.isDate()) {
javaWriter.emitStatement(
"values.put(\"%s\", element.%s.getTime())", columnName, columnName);
javaWriter.emitStatement("values.put(\"%s\", element.%s.getTime())", columnName,
columnName);
} else if (column.isOneToMany()) {
childColumns.add(column);
} else if (!column.isOneToManyChild()) {
Expand All @@ -237,8 +232,8 @@ private void emitInsert(JavaWriter javaWriter) throws IOException {
+ "\"SELECT ROWID FROM %s ORDER BY ROWID DESC LIMIT 1\", null)", tableName);
}
for (TableColumn childColumn : childColumns) {
javaWriter.emitStatement("%s%s.%s(id, element.%s, db)", childColumn.getType(),
$$SUFFIX, PARENT_INSERT_FUNCTION, childColumn.getColumnName());
javaWriter.emitStatement("%s%s.%s(id, element.%s, db)", childColumn.getType(), $$SUFFIX,
PARENT_INSERT_FUNCTION, childColumn.getColumnName());
}

javaWriter.endMethod();
Expand Down Expand Up @@ -305,8 +300,7 @@ private void emitDeleteWithObject(JavaWriter javaWriter) throws IOException {
logger.d("emitDeleteWithObject");
javaWriter.beginMethod("void", $$DELETE_OBJECT_FUNCTION, EnumSet.of(PUBLIC, STATIC),
getTargetClass(), "element", "SQLiteDatabase", "db")
.emitStatement(
"%s(element.%s, db)", $$DELETE_OBJECT_FUNCTION, idColumnName)
.emitStatement("%s(element.%s, db)", $$DELETE_OBJECT_FUNCTION, idColumnName)
.endMethod();
}

Expand All @@ -332,8 +326,8 @@ private void emitMapCursorToObject(JavaWriter javaWriter) throws IOException {

private void emitSingleMap(JavaWriter javaWriter) throws IOException {
String targetClass = getTargetClass();
javaWriter.beginMethod(targetClass, $$MAP_SINGLE_FUNCTION, EnumSet.of(PUBLIC, STATIC),
"Cursor", "cursor", "SQLiteDatabase", "db")
javaWriter.beginMethod(targetClass, $$MAP_SINGLE_FUNCTION, EnumSet.of(PUBLIC, STATIC), "Cursor",
"cursor", "SQLiteDatabase", "db")
.emitStatement("%s tableObject = new %s()", targetClass, getTargetClass())
.emitStatement("tableObject.%s = cursor.getLong(cursor.getColumnIndex(\"%s\"))",
idColumnName, idColumnName);
Expand All @@ -346,8 +340,8 @@ private void emitSingleMap(JavaWriter javaWriter) throws IOException {
CursorFunctions.get(long.class.getName()), columnName);
} else if (column.isOneToOne()) {
javaWriter.emitStatement(
"tableObject.%s = %s%s.%s(cursor.%s(cursor.getColumnIndex(\"%s\")), db)",
columnName, column.getType(), $$SUFFIX, $$GET_OBJECT_BY_ID,
"tableObject.%s = %s%s.%s(cursor.%s(cursor.getColumnIndex(\"%s\")), db)", columnName,
column.getType(), $$SUFFIX, $$GET_OBJECT_BY_ID,
CursorFunctions.get(Long.class.getName()), columnName);
} else if (column.isBoolean()) {
javaWriter.emitStatement("tableObject.%s = cursor.%s(cursor.getColumnIndex(\"%s\")) == 1",
Expand All @@ -357,15 +351,14 @@ private void emitSingleMap(JavaWriter javaWriter) throws IOException {
javaWriter.emitStatement("tableObject.%s = cursor.%s(cursor.getColumnIndex(\"%s\"))",
columnName, CursorFunctions.get(column.getType()), columnName);
} else {
javaWriter.emitStatement(
"tableObject.%s = %s(cursor.%s(cursor.getColumnIndex(\"%s\")));", columnName,
DESERIALIZE_FUNCTION, CursorFunctions.get(column.getType()), columnName);
javaWriter.emitStatement("tableObject.%s = %s(cursor.%s(cursor.getColumnIndex(\"%s\")));",
columnName, DESERIALIZE_FUNCTION, CursorFunctions.get(column.getType()), columnName);
}
} else if (column.isOneToMany()) {
javaWriter.emitStatement("Cursor childCursor = %s%s.%s(db)", column.getType(),
$$SUFFIX, SELECT_ALL_FUNCTION)
.emitStatement("tableObject.%s = %s%s.%s(childCursor, db)",
column.getColumnName(), column.getType(), $$SUFFIX, $$MAP_OBJECT_FUNCTION)
javaWriter.emitStatement("Cursor childCursor = %s%s.%s(db)", column.getType(), $$SUFFIX,
SELECT_ALL_FUNCTION)
.emitStatement("tableObject.%s = %s%s.%s(childCursor, db)", column.getColumnName(),
column.getType(), $$SUFFIX, $$MAP_OBJECT_FUNCTION)
.emitStatement("childCursor.close()");
} else if (column.isOneToManyChild()) {
// TODO Skip and have custom mapping?
Expand All @@ -375,43 +368,40 @@ private void emitSingleMap(JavaWriter javaWriter) throws IOException {
}
}

javaWriter.emitStatement("return tableObject")
.endMethod();
javaWriter.emitStatement("return tableObject").endMethod();
}

/** Creates function for getting an object by value */
private void emitSelectById(JavaWriter javaWriter) throws IOException {
logger.d("emitSelectById");
javaWriter.beginMethod(getTargetClass(), $$GET_OBJECT_BY_ID, EnumSet.of(PUBLIC, STATIC), "long",
"id", "SQLiteDatabase", "db")
.emitStatement("Cursor cursor = db.rawQuery(\"SELECT * FROM %s WHERE %s = id\", null)"
, getTableName(), idColumnName)
.emitStatement("Cursor cursor = db.rawQuery(\"SELECT * FROM %s WHERE %s = id\", null)",
getTableName(), idColumnName)
.emitStatement("%s value = %s(cursor, db).get(0)", getTargetClass(), $$MAP_OBJECT_FUNCTION)
.emitStatement("cursor.close()")
.emitStatement("return value")
.endMethod();
}

private void emitParentInsert(JavaWriter javaWriter) throws IOException {
javaWriter.beginMethod("void", PARENT_INSERT_FUNCTION, EnumSet.of(PUBLIC, STATIC),
"long", "parentId", String.format("List<%s>", getTargetClass()), "children",
"SQLiteDatabase", "db")
javaWriter.beginMethod("void", PARENT_INSERT_FUNCTION, EnumSet.of(PUBLIC, STATIC), "long",
"parentId", String.format("List<%s>", getTargetClass()), "children", "SQLiteDatabase", "db")
.beginControlFlow("for(%s child : children)", getTargetClass())
.emitStatement("ContentValues values = new ContentValues()");
for (TableColumn column : columns) {
String columnName = column.getColumnName();
if (column.getSqlType() == SqliteType.BLOB && !column.isByteArray()) {
javaWriter.emitStatement("values.put(\"%s\", %s(child.%s))", columnName,
SERIALIZE_FUNCTION, columnName);
javaWriter.emitStatement("values.put(\"%s\", %s(child.%s))", columnName, SERIALIZE_FUNCTION,
columnName);
} else if (column.isOneToOne()) {
javaWriter.emitStatement("values.put(\"%s\", %s%s.%s(child.%s))", columnName,
column.getType(), $$SUFFIX, GET_ID_FUNCTION, columnName);
} else if (column.isDate()) {
javaWriter.emitStatement(
"values.put(\"%s\", child.%s.getTime())", columnName, columnName);
javaWriter.emitStatement("values.put(\"%s\", child.%s.getTime())", columnName, columnName);
} else if (column.getSqlType() == SqliteType.ONE_TO_MANY) {
javaWriter.emitStatement("%s.%s.%s(%s)", column.getType(), $$SUFFIX,
PARENT_INSERT_FUNCTION, columnName);
javaWriter.emitStatement("%s.%s.%s(%s)", column.getType(), $$SUFFIX, PARENT_INSERT_FUNCTION,
columnName);
} else if (column.getSqlType() == SqliteType.ONE_TO_MANY_CHILD) {
javaWriter.emitStatement("values.put(\"%s\", %s)", columnName, "parentId");
} else {
Expand Down Expand Up @@ -445,35 +435,7 @@ private void emitOneToOneInsert(JavaWriter javaWriter) throws IOException {
.endMethod();
}

/** Creates functions for serialization to and from byte arrays */
private void emitByteArraySerialization(JavaWriter javaWriter) throws IOException {
logger.d("emitByteArraySerialization");
javaWriter.beginMethod("<K> byte[]", SERIALIZE_FUNCTION, EnumSet.of(STATIC), "K", "object")
.beginControlFlow("try")
.emitStatement("ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream()")
.emitStatement(
"ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream)")
.emitStatement("objectOutputStream.writeObject(object)")
.emitStatement("return byteArrayOutputStream.toByteArray()")
.nextControlFlow("catch (IOException e)")
.emitStatement("throw new RuntimeException(e)")
.endControlFlow()
.endMethod()
.beginMethod("<K> K", DESERIALIZE_FUNCTION, EnumSet.of(STATIC), "byte[]", "bytes")
.beginControlFlow("try")
.emitStatement(
"ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes)")
.emitStatement(
"ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream)")
.emitStatement("return (K) objectInputStream.readObject()")
.nextControlFlow("catch (IOException e)")
.emitStatement("throw new RuntimeException(e)")
.nextControlFlow("catch (ClassNotFoundException e)")
.emitStatement("throw new RuntimeException(e)")
.endControlFlow()
.endMethod();
}

/** Retruns the create statement for this table object */
@Override public String toString() {
return getSchema();
}
Expand Down
54 changes: 54 additions & 0 deletions shillelagh/src/main/java/shillelagh/internal/ShillelaghUtil.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/*
* Copyright 2014 Andrew Reitz
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package shillelagh.internal;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

public final class ShillelaghUtil {

public static <K> byte[] serialize(K object) {
try {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
objectOutputStream.writeObject(object);
return byteArrayOutputStream.toByteArray();
} catch (IOException e) {
throw new RuntimeException(e);
}
}

public static <K> K deserialize(byte[] bytes) {
try {
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);
ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream);
@SuppressWarnings("unchecked") final K k = (K) objectInputStream.readObject();
return k;
} catch (IOException e) {
throw new RuntimeException(e);
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
}

private ShillelaghUtil() {
/* No Instances */
}
}

0 comments on commit 35cb20d

Please sign in to comment.