diff --git a/pom.xml b/pom.xml
index 89c87e6b..062ed078 100644
--- a/pom.xml
+++ b/pom.xml
@@ -146,6 +146,24 @@
1.5
1.5
+
+
+ default-compile
+
+ -proc:none
+
+ com/j256/ormlite/android/processor/OrmLiteAnnotationProcessor.java
+
+
+
+
+ compile-everything-else
+ compile
+
+ compile
+
+
+
org.apache.maven.plugins
@@ -248,6 +266,33 @@
$1${version}$2
+
+ org.apache.maven.plugins
+ maven-shade-plugin
+ 2.3
+
+
+ package
+
+ shade
+
+
+
+
+ com.squareup:javapoet
+
+
+ true
+
+
+ com.squareup.javapoet
+ com.j256.ormlite.android.processor.javapoet
+
+
+
+
+
+
@@ -330,6 +375,11 @@
${android-support-version}
true
+
+ com.squareup
+ javapoet
+ 1.0.0
+
@@ -386,5 +436,11 @@
${easymock-version}
test
+
+ com.google.testing.compile
+ compile-testing
+ 0.6
+ test
+
diff --git a/src/main/java/com/j256/ormlite/android/annotations/Database.java b/src/main/java/com/j256/ormlite/android/annotations/Database.java
new file mode 100644
index 00000000..f9623658
--- /dev/null
+++ b/src/main/java/com/j256/ormlite/android/annotations/Database.java
@@ -0,0 +1,135 @@
+package com.j256.ormlite.android.annotations;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * This class is applied to a class derived from
+ * {@link com.j256.ormlite.android.apptools.OrmLiteSqliteOpenHelper} and lists
+ * the classes representing the tables in the database. Compile-time annotation
+ * processing will generate a method that can be called from your constructor to
+ * cache table information to avoid slow reflection on Android. This
+ * functionality replaces table configuration files which achieved the same goal
+ * by manually creating a text file at build time and parsing it at runtime.
+ *
+ * Add a call to YOUR_CLASS_NAME_TableConfig.cacheTableConfigurations() to your
+ * constructor to make use of this functionality. You can also call
+ * YOUR_CLASS_NAME_TableConfig.createTables(connectionSource) from your onCreate
+ * to create all tables included in this annotation.
+ *
+ * For inner/nested classes, the generated class name will use underscores to
+ * separate the classes (e.g. package.Outer.Inner will result in
+ * package.Outer_Inner_TableConfig begin generated).
+ *
+ *
+ * Example (Table.java)
+ *
+ *
+ *
+ *
+ *
+ *
+ * @DatabaseTable
+ * class Table {
+ * @DatabaseField
+ * int field;
+ * }
+ *
+ *
+ *
+ *
+ *
+ *
+ * Example (Outer.java)
+ *
+ *
+ *
+ *
+ *
+ *
+ * class Outer {
+ * @DatabaseTable
+ * class Inner {
+ * @DatabaseField
+ * int field;
+ * }
+ * }
+ *
+ *
+ *
+ *
+ *
+ *
+ * Example (OpenHelper.java)
+ *
+ *
+ *
+ *
+ *
+ *
+ * @Database({ Table.class, Outer.Inner.class })
+ * class OpenHelper extends OrmLiteSqliteOpenHelper {
+ * OpenHelper(Context context, String databaseName, CursorFactory factory,
+ * int databaseVersion) {
+ * super(context, databaseName, factory, databaseVersion);
+ * OpenHelper_TableConfig.cacheTableConfigurations();
+ * }
+ *
+ * @Override
+ * public void onCreate(SQLiteDatabase database,
+ * ConnectionSource connectionSource) {
+ * try {
+ * OpenHelper_TableConfig.createTables(connectionSource);
+ * } catch (SQLException e) {
+ * throw new RuntimeException(e);
+ * }
+ * }
+ * }
+ *
+ *
+ *
+ *
+ *
+ * *
+ *
+ * Example (InnerOpenHelper.java)
+ *
+ *
+ *
+ *
+ *
+ *
+ * class Outer {
+ * @Database({ Table.class, Outer.Inner.class })
+ * class OpenHelper extends OrmLiteSqliteOpenHelper {
+ * OpenHelper(Context context, String databaseName, CursorFactory factory,
+ * int databaseVersion) {
+ * super(context, databaseName, factory, databaseVersion);
+ * Outer_OpenHelper_TableConfig.cacheTableConfigurations();
+ * }
+ *
+ * @Override
+ * public void onCreate(SQLiteDatabase database,
+ * ConnectionSource connectionSource) {
+ * try {
+ * Outer_OpenHelper_TableConfig.createTables(connectionSource);
+ * } catch (SQLException e) {
+ * throw new RuntimeException(e);
+ * }
+ * }
+ * }
+ * }
+ *
+ *
+ *
+ *
+ *
+ * @author nathancrouther
+ */
+@Retention(RetentionPolicy.SOURCE)
+@Target(ElementType.TYPE)
+public @interface Database {
+ Class>[] value();
+}
diff --git a/src/main/java/com/j256/ormlite/android/apptools/OrmLiteConfigUtil.java b/src/main/java/com/j256/ormlite/android/apptools/OrmLiteConfigUtil.java
index 52c45966..d2513305 100644
--- a/src/main/java/com/j256/ormlite/android/apptools/OrmLiteConfigUtil.java
+++ b/src/main/java/com/j256/ormlite/android/apptools/OrmLiteConfigUtil.java
@@ -52,7 +52,12 @@
*
*
* @author graywatson
+ *
+ * @deprecated As of version 4.49 configuration files have been replaced by
+ * automatic annotation processing at compile time.
+ * @see com.j256.ormlite.android.annotations.Database
*/
+@Deprecated
public class OrmLiteConfigUtil {
/**
diff --git a/src/main/java/com/j256/ormlite/android/apptools/OrmLiteSqliteOpenHelper.java b/src/main/java/com/j256/ormlite/android/apptools/OrmLiteSqliteOpenHelper.java
index 62a3f457..323c30cc 100644
--- a/src/main/java/com/j256/ormlite/android/apptools/OrmLiteSqliteOpenHelper.java
+++ b/src/main/java/com/j256/ormlite/android/apptools/OrmLiteSqliteOpenHelper.java
@@ -70,7 +70,14 @@ public OrmLiteSqliteOpenHelper(Context context, String databaseName, CursorFacto
* called if the stored database is a different version.
* @param configFileId
* file-id which probably should be a R.raw.ormlite_config.txt or some static value.
+ *
+ * @deprecated As of version 4.49 configuration files have been replaced by
+ * automatic annotation processing at compile time. Add an
+ * {@link com.j256.ormlite.android.annotations.Database}
+ * annotation to the class that inherits from this class to
+ * activate annotation processing.
*/
+ @Deprecated
public OrmLiteSqliteOpenHelper(Context context, String databaseName, CursorFactory factory, int databaseVersion,
int configFileId) {
this(context, databaseName, factory, databaseVersion, openFileId(context, configFileId));
@@ -90,7 +97,14 @@ public OrmLiteSqliteOpenHelper(Context context, String databaseName, CursorFacto
* called if the stored database is a different version.
* @param configFile
* Configuration file to be loaded.
+ *
+ * @deprecated As of version 4.49 configuration files have been replaced by
+ * automatic annotation processing at compile time. Add an
+ * {@link com.j256.ormlite.android.annotations.Database}
+ * annotation to the class that inherits from this class to
+ * activate annotation processing.
*/
+ @Deprecated
public OrmLiteSqliteOpenHelper(Context context, String databaseName, CursorFactory factory, int databaseVersion,
File configFile) {
this(context, databaseName, factory, databaseVersion, openFile(configFile));
@@ -111,7 +125,14 @@ public OrmLiteSqliteOpenHelper(Context context, String databaseName, CursorFacto
* called if the stored database is a different version.
* @param stream
* Stream opened to the configuration file to be loaded. It will be closed when this method returns.
+ *
+ * @deprecated As of version 4.49 configuration files have been replaced by
+ * automatic annotation processing at compile time. Add an
+ * {@link com.j256.ormlite.android.annotations.Database}
+ * annotation to the class that inherits from this class to
+ * activate annotation processing.
*/
+ @Deprecated
public OrmLiteSqliteOpenHelper(Context context, String databaseName, CursorFactory factory, int databaseVersion,
InputStream stream) {
super(context, databaseName, factory, databaseVersion);
diff --git a/src/main/java/com/j256/ormlite/android/processor/FieldBindings.java b/src/main/java/com/j256/ormlite/android/processor/FieldBindings.java
new file mode 100644
index 00000000..6a99b4df
--- /dev/null
+++ b/src/main/java/com/j256/ormlite/android/processor/FieldBindings.java
@@ -0,0 +1,21 @@
+package com.j256.ormlite.android.processor;
+
+import java.util.List;
+
+class FieldBindings {
+ private final String fieldName;
+ private final List setters;
+
+ FieldBindings(String fieldName, List setters) {
+ this.fieldName = fieldName;
+ this.setters = setters;
+ }
+
+ String getFieldName() {
+ return fieldName;
+ }
+
+ List getSetters() {
+ return setters;
+ }
+}
diff --git a/src/main/java/com/j256/ormlite/android/processor/OrmLiteAnnotationProcessor.java b/src/main/java/com/j256/ormlite/android/processor/OrmLiteAnnotationProcessor.java
new file mode 100644
index 00000000..e6918adb
--- /dev/null
+++ b/src/main/java/com/j256/ormlite/android/processor/OrmLiteAnnotationProcessor.java
@@ -0,0 +1,764 @@
+package com.j256.ormlite.android.processor;
+
+import com.j256.ormlite.android.annotations.Database;
+import com.j256.ormlite.dao.DaoManager;
+import com.j256.ormlite.field.DatabaseField;
+import com.j256.ormlite.field.DatabaseFieldConfig;
+import com.j256.ormlite.field.ForeignCollectionField;
+import com.j256.ormlite.support.ConnectionSource;
+import com.j256.ormlite.table.DatabaseTable;
+import com.j256.ormlite.table.DatabaseTableConfig;
+import com.j256.ormlite.table.TableUtils;
+
+import com.squareup.javapoet.ClassName;
+import com.squareup.javapoet.JavaFile;
+import com.squareup.javapoet.MethodSpec;
+import com.squareup.javapoet.ParameterizedTypeName;
+import com.squareup.javapoet.TypeName;
+import com.squareup.javapoet.TypeSpec;
+import com.squareup.javapoet.WildcardTypeName;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Writer;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Method;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+import javax.annotation.processing.AbstractProcessor;
+import javax.annotation.processing.FilerException;
+import javax.annotation.processing.RoundEnvironment;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.Modifier;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.SourceVersion;
+import javax.lang.model.type.MirroredTypeException;
+import javax.lang.model.type.MirroredTypesException;
+import javax.lang.model.type.TypeMirror;
+import javax.tools.Diagnostic.Kind;
+import javax.tools.FileObject;
+import javax.tools.JavaFileObject;
+import javax.tools.StandardLocation;
+
+/**
+ * Class that is automatically run when compiling client code that automatically
+ * generates code to call DaoManager.addCachedDatabaseConfigs() without needing
+ * a config file.
+ *
+ * @author nathancrouther
+ */
+/*
+ * Eclipse doesn't like the link to rt.jar and classes therein. This is a
+ * spurious warning that can be ignored. It is intended to prevent referencing
+ * com.sun packages that may not be in every JVM, but the annotation processing
+ * stuff is part of JSR-269, so will always be present.
+ */
+@SuppressWarnings("restriction")
+public final class OrmLiteAnnotationProcessor extends AbstractProcessor {
+ private static final String FQCN_Object = "java.lang.Object";
+ private static final String FQCN_Class = "java.lang.Class";
+ private static final String FQCN_OpenHelper = "com.j256.ormlite.android.apptools.OrmLiteSqliteOpenHelper";
+ private static final String CN_OpenHelper = "OrmLiteSqliteOpenHelper";
+
+ private Map> foundDatabases = new HashMap>();
+ private Set foundTables = new HashSet();
+
+ @Override
+ public Set getSupportedAnnotationTypes() {
+ Set types = new LinkedHashSet();
+ types.add(DatabaseTable.class.getCanonicalName());
+ types.add(Database.class.getCanonicalName());
+ return types;
+ }
+
+ @Override
+ public SourceVersion getSupportedSourceVersion() {
+ return SourceVersion.latest();
+ }
+
+ @Override
+ public boolean process(Set extends TypeElement> elements,
+ RoundEnvironment env) {
+ for (Element element : env
+ .getElementsAnnotatedWith(DatabaseTable.class)) {
+ DatabaseTable annotation = element
+ .getAnnotation(DatabaseTable.class);
+ if (annotation == null) {
+ continue;
+ }
+
+ raiseNote(String.format("Processing %s class: %s",
+ DatabaseTable.class.getSimpleName(),
+ ((TypeElement) element).getQualifiedName()));
+
+ ParsedClassName parsedClassName = new ParsedClassName(element);
+
+ String tableName;
+ if (annotation.tableName() != null
+ && annotation.tableName().length() > 0) {
+ tableName = annotation.tableName();
+ } else {
+ tableName = element.getSimpleName().toString().toLowerCase();
+ }
+
+ TableBindings table = new TableBindings(parsedClassName, tableName);
+
+ // get all fields from this and all parents until we hit Object
+ TypeElement tableClassElement = (TypeElement) element;
+ foundTables.add(tableClassElement);
+ do {
+ for (Element child : tableClassElement.getEnclosedElements()) {
+ if (child.getKind().isField()) {
+ DatabaseField databaseField = child
+ .getAnnotation(DatabaseField.class);
+ ForeignCollectionField foreignCollectionField = child
+ .getAnnotation(ForeignCollectionField.class);
+
+ if (databaseField != null) {
+ if (databaseField.persisted()) {
+ table.addField(new FieldBindings(child
+ .getSimpleName().toString(),
+ getSettersForDatabaseField(
+ databaseField, child.asType()
+ .toString())));
+ }
+ if (foreignCollectionField != null) {
+ raiseError(
+ String.format(
+ "Fields cannot be annotated with both %s and %s",
+ DatabaseField.class
+ .getSimpleName(),
+ ForeignCollectionField.class
+ .getSimpleName()),
+ child);
+ }
+ } else if (foreignCollectionField != null) {
+ table.addField(new FieldBindings(
+ child.getSimpleName().toString(),
+ getSettersForForeignCollectionField(foreignCollectionField)));
+ }
+
+ if (databaseField != null
+ && foreignCollectionField != null) {
+ raiseError(
+ String.format(
+ "Fields cannot be annotated with both %s and %s",
+ DatabaseField.class.getSimpleName(),
+ ForeignCollectionField.class
+ .getSimpleName()), child);
+ }
+ }
+ }
+
+ tableClassElement = (TypeElement) processingEnv.getTypeUtils()
+ .asElement(tableClassElement.getSuperclass());
+ } while (!tableClassElement.getQualifiedName().toString()
+ .equals(FQCN_Object));
+
+ if (table.getFields().isEmpty()) {
+ raiseWarning(
+ String.format(
+ "No fields annotated with %s found for class annotated with %s",
+ DatabaseField.class.getSimpleName(),
+ DatabaseTable.class.getSimpleName()), element);
+ }
+
+ createTableConfigSourceFile(table, element);
+ }
+
+ Set extends Element> tablesCollectionElements = env
+ .getElementsAnnotatedWith(Database.class);
+ for (Element element : tablesCollectionElements) {
+ Database annotation = element.getAnnotation(Database.class);
+ if (annotation == null) {
+ continue;
+ }
+
+ raiseNote(String.format("Processing %s class: %s",
+ Database.class.getSimpleName(),
+ ((TypeElement) element).getQualifiedName()));
+
+ boolean derivedFromOpenHelper = false;
+ TypeElement annotatedClassElement = (TypeElement) element;
+ do {
+ if (annotatedClassElement.getQualifiedName().toString()
+ .equals(FQCN_OpenHelper)) {
+ derivedFromOpenHelper = true;
+ }
+ annotatedClassElement = (TypeElement) processingEnv
+ .getTypeUtils().asElement(
+ annotatedClassElement.getSuperclass());
+ } while (!annotatedClassElement.getQualifiedName().toString()
+ .equals(FQCN_Object));
+ if (!derivedFromOpenHelper) {
+ raiseError(
+ String.format(
+ "%s annotation must be applied to a class deriving from %s",
+ Database.class.getSimpleName(), CN_OpenHelper),
+ element);
+ }
+
+ List tableTypes = new ArrayList();
+ try {
+ Class>[] classes = annotation.value();
+ if (classes != null) {
+ for (int i = 0; i < classes.length; ++i) {
+ TypeElement typeElement;
+ try {
+ typeElement = processingEnv.getElementUtils()
+ .getTypeElement(
+ classes[i].getCanonicalName());
+ } catch (MirroredTypeException mte) {
+ typeElement = (TypeElement) processingEnv
+ .getTypeUtils().asElement(
+ mte.getTypeMirror());
+ }
+ tableTypes.add(typeElement);
+ }
+ } else {
+ // eclipse populates this with null if annotation populated
+ // with scalar (no {}) even though this is a legal shortcut
+ raiseError(String.format(
+ "%s annotation must enclose values array with {}",
+ Database.class.getSimpleName()), element);
+ continue;
+ }
+ } catch (MirroredTypesException mte) {
+ for (TypeMirror m : mte.getTypeMirrors()) {
+ tableTypes.add((TypeElement) processingEnv.getTypeUtils()
+ .asElement(m));
+ }
+ }
+
+ if (tableTypes.isEmpty()) {
+ raiseError(
+ String.format(
+ "%s annotation must contain at least one class annotated with %s",
+ Database.class.getSimpleName(),
+ DatabaseTable.class.getSimpleName()), element);
+ }
+
+ foundDatabases.put((TypeElement) element, tableTypes);
+
+ createDatabaseConfigSourceFile((TypeElement) element, tableTypes);
+ }
+
+ if (env.processingOver()) {
+ raiseNote(String.format(
+ "Finished processing %d %s class(es) and %d %s class(es)",
+ foundTables.size(), DatabaseTable.class.getSimpleName(),
+ foundDatabases.size(), Database.class.getSimpleName()));
+
+ final StandardLocation savedDatabaseInfoLocation = StandardLocation.SOURCE_OUTPUT;
+ final String savedDatabaseInfoPackageName = getClass().getPackage()
+ .getName();
+ final String savedDatabaseInfoFileName = "savedDatabaseInfo";
+
+ // Try to read a file from before
+ Map> savedDatabaseInfo;
+ try {
+ FileObject file = processingEnv.getFiler()
+ .getResource(savedDatabaseInfoLocation,
+ savedDatabaseInfoPackageName,
+ savedDatabaseInfoFileName);
+ ObjectInputStream reader = new ObjectInputStream(
+ file.openInputStream());
+ try {
+ // We created the file previously, so the cast is safe
+ @SuppressWarnings("unchecked")
+ Map> oldDatabaseInfo = (Map>) reader
+ .readObject();
+ raiseNote(String.format(
+ "Loaded %d Database-to-DatabaseTable mappings",
+ oldDatabaseInfo.size()));
+ savedDatabaseInfo = oldDatabaseInfo;
+ } finally {
+ reader.close();
+ }
+ } catch (FilerException e) {
+ // This file will only exist and have content during a round of
+ // incremental compilation, there is no clean way to detect this
+ // without trying and failing to read the file, so we catch the
+ // error and initialize with empty contents.
+ savedDatabaseInfo = new HashMap>();
+ } catch (IOException e) {
+ // This file will only exist and have content during a round of
+ // incremental compilation, there is no clean way to detect this
+ // without trying and failing to read the file, so we catch the
+ // error and initialize with empty contents.
+ savedDatabaseInfo = new HashMap>();
+ } catch (ClassNotFoundException e) {
+ // Built-in Java classes will always be available so this should
+ // never happen
+ throw new RuntimeException(e);
+ }
+
+ // Verify each Database annotation only contains valid tables and
+ // add it to the saved list for future rounds of incremental
+ // compilation
+ for (Entry> databaseAndTables : foundDatabases
+ .entrySet()) {
+ List tableNames = new ArrayList();
+
+ for (TypeElement table : databaseAndTables.getValue()) {
+ if (table.getAnnotation(DatabaseTable.class) == null) {
+ raiseError(
+ String.format(
+ "%s annotation contains class %s not annotated with %s",
+ Database.class.getSimpleName(),
+ table.getSimpleName(),
+ DatabaseTable.class.getSimpleName()),
+ databaseAndTables.getKey());
+ }
+
+ tableNames.add(table.getQualifiedName().toString());
+ }
+
+ savedDatabaseInfo.put(databaseAndTables.getKey()
+ .getQualifiedName().toString(), tableNames);
+ }
+
+ // Save the updated information for future rounds of incremental
+ // compilation
+ try {
+ FileObject file = processingEnv.getFiler()
+ .createResource(savedDatabaseInfoLocation,
+ savedDatabaseInfoPackageName,
+ savedDatabaseInfoFileName);
+ ObjectOutputStream writer = new ObjectOutputStream(
+ file.openOutputStream());
+ writer.writeObject(savedDatabaseInfo);
+ writer.close();
+ raiseNote(String.format(
+ "Stored %d Database-to-DatabaseTable mappings",
+ savedDatabaseInfo.size()));
+ } catch (FilerException e) {
+ // should never happen, but if it does, it shouldn't be fatal
+ // since the worst consequence would be a spurious warning
+ // during future incremental compilations that would be cleared
+ // with a full rebuild.
+ raiseNote("FilerException while saving Database-to-DatabaseTable mappings: "
+ + e.toString());
+ } catch (IOException e) {
+ // should never happen, but if it does, it shouldn't be fatal
+ // since the worst consequence would be a spurious warning
+ // during future incremental compilations that would be cleared
+ // with a full rebuild.
+ raiseNote("IOException while saving Database-to-DatabaseTable mappings: "
+ + e.toString());
+ }
+
+ // Verify that every table is in a database (try to enforce using
+ // the database annotation for better performance)
+ Set tablesIncludedInDatabases = new HashSet();
+ for (List tableNames : savedDatabaseInfo.values()) {
+ for (String tableName : tableNames) {
+ tablesIncludedInDatabases.add(tableName);
+ }
+ }
+ for (TypeElement foundTable : foundTables) {
+ if (!tablesIncludedInDatabases.contains(foundTable
+ .getQualifiedName().toString())) {
+ raiseWarning(
+ String.format(
+ "Class annotated with %s is not included in any %s annotation",
+ DatabaseTable.class.getSimpleName(),
+ Database.class.getSimpleName()), foundTable);
+ }
+ }
+ }
+
+ return true;
+ }
+
+ private void createDatabaseConfigSourceFile(
+ TypeElement openHelperClassElement, List tableClasses) {
+ ParsedClassName openHelperClassName = new ParsedClassName(
+ openHelperClassElement);
+
+ try {
+ JavaFileObject javaFileObject = processingEnv
+ .getFiler()
+ .createSourceFile(
+ openHelperClassName
+ .getGeneratedFullyQualifiedClassName(),
+ openHelperClassElement);
+
+ Writer writer = javaFileObject.openWriter();
+
+ try {
+ MethodSpec.Builder constructor = MethodSpec
+ .constructorBuilder().addModifiers(Modifier.PRIVATE);
+
+ MethodSpec.Builder cacheTableConfigurations = MethodSpec
+ .methodBuilder("cacheTableConfigurations")
+ .addModifiers(Modifier.PUBLIC, Modifier.STATIC);
+ cacheTableConfigurations.addStatement(
+ "$T tableConfigs = new $T()",
+ ParameterizedTypeName.get(ClassName.get(List.class),
+ ParameterizedTypeName.get(ClassName
+ .get(DatabaseTableConfig.class),
+ WildcardTypeName
+ .subtypeOf(Object.class))),
+ ParameterizedTypeName.get(ClassName
+ .get(ArrayList.class), ParameterizedTypeName
+ .get(ClassName.get(DatabaseTableConfig.class),
+ WildcardTypeName
+ .subtypeOf(Object.class))));
+ for (TypeElement tableClass : tableClasses) {
+ ParsedClassName tableClassName = new ParsedClassName(
+ tableClass);
+ cacheTableConfigurations.addStatement(
+ "tableConfigs.add($T.createConfig())", ClassName
+ .get(tableClassName.getPackageName(),
+ tableClassName
+ .getGeneratedClassName()));
+ }
+ cacheTableConfigurations.addStatement(
+ "$T.addCachedDatabaseConfigs(tableConfigs)",
+ DaoManager.class);
+
+ MethodSpec.Builder createTables = MethodSpec
+ .methodBuilder("createTables")
+ .addParameter(ConnectionSource.class,
+ "connectionSource")
+ .addModifiers(Modifier.PUBLIC, Modifier.STATIC)
+ .addException(SQLException.class);
+ for (TypeElement tableClass : tableClasses) {
+ createTables.addStatement(
+ "$T.createTable(connectionSource, $T.class)",
+ TableUtils.class, tableClass.asType());
+ }
+
+ TypeSpec.Builder openHelperClass = TypeSpec
+ .classBuilder(
+ openHelperClassName.getGeneratedClassName())
+ .addModifiers(Modifier.PUBLIC, Modifier.FINAL)
+ .addMethod(constructor.build())
+ .addMethod(cacheTableConfigurations.build())
+ .addMethod(createTables.build());
+
+ JavaFile openHelperFile = JavaFile.builder(
+ openHelperClassName.getPackageName(),
+ openHelperClass.build()).build();
+ openHelperFile.writeTo(writer);
+ } finally {
+ writer.close();
+ }
+ } catch (FilerException e) {
+ // if multiple classes are in the same file (e.g. inner/nested
+ // classes), eclipse will do an incremental compilation for all of
+ // them. The unchanged ones' generated files will not be deleted, so
+ // we can ignore this benign error.
+ raiseNote(String
+ .format("Skipping file generation for %s since file already exists",
+ openHelperClassName
+ .getGeneratedFullyQualifiedClassName()));
+ } catch (IOException e) {
+ // We should always be able to generate the source files and if we
+ // can't we should bail out
+ throw new RuntimeException(e);
+ }
+ }
+
+ private List getSettersForDatabaseField(
+ DatabaseField annotation, String fullyQualifiedFieldType) {
+ List output = new ArrayList();
+ addSetterIfNotDefault(annotation, "columnName", "setColumnName($S)",
+ output);
+ addSetterIfNotDefault(annotation, "dataType",
+ "setDataType(com.j256.ormlite.field.DataType.$L)", output);
+ addSetterIfNotDefault(annotation, "defaultValue",
+ "setDefaultValue($S)", output);
+ addSetterIfNotDefault(annotation, "width", "setWidth($L)", output);
+ addSetterIfNotDefault(annotation, "canBeNull", "setCanBeNull($L)",
+ output);
+ addSetterIfNotDefault(annotation, "id", "setId($L)", output);
+ addSetterIfNotDefault(annotation, "generatedId", "setGeneratedId($L)",
+ output);
+ addSetterIfNotDefault(annotation, "generatedIdSequence",
+ "setGeneratedIdSequence($S)", output);
+ addSetterIfNotDefault(annotation, "foreign", "setForeign($L)", output);
+ addSetterIfNotDefault(annotation, "useGetSet", "setUseGetSet($L)",
+ output);
+ addSetterIfNotDefault(annotation, "unknownEnumName",
+ "setUnknownEnumValue(" + fullyQualifiedFieldType + ".$L)",
+ output);
+ addSetterIfNotDefault(annotation, "throwIfNull", "setThrowIfNull($L)",
+ output);
+ addSetterIfNotDefault(annotation, "format", "setFormat($S)", output);
+ addSetterIfNotDefault(annotation, "unique", "setUnique($L)", output);
+ addSetterIfNotDefault(annotation, "uniqueCombo", "setUniqueCombo($L)",
+ output);
+ addSetterIfNotDefault(annotation, "index", "setIndex($L)", output);
+ addSetterIfNotDefault(annotation, "uniqueIndex", "setUniqueIndex($L)",
+ output);
+ addSetterIfNotDefault(annotation, "indexName", "setIndexName($S)",
+ output);
+ addSetterIfNotDefault(annotation, "uniqueIndexName",
+ "setUniqueIndexName($S)", output);
+ addSetterIfNotDefault(annotation, "foreignAutoRefresh",
+ "setForeignAutoRefresh($L)", output);
+ addSetterIfNotDefault(annotation, "maxForeignAutoRefreshLevel",
+ "setMaxForeignAutoRefreshLevel($L)", output);
+ addSetterIfNotDefault(annotation, "persisterClass",
+ "setPersisterClass($T.class)", output);
+ addSetterIfNotDefault(annotation, "allowGeneratedIdInsert",
+ "setAllowGeneratedIdInsert($L)", output);
+ addSetterIfNotDefault(annotation, "columnDefinition",
+ "setColumnDefinition($S)", output);
+ addSetterIfNotDefault(annotation, "foreignAutoCreate",
+ "setForeignAutoCreate($L)", output);
+ addSetterIfNotDefault(annotation, "version", "setVersion($L)", output);
+ addSetterIfNotDefault(annotation, "foreignColumnName",
+ "setForeignColumnName($S)", output);
+ addSetterIfNotDefault(annotation, "readOnly", "setReadOnly($L)", output);
+ return output;
+ }
+
+ private List getSettersForForeignCollectionField(
+ ForeignCollectionField annotation) {
+ List output = new ArrayList();
+ addSetterIfNotDefault(annotation, "columnName", "setColumnName($S)",
+ output);
+ addSetter("setForeignCollection($L)", true, output);
+ addSetterIfNotDefault(annotation, "eager",
+ "setForeignCollectionEager($L)", output);
+ addSetterIfNotDefault(annotation, "maxEagerLevel",
+ "maxEagerForeignCollectionLevel",
+ "setForeignCollectionMaxEagerLevel($L)", output);
+ addSetterIfNotDefault(annotation, "columnName",
+ "setForeignCollectionColumnName($S)", output);
+ addSetterIfNotDefault(annotation, "orderColumnName",
+ "setForeignCollectionOrderColumnName($S)", output);
+ addSetterIfNotDefault(annotation, "orderAscending",
+ "setForeignCollectionOrderAscending($L)", output);
+ addSetterIfNotDefault(annotation, "foreignFieldName",
+ "foreignColumnName",
+ "setForeignCollectionForeignFieldName($S)", output);
+ return output;
+ }
+
+ private void addSetterIfNotDefault(Annotation annotation, String name,
+ String format, List output) {
+ addSetterIfNotDefault(annotation, name, null, format, output);
+ }
+
+ private void addSetterIfNotDefault(Annotation annotation, String name,
+ String fallbackName, String format, List output) {
+ Object value = getValueIfNotDefault(annotation, name);
+ if (value != null) {
+ addSetter(format, value, output);
+ } else if (fallbackName != null) {
+ value = getValueIfNotDefault(annotation, fallbackName);
+ if (value != null) {
+ addSetter(format, value, output);
+ }
+ }
+ }
+
+ private void addSetter(String format, Object value,
+ List output) {
+ output.add(new SetterBindings(format, value));
+ }
+
+ /**
+ * This function examines a single field in an annotation and if the current
+ * value doesn't match the default returns the current value. If the current
+ * value matches the default, it returns null.
+ *
+ * @param annotation
+ * the annotation containing the field of interest
+ * @param name
+ * the name of the field in the annotation to read
+ * @return the current value if it is not the default, null otherwise
+ */
+ private Object getValueIfNotDefault(Annotation annotation, String name) {
+ try {
+ Method method = annotation.annotationType().getMethod(name);
+
+ Object actualValue;
+ Object defaultValue;
+ if (method.getReturnType().getCanonicalName().equals(FQCN_Class)) {
+ try {
+ actualValue = getClassNameFromClassObject(method
+ .invoke(annotation));
+ } catch (Exception ex) {
+ actualValue = getMirroredClassNameFromException(ex);
+ }
+ try {
+ defaultValue = getClassNameFromClassObject(method
+ .getDefaultValue());
+ } catch (Exception ex) {
+ defaultValue = getMirroredClassNameFromException(ex);
+ }
+ } else {
+ actualValue = method.invoke(annotation);
+ defaultValue = method.getDefaultValue();
+ }
+
+ if (defaultValue.equals(actualValue)) {
+ return null;
+ } else {
+ return actualValue;
+ }
+ } catch (Exception e) {
+ // All possible annotation properties are unit tested, so it is not
+ // possible to get an exception here
+ throw new RuntimeException(e);
+ }
+ }
+
+ private TypeName getClassNameFromClassObject(Object object) {
+ return TypeName.get((Class>) object);
+ }
+
+ private TypeName getMirroredClassNameFromException(Exception ex)
+ throws Exception {
+ Throwable t = ex;
+ do {
+ if (t instanceof MirroredTypeException) {
+ return TypeName
+ .get(((MirroredTypeException) t).getTypeMirror());
+ }
+ t = t.getCause();
+ } while (t != null);
+
+ throw ex;
+ }
+
+ private void createTableConfigSourceFile(TableBindings table,
+ Element tableClassElement) {
+ try {
+ JavaFileObject javaFileObject = processingEnv.getFiler()
+ .createSourceFile(
+ table.getParsedClassName()
+ .getGeneratedFullyQualifiedClassName(),
+ tableClassElement);
+
+ Writer writer = javaFileObject.openWriter();
+ try {
+ writeTable(writer, table);
+ } finally {
+ writer.close();
+ }
+ } catch (FilerException e) {
+ // if multiple classes are in the same file (e.g. inner/nested
+ // classes), eclipse will do an incremental compilation for all of
+ // them. The unchanged ones' generated files will not be deleted, so
+ // we can ignore this benign error.
+ raiseNote(String
+ .format("Skipping file generation for %s since file already exists",
+ table.getParsedClassName()
+ .getGeneratedFullyQualifiedClassName()));
+ } catch (IOException e) {
+ // We should always be able to generate the source files and if we
+ // can't we should bail out
+ throw new RuntimeException(e);
+ }
+ }
+
+ private void writeTable(Writer writer, TableBindings table)
+ throws IOException {
+ MethodSpec.Builder constructor = MethodSpec.constructorBuilder()
+ .addModifiers(Modifier.PRIVATE);
+
+ MethodSpec.Builder createConfig = MethodSpec
+ .methodBuilder("createConfig")
+ .addModifiers(Modifier.PUBLIC, Modifier.STATIC)
+ .returns(
+ ParameterizedTypeName.get(
+ ClassName.get(DatabaseTableConfig.class),
+ WildcardTypeName.subtypeOf(Object.class)));
+ createConfig.addStatement("$T databaseFieldConfigs = new $T()",
+ ParameterizedTypeName.get(ClassName.get(List.class),
+ TypeName.get(DatabaseFieldConfig.class)),
+ ParameterizedTypeName.get(ClassName.get(ArrayList.class),
+ TypeName.get(DatabaseFieldConfig.class)));
+
+ for (FieldBindings field : table.getFields()) {
+ createConfig.addStatement("$T $LFieldConfig = new $T($S)",
+ DatabaseFieldConfig.class, field.getFieldName(),
+ DatabaseFieldConfig.class, field.getFieldName());
+
+ for (SetterBindings setter : field.getSetters()) {
+ createConfig.addStatement(
+ "$LFieldConfig." + setter.getFormat(),
+ field.getFieldName(), setter.getParameter());
+ }
+
+ createConfig.addStatement(
+ "databaseFieldConfigs.add($LFieldConfig)",
+ field.getFieldName());
+ }
+
+ createConfig.addStatement(
+ "return new $T<$T>($T.class, $S, databaseFieldConfigs)",
+ DatabaseTableConfig.class, ClassName.get(table
+ .getParsedClassName().getPackageName(), table
+ .getParsedClassName().getInputClassName()), ClassName
+ .get(table.getParsedClassName().getPackageName(), table
+ .getParsedClassName().getInputClassName()),
+ table.getTableName());
+
+ TypeSpec.Builder tableConfigClass = TypeSpec
+ .classBuilder(
+ table.getParsedClassName().getGeneratedClassName())
+ .addModifiers(Modifier.PUBLIC, Modifier.FINAL)
+ .addMethod(constructor.build()).addMethod(createConfig.build());
+
+ JavaFile tableConfigFile = JavaFile.builder(
+ table.getParsedClassName().getPackageName(),
+ tableConfigClass.build()).build();
+ tableConfigFile.writeTo(writer);
+ }
+
+ private void raiseNote(String message) {
+ this.processingEnv.getMessager().printMessage(Kind.NOTE, message);
+ }
+
+ /*
+ * During incremental compiles in eclipse, if the same element raises
+ * multiple warnings, the internal message printing code can throw a NPE.
+ * When this happens, all warnings are displayed properly, so we should
+ * ignore the error. We will validate our arguments ourself to ensure that
+ * this code doesn't mask a real bug.
+ */
+
+ private void raiseWarning(String message, Element element) {
+ if (message == null || element == null) {
+ throw new NullPointerException();
+ }
+ try {
+ this.processingEnv.getMessager().printMessage(Kind.WARNING,
+ message, element);
+ } catch (NullPointerException e) {
+ // ignore to workaround issues with eclipse incremental compilation
+ raiseNote("NullPointerException while raising a warning: "
+ + e.toString());
+ }
+ }
+
+ private void raiseError(String message, Element element) {
+ if (message == null || element == null) {
+ throw new NullPointerException();
+ }
+ try {
+ this.processingEnv.getMessager().printMessage(Kind.ERROR, message,
+ element);
+ } catch (NullPointerException e) {
+ // ignore to workaround issues with eclipse incremental compilation
+ raiseNote("NullPointerException while raising an error: "
+ + e.toString());
+ }
+ }
+}
diff --git a/src/main/java/com/j256/ormlite/android/processor/ParsedClassName.java b/src/main/java/com/j256/ormlite/android/processor/ParsedClassName.java
new file mode 100644
index 00000000..bc136c2e
--- /dev/null
+++ b/src/main/java/com/j256/ormlite/android/processor/ParsedClassName.java
@@ -0,0 +1,80 @@
+package com.j256.ormlite.android.processor;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import javax.lang.model.element.Element;
+import javax.lang.model.element.PackageElement;
+
+/*
+ * Eclipse doesn't like the link to rt.jar and classes therein. This is a
+ * spurious warning that can be ignored. It is intended to prevent referencing
+ * com.sun packages that may not be in every JVM, but the annotation processing
+ * stuff is part of JSR-269, so will always be present.
+ */
+@SuppressWarnings("restriction")
+class ParsedClassName {
+ private String packageName;
+ private List nestedClasses = new ArrayList();
+
+ ParsedClassName(Element element) {
+ Element elementIterator = element;
+ do {
+ nestedClasses.add(elementIterator.getSimpleName().toString());
+ elementIterator = elementIterator.getEnclosingElement();
+ } while (elementIterator.getKind().isClass());
+ Collections.reverse(nestedClasses);
+ packageName = ((PackageElement) elementIterator).getQualifiedName()
+ .toString();
+ }
+
+ String getPackageName() {
+ return packageName;
+ }
+
+ String getInputFullyQualifiedClassName() {
+ StringBuilder sb = new StringBuilder();
+ if (!packageName.isEmpty()) {
+ sb.append(packageName);
+ sb.append('.');
+ }
+ sb.append(getInputClassName());
+ return sb.toString();
+ }
+
+ String getInputClassName() {
+ StringBuilder sb = new StringBuilder();
+ for (int i = 0; i < nestedClasses.size(); ++i) {
+ if (i != 0) {
+ sb.append('.');
+ }
+ sb.append(nestedClasses.get(i));
+ }
+ return sb.toString();
+ }
+
+ String getGeneratedClassName() {
+ final String SUFFIX = "_TableConfig";
+
+ StringBuilder sb = new StringBuilder();
+ for (int i = 0; i < nestedClasses.size(); ++i) {
+ if (i != 0) {
+ sb.append('_');
+ }
+ sb.append(nestedClasses.get(i));
+ }
+ sb.append(SUFFIX);
+ return sb.toString();
+ }
+
+ String getGeneratedFullyQualifiedClassName() {
+ StringBuilder sb = new StringBuilder();
+ if (!packageName.isEmpty()) {
+ sb.append(packageName);
+ sb.append('.');
+ }
+ sb.append(getGeneratedClassName());
+ return sb.toString();
+ }
+}
diff --git a/src/main/java/com/j256/ormlite/android/processor/SetterBindings.java b/src/main/java/com/j256/ormlite/android/processor/SetterBindings.java
new file mode 100644
index 00000000..0bf22b4e
--- /dev/null
+++ b/src/main/java/com/j256/ormlite/android/processor/SetterBindings.java
@@ -0,0 +1,19 @@
+package com.j256.ormlite.android.processor;
+
+class SetterBindings {
+ private final String format;
+ private final Object parameter;
+
+ SetterBindings(String format, Object parameter) {
+ this.format = format;
+ this.parameter = parameter;
+ }
+
+ String getFormat() {
+ return format;
+ }
+
+ Object getParameter() {
+ return parameter;
+ }
+}
diff --git a/src/main/java/com/j256/ormlite/android/processor/TableBindings.java b/src/main/java/com/j256/ormlite/android/processor/TableBindings.java
new file mode 100644
index 00000000..5c98fb3b
--- /dev/null
+++ b/src/main/java/com/j256/ormlite/android/processor/TableBindings.java
@@ -0,0 +1,31 @@
+package com.j256.ormlite.android.processor;
+
+import java.util.ArrayList;
+import java.util.List;
+
+class TableBindings {
+ private final ParsedClassName parsedClassName;
+ private final String tableName;
+ private final List fields = new ArrayList();
+
+ TableBindings(ParsedClassName parsedClassName, String tableName) {
+ this.parsedClassName = parsedClassName;
+ this.tableName = tableName;
+ }
+
+ void addField(FieldBindings field) {
+ fields.add(field);
+ }
+
+ ParsedClassName getParsedClassName() {
+ return parsedClassName;
+ }
+
+ String getTableName() {
+ return tableName;
+ }
+
+ List getFields() {
+ return fields;
+ }
+}
diff --git a/src/main/resources/META-INF/services/javax.annotation.processing.Processor b/src/main/resources/META-INF/services/javax.annotation.processing.Processor
new file mode 100644
index 00000000..a63788c0
--- /dev/null
+++ b/src/main/resources/META-INF/services/javax.annotation.processing.Processor
@@ -0,0 +1 @@
+com.j256.ormlite.android.processor.OrmLiteAnnotationProcessor
diff --git a/src/test/java/com/j256/ormlite/android/apptools/OrmLiteConfigUtilTest.java b/src/test/java/com/j256/ormlite/android/apptools/OrmLiteConfigUtilTest.java
index 0859bc6e..52ec0bfc 100644
--- a/src/test/java/com/j256/ormlite/android/apptools/OrmLiteConfigUtilTest.java
+++ b/src/test/java/com/j256/ormlite/android/apptools/OrmLiteConfigUtilTest.java
@@ -11,6 +11,7 @@
import com.j256.ormlite.field.DatabaseField;
import com.j256.ormlite.field.ForeignCollectionField;
+@SuppressWarnings("deprecation")
public class OrmLiteConfigUtilTest {
private static final String lineSeparator = System.getProperty("line.separator");
diff --git a/src/test/java/com/j256/ormlite/android/processor/OrmLiteAnnotationProcessorTest.java b/src/test/java/com/j256/ormlite/android/processor/OrmLiteAnnotationProcessorTest.java
new file mode 100644
index 00000000..73e1d2d6
--- /dev/null
+++ b/src/test/java/com/j256/ormlite/android/processor/OrmLiteAnnotationProcessorTest.java
@@ -0,0 +1,160 @@
+package com.j256.ormlite.android.processor;
+
+import static com.google.common.truth.Truth.assert_;
+import static com.google.testing.compile.JavaSourceSubjectFactory.javaSource;
+
+import org.junit.Test;
+
+import com.google.testing.compile.JavaFileObjects;
+
+import com.j256.ormlite.android.annotations.Database;
+import com.j256.ormlite.android.apptools.OrmLiteSqliteOpenHelper;
+import com.j256.ormlite.field.DatabaseField;
+import com.j256.ormlite.field.ForeignCollectionField;
+import com.j256.ormlite.table.DatabaseTable;
+
+public class OrmLiteAnnotationProcessorTest {
+
+ @Test
+ public void testDatabaseFieldAllDefaults() {
+ assert_()
+ .about(javaSource())
+ .that(JavaFileObjects
+ .forResource("inputs/UnnamedTableWithDefaultDatabaseField.java"))
+ .processedWith(new OrmLiteAnnotationProcessor())
+ .compilesWithoutError()
+ .and()
+ .generatesSources(
+ JavaFileObjects
+ .forResource("outputs/UnnamedTableWithDefaultDatabaseField_TableConfig.java"),
+ JavaFileObjects
+ .forResource("outputs/UnnamedTableWithDefaultDatabaseField_OpenHelper_TableConfig.java"));
+ }
+
+ @Test
+ public void testDatabaseFieldAllSpecified() {
+ assert_()
+ .about(javaSource())
+ .that(JavaFileObjects
+ .forResource("inputs/NamedTableWithSpecifiedDatabaseField.java"))
+ .processedWith(new OrmLiteAnnotationProcessor())
+ .compilesWithoutError()
+ .and()
+ .generatesSources(
+ JavaFileObjects
+ .forResource("outputs/NamedTableWithSpecifiedDatabaseField_TableConfig.java"),
+ JavaFileObjects
+ .forResource("outputs/NamedTableWithSpecifiedDatabaseField_OpenHelper_TableConfig.java"));
+ }
+
+ @Test
+ public void testForeignCollectionFieldAllDefaults() {
+ assert_()
+ .about(javaSource())
+ .that(JavaFileObjects
+ .forResource("inputs/UnnamedTableWithDefaultForeignCollectionField.java"))
+ .processedWith(new OrmLiteAnnotationProcessor())
+ .compilesWithoutError()
+ .and()
+ .generatesSources(
+ JavaFileObjects
+ .forResource("outputs/UnnamedTableWithDefaultForeignCollectionField_TableConfig.java"),
+ JavaFileObjects
+ .forResource("outputs/UnnamedTableWithDefaultForeignCollectionField_OpenHelper_TableConfig.java"));
+ }
+
+ @Test
+ public void testForeignCollectionFieldAllSpecified() {
+ assert_()
+ .about(javaSource())
+ .that(JavaFileObjects
+ .forResource("inputs/NamedTableWithSpecifiedForeignCollectionField.java"))
+ .processedWith(new OrmLiteAnnotationProcessor())
+ .compilesWithoutError()
+ .and()
+ .generatesSources(
+ JavaFileObjects
+ .forResource("outputs/NamedTableWithSpecifiedForeignCollectionField_TableConfig.java"),
+ JavaFileObjects
+ .forResource("outputs/NamedTableWithSpecifiedForeignCollectionField_OpenHelper_TableConfig.java"));
+ }
+
+ @Test
+ public void testInnerClasses() {
+ assert_()
+ .about(javaSource())
+ .that(JavaFileObjects
+ .forResource("inputs/InnerClassTable.java"))
+ .processedWith(new OrmLiteAnnotationProcessor())
+ .compilesWithoutError()
+ .and()
+ .generatesSources(
+ JavaFileObjects
+ .forResource("outputs/InnerClassTable_InnerClass_TableConfig.java"),
+ JavaFileObjects
+ .forResource("outputs/InnerClassTable_OtherInnerClass_TableConfig.java"),
+ JavaFileObjects
+ .forResource("outputs/InnerClassTable_OpenHelper_TableConfig.java"));
+ }
+
+ @Test
+ public void testErrorBothAnnotationsOnField() {
+ assert_()
+ .about(javaSource())
+ .that(JavaFileObjects
+ .forResource("inputs/TableWithFieldWithBothAnnotations.java"))
+ .processedWith(new OrmLiteAnnotationProcessor())
+ .failsToCompile()
+ .withErrorContaining(
+ String.format(
+ "Fields cannot be annotated with both %s and %s",
+ DatabaseField.class.getSimpleName(),
+ ForeignCollectionField.class.getSimpleName()));
+ }
+
+ @Test
+ public void testErrorDatabaseWithNoTables() {
+ assert_()
+ .about(javaSource())
+ .that(JavaFileObjects
+ .forResource("inputs/DatabaseWithNoTables.java"))
+ .processedWith(new OrmLiteAnnotationProcessor())
+ .failsToCompile()
+ .withErrorContaining(
+ String.format(
+ "%s annotation must contain at least one class annotated with %s",
+ Database.class.getSimpleName(),
+ DatabaseTable.class.getSimpleName()));
+ }
+
+ @Test
+ public void testErrorDatabaseDerivedFromWrongClass() {
+ assert_()
+ .about(javaSource())
+ .that(JavaFileObjects
+ .forResource("inputs/DatabaseDerivedFromWrongClass.java"))
+ .processedWith(new OrmLiteAnnotationProcessor())
+ .failsToCompile()
+ .withErrorContaining(
+ String.format(
+ "%s annotation must be applied to a class deriving from %s",
+ Database.class.getSimpleName(),
+ OrmLiteSqliteOpenHelper.class.getSimpleName()));
+ }
+
+ @Test
+ public void testErrorDatabaseWithNonTable() {
+ assert_()
+ .about(javaSource())
+ .that(JavaFileObjects
+ .forResource("inputs/DatabaseWithNonTable.java"))
+ .processedWith(new OrmLiteAnnotationProcessor())
+ .failsToCompile()
+ .withErrorContaining(
+ String.format(
+ "%s annotation contains class %s not annotated with %s",
+ Database.class.getSimpleName(),
+ String.class.getSimpleName(),
+ DatabaseTable.class.getSimpleName()));
+ }
+}
diff --git a/src/test/resources/inputs/DatabaseDerivedFromWrongClass.java b/src/test/resources/inputs/DatabaseDerivedFromWrongClass.java
new file mode 100644
index 00000000..50149f2e
--- /dev/null
+++ b/src/test/resources/inputs/DatabaseDerivedFromWrongClass.java
@@ -0,0 +1,15 @@
+package com.j256.ormlite.android.processor.inputs;
+
+import com.j256.ormlite.android.annotations.Database;
+import com.j256.ormlite.field.DatabaseField;
+import com.j256.ormlite.table.DatabaseTable;
+
+@DatabaseTable
+class DatabaseDerivedFromWrongClass {
+ @DatabaseField
+ int field;
+
+ @Database({ DatabaseDerivedFromWrongClass.class })
+ static abstract class OpenHelper {
+ }
+}
diff --git a/src/test/resources/inputs/DatabaseWithNoTables.java b/src/test/resources/inputs/DatabaseWithNoTables.java
new file mode 100644
index 00000000..f051a610
--- /dev/null
+++ b/src/test/resources/inputs/DatabaseWithNoTables.java
@@ -0,0 +1,15 @@
+package com.j256.ormlite.android.processor.inputs;
+
+import android.content.Context;
+import android.database.sqlite.SQLiteDatabase.CursorFactory;
+
+import com.j256.ormlite.android.annotations.Database;
+import com.j256.ormlite.android.apptools.OrmLiteSqliteOpenHelper;
+
+@Database({})
+abstract class DatabaseWithNoTables extends OrmLiteSqliteOpenHelper {
+ DatabaseWithNoTables(Context context, String databaseName,
+ CursorFactory factory, int databaseVersion) {
+ super(context, databaseName, factory, databaseVersion);
+ }
+}
diff --git a/src/test/resources/inputs/DatabaseWithNonTable.java b/src/test/resources/inputs/DatabaseWithNonTable.java
new file mode 100644
index 00000000..3f3cc082
--- /dev/null
+++ b/src/test/resources/inputs/DatabaseWithNonTable.java
@@ -0,0 +1,23 @@
+package com.j256.ormlite.android.processor.inputs;
+
+import android.content.Context;
+import android.database.sqlite.SQLiteDatabase.CursorFactory;
+
+import com.j256.ormlite.android.annotations.Database;
+import com.j256.ormlite.android.apptools.OrmLiteSqliteOpenHelper;
+import com.j256.ormlite.field.DatabaseField;
+import com.j256.ormlite.table.DatabaseTable;
+
+@DatabaseTable
+class DatabaseWithNonTable {
+ @DatabaseField
+ int field;
+
+ @Database({ DatabaseWithNonTable.class, String.class })
+ static abstract class OpenHelper extends OrmLiteSqliteOpenHelper {
+ OpenHelper(Context context, String databaseName, CursorFactory factory,
+ int databaseVersion) {
+ super(context, databaseName, factory, databaseVersion);
+ }
+ }
+}
diff --git a/src/test/resources/inputs/InnerClassTable.java b/src/test/resources/inputs/InnerClassTable.java
new file mode 100644
index 00000000..45d0c638
--- /dev/null
+++ b/src/test/resources/inputs/InnerClassTable.java
@@ -0,0 +1,47 @@
+package com.j256.ormlite.android.processor.inputs;
+
+import java.sql.SQLException;
+
+import android.content.Context;
+import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteDatabase.CursorFactory;
+
+import com.j256.ormlite.android.annotations.Database;
+import com.j256.ormlite.android.apptools.OrmLiteSqliteOpenHelper;
+import com.j256.ormlite.field.DatabaseField;
+import com.j256.ormlite.support.ConnectionSource;
+import com.j256.ormlite.table.DatabaseTable;
+
+class InnerClassTable {
+ @DatabaseTable
+ static class InnerClass {
+ @DatabaseField
+ int field;
+ }
+
+ @DatabaseTable
+ static class OtherInnerClass {
+ @DatabaseField
+ int field;
+ }
+
+ @Database({ InnerClass.class, OtherInnerClass.class })
+ static abstract class OpenHelper extends OrmLiteSqliteOpenHelper {
+ OpenHelper(Context context, String databaseName, CursorFactory factory,
+ int databaseVersion) {
+ super(context, databaseName, factory, databaseVersion);
+ InnerClassTable_OpenHelper_TableConfig.cacheTableConfigurations();
+ }
+
+ @Override
+ public void onCreate(SQLiteDatabase database,
+ ConnectionSource connectionSource) {
+ try {
+ InnerClassTable_OpenHelper_TableConfig
+ .createTables(connectionSource);
+ } catch (SQLException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+}
diff --git a/src/test/resources/inputs/NamedTableWithSpecifiedDatabaseField.java b/src/test/resources/inputs/NamedTableWithSpecifiedDatabaseField.java
new file mode 100644
index 00000000..d2ebb6bb
--- /dev/null
+++ b/src/test/resources/inputs/NamedTableWithSpecifiedDatabaseField.java
@@ -0,0 +1,170 @@
+package com.j256.ormlite.android.processor.inputs;
+
+import java.lang.reflect.Field;
+import java.sql.SQLException;
+
+import android.content.Context;
+import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteDatabase.CursorFactory;
+
+import com.j256.ormlite.android.annotations.Database;
+import com.j256.ormlite.android.apptools.OrmLiteSqliteOpenHelper;
+import com.j256.ormlite.field.DataPersister;
+import com.j256.ormlite.field.DataType;
+import com.j256.ormlite.field.DatabaseField;
+import com.j256.ormlite.field.FieldType;
+import com.j256.ormlite.field.SqlType;
+import com.j256.ormlite.support.ConnectionSource;
+import com.j256.ormlite.support.DatabaseResults;
+import com.j256.ormlite.table.DatabaseTable;
+
+@DatabaseTable(tableName = "table")
+class NamedTableWithSpecifiedDatabaseField {
+
+ public static enum FieldTypeEnum {
+ VALUE, OTHER_VALUE;
+ }
+
+ public static class CustomPersister implements DataPersister {
+ public Object parseDefaultString(FieldType fieldType, String defaultStr)
+ throws SQLException {
+ return null;
+ }
+
+ public Object javaToSqlArg(FieldType fieldType, Object obj)
+ throws SQLException {
+ return null;
+ }
+
+ public Object resultToSqlArg(FieldType fieldType,
+ DatabaseResults results, int columnPos) throws SQLException {
+ return null;
+ }
+
+ public Object resultToJava(FieldType fieldType,
+ DatabaseResults results, int columnPos) throws SQLException {
+ return null;
+ }
+
+ public Object sqlArgToJava(FieldType fieldType, Object sqlArg,
+ int columnPos) throws SQLException {
+ return null;
+ }
+
+ public SqlType getSqlType() {
+ return null;
+ }
+
+ public boolean isStreamType() {
+ return false;
+ }
+
+ public Object resultStringToJava(FieldType fieldType,
+ String stringValue, int columnPos) throws SQLException {
+ return null;
+ }
+
+ public Class>[] getAssociatedClasses() {
+ return null;
+ }
+
+ public String[] getAssociatedClassNames() {
+ return null;
+ }
+
+ public Object makeConfigObject(FieldType fieldType) throws SQLException {
+ return null;
+ }
+
+ public Object convertIdNumber(Number number) {
+ return null;
+ }
+
+ public boolean isValidGeneratedType() {
+ return false;
+ }
+
+ public boolean isValidForField(Field field) {
+ return false;
+ }
+
+ public Class> getPrimaryClass() {
+ return null;
+ }
+
+ public boolean isEscapedDefaultValue() {
+ return false;
+ }
+
+ public boolean isEscapedValue() {
+ return false;
+ }
+
+ public boolean isPrimitive() {
+ return false;
+ }
+
+ public boolean isComparable() {
+ return false;
+ }
+
+ public boolean isAppropriateId() {
+ return false;
+ }
+
+ public boolean isArgumentHolderRequired() {
+ return false;
+ }
+
+ public boolean isSelfGeneratedId() {
+ return false;
+ }
+
+ public Object generateId() {
+ return null;
+ }
+
+ public int getDefaultWidth() {
+ return 0;
+ }
+
+ public boolean dataIsEqual(Object obj1, Object obj2) {
+ return false;
+ }
+
+ public boolean isValidForVersion() {
+ return false;
+ }
+
+ public Object moveToNextValue(Object currentValue) throws SQLException {
+ return null;
+ }
+ }
+
+ @DatabaseField(columnName = "column", dataType = DataType.ENUM_INTEGER, defaultValue = "VALUE", width = 100, canBeNull = false, id = true, generatedId = true, generatedIdSequence = "id_sequence", foreign = true, useGetSet = true, unknownEnumName = "OTHER_VALUE", throwIfNull = true, format = "%f", unique = true, uniqueCombo = true, index = true, uniqueIndex = true, indexName = "index", uniqueIndexName = "unique_index", foreignAutoRefresh = true, maxForeignAutoRefreshLevel = 5, persisterClass = CustomPersister.class, allowGeneratedIdInsert = true, columnDefinition = "INT NOT NULL", foreignAutoCreate = true, version = true, foreignColumnName = "foreign", readOnly = true)
+ FieldTypeEnum field;
+
+ @DatabaseField(persisted = false)
+ int ignored;
+
+ @Database({ NamedTableWithSpecifiedDatabaseField.class })
+ static abstract class OpenHelper extends OrmLiteSqliteOpenHelper {
+ OpenHelper(Context context, String databaseName, CursorFactory factory,
+ int databaseVersion) {
+ super(context, databaseName, factory, databaseVersion);
+ NamedTableWithSpecifiedDatabaseField_OpenHelper_TableConfig
+ .cacheTableConfigurations();
+ }
+
+ @Override
+ public void onCreate(SQLiteDatabase database,
+ ConnectionSource connectionSource) {
+ try {
+ NamedTableWithSpecifiedDatabaseField_OpenHelper_TableConfig
+ .createTables(connectionSource);
+ } catch (SQLException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+}
diff --git a/src/test/resources/inputs/NamedTableWithSpecifiedForeignCollectionField.java b/src/test/resources/inputs/NamedTableWithSpecifiedForeignCollectionField.java
new file mode 100644
index 00000000..d1257b56
--- /dev/null
+++ b/src/test/resources/inputs/NamedTableWithSpecifiedForeignCollectionField.java
@@ -0,0 +1,44 @@
+package com.j256.ormlite.android.processor.inputs;
+
+import java.sql.SQLException;
+import java.util.List;
+
+import android.content.Context;
+import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteDatabase.CursorFactory;
+
+import com.j256.ormlite.android.annotations.Database;
+import com.j256.ormlite.android.apptools.OrmLiteSqliteOpenHelper;
+import com.j256.ormlite.field.ForeignCollectionField;
+import com.j256.ormlite.support.ConnectionSource;
+import com.j256.ormlite.table.DatabaseTable;
+
+@DatabaseTable(tableName = "table")
+class NamedTableWithSpecifiedForeignCollectionField {
+ @ForeignCollectionField(eager = true, maxEagerLevel = 5, columnName = "column", orderColumnName = "order_column", orderAscending = false, foreignFieldName = "foreign_field")
+ List numbers;
+
+ @ForeignCollectionField(maxEagerForeignCollectionLevel = 5, foreignColumnName = "foreign_field")
+ List numbers_deprecated;
+
+ @Database({ NamedTableWithSpecifiedForeignCollectionField.class })
+ static abstract class OpenHelper extends OrmLiteSqliteOpenHelper {
+ OpenHelper(Context context, String databaseName, CursorFactory factory,
+ int databaseVersion) {
+ super(context, databaseName, factory, databaseVersion);
+ NamedTableWithSpecifiedForeignCollectionField_OpenHelper_TableConfig
+ .cacheTableConfigurations();
+ }
+
+ @Override
+ public void onCreate(SQLiteDatabase database,
+ ConnectionSource connectionSource) {
+ try {
+ NamedTableWithSpecifiedForeignCollectionField_OpenHelper_TableConfig
+ .createTables(connectionSource);
+ } catch (SQLException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+}
diff --git a/src/test/resources/inputs/TableWithFieldWithBothAnnotations.java b/src/test/resources/inputs/TableWithFieldWithBothAnnotations.java
new file mode 100644
index 00000000..ad3543d1
--- /dev/null
+++ b/src/test/resources/inputs/TableWithFieldWithBothAnnotations.java
@@ -0,0 +1,27 @@
+package com.j256.ormlite.android.processor.inputs;
+
+import java.util.List;
+
+import android.content.Context;
+import android.database.sqlite.SQLiteDatabase.CursorFactory;
+
+import com.j256.ormlite.android.annotations.Database;
+import com.j256.ormlite.android.apptools.OrmLiteSqliteOpenHelper;
+import com.j256.ormlite.field.DatabaseField;
+import com.j256.ormlite.field.ForeignCollectionField;
+import com.j256.ormlite.table.DatabaseTable;
+
+@DatabaseTable
+class TableWithFieldWithBothAnnotations {
+ @DatabaseField
+ @ForeignCollectionField
+ List field;
+
+ @Database({ TableWithFieldWithBothAnnotations.class })
+ static abstract class OpenHelper extends OrmLiteSqliteOpenHelper {
+ OpenHelper(Context context, String databaseName, CursorFactory factory,
+ int databaseVersion) {
+ super(context, databaseName, factory, databaseVersion);
+ }
+ }
+}
diff --git a/src/test/resources/inputs/UnnamedTableWithDefaultDatabaseField.java b/src/test/resources/inputs/UnnamedTableWithDefaultDatabaseField.java
new file mode 100644
index 00000000..a8a46b29
--- /dev/null
+++ b/src/test/resources/inputs/UnnamedTableWithDefaultDatabaseField.java
@@ -0,0 +1,40 @@
+package com.j256.ormlite.android.processor.inputs;
+
+import java.sql.SQLException;
+
+import android.content.Context;
+import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteDatabase.CursorFactory;
+
+import com.j256.ormlite.android.annotations.Database;
+import com.j256.ormlite.android.apptools.OrmLiteSqliteOpenHelper;
+import com.j256.ormlite.field.DatabaseField;
+import com.j256.ormlite.support.ConnectionSource;
+import com.j256.ormlite.table.DatabaseTable;
+
+@DatabaseTable
+class UnnamedTableWithDefaultDatabaseField {
+ @DatabaseField
+ int field;
+
+ @Database({ UnnamedTableWithDefaultDatabaseField.class })
+ static abstract class OpenHelper extends OrmLiteSqliteOpenHelper {
+ OpenHelper(Context context, String databaseName, CursorFactory factory,
+ int databaseVersion) {
+ super(context, databaseName, factory, databaseVersion);
+ UnnamedTableWithDefaultDatabaseField_OpenHelper_TableConfig
+ .cacheTableConfigurations();
+ }
+
+ @Override
+ public void onCreate(SQLiteDatabase database,
+ ConnectionSource connectionSource) {
+ try {
+ UnnamedTableWithDefaultDatabaseField_OpenHelper_TableConfig
+ .createTables(connectionSource);
+ } catch (SQLException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+}
diff --git a/src/test/resources/inputs/UnnamedTableWithDefaultForeignCollectionField.java b/src/test/resources/inputs/UnnamedTableWithDefaultForeignCollectionField.java
new file mode 100644
index 00000000..a8d94f65
--- /dev/null
+++ b/src/test/resources/inputs/UnnamedTableWithDefaultForeignCollectionField.java
@@ -0,0 +1,41 @@
+package com.j256.ormlite.android.processor.inputs;
+
+import java.sql.SQLException;
+import java.util.List;
+
+import android.content.Context;
+import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteDatabase.CursorFactory;
+
+import com.j256.ormlite.android.annotations.Database;
+import com.j256.ormlite.android.apptools.OrmLiteSqliteOpenHelper;
+import com.j256.ormlite.field.ForeignCollectionField;
+import com.j256.ormlite.support.ConnectionSource;
+import com.j256.ormlite.table.DatabaseTable;
+
+@DatabaseTable
+class UnnamedTableWithDefaultForeignCollectionField {
+ @ForeignCollectionField
+ List numbers;
+
+ @Database({ UnnamedTableWithDefaultForeignCollectionField.class })
+ static abstract class OpenHelper extends OrmLiteSqliteOpenHelper {
+ OpenHelper(Context context, String databaseName, CursorFactory factory,
+ int databaseVersion) {
+ super(context, databaseName, factory, databaseVersion);
+ UnnamedTableWithDefaultForeignCollectionField_OpenHelper_TableConfig
+ .cacheTableConfigurations();
+ }
+
+ @Override
+ public void onCreate(SQLiteDatabase database,
+ ConnectionSource connectionSource) {
+ try {
+ UnnamedTableWithDefaultForeignCollectionField_OpenHelper_TableConfig
+ .createTables(connectionSource);
+ } catch (SQLException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+}
diff --git a/src/test/resources/outputs/InnerClassTable_InnerClass_TableConfig.java b/src/test/resources/outputs/InnerClassTable_InnerClass_TableConfig.java
new file mode 100644
index 00000000..9adc54bc
--- /dev/null
+++ b/src/test/resources/outputs/InnerClassTable_InnerClass_TableConfig.java
@@ -0,0 +1,20 @@
+package com.j256.ormlite.android.processor.inputs;
+
+import com.j256.ormlite.field.DatabaseFieldConfig;
+import com.j256.ormlite.table.DatabaseTableConfig;
+import java.util.ArrayList;
+import java.util.List;
+
+public final class InnerClassTable_InnerClass_TableConfig {
+ private InnerClassTable_InnerClass_TableConfig() {
+ }
+
+ public static DatabaseTableConfig> createConfig() {
+ List databaseFieldConfigs = new ArrayList();
+ DatabaseFieldConfig fieldFieldConfig = new DatabaseFieldConfig("field");
+ databaseFieldConfigs.add(fieldFieldConfig);
+ return new DatabaseTableConfig(
+ InnerClassTable.InnerClass.class, "innerclass",
+ databaseFieldConfigs);
+ }
+}
\ No newline at end of file
diff --git a/src/test/resources/outputs/InnerClassTable_OpenHelper_TableConfig.java b/src/test/resources/outputs/InnerClassTable_OpenHelper_TableConfig.java
new file mode 100644
index 00000000..f1e21202
--- /dev/null
+++ b/src/test/resources/outputs/InnerClassTable_OpenHelper_TableConfig.java
@@ -0,0 +1,30 @@
+package com.j256.ormlite.android.processor.inputs;
+
+import com.j256.ormlite.dao.DaoManager;
+import com.j256.ormlite.support.ConnectionSource;
+import com.j256.ormlite.table.DatabaseTableConfig;
+import com.j256.ormlite.table.TableUtils;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.List;
+
+public final class InnerClassTable_OpenHelper_TableConfig {
+ private InnerClassTable_OpenHelper_TableConfig() {
+ }
+
+ public static void cacheTableConfigurations() {
+ List> tableConfigs = new ArrayList>();
+ tableConfigs.add(InnerClassTable_InnerClass_TableConfig.createConfig());
+ tableConfigs.add(InnerClassTable_OtherInnerClass_TableConfig
+ .createConfig());
+ DaoManager.addCachedDatabaseConfigs(tableConfigs);
+ }
+
+ public static void createTables(ConnectionSource connectionSource)
+ throws SQLException {
+ TableUtils.createTable(connectionSource,
+ InnerClassTable.InnerClass.class);
+ TableUtils.createTable(connectionSource,
+ InnerClassTable.OtherInnerClass.class);
+ }
+}
\ No newline at end of file
diff --git a/src/test/resources/outputs/InnerClassTable_OtherInnerClass_TableConfig.java b/src/test/resources/outputs/InnerClassTable_OtherInnerClass_TableConfig.java
new file mode 100644
index 00000000..da900b17
--- /dev/null
+++ b/src/test/resources/outputs/InnerClassTable_OtherInnerClass_TableConfig.java
@@ -0,0 +1,20 @@
+package com.j256.ormlite.android.processor.inputs;
+
+import com.j256.ormlite.field.DatabaseFieldConfig;
+import com.j256.ormlite.table.DatabaseTableConfig;
+import java.util.ArrayList;
+import java.util.List;
+
+public final class InnerClassTable_OtherInnerClass_TableConfig {
+ private InnerClassTable_OtherInnerClass_TableConfig() {
+ }
+
+ public static DatabaseTableConfig> createConfig() {
+ List databaseFieldConfigs = new ArrayList();
+ DatabaseFieldConfig fieldFieldConfig = new DatabaseFieldConfig("field");
+ databaseFieldConfigs.add(fieldFieldConfig);
+ return new DatabaseTableConfig(
+ InnerClassTable.OtherInnerClass.class, "otherinnerclass",
+ databaseFieldConfigs);
+ }
+}
\ No newline at end of file
diff --git a/src/test/resources/outputs/NamedTableWithSpecifiedDatabaseField_OpenHelper_TableConfig.java b/src/test/resources/outputs/NamedTableWithSpecifiedDatabaseField_OpenHelper_TableConfig.java
new file mode 100644
index 00000000..399d4612
--- /dev/null
+++ b/src/test/resources/outputs/NamedTableWithSpecifiedDatabaseField_OpenHelper_TableConfig.java
@@ -0,0 +1,27 @@
+package com.j256.ormlite.android.processor.inputs;
+
+import com.j256.ormlite.dao.DaoManager;
+import com.j256.ormlite.support.ConnectionSource;
+import com.j256.ormlite.table.DatabaseTableConfig;
+import com.j256.ormlite.table.TableUtils;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.List;
+
+public final class NamedTableWithSpecifiedDatabaseField_OpenHelper_TableConfig {
+ private NamedTableWithSpecifiedDatabaseField_OpenHelper_TableConfig() {
+ }
+
+ public static void cacheTableConfigurations() {
+ List> tableConfigs = new ArrayList>();
+ tableConfigs.add(NamedTableWithSpecifiedDatabaseField_TableConfig
+ .createConfig());
+ DaoManager.addCachedDatabaseConfigs(tableConfigs);
+ }
+
+ public static void createTables(ConnectionSource connectionSource)
+ throws SQLException {
+ TableUtils.createTable(connectionSource,
+ NamedTableWithSpecifiedDatabaseField.class);
+ }
+}
\ No newline at end of file
diff --git a/src/test/resources/outputs/NamedTableWithSpecifiedDatabaseField_TableConfig.java b/src/test/resources/outputs/NamedTableWithSpecifiedDatabaseField_TableConfig.java
new file mode 100644
index 00000000..95f86bec
--- /dev/null
+++ b/src/test/resources/outputs/NamedTableWithSpecifiedDatabaseField_TableConfig.java
@@ -0,0 +1,51 @@
+package com.j256.ormlite.android.processor.inputs;
+
+import com.j256.ormlite.field.DatabaseFieldConfig;
+import com.j256.ormlite.table.DatabaseTableConfig;
+import java.util.ArrayList;
+import java.util.List;
+
+public final class NamedTableWithSpecifiedDatabaseField_TableConfig {
+ private NamedTableWithSpecifiedDatabaseField_TableConfig() {
+ }
+
+ public static DatabaseTableConfig> createConfig() {
+ List databaseFieldConfigs = new ArrayList();
+ DatabaseFieldConfig fieldFieldConfig = new DatabaseFieldConfig("field");
+ fieldFieldConfig.setColumnName("column");
+ fieldFieldConfig
+ .setDataType(com.j256.ormlite.field.DataType.ENUM_INTEGER);
+ fieldFieldConfig.setDefaultValue("VALUE");
+ fieldFieldConfig.setWidth(100);
+ fieldFieldConfig.setCanBeNull(false);
+ fieldFieldConfig.setId(true);
+ fieldFieldConfig.setGeneratedId(true);
+ fieldFieldConfig.setGeneratedIdSequence("id_sequence");
+ fieldFieldConfig.setForeign(true);
+ fieldFieldConfig.setUseGetSet(true);
+ fieldFieldConfig
+ .setUnknownEnumValue(com.j256.ormlite.android.processor.inputs.NamedTableWithSpecifiedDatabaseField.FieldTypeEnum.OTHER_VALUE);
+ fieldFieldConfig.setThrowIfNull(true);
+ fieldFieldConfig.setFormat("%f");
+ fieldFieldConfig.setUnique(true);
+ fieldFieldConfig.setUniqueCombo(true);
+ fieldFieldConfig.setIndex(true);
+ fieldFieldConfig.setUniqueIndex(true);
+ fieldFieldConfig.setIndexName("index");
+ fieldFieldConfig.setUniqueIndexName("unique_index");
+ fieldFieldConfig.setForeignAutoRefresh(true);
+ fieldFieldConfig.setMaxForeignAutoRefreshLevel(5);
+ fieldFieldConfig
+ .setPersisterClass(NamedTableWithSpecifiedDatabaseField.CustomPersister.class);
+ fieldFieldConfig.setAllowGeneratedIdInsert(true);
+ fieldFieldConfig.setColumnDefinition("INT NOT NULL");
+ fieldFieldConfig.setForeignAutoCreate(true);
+ fieldFieldConfig.setVersion(true);
+ fieldFieldConfig.setForeignColumnName("foreign");
+ fieldFieldConfig.setReadOnly(true);
+ databaseFieldConfigs.add(fieldFieldConfig);
+ return new DatabaseTableConfig(
+ NamedTableWithSpecifiedDatabaseField.class, "table",
+ databaseFieldConfigs);
+ }
+}
\ No newline at end of file
diff --git a/src/test/resources/outputs/NamedTableWithSpecifiedForeignCollectionField_OpenHelper_TableConfig.java b/src/test/resources/outputs/NamedTableWithSpecifiedForeignCollectionField_OpenHelper_TableConfig.java
new file mode 100644
index 00000000..2c74f06e
--- /dev/null
+++ b/src/test/resources/outputs/NamedTableWithSpecifiedForeignCollectionField_OpenHelper_TableConfig.java
@@ -0,0 +1,28 @@
+package com.j256.ormlite.android.processor.inputs;
+
+import com.j256.ormlite.dao.DaoManager;
+import com.j256.ormlite.support.ConnectionSource;
+import com.j256.ormlite.table.DatabaseTableConfig;
+import com.j256.ormlite.table.TableUtils;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.List;
+
+public final class NamedTableWithSpecifiedForeignCollectionField_OpenHelper_TableConfig {
+ private NamedTableWithSpecifiedForeignCollectionField_OpenHelper_TableConfig() {
+ }
+
+ public static void cacheTableConfigurations() {
+ List> tableConfigs = new ArrayList>();
+ tableConfigs
+ .add(NamedTableWithSpecifiedForeignCollectionField_TableConfig
+ .createConfig());
+ DaoManager.addCachedDatabaseConfigs(tableConfigs);
+ }
+
+ public static void createTables(ConnectionSource connectionSource)
+ throws SQLException {
+ TableUtils.createTable(connectionSource,
+ NamedTableWithSpecifiedForeignCollectionField.class);
+ }
+}
\ No newline at end of file
diff --git a/src/test/resources/outputs/NamedTableWithSpecifiedForeignCollectionField_TableConfig.java b/src/test/resources/outputs/NamedTableWithSpecifiedForeignCollectionField_TableConfig.java
new file mode 100644
index 00000000..d2fc7447
--- /dev/null
+++ b/src/test/resources/outputs/NamedTableWithSpecifiedForeignCollectionField_TableConfig.java
@@ -0,0 +1,37 @@
+package com.j256.ormlite.android.processor.inputs;
+
+import com.j256.ormlite.field.DatabaseFieldConfig;
+import com.j256.ormlite.table.DatabaseTableConfig;
+import java.util.ArrayList;
+import java.util.List;
+
+public final class NamedTableWithSpecifiedForeignCollectionField_TableConfig {
+ private NamedTableWithSpecifiedForeignCollectionField_TableConfig() {
+ }
+
+ public static DatabaseTableConfig> createConfig() {
+ List databaseFieldConfigs = new ArrayList();
+ DatabaseFieldConfig numbersFieldConfig = new DatabaseFieldConfig(
+ "numbers");
+ numbersFieldConfig.setColumnName("column");
+ numbersFieldConfig.setForeignCollection(true);
+ numbersFieldConfig.setForeignCollectionEager(true);
+ numbersFieldConfig.setForeignCollectionMaxEagerLevel(5);
+ numbersFieldConfig.setForeignCollectionColumnName("column");
+ numbersFieldConfig.setForeignCollectionOrderColumnName("order_column");
+ numbersFieldConfig.setForeignCollectionOrderAscending(false);
+ numbersFieldConfig
+ .setForeignCollectionForeignFieldName("foreign_field");
+ databaseFieldConfigs.add(numbersFieldConfig);
+ DatabaseFieldConfig numbers_deprecatedFieldConfig = new DatabaseFieldConfig(
+ "numbers_deprecated");
+ numbers_deprecatedFieldConfig.setForeignCollection(true);
+ numbers_deprecatedFieldConfig.setForeignCollectionMaxEagerLevel(5);
+ numbers_deprecatedFieldConfig
+ .setForeignCollectionForeignFieldName("foreign_field");
+ databaseFieldConfigs.add(numbers_deprecatedFieldConfig);
+ return new DatabaseTableConfig(
+ NamedTableWithSpecifiedForeignCollectionField.class, "table",
+ databaseFieldConfigs);
+ }
+}
\ No newline at end of file
diff --git a/src/test/resources/outputs/UnnamedTableWithDefaultDatabaseField_OpenHelper_TableConfig.java b/src/test/resources/outputs/UnnamedTableWithDefaultDatabaseField_OpenHelper_TableConfig.java
new file mode 100644
index 00000000..c847816d
--- /dev/null
+++ b/src/test/resources/outputs/UnnamedTableWithDefaultDatabaseField_OpenHelper_TableConfig.java
@@ -0,0 +1,27 @@
+package com.j256.ormlite.android.processor.inputs;
+
+import com.j256.ormlite.dao.DaoManager;
+import com.j256.ormlite.support.ConnectionSource;
+import com.j256.ormlite.table.DatabaseTableConfig;
+import com.j256.ormlite.table.TableUtils;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.List;
+
+public final class UnnamedTableWithDefaultDatabaseField_OpenHelper_TableConfig {
+ private UnnamedTableWithDefaultDatabaseField_OpenHelper_TableConfig() {
+ }
+
+ public static void cacheTableConfigurations() {
+ List> tableConfigs = new ArrayList>();
+ tableConfigs.add(UnnamedTableWithDefaultDatabaseField_TableConfig
+ .createConfig());
+ DaoManager.addCachedDatabaseConfigs(tableConfigs);
+ }
+
+ public static void createTables(ConnectionSource connectionSource)
+ throws SQLException {
+ TableUtils.createTable(connectionSource,
+ UnnamedTableWithDefaultDatabaseField.class);
+ }
+}
\ No newline at end of file
diff --git a/src/test/resources/outputs/UnnamedTableWithDefaultDatabaseField_TableConfig.java b/src/test/resources/outputs/UnnamedTableWithDefaultDatabaseField_TableConfig.java
new file mode 100644
index 00000000..fa5836f4
--- /dev/null
+++ b/src/test/resources/outputs/UnnamedTableWithDefaultDatabaseField_TableConfig.java
@@ -0,0 +1,20 @@
+package com.j256.ormlite.android.processor.inputs;
+
+import com.j256.ormlite.field.DatabaseFieldConfig;
+import com.j256.ormlite.table.DatabaseTableConfig;
+import java.util.ArrayList;
+import java.util.List;
+
+public final class UnnamedTableWithDefaultDatabaseField_TableConfig {
+ private UnnamedTableWithDefaultDatabaseField_TableConfig() {
+ }
+
+ public static DatabaseTableConfig> createConfig() {
+ List databaseFieldConfigs = new ArrayList();
+ DatabaseFieldConfig fieldFieldConfig = new DatabaseFieldConfig("field");
+ databaseFieldConfigs.add(fieldFieldConfig);
+ return new DatabaseTableConfig(
+ UnnamedTableWithDefaultDatabaseField.class,
+ "unnamedtablewithdefaultdatabasefield", databaseFieldConfigs);
+ }
+}
\ No newline at end of file
diff --git a/src/test/resources/outputs/UnnamedTableWithDefaultForeignCollectionField_OpenHelper_TableConfig.java b/src/test/resources/outputs/UnnamedTableWithDefaultForeignCollectionField_OpenHelper_TableConfig.java
new file mode 100644
index 00000000..c0a61c6a
--- /dev/null
+++ b/src/test/resources/outputs/UnnamedTableWithDefaultForeignCollectionField_OpenHelper_TableConfig.java
@@ -0,0 +1,28 @@
+package com.j256.ormlite.android.processor.inputs;
+
+import com.j256.ormlite.dao.DaoManager;
+import com.j256.ormlite.support.ConnectionSource;
+import com.j256.ormlite.table.DatabaseTableConfig;
+import com.j256.ormlite.table.TableUtils;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.List;
+
+public final class UnnamedTableWithDefaultForeignCollectionField_OpenHelper_TableConfig {
+ private UnnamedTableWithDefaultForeignCollectionField_OpenHelper_TableConfig() {
+ }
+
+ public static void cacheTableConfigurations() {
+ List> tableConfigs = new ArrayList>();
+ tableConfigs
+ .add(UnnamedTableWithDefaultForeignCollectionField_TableConfig
+ .createConfig());
+ DaoManager.addCachedDatabaseConfigs(tableConfigs);
+ }
+
+ public static void createTables(ConnectionSource connectionSource)
+ throws SQLException {
+ TableUtils.createTable(connectionSource,
+ UnnamedTableWithDefaultForeignCollectionField.class);
+ }
+}
\ No newline at end of file
diff --git a/src/test/resources/outputs/UnnamedTableWithDefaultForeignCollectionField_TableConfig.java b/src/test/resources/outputs/UnnamedTableWithDefaultForeignCollectionField_TableConfig.java
new file mode 100644
index 00000000..c58675df
--- /dev/null
+++ b/src/test/resources/outputs/UnnamedTableWithDefaultForeignCollectionField_TableConfig.java
@@ -0,0 +1,23 @@
+package com.j256.ormlite.android.processor.inputs;
+
+import com.j256.ormlite.field.DatabaseFieldConfig;
+import com.j256.ormlite.table.DatabaseTableConfig;
+import java.util.ArrayList;
+import java.util.List;
+
+public final class UnnamedTableWithDefaultForeignCollectionField_TableConfig {
+ private UnnamedTableWithDefaultForeignCollectionField_TableConfig() {
+ }
+
+ public static DatabaseTableConfig> createConfig() {
+ List databaseFieldConfigs = new ArrayList();
+ DatabaseFieldConfig numbersFieldConfig = new DatabaseFieldConfig(
+ "numbers");
+ numbersFieldConfig.setForeignCollection(true);
+ databaseFieldConfigs.add(numbersFieldConfig);
+ return new DatabaseTableConfig(
+ UnnamedTableWithDefaultForeignCollectionField.class,
+ "unnamedtablewithdefaultforeigncollectionfield",
+ databaseFieldConfigs);
+ }
+}
\ No newline at end of file