com.nhaarman.ellie.internal.codegen.writer.ModelRepositoryWriter Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of compiler Show documentation
Show all versions of compiler Show documentation
Compile-time active record ORM for Android.
The newest version!
/*
* Copyright (C) 2014 Niek Haarman
*
* 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 com.nhaarman.ellie.internal.codegen.writer;
import android.content.ContentValues;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import com.google.common.collect.Sets;
import com.nhaarman.ellie.Ellie;
import com.nhaarman.ellie.Model;
import com.nhaarman.ellie.ModelRepository;
import com.nhaarman.ellie.annotation.Table;
import com.nhaarman.ellie.internal.codegen.Registry;
import com.nhaarman.ellie.internal.codegen.element.ColumnElement;
import com.nhaarman.ellie.query.Select;
import com.nhaarman.ellie.util.LruCache;
import com.squareup.javawriter.JavaWriter;
import java.io.IOException;
import java.io.Writer;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import javax.lang.model.element.Modifier;
import javax.lang.model.element.TypeElement;
import static javax.lang.model.element.Modifier.FINAL;
import static javax.lang.model.element.Modifier.STATIC;
@SuppressWarnings("HardCodedStringLiteral") public class ModelRepositoryWriter implements SourceWriter {
private static final Map CURSOR_METHOD_MAP = new HashMap() {
{
put(byte[].class.getName(), "getBlob");
put(Byte[].class.getName(), "getBlob");
put(double.class.getName(), "getDouble");
put(Double.class.getName(), "getDouble");
put(float.class.getName(), "getFloat");
put(Float.class.getName(), "getFloat");
put(int.class.getName(), "getInt");
put(Integer.class.getName(), "getInt");
put(long.class.getName(), "getLong");
put(Long.class.getName(), "getLong");
put(short.class.getName(), "getShort");
put(Short.class.getName(), "getShort");
put(String.class.getName(), "getString");
}
};
private static final EnumSet PRIVATE = EnumSet.of(Modifier.PRIVATE, FINAL);
private static final EnumSet PUBLIC = EnumSet.of(Modifier.PUBLIC, FINAL);
private static final EnumSet PUBLIC_FINAL = EnumSet.of(Modifier.PUBLIC, FINAL);
private static final EnumSet PRIVATE_STATIC = EnumSet.of(Modifier.PRIVATE, STATIC);
private final Registry mRegistry;
public ModelRepositoryWriter(final Registry registry) {
mRegistry = registry;
}
@Override
public String createSourceName(final TypeElement element) {
return "com.nhaarman.ellie." + createSimpleName(element);
}
@Override
public void writeSource(final Writer writer, final TypeElement element) throws IOException {
final String classSimpleName = createSimpleName(element);
final String modelSimpleName = element.getSimpleName().toString();
final String modelQualifiedName = element.getQualifiedName().toString();
final String tableName = element.getAnnotation(Table.class).value();
final Set columns = mRegistry.getColumnElements(element);
JavaWriter javaWriter = new JavaWriter(writer);
javaWriter.setCompressingTypes(true);
javaWriter.setIndent(" ");
javaWriter.emitSingleLineComment("Generated by Ellie. Do not modify!");
javaWriter.emitPackage("com.nhaarman.ellie");
writeImports(javaWriter, modelQualifiedName, columns);
writeBeginType(javaWriter, classSimpleName, modelSimpleName, modelQualifiedName);
writeFields(javaWriter, modelSimpleName);
writeConstructor(javaWriter);
writeFind(javaWriter, modelSimpleName);
writeCreate(javaWriter, modelSimpleName, tableName);
writeUpdate(javaWriter, modelSimpleName, tableName);
writeLoad(javaWriter, modelQualifiedName, columns);
writeCreateOrUpdate(javaWriter, modelSimpleName);
writeDelete(javaWriter, modelSimpleName, tableName);
writePutEntity(javaWriter, modelSimpleName);
writeGetEntity(javaWriter, modelSimpleName);
writeRemoveEntity(javaWriter, modelSimpleName);
writeGetOrFindEntity(javaWriter, modelSimpleName);
writeCreateContentValues(javaWriter, modelQualifiedName, columns);
writeGetEntityIdentifier(javaWriter, modelSimpleName);
javaWriter.endType();
}
private void writeImports(final JavaWriter writer, final String modelQualifiedName, final Set columns)
throws IOException {
Set imports = Sets.newHashSet(
modelQualifiedName,
Ellie.class.getName(),
ContentValues.class.getName(),
Cursor.class.getName(),
SQLiteDatabase.class.getName(),
ModelRepository.class.getName(),
Select.class.getName(),
LruCache.class.getName()
);
for (ColumnElement column : columns) {
if (column.isModel()) {
imports.add(Long.class.getName());
}
if (column.requiresTypeAdapter()) {
imports.add(column.getDeserializedQualifiedName());
imports.add(column.getSerializedQualifiedName());
}
}
TypeElement modelRepositoryElement = mRegistry.getModelElement(modelQualifiedName).getModelRepositoryElement();
if (modelRepositoryElement != null) {
imports.add(modelRepositoryElement.getQualifiedName().toString());
}
writer.emitImports(imports);
writer.emitEmptyLine();
}
private void writeBeginType(final JavaWriter javaWriter, final String classSimpleName, final String modelSimpleName, final String modelQualifiedName) throws IOException {
TypeElement modelRepositoryElement = mRegistry.getModelElement(modelQualifiedName).getModelRepositoryElement();
String modelRepositoryName = modelRepositoryElement == null ? null : modelRepositoryElement.getQualifiedName().toString();
javaWriter.beginType(classSimpleName, "class", PUBLIC_FINAL, modelRepositoryName, "ModelRepository<" + modelSimpleName + ">");
javaWriter.emitEmptyLine();
}
private void writeFields(final JavaWriter javaWriter, final String modelSimpleName) throws IOException {
javaWriter.emitField(Ellie.class.getSimpleName(), "mEllie", PRIVATE);
javaWriter.emitField(SQLiteDatabase.class.getSimpleName(), "mDatabase", PRIVATE);
javaWriter.emitField(
String.format(
"%s<%s, %s>",
LruCache.class.getSimpleName(),
String.class.getSimpleName(),
modelSimpleName
),
"mCache",
PRIVATE
);
javaWriter.emitEmptyLine();
}
private void writeConstructor(final JavaWriter javaWriter) throws IOException {
javaWriter.beginConstructor(
EnumSet.of(Modifier.PUBLIC),
"final " + Ellie.class.getSimpleName(), "ellie",
"final " + SQLiteDatabase.class.getSimpleName(), "database",
"final int", "cacheSize"
);
javaWriter.emitStatement("mEllie = ellie");
javaWriter.emitStatement("mDatabase = database");
javaWriter.emitStatement("mCache = new LruCache<>(cacheSize)");
javaWriter.endConstructor();
javaWriter.emitEmptyLine();
}
private void writeFind(final JavaWriter javaWriter, final String modelSimpleName) throws IOException {
javaWriter.emitAnnotation(Override.class);
javaWriter.beginMethod(modelSimpleName, "find", PUBLIC, "final long", " id");
javaWriter.emitStatement("return new Select().from(%s.class).where(\"%s=?\", id).fetchSingle()", modelSimpleName, Model.COLUMN_ID);
javaWriter.endMethod();
javaWriter.emitEmptyLine();
}
private void writeCreate(final JavaWriter javaWriter, final String modelSimpleName, final String tableName) throws IOException {
javaWriter.emitAnnotation(Override.class);
javaWriter.beginMethod(Long.class.getSimpleName(), "create", PUBLIC, "final " + modelSimpleName, " entity");
javaWriter.emitStatement("ContentValues values = createContentValues(entity)");
javaWriter.emitStatement("entity.setId(mDatabase.insert(\"%s\", null, values))", tableName);
javaWriter.emitStatement("return entity.getId()");
javaWriter.endMethod();
javaWriter.emitEmptyLine();
}
private void writeUpdate(final JavaWriter javaWriter, final String modelSimpleName, final String tableName) throws IOException {
javaWriter.emitAnnotation(Override.class);
javaWriter.beginMethod(Long.class.getSimpleName(), "update", PUBLIC, "final " + modelSimpleName, " entity");
javaWriter.emitStatement("ContentValues values = createContentValues(entity)");
javaWriter.emitStatement("mDatabase.update(\"%s\", values, Model.COLUMN_ID + \"=?\", new String[]{entity.getId().toString()})", tableName);
javaWriter.emitStatement("return entity.getId()");
javaWriter.endMethod();
javaWriter.emitEmptyLine();
}
private void writeLoad(final JavaWriter writer, final String modelQualifiedName, final Set columns) throws IOException {
writer.emitAnnotation(Override.class);
writer.beginMethod(void.class.getSimpleName(), "load", EnumSet.of(Modifier.PUBLIC, FINAL), "final " + modelQualifiedName, "entity", "final Cursor", "cursor");
for (ColumnElement column : columns) {
final StringBuilder value = new StringBuilder();
int closeParens = 1;
if (column.isModel()) {
closeParens++;
value.append("mEllie.getModelRepository(")
.append(column.getDeserializedQualifiedName())
.append(".class).getOrFindEntity(");
} else if (column.requiresTypeAdapter()) {
closeParens++;
value.append("mEllie.getTypeAdapter(")
.append(column.getDeserializedSimpleName())
.append(".class).deserialize(");
}
value.append("cursor.").append(CURSOR_METHOD_MAP.get(column.getSerializedQualifiedName())).append("(");
value.append("cursor.getColumnIndex(\"").append(column.getColumnName()).append("\")");
for (int i = 0; i < closeParens; i++) {
value.append(")");
}
if (column.getSetter() == null) {
writer.emitStatement("entity.%s = %s", column.getFieldName(), value.toString());
} else {
writer.emitStatement("entity.%s(%s)", column.getSetter().getSimpleName(), value.toString());
}
}
writer.endMethod();
writer.emitEmptyLine();
}
private void writeCreateOrUpdate(final JavaWriter writer, final String modelSimpleName) throws IOException {
writer.emitAnnotation(Override.class);
writer.beginMethod(Long.class.getSimpleName(), "createOrUpdate", PUBLIC, "final " + modelSimpleName, "entity");
writer.beginControlFlow("if (entity.getId() == null)");
writer.emitStatement("return create(entity)");
writer.nextControlFlow("else");
writer.emitStatement("return update(entity)");
writer.endControlFlow();
writer.endMethod();
writer.emitEmptyLine();
}
private void writeDelete(final JavaWriter writer, final String modelSimpleName, final String tableName) throws IOException {
writer.emitAnnotation(Override.class);
writer.beginMethod(void.class.getSimpleName(), "delete", PUBLIC, "final " + modelSimpleName, "entity");
writer.emitStatement("mDatabase.delete(\"%s\", \"%s=?\", new String[]{entity.getId().toString()});", tableName, Model.COLUMN_ID);
writer.endMethod();
writer.emitEmptyLine();
}
private void writePutEntity(final JavaWriter writer, final String modelSimpleName) throws IOException {
writer.emitAnnotation(Override.class);
writer.beginMethod(void.class.getSimpleName(), "putEntity", PUBLIC, "final " + modelSimpleName, "entity");
writer.beginControlFlow("if (entity.getId() != null)");
writer.emitStatement("mCache.put(getEntityIdentifier(entity.getId()), entity)");
writer.endControlFlow();
writer.endMethod();
writer.emitEmptyLine();
}
private void writeGetEntity(final JavaWriter writer, final String modelSimpleName) throws IOException {
writer.emitAnnotation(Override.class);
writer.beginMethod(modelSimpleName, "getEntity", PUBLIC, "final long", "id");
writer.emitStatement("return mCache.get(getEntityIdentifier(id))");
writer.endMethod();
writer.emitEmptyLine();
}
private void writeRemoveEntity(final JavaWriter writer, final String modelSimpleName) throws IOException {
writer.emitAnnotation(Override.class);
writer.beginMethod(void.class.getSimpleName(), "removeEntity", PUBLIC, "final " + modelSimpleName, "entity");
writer.beginControlFlow("if (entity.getId() != null)");
writer.emitStatement("mCache.remove(getEntityIdentifier(entity.getId()))");
writer.endControlFlow();
writer.endMethod();
writer.emitEmptyLine();
}
private void writeGetOrFindEntity(final JavaWriter writer, final String modelSimpleName) throws IOException {
writer.emitAnnotation(Override.class);
writer.beginMethod(modelSimpleName, "getOrFindEntity", PUBLIC, "final long", "id");
writer.emitStatement("%s entity = getEntity(id)", modelSimpleName);
writer.beginControlFlow("if (entity == null)");
writer.emitStatement("entity = find(id)");
writer.endControlFlow();
writer.emitStatement("return entity");
writer.endMethod();
writer.emitEmptyLine();
}
private void writeGetEntityIdentifier(final JavaWriter writer, final String modelSimpleName) throws IOException {
writer.beginMethod(String.class.getSimpleName(), "getEntityIdentifier", PRIVATE_STATIC, "final long", "id");
writer.emitStatement("return \"%s@\" + id", modelSimpleName);
writer.endMethod();
writer.emitEmptyLine();
}
private void writeCreateContentValues(final JavaWriter writer, final String modelQualifiedName, final Set columns) throws IOException {
writer.beginMethod(ContentValues.class.getSimpleName(), "createContentValues", PUBLIC, "final " + modelQualifiedName, "entity");
writer.emitStatement("ContentValues values = new ContentValues()");
final StringBuilder value = new StringBuilder();
for (ColumnElement column : columns) {
value.setLength(0);
int closeParens = 0;
if (!column.isModel() && column.requiresTypeAdapter()) {
closeParens++;
value.append("(").append(column.getSerializedSimpleName())
.append(") mEllie.getTypeAdapter(")
.append(column.getDeserializedSimpleName())
.append(".class).serialize(");
}
if (column.getGetter() == null) {
value.append("entity.").append(column.getFieldName());
} else {
value.append("entity.").append(column.getGetter());
}
if (column.isModel()) {
value.append(" != null ? ");
value.append("entity.");
if (column.getGetter() == null) {
value.append(column.getFieldName());
} else {
value.append(column.getGetter());
}
value.append(".getId()");
value.append(" : null");
}
for (int i = 0; i < closeParens; i++) {
value.append(")");
}
writer.emitStatement("values.put(\"" + column.getColumnName() + "\", " + value + ")");
}
writer.emitStatement("return values");
writer.endMethod();
writer.emitEmptyLine();
}
private String createSimpleName(final TypeElement element) {
return element.getSimpleName() + "$$Repository";
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy