From 91326fb72ce37ea34707785e733bcd9091643ddf Mon Sep 17 00:00:00 2001 From: "James H. Hill" Date: Sat, 30 Jan 2016 19:46:45 -0500 Subject: [PATCH 01/47] First pass at external foreign key references --- .../raizlabs/android/dbflow/SecondModel.java | 8 +- build.gradle | 3 +- .../android/dbflow/processor/ClassNames.java | 1 + .../definition/ModelContainerDefinition.java | 4 +- .../processor/definition/TableDefinition.java | 7 +- .../column/ForeignKeyColumnDefinition.java | 336 +----------------- .../column/ForeignKeyReferenceDefinition.java | 15 +- .../container/ForeignInteractionModel.java | 17 +- .../container/ForeignKeyContainer.java | 2 - .../container/ModelContainerAdapter.java | 3 +- 10 files changed, 41 insertions(+), 355 deletions(-) diff --git a/app/src/main/java/com/raizlabs/android/dbflow/SecondModel.java b/app/src/main/java/com/raizlabs/android/dbflow/SecondModel.java index 5097b3e8f..43ed68118 100644 --- a/app/src/main/java/com/raizlabs/android/dbflow/SecondModel.java +++ b/app/src/main/java/com/raizlabs/android/dbflow/SecondModel.java @@ -1,17 +1,19 @@ package com.raizlabs.android.dbflow; -import com.raizlabs.android.dbflow.annotation.Column; +import com.raizlabs.android.dbflow.annotation.ForeignKey; import com.raizlabs.android.dbflow.annotation.PrimaryKey; import com.raizlabs.android.dbflow.annotation.Table; import com.raizlabs.android.dbflow.structure.BaseModel; +import com.raizlabs.android.dbflow.structure.container.ForeignKeyContainer; /** * Description: */ @Table(database = SecondAppDatabase.class) public class SecondModel extends BaseModel { - - @Column @PrimaryKey String name; + + @ForeignKey + ForeignKeyContainer secondModel; } diff --git a/build.gradle b/build.gradle index 0bb1c63f3..0cbbea3d3 100644 --- a/build.gradle +++ b/build.gradle @@ -3,7 +3,8 @@ buildscript { jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:1.5.0-beta1' + classpath 'com.android.tools.build:gradle:1.3.0' + //classpath 'com.android.tools.build:gradle:1.5.0' classpath 'com.neenbedankt.gradle.plugins:android-apt:1.7' classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.1' } diff --git a/dbflow-processor/src/main/java/com/raizlabs/android/dbflow/processor/ClassNames.java b/dbflow-processor/src/main/java/com/raizlabs/android/dbflow/processor/ClassNames.java index a99b197da..bbb140d50 100644 --- a/dbflow-processor/src/main/java/com/raizlabs/android/dbflow/processor/ClassNames.java +++ b/dbflow-processor/src/main/java/com/raizlabs/android/dbflow/processor/ClassNames.java @@ -86,6 +86,7 @@ public class ClassNames { public static final ClassName MODEL_CONTAINER = ClassName.get(CONTAINER, "ModelContainer"); public static final ClassName MODEL_CONTAINER_ADAPTER = ClassName.get(CONTAINER, "ModelContainerAdapter"); public static final ClassName FOREIGN_KEY_CONTAINER = ClassName.get(CONTAINER, "ForeignKeyContainer"); + public static final ClassName EXTERNAL_FOREIGN_KEY_CONTAINER = ClassName.get(CONTAINER, "ExternalForeignKeyContainer"); public static final ClassName BASE_MODEL = ClassName.get(STRUCTURE, "BaseModel"); public static final ClassName MODEL_CACHE = ClassName.get(STRUCTURE + ".cache", "ModelCache"); public static final ClassName MULTI_KEY_CACHE_CONVERTER = ClassName.get(STRUCTURE + ".cache", "IMultiKeyCacheConverter"); diff --git a/dbflow-processor/src/main/java/com/raizlabs/android/dbflow/processor/definition/ModelContainerDefinition.java b/dbflow-processor/src/main/java/com/raizlabs/android/dbflow/processor/definition/ModelContainerDefinition.java index 73441d126..1ac7bb93c 100644 --- a/dbflow-processor/src/main/java/com/raizlabs/android/dbflow/processor/definition/ModelContainerDefinition.java +++ b/dbflow-processor/src/main/java/com/raizlabs/android/dbflow/processor/definition/ModelContainerDefinition.java @@ -7,6 +7,7 @@ import com.raizlabs.android.dbflow.processor.definition.method.BindToStatementMethod; import com.raizlabs.android.dbflow.processor.definition.method.CustomTypeConverterPropertyMethod; import com.raizlabs.android.dbflow.processor.definition.method.ExistenceMethod; +import com.raizlabs.android.dbflow.processor.definition.method.ExternalForeignKeyContainerMethod; import com.raizlabs.android.dbflow.processor.definition.method.ForeignKeyContainerMethod; import com.raizlabs.android.dbflow.processor.definition.method.LoadFromCursorMethod; import com.raizlabs.android.dbflow.processor.definition.method.MethodDefinition; @@ -58,7 +59,8 @@ public ModelContainerDefinition(TypeElement classElement, ProcessorManager manag new PrimaryConditionMethod(tableDefinition, true), new ToModelMethod(tableDefinition), new LoadFromCursorMethod(tableDefinition, true, tableDefinition.implementsLoadFromCursorListener, putDefaultValue), - new ForeignKeyContainerMethod(tableDefinition) + new ForeignKeyContainerMethod(tableDefinition), + new ExternalForeignKeyContainerMethod(tableDefinition) }; } } diff --git a/dbflow-processor/src/main/java/com/raizlabs/android/dbflow/processor/definition/TableDefinition.java b/dbflow-processor/src/main/java/com/raizlabs/android/dbflow/processor/definition/TableDefinition.java index 58c004713..be0f03ebb 100644 --- a/dbflow-processor/src/main/java/com/raizlabs/android/dbflow/processor/definition/TableDefinition.java +++ b/dbflow-processor/src/main/java/com/raizlabs/android/dbflow/processor/definition/TableDefinition.java @@ -5,6 +5,7 @@ import com.raizlabs.android.dbflow.annotation.Column; import com.raizlabs.android.dbflow.annotation.ConflictAction; import com.raizlabs.android.dbflow.annotation.ContainerKey; +import com.raizlabs.android.dbflow.annotation.ExternalForeignKey; import com.raizlabs.android.dbflow.annotation.ForeignKey; import com.raizlabs.android.dbflow.annotation.IndexGroup; import com.raizlabs.android.dbflow.annotation.InheritedColumn; @@ -19,6 +20,7 @@ import com.raizlabs.android.dbflow.processor.ProcessorUtils; import com.raizlabs.android.dbflow.processor.definition.column.ColumnDefinition; import com.raizlabs.android.dbflow.processor.definition.column.ContainerKeyDefinition; +import com.raizlabs.android.dbflow.processor.definition.column.ExternalForeignKeyColumnDefinition; import com.raizlabs.android.dbflow.processor.definition.column.ForeignKeyColumnDefinition; import com.raizlabs.android.dbflow.processor.definition.method.BindToContentValuesMethod; import com.raizlabs.android.dbflow.processor.definition.method.BindToStatementMethod; @@ -285,10 +287,11 @@ protected void createColumnDefinitions(TypeElement typeElement) { boolean isPackagePrivateNotInSamePackage = isPackagePrivate && !ElementUtility.isInSamePackage(manager, element, this.element); boolean isForeign = element.getAnnotation(ForeignKey.class) != null; + boolean isExternalForeign = element.getAnnotation(ExternalForeignKey.class) != null; boolean isPrimary = element.getAnnotation(PrimaryKey.class) != null; boolean isInherited = inheritedColumnMap.containsKey(element.getSimpleName().toString()); boolean isInheritedPrimaryKey = inheritedPrimaryKeyMap.containsKey(element.getSimpleName().toString()); - if (element.getAnnotation(Column.class) != null || isForeign || isPrimary + if (element.getAnnotation(Column.class) != null || isForeign || isExternalForeign || isPrimary || isValidColumn || isInherited || isInheritedPrimaryKey) { @@ -303,6 +306,8 @@ protected void createColumnDefinitions(TypeElement typeElement) { inherited.column(), null); } else if (isForeign) { columnDefinition = new ForeignKeyColumnDefinition(manager, this, element, isPackagePrivateNotInSamePackage); + } else if (isExternalForeign) { + columnDefinition = new ExternalForeignKeyColumnDefinition(manager, this, element, isPackagePrivateNotInSamePackage); } else { columnDefinition = new ColumnDefinition(manager, element, this, isPackagePrivateNotInSamePackage); } diff --git a/dbflow-processor/src/main/java/com/raizlabs/android/dbflow/processor/definition/column/ForeignKeyColumnDefinition.java b/dbflow-processor/src/main/java/com/raizlabs/android/dbflow/processor/definition/column/ForeignKeyColumnDefinition.java index b45dd549f..b7f90dde5 100644 --- a/dbflow-processor/src/main/java/com/raizlabs/android/dbflow/processor/definition/column/ForeignKeyColumnDefinition.java +++ b/dbflow-processor/src/main/java/com/raizlabs/android/dbflow/processor/definition/column/ForeignKeyColumnDefinition.java @@ -1,63 +1,28 @@ package com.raizlabs.android.dbflow.processor.definition.column; -import com.raizlabs.android.dbflow.annotation.Column; import com.raizlabs.android.dbflow.annotation.ForeignKey; import com.raizlabs.android.dbflow.annotation.ForeignKeyAction; import com.raizlabs.android.dbflow.annotation.ForeignKeyReference; -import com.raizlabs.android.dbflow.processor.ClassNames; -import com.raizlabs.android.dbflow.processor.ProcessorUtils; import com.raizlabs.android.dbflow.processor.definition.TableDefinition; -import com.raizlabs.android.dbflow.processor.definition.method.BindToContentValuesMethod; -import com.raizlabs.android.dbflow.processor.definition.method.BindToStatementMethod; -import com.raizlabs.android.dbflow.processor.definition.method.LoadFromCursorMethod; import com.raizlabs.android.dbflow.processor.model.ProcessorManager; -import com.raizlabs.android.dbflow.processor.utils.ModelUtils; -import com.raizlabs.android.dbflow.processor.utils.StringUtils; -import com.raizlabs.android.dbflow.sql.QueryBuilder; import com.squareup.javapoet.ClassName; -import com.squareup.javapoet.CodeBlock; -import com.squareup.javapoet.FieldSpec; -import com.squareup.javapoet.MethodSpec; import com.squareup.javapoet.ParameterizedTypeName; import com.squareup.javapoet.TypeName; -import com.squareup.javapoet.TypeSpec; -import java.util.ArrayList; import java.util.List; -import java.util.concurrent.atomic.AtomicInteger; import javax.lang.model.element.Element; -import javax.lang.model.element.Modifier; -import javax.lang.model.element.TypeElement; import javax.lang.model.type.MirroredTypeException; /** * Description: */ -public class ForeignKeyColumnDefinition extends ColumnDefinition { - - public final List foreignKeyReferenceDefinitionList = new ArrayList<>(); - - public final TableDefinition tableDefinition; - - public ClassName referencedTableClassName; - +public class ForeignKeyColumnDefinition extends BaseForeignKeyColumnDefinition { public ForeignKeyAction onDelete; public ForeignKeyAction onUpdate; - public boolean isModelContainer; - - public boolean isModel; - - public boolean needsReferences; - - public boolean nonModelColumn; - - public boolean saveForeignKeyModel; - public ForeignKeyColumnDefinition(ProcessorManager manager, TableDefinition tableDefinition, Element typeElement, boolean isPackagePrivate) { - super(manager, typeElement, tableDefinition, isPackagePrivate); - this.tableDefinition = tableDefinition; + super(manager, tableDefinition, typeElement, isPackagePrivate); ForeignKey foreignKey = typeElement.getAnnotation(ForeignKey.class); onUpdate = foreignKey.onUpdate(); @@ -86,26 +51,6 @@ public ForeignKeyColumnDefinition(ProcessorManager manager, TableDefinition tabl manager.logError("Referenced was null for %1s within %1s", typeElement, elementTypeName); } - TypeElement element = manager.getElements().getTypeElement( - manager.getTypeUtils().erasure(typeElement.asType()).toString()); - - isModel = ProcessorUtils.implementsClass(manager.getProcessingEnvironment(), ClassNames.MODEL.toString(), element); - isModelContainer = isModelContainer || ProcessorUtils.implementsClass(manager.getProcessingEnvironment(), ClassNames.MODEL_CONTAINER.toString(), element); - nonModelColumn = !isModel && !isModelContainer; - - saveForeignKeyModel = foreignKey.saveForeignKeyModel(); - - // we need to recheck for this instance - if (columnAccess instanceof TypeConverterAccess) { - if (typeElement.getModifiers().contains(Modifier.PRIVATE)) { - boolean useIs = elementTypeName.box().equals(TypeName.BOOLEAN.box()) - && tableDefinition.useIsForPrivateBooleans; - columnAccess = new PrivateColumnAccess(typeElement.getAnnotation(Column.class), useIs); - } else { - columnAccess = new SimpleColumnAccess(); - } - } - ForeignKeyReference[] references = foreignKey.references(); if (references.length == 0) { // no references specified we will delegate references call to post-evaluation @@ -117,292 +62,23 @@ public ForeignKeyColumnDefinition(ProcessorManager manager, TableDefinition tabl foreignKeyReferenceDefinitionList.add(referenceDefinition); } } - - } - - @Override - public void addPropertyDefinition(TypeSpec.Builder typeBuilder, TypeName tableClassName) { - checkNeedsReferences(); - for (ForeignKeyReferenceDefinition reference : foreignKeyReferenceDefinitionList) { - TypeName propParam; - if (reference.columnClassName.isPrimitive() && !reference.columnClassName.equals(TypeName.BOOLEAN)) { - propParam = ClassName.get(ClassNames.PROPERTY_PACKAGE, StringUtils.capitalize(reference.columnClassName.toString()) + "Property"); - } else { - propParam = ParameterizedTypeName.get(ClassNames.PROPERTY, reference.columnClassName.box()); - } - typeBuilder.addField(FieldSpec.builder(propParam, reference.columnName, Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL) - .initializer("new $T($T.class, $S)", propParam, tableClassName, reference.columnName).build()); - } - } - - @Override - public void addPropertyCase(MethodSpec.Builder methodBuilder) { - checkNeedsReferences(); - for (ForeignKeyReferenceDefinition reference : foreignKeyReferenceDefinitionList) { - methodBuilder.beginControlFlow("case $S: ", reference.columnName); - methodBuilder.addStatement("return $L", reference.columnName); - methodBuilder.endControlFlow(); - } - } - - @Override - public CodeBlock getInsertStatementColumnName() { - checkNeedsReferences(); - CodeBlock.Builder builder = CodeBlock.builder(); - for (int i = 0; i < foreignKeyReferenceDefinitionList.size(); i++) { - if (i > 0) { - builder.add(","); - } - ForeignKeyReferenceDefinition referenceDefinition = foreignKeyReferenceDefinitionList.get(i); - builder.add("$L", QueryBuilder.quote(referenceDefinition.columnName)); - } - return builder.build(); - } - - @Override - public CodeBlock getInsertStatementValuesString() { - checkNeedsReferences(); - CodeBlock.Builder builder = CodeBlock.builder(); - for (int i = 0; i < foreignKeyReferenceDefinitionList.size(); i++) { - if (i > 0) { - builder.add(","); - } - builder.add("?"); - } - return builder.build(); - } - - @Override - public CodeBlock getCreationName() { - checkNeedsReferences(); - CodeBlock.Builder builder = CodeBlock.builder(); - for (int i = 0; i < foreignKeyReferenceDefinitionList.size(); i++) { - if (i > 0) { - builder.add(" ,"); - } - ForeignKeyReferenceDefinition referenceDefinition = foreignKeyReferenceDefinitionList.get(i); - builder.add(referenceDefinition.getCreationStatement()); - } - return builder.build(); - } - - @Override - public CodeBlock getContentValuesStatement(boolean isModelContainerAdapter) { - if (nonModelColumn) { - return super.getContentValuesStatement(isModelContainerAdapter); - } else { - checkNeedsReferences(); - CodeBlock.Builder builder = CodeBlock.builder(); - String statement = columnAccess - .getColumnAccessString(elementTypeName, elementName, elementName, - ModelUtils.getVariable(isModelContainerAdapter), isModelContainerAdapter, false); - String finalAccessStatement = getFinalAccessStatement(builder, isModelContainerAdapter, statement); - builder.beginControlFlow("if ($L != null)", finalAccessStatement); - CodeBlock.Builder elseBuilder = CodeBlock.builder(); - for (ForeignKeyReferenceDefinition referenceDefinition : foreignKeyReferenceDefinitionList) { - builder.add(referenceDefinition.getContentValuesStatement(isModelContainerAdapter)); - elseBuilder.addStatement("$L.putNull($S)", BindToContentValuesMethod.PARAM_CONTENT_VALUES, QueryBuilder.quote(referenceDefinition.columnName)); - } - - if (saveForeignKeyModel) { - builder.addStatement("$L.save()", finalAccessStatement); - } - - builder.nextControlFlow("else") - .add(elseBuilder.build()) - .endControlFlow(); - return builder.build(); - } - } - - @Override - public CodeBlock getSQLiteStatementMethod(AtomicInteger index, boolean isModelContainerAdapter) { - if (nonModelColumn) { - return super.getSQLiteStatementMethod(index, isModelContainerAdapter); - } else { - checkNeedsReferences(); - CodeBlock.Builder builder = CodeBlock.builder(); - String statement = columnAccess - .getColumnAccessString(elementTypeName, elementName, elementName, - ModelUtils.getVariable(isModelContainerAdapter), isModelContainerAdapter, true); - String finalAccessStatement = getFinalAccessStatement(builder, isModelContainerAdapter, statement); - builder.beginControlFlow("if ($L != null)", finalAccessStatement); - CodeBlock.Builder elseBuilder = CodeBlock.builder(); - for (int i = 0; i < foreignKeyReferenceDefinitionList.size(); i++) { - if (i > 0) { - index.incrementAndGet(); - } - ForeignKeyReferenceDefinition referenceDefinition = foreignKeyReferenceDefinitionList.get(i); - builder.add(referenceDefinition.getSQLiteStatementMethod(index, isModelContainerAdapter)); - elseBuilder.addStatement("$L.bindNull($L)", BindToStatementMethod.PARAM_STATEMENT, index.intValue() + " + " + BindToStatementMethod.PARAM_START); - } - - if (saveForeignKeyModel) { - builder.addStatement("$L.save()", finalAccessStatement); - } - - builder.nextControlFlow("else") - .add(elseBuilder.build()) - .endControlFlow(); - return builder.build(); - } - } - - @Override - public CodeBlock getLoadFromCursorMethod(boolean isModelContainerAdapter, boolean putNullForContainerAdapter, - boolean endNonPrimitiveIf) { - if (nonModelColumn) { - return super.getLoadFromCursorMethod(isModelContainerAdapter, putNullForContainerAdapter, endNonPrimitiveIf); - } else { - checkNeedsReferences(); - CodeBlock.Builder builder = CodeBlock.builder() - .add("//// Only load model if references match, for efficiency\n"); - CodeBlock.Builder ifNullBuilder = CodeBlock.builder() - .add("if ("); - CodeBlock.Builder selectBuilder = CodeBlock.builder(); - for (int i = 0; i < foreignKeyReferenceDefinitionList.size(); i++) { - ForeignKeyReferenceDefinition referenceDefinition = foreignKeyReferenceDefinitionList.get(i); - String indexName = "index" + referenceDefinition.columnName; - builder.addStatement("int $L = $L.getColumnIndex($S)", indexName, LoadFromCursorMethod.PARAM_CURSOR, referenceDefinition.columnName); - if (i > 0) { - ifNullBuilder.add(" && "); - } - ifNullBuilder.add("$L != -1 && !$L.isNull($L)", indexName, LoadFromCursorMethod.PARAM_CURSOR, indexName); - - // TODO: respect separator here. - selectBuilder.add("\n.and($L.$L.eq($L))", - ClassName.get(referencedTableClassName.packageName(), referencedTableClassName.simpleName() + "_" + TableDefinition.DBFLOW_TABLE_TAG), - referenceDefinition.foreignColumnName, - CodeBlock.builder().add("$L.$L($L)", LoadFromCursorMethod.PARAM_CURSOR, - DefinitionUtils.getLoadFromCursorMethodString(referenceDefinition.columnClassName, - referenceDefinition.columnAccess), indexName).build()); - } - ifNullBuilder.add(")"); - builder.beginControlFlow(ifNullBuilder.build().toString()); - - CodeBlock.Builder initializer = CodeBlock.builder(); - - initializer.add("new $T().from($T.class).where()", ClassNames.SELECT, referencedTableClassName) - .add(selectBuilder.build()); - if (!isModelContainerAdapter && !isModelContainer) { - initializer.add(".querySingle()"); - } else { - if (isModelContainerAdapter) { - initializer.add(".queryModelContainer($L.getInstance($L.newDataInstance(), $T.class)).getData()", ModelUtils.getVariable(true), - ModelUtils.getVariable(true), referencedTableClassName); - } else { - initializer.add(".queryModelContainer(new $T($T.class))", elementTypeName, referencedTableClassName); - } - } - - builder.addStatement(columnAccess.setColumnAccessString(elementTypeName, elementName, elementName, - isModelContainerAdapter, ModelUtils.getVariable(isModelContainerAdapter), initializer.build(), false)); - - boolean putDefaultValue = putNullForContainerAdapter; - if (putContainerDefaultValue != putDefaultValue && isModelContainerAdapter) { - putDefaultValue = putContainerDefaultValue; - } - if (putDefaultValue) { - builder.nextControlFlow("else"); - builder.addStatement("$L.putDefault($S)", ModelUtils.getVariable(true), columnName); - } - if (endNonPrimitiveIf) { - builder.endControlFlow(); - } - return builder.build(); - } - } - - @Override - public CodeBlock getToModelMethod() { - checkNeedsReferences(); - if (nonModelColumn) { - return super.getToModelMethod(); - } else { - CodeBlock.Builder builder = CodeBlock.builder(); - String statement = columnAccess - .getColumnAccessString(elementTypeName, elementName, elementName, - ModelUtils.getVariable(true), true, true); - String finalAccessStatement = getFinalAccessStatement(builder, true, statement); - - builder.beginControlFlow("if ($L != null)", finalAccessStatement); - if (!isModelContainer) { - CodeBlock.Builder modelContainerRetrieval = CodeBlock.builder(); - modelContainerRetrieval.add("$L.getContainerAdapter($T.class).toModel($L)", ClassNames.FLOW_MANAGER, - referencedTableClassName, finalAccessStatement); - builder.addStatement(columnAccess.setColumnAccessString(elementTypeName, elementName, elementName, - false, ModelUtils.getVariable(false), modelContainerRetrieval.build(), true)); - } else { - builder.addStatement(columnAccess.setColumnAccessString(elementTypeName, elementName, elementName, - false, ModelUtils.getVariable(false), CodeBlock.builder().add("new $T($L)", - elementTypeName, finalAccessStatement).build(), true)); - } - builder.endControlFlow(); - return builder.build(); - } - } - - String getFinalAccessStatement(CodeBlock.Builder codeBuilder, boolean isModelContainerAdapter, String statement) { - String finalAccessStatement = statement; - if (columnAccess instanceof TypeConverterAccess || - columnAccess instanceof ModelContainerAccess || - isModelContainerAdapter) { - finalAccessStatement = getRefName(); - - TypeName typeName; - if (columnAccess instanceof TypeConverterAccess) { - typeName = ((TypeConverterAccess) columnAccess).typeConverterDefinition.getDbTypeName(); - } else if (columnAccess instanceof ModelContainerAccess) { - typeName = ModelUtils.getModelContainerType(manager, referencedTableClassName); - } else { - if (isModelContainer || isModel) { - typeName = ModelUtils.getModelContainerType(manager, referencedTableClassName); - statement = ModelUtils.getVariable(isModelContainerAdapter) + ".getInstance(" + statement + ", " + referencedTableClassName + ".class)"; - } else { - typeName = referencedTableClassName; - } - } - - codeBuilder.addStatement("$T $L = $L", typeName, - finalAccessStatement, statement); - } - return finalAccessStatement; - } - - String getForeignKeyReferenceAccess(boolean isModelContainerAdapter, String statement) { - if (columnAccess instanceof TypeConverterAccess || - columnAccess instanceof ModelContainerAccess || - isModelContainerAdapter) { - return getRefName(); - } else { - return statement; - } - } - - public String getRefName() { - return "ref" + elementName; - } - - public List getForeignKeyReferenceDefinitionList() { - checkNeedsReferences(); - return foreignKeyReferenceDefinitionList; } /** * If {@link ForeignKey} has no {@link ForeignKeyReference}s, we use the primary key the referenced * table. We do this post-evaluation so all of the {@link TableDefinition} can be generated. */ - private void checkNeedsReferences() { + protected void checkNeedsReferences() { TableDefinition referencedTableDefinition = manager.getTableDefinition(tableDefinition.databaseTypeName, referencedTableClassName); if (referencedTableDefinition == null) { - manager.logError("Could not find the referenced table definition %1s from %1s. Ensure it exists in the same" + - "database %1s", referencedTableClassName, tableDefinition.tableName, tableDefinition.databaseTypeName); + System.err.println ("Must use @ExternalForeignKey"); } else { if (needsReferences) { List primaryColumns = referencedTableDefinition.getPrimaryColumnDefinitions(); for (ColumnDefinition primaryColumn : primaryColumns) { ForeignKeyReferenceDefinition foreignKeyReferenceDefinition = - new ForeignKeyReferenceDefinition(manager, elementName, primaryColumn, columnAccess, this); + new ForeignKeyReferenceDefinition(manager, elementName, primaryColumn, columnAccess, this); + foreignKeyReferenceDefinitionList.add(foreignKeyReferenceDefinition); } if (nonModelColumn) { diff --git a/dbflow-processor/src/main/java/com/raizlabs/android/dbflow/processor/definition/column/ForeignKeyReferenceDefinition.java b/dbflow-processor/src/main/java/com/raizlabs/android/dbflow/processor/definition/column/ForeignKeyReferenceDefinition.java index 1eac60f85..ca1fa6efe 100644 --- a/dbflow-processor/src/main/java/com/raizlabs/android/dbflow/processor/definition/column/ForeignKeyReferenceDefinition.java +++ b/dbflow-processor/src/main/java/com/raizlabs/android/dbflow/processor/definition/column/ForeignKeyReferenceDefinition.java @@ -31,14 +31,15 @@ public class ForeignKeyReferenceDefinition { public BaseColumnAccess columnAccess; private final BaseColumnAccess tableColumnAccess; - private final ForeignKeyColumnDefinition foreignKeyColumnDefinition; + private final BaseForeignKeyColumnDefinition foreignKeyColumnDefinition; private final BaseColumnAccess simpleColumnAccess; - public ForeignKeyReferenceDefinition(ProcessorManager manager, String foreignKeyFieldName, + public ForeignKeyReferenceDefinition(ProcessorManager manager, + String foreignKeyFieldName, ColumnDefinition referencedColumn, BaseColumnAccess tableColumnAccess, - ForeignKeyColumnDefinition foreignKeyColumnDefinition) { + BaseForeignKeyColumnDefinition foreignKeyColumnDefinition) { this.manager = manager; this.foreignKeyColumnDefinition = foreignKeyColumnDefinition; this.tableColumnAccess = tableColumnAccess; @@ -76,9 +77,11 @@ public ForeignKeyReferenceDefinition(ProcessorManager manager, String foreignKey simpleColumnAccess = new SimpleColumnAccess(columnAccess instanceof PackagePrivateAccess); } - public ForeignKeyReferenceDefinition(ProcessorManager manager, String foreignKeyFieldName, - ForeignKeyReference foreignKeyReference, BaseColumnAccess tableColumnAccess, - ForeignKeyColumnDefinition foreignKeyColumnDefinition) { + public ForeignKeyReferenceDefinition(ProcessorManager manager, + String foreignKeyFieldName, + ForeignKeyReference foreignKeyReference, + BaseColumnAccess tableColumnAccess, + BaseForeignKeyColumnDefinition foreignKeyColumnDefinition) { this.manager = manager; this.tableColumnAccess = tableColumnAccess; this.foreignKeyColumnDefinition = foreignKeyColumnDefinition; diff --git a/dbflow/src/androidTest/java/com/raizlabs/android/dbflow/test/container/ForeignInteractionModel.java b/dbflow/src/androidTest/java/com/raizlabs/android/dbflow/test/container/ForeignInteractionModel.java index 5b2d5f38d..5fde7e616 100644 --- a/dbflow/src/androidTest/java/com/raizlabs/android/dbflow/test/container/ForeignInteractionModel.java +++ b/dbflow/src/androidTest/java/com/raizlabs/android/dbflow/test/container/ForeignInteractionModel.java @@ -20,16 +20,13 @@ public class ForeignInteractionModel extends TestModel1 { @Column @ForeignKey( - onDelete = ForeignKeyAction.CASCADE, - onUpdate = ForeignKeyAction.CASCADE, - references = - {@ForeignKeyReference(columnName = "testmodel_id", - foreignKeyColumnName = "name", - columnType = String.class), - @ForeignKeyReference(columnName = "testmodel_type", - foreignKeyColumnName = "type", - columnType = String.class)}, - saveForeignKeyModel = false) + onDelete = ForeignKeyAction.CASCADE, + onUpdate = ForeignKeyAction.CASCADE, + references = { + @ForeignKeyReference(columnName = "testmodel_id", foreignKeyColumnName = "name", columnType = String.class), + @ForeignKeyReference(columnName = "testmodel_type", foreignKeyColumnName = "type", columnType = String.class) + }, + saveForeignKeyModel = true) ForeignKeyContainer testModel1; public TestModel1 getTestModel1() { diff --git a/dbflow/src/main/java/com/raizlabs/android/dbflow/structure/container/ForeignKeyContainer.java b/dbflow/src/main/java/com/raizlabs/android/dbflow/structure/container/ForeignKeyContainer.java index e7cc023d5..deca79acc 100644 --- a/dbflow/src/main/java/com/raizlabs/android/dbflow/structure/container/ForeignKeyContainer.java +++ b/dbflow/src/main/java/com/raizlabs/android/dbflow/structure/container/ForeignKeyContainer.java @@ -70,8 +70,6 @@ public void put(String columnName, Object value) { @Override public void setModel(ModelClass model) { super.setModel(model); - - } /** diff --git a/dbflow/src/main/java/com/raizlabs/android/dbflow/structure/container/ModelContainerAdapter.java b/dbflow/src/main/java/com/raizlabs/android/dbflow/structure/container/ModelContainerAdapter.java index 54ed9c74c..7b2afe2c2 100644 --- a/dbflow/src/main/java/com/raizlabs/android/dbflow/structure/container/ModelContainerAdapter.java +++ b/dbflow/src/main/java/com/raizlabs/android/dbflow/structure/container/ModelContainerAdapter.java @@ -1,6 +1,5 @@ package com.raizlabs.android.dbflow.structure.container; -import android.database.Cursor; import android.database.sqlite.SQLiteStatement; import android.support.annotation.NonNull; @@ -76,6 +75,8 @@ public void delete(ModelContainer modelContainer) { */ public abstract ForeignKeyContainer toForeignKeyContainer(ModelClass model); + public abstract ExternalForeignKeyContainer toExternalForeignKeyContainer(ModelClass model); + /** * If a {@link com.raizlabs.android.dbflow.structure.Model} has an autoincrementing primary key, then * this method will be overridden. From 50382fcc0195811a49816321f66ebd3a680ecb81 Mon Sep 17 00:00:00 2001 From: "James H. Hill" Date: Sat, 30 Jan 2016 19:51:23 -0500 Subject: [PATCH 02/47] Added missing files --- .../dbflow/annotation/ExternalForeignKey.java | 41 +++ .../BaseForeignKeyColumnDefinition.java | 348 ++++++++++++++++++ .../ExternalForeignKeyColumnDefinition.java | 104 ++++++ .../ExternalForeignKeyContainerMethod.java | 45 +++ .../ExternalForeignKeyTest.java | 33 ++ .../externalforeignkey/ForeignModel.java | 17 + .../ForeignParentModel.java | 13 + .../externalforeignkey/TestDatabase1.java | 7 + .../externalforeignkey/TestDatabase2.java | 7 + .../ExternalForeignKeyContainer.java | 44 +++ 10 files changed, 659 insertions(+) create mode 100644 dbflow-core/src/main/java/com/raizlabs/android/dbflow/annotation/ExternalForeignKey.java create mode 100644 dbflow-processor/src/main/java/com/raizlabs/android/dbflow/processor/definition/column/BaseForeignKeyColumnDefinition.java create mode 100644 dbflow-processor/src/main/java/com/raizlabs/android/dbflow/processor/definition/column/ExternalForeignKeyColumnDefinition.java create mode 100644 dbflow-processor/src/main/java/com/raizlabs/android/dbflow/processor/definition/method/ExternalForeignKeyContainerMethod.java create mode 100644 dbflow/src/androidTest/java/com/raizlabs/android/dbflow/test/structure/externalforeignkey/ExternalForeignKeyTest.java create mode 100644 dbflow/src/androidTest/java/com/raizlabs/android/dbflow/test/structure/externalforeignkey/ForeignModel.java create mode 100644 dbflow/src/androidTest/java/com/raizlabs/android/dbflow/test/structure/externalforeignkey/ForeignParentModel.java create mode 100644 dbflow/src/androidTest/java/com/raizlabs/android/dbflow/test/structure/externalforeignkey/TestDatabase1.java create mode 100644 dbflow/src/androidTest/java/com/raizlabs/android/dbflow/test/structure/externalforeignkey/TestDatabase2.java create mode 100644 dbflow/src/main/java/com/raizlabs/android/dbflow/structure/container/ExternalForeignKeyContainer.java diff --git a/dbflow-core/src/main/java/com/raizlabs/android/dbflow/annotation/ExternalForeignKey.java b/dbflow-core/src/main/java/com/raizlabs/android/dbflow/annotation/ExternalForeignKey.java new file mode 100644 index 000000000..a6460a523 --- /dev/null +++ b/dbflow-core/src/main/java/com/raizlabs/android/dbflow/annotation/ExternalForeignKey.java @@ -0,0 +1,41 @@ +package com.raizlabs.android.dbflow.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Description: + */ +@Retention(RetentionPolicy.SOURCE) +@Target(ElementType.FIELD) +public @interface ExternalForeignKey { + /** + * @return When this column is a {@link ExternalForeignKey} and a Model, returning true with save the model + * before adding the fields to save as a foreign key. If false, we expect the field to not change + * and must save the model manually outside of the ModelAdapter. This also applies to ModelContainer objects + * as foreign key fields. + */ + boolean saveForeignKeyModel() default true; + + /** + * @return Required table class that this reference points to. + */ + Class tableClass() default Object.class; + + /** + * @return Optional database class that owns the tableClass. This field is necessary if + * the table is in a database that is not defined in the current application, such as + * a module. + */ + Class databaseClass() default Object.class; + + /** + * Defines explicit references for a composite {@link ExternalForeignKey} definition. This is no required + * if the table is imported from a module. + * + * @return the set of explicit references if you wish to have different values than default generated. + */ + ForeignKeyReference[] references() default {}; +} diff --git a/dbflow-processor/src/main/java/com/raizlabs/android/dbflow/processor/definition/column/BaseForeignKeyColumnDefinition.java b/dbflow-processor/src/main/java/com/raizlabs/android/dbflow/processor/definition/column/BaseForeignKeyColumnDefinition.java new file mode 100644 index 000000000..502094c57 --- /dev/null +++ b/dbflow-processor/src/main/java/com/raizlabs/android/dbflow/processor/definition/column/BaseForeignKeyColumnDefinition.java @@ -0,0 +1,348 @@ +package com.raizlabs.android.dbflow.processor.definition.column; + +import com.raizlabs.android.dbflow.annotation.Column; +import com.raizlabs.android.dbflow.processor.ClassNames; +import com.raizlabs.android.dbflow.processor.ProcessorUtils; +import com.raizlabs.android.dbflow.processor.definition.TableDefinition; +import com.raizlabs.android.dbflow.processor.definition.method.BindToContentValuesMethod; +import com.raizlabs.android.dbflow.processor.definition.method.BindToStatementMethod; +import com.raizlabs.android.dbflow.processor.definition.method.LoadFromCursorMethod; +import com.raizlabs.android.dbflow.processor.model.ProcessorManager; +import com.raizlabs.android.dbflow.processor.utils.ModelUtils; +import com.raizlabs.android.dbflow.processor.utils.StringUtils; +import com.raizlabs.android.dbflow.sql.QueryBuilder; +import com.squareup.javapoet.ClassName; +import com.squareup.javapoet.CodeBlock; +import com.squareup.javapoet.FieldSpec; +import com.squareup.javapoet.MethodSpec; +import com.squareup.javapoet.ParameterizedTypeName; +import com.squareup.javapoet.TypeName; +import com.squareup.javapoet.TypeSpec; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.atomic.AtomicInteger; + +import javax.lang.model.element.Element; +import javax.lang.model.element.Modifier; +import javax.lang.model.element.TypeElement; + +/** + * Description: + */ +public abstract class BaseForeignKeyColumnDefinition extends ColumnDefinition { + + public final List foreignKeyReferenceDefinitionList = new ArrayList<>(); + + public final TableDefinition tableDefinition; + + public ClassName referencedTableClassName; + + public boolean isModelContainer; + + public boolean isModel; + + public boolean nonModelColumn; + + public boolean saveForeignKeyModel = false; + + public boolean needsReferences; + + public BaseForeignKeyColumnDefinition(ProcessorManager manager, TableDefinition tableDefinition, Element typeElement, boolean isPackagePrivate) { + super(manager, typeElement, tableDefinition, isPackagePrivate); + this.tableDefinition = tableDefinition; + + TypeElement element = manager.getElements().getTypeElement( + manager.getTypeUtils().erasure(typeElement.asType()).toString()); + + isModel = ProcessorUtils.implementsClass(manager.getProcessingEnvironment(), ClassNames.MODEL.toString(), element); + isModelContainer = isModelContainer || ProcessorUtils.implementsClass(manager.getProcessingEnvironment(), ClassNames.MODEL_CONTAINER.toString(), element); + nonModelColumn = !isModel && !isModelContainer; + + // we need to recheck for this instance + if (columnAccess instanceof TypeConverterAccess) { + if (typeElement.getModifiers().contains(Modifier.PRIVATE)) { + boolean useIs = elementTypeName.box().equals(TypeName.BOOLEAN.box()) + && tableDefinition.useIsForPrivateBooleans; + columnAccess = new PrivateColumnAccess(typeElement.getAnnotation(Column.class), useIs); + } else { + columnAccess = new SimpleColumnAccess(); + } + } + } + + @Override + public void addPropertyDefinition(TypeSpec.Builder typeBuilder, TypeName tableClassName) { + checkNeedsReferences(); + for (ForeignKeyReferenceDefinition reference : foreignKeyReferenceDefinitionList) { + TypeName propParam; + if (reference.columnClassName.isPrimitive() && !reference.columnClassName.equals(TypeName.BOOLEAN)) { + propParam = ClassName.get(ClassNames.PROPERTY_PACKAGE, StringUtils.capitalize(reference.columnClassName.toString()) + "Property"); + } else { + propParam = ParameterizedTypeName.get(ClassNames.PROPERTY, reference.columnClassName.box()); + } + typeBuilder.addField(FieldSpec.builder(propParam, reference.columnName, Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL) + .initializer("new $T($T.class, $S)", propParam, tableClassName, reference.columnName).build()); + } + } + + @Override + public void addPropertyCase(MethodSpec.Builder methodBuilder) { + checkNeedsReferences(); + for (ForeignKeyReferenceDefinition reference : foreignKeyReferenceDefinitionList) { + methodBuilder.beginControlFlow("case $S: ", reference.columnName); + methodBuilder.addStatement("return $L", reference.columnName); + methodBuilder.endControlFlow(); + } + } + + @Override + public CodeBlock getInsertStatementColumnName() { + checkNeedsReferences(); + CodeBlock.Builder builder = CodeBlock.builder(); + for (int i = 0; i < foreignKeyReferenceDefinitionList.size(); i++) { + if (i > 0) { + builder.add(","); + } + ForeignKeyReferenceDefinition referenceDefinition = foreignKeyReferenceDefinitionList.get(i); + builder.add("$L", QueryBuilder.quote(referenceDefinition.columnName)); + } + return builder.build(); + } + + @Override + public CodeBlock getInsertStatementValuesString() { + checkNeedsReferences(); + CodeBlock.Builder builder = CodeBlock.builder(); + for (int i = 0; i < foreignKeyReferenceDefinitionList.size(); i++) { + if (i > 0) { + builder.add(","); + } + builder.add("?"); + } + return builder.build(); + } + + @Override + public CodeBlock getCreationName() { + checkNeedsReferences(); + CodeBlock.Builder builder = CodeBlock.builder(); + for (int i = 0; i < foreignKeyReferenceDefinitionList.size(); i++) { + if (i > 0) { + builder.add(" ,"); + } + ForeignKeyReferenceDefinition referenceDefinition = foreignKeyReferenceDefinitionList.get(i); + builder.add(referenceDefinition.getCreationStatement()); + } + return builder.build(); + } + + @Override + public CodeBlock getContentValuesStatement(boolean isModelContainerAdapter) { + if (nonModelColumn) { + return super.getContentValuesStatement(isModelContainerAdapter); + } else { + checkNeedsReferences(); + CodeBlock.Builder builder = CodeBlock.builder(); + String statement = columnAccess + .getColumnAccessString(elementTypeName, elementName, elementName, + ModelUtils.getVariable(isModelContainerAdapter), isModelContainerAdapter, false); + String finalAccessStatement = getFinalAccessStatement(builder, isModelContainerAdapter, statement); + builder.beginControlFlow("if ($L != null)", finalAccessStatement); + CodeBlock.Builder elseBuilder = CodeBlock.builder(); + for (ForeignKeyReferenceDefinition referenceDefinition : foreignKeyReferenceDefinitionList) { + builder.add(referenceDefinition.getContentValuesStatement(isModelContainerAdapter)); + elseBuilder.addStatement("$L.putNull($S)", BindToContentValuesMethod.PARAM_CONTENT_VALUES, QueryBuilder.quote(referenceDefinition.columnName)); + } + + if (saveForeignKeyModel) { + builder.addStatement("$L.save()", finalAccessStatement); + } + + builder.nextControlFlow("else") + .add(elseBuilder.build()) + .endControlFlow(); + return builder.build(); + } + } + + @Override + public CodeBlock getSQLiteStatementMethod(AtomicInteger index, boolean isModelContainerAdapter) { + if (nonModelColumn) { + return super.getSQLiteStatementMethod(index, isModelContainerAdapter); + } else { + checkNeedsReferences(); + CodeBlock.Builder builder = CodeBlock.builder(); + String statement = columnAccess + .getColumnAccessString(elementTypeName, elementName, elementName, + ModelUtils.getVariable(isModelContainerAdapter), isModelContainerAdapter, true); + + String finalAccessStatement = getFinalAccessStatement(builder, isModelContainerAdapter, statement); + + builder.beginControlFlow("if ($L != null)", finalAccessStatement); + CodeBlock.Builder elseBuilder = CodeBlock.builder(); + + for (int i = 0; i < foreignKeyReferenceDefinitionList.size(); i++) { + if (i > 0) { + index.incrementAndGet(); + } + ForeignKeyReferenceDefinition referenceDefinition = foreignKeyReferenceDefinitionList.get(i); + builder.add(referenceDefinition.getSQLiteStatementMethod(index, isModelContainerAdapter)); + elseBuilder.addStatement("$L.bindNull($L)", BindToStatementMethod.PARAM_STATEMENT, index.intValue() + " + " + BindToStatementMethod.PARAM_START); + } + + if (saveForeignKeyModel) { + System.err.println ("==== Saving the foreign model!!!!"); + builder.addStatement("$L.save()", finalAccessStatement); + } + + builder.nextControlFlow("else") + .add(elseBuilder.build()) + .endControlFlow(); + return builder.build(); + } + } + + @Override + public CodeBlock getLoadFromCursorMethod(boolean isModelContainerAdapter, boolean putNullForContainerAdapter, + boolean endNonPrimitiveIf) { + if (nonModelColumn) { + return super.getLoadFromCursorMethod(isModelContainerAdapter, putNullForContainerAdapter, endNonPrimitiveIf); + } else { + checkNeedsReferences(); + + CodeBlock.Builder builder = CodeBlock.builder() + .add("//// Only load model if references match, for efficiency\n"); + CodeBlock.Builder ifNullBuilder = CodeBlock.builder() + .add("if ("); + CodeBlock.Builder selectBuilder = CodeBlock.builder(); + for (int i = 0; i < foreignKeyReferenceDefinitionList.size(); i++) { + ForeignKeyReferenceDefinition referenceDefinition = foreignKeyReferenceDefinitionList.get(i); + String indexName = "index" + referenceDefinition.columnName; + builder.addStatement("int $L = $L.getColumnIndex($S)", indexName, LoadFromCursorMethod.PARAM_CURSOR, referenceDefinition.columnName); + if (i > 0) { + ifNullBuilder.add(" && "); + } + ifNullBuilder.add("$L != -1 && !$L.isNull($L)", indexName, LoadFromCursorMethod.PARAM_CURSOR, indexName); + + // TODO: respect separator here. + selectBuilder.add("\n.and($L.$L.eq($L))", + ClassName.get(referencedTableClassName.packageName(), referencedTableClassName.simpleName() + "_" + TableDefinition.DBFLOW_TABLE_TAG), + referenceDefinition.foreignColumnName, + CodeBlock.builder().add("$L.$L($L)", LoadFromCursorMethod.PARAM_CURSOR, + DefinitionUtils.getLoadFromCursorMethodString(referenceDefinition.columnClassName, + referenceDefinition.columnAccess), indexName).build()); + } + ifNullBuilder.add(")"); + builder.beginControlFlow(ifNullBuilder.build().toString()); + + CodeBlock.Builder initializer = CodeBlock.builder(); + + initializer.add("new $T().from($T.class).where()", ClassNames.SELECT, referencedTableClassName) + .add(selectBuilder.build()); + if (!isModelContainerAdapter && !isModelContainer) { + initializer.add(".querySingle()"); + } else { + if (isModelContainerAdapter) { + initializer.add(".queryModelContainer($L.getInstance($L.newDataInstance(), $T.class)).getData()", ModelUtils.getVariable(true), + ModelUtils.getVariable(true), referencedTableClassName); + } else { + initializer.add(".queryModelContainer(new $T($T.class))", elementTypeName, referencedTableClassName); + } + } + + builder.addStatement(columnAccess.setColumnAccessString(elementTypeName, elementName, elementName, + isModelContainerAdapter, ModelUtils.getVariable(isModelContainerAdapter), initializer.build(), false)); + + boolean putDefaultValue = putNullForContainerAdapter; + if (putContainerDefaultValue != putDefaultValue && isModelContainerAdapter) { + putDefaultValue = putContainerDefaultValue; + } + if (putDefaultValue) { + builder.nextControlFlow("else"); + builder.addStatement("$L.putDefault($S)", ModelUtils.getVariable(true), columnName); + } + if (endNonPrimitiveIf) { + builder.endControlFlow(); + } + return builder.build(); + } + } + + @Override + public CodeBlock getToModelMethod() { + checkNeedsReferences(); + if (nonModelColumn) { + return super.getToModelMethod(); + } else { + CodeBlock.Builder builder = CodeBlock.builder(); + String statement = columnAccess + .getColumnAccessString(elementTypeName, elementName, elementName, + ModelUtils.getVariable(true), true, true); + String finalAccessStatement = getFinalAccessStatement(builder, true, statement); + + builder.beginControlFlow("if ($L != null)", finalAccessStatement); + if (!isModelContainer) { + CodeBlock.Builder modelContainerRetrieval = CodeBlock.builder(); + modelContainerRetrieval.add("$L.getContainerAdapter($T.class).toModel($L)", ClassNames.FLOW_MANAGER, + referencedTableClassName, finalAccessStatement); + builder.addStatement(columnAccess.setColumnAccessString(elementTypeName, elementName, elementName, + false, ModelUtils.getVariable(false), modelContainerRetrieval.build(), true)); + } else { + builder.addStatement(columnAccess.setColumnAccessString(elementTypeName, elementName, elementName, + false, ModelUtils.getVariable(false), CodeBlock.builder().add("new $T($L)", + elementTypeName, finalAccessStatement).build(), true)); + } + builder.endControlFlow(); + return builder.build(); + } + } + + String getFinalAccessStatement(CodeBlock.Builder codeBuilder, boolean isModelContainerAdapter, String statement) { + String finalAccessStatement = statement; + if (columnAccess instanceof TypeConverterAccess || + columnAccess instanceof ModelContainerAccess || + isModelContainerAdapter) { + finalAccessStatement = getRefName(); + + TypeName typeName; + if (columnAccess instanceof TypeConverterAccess) { + typeName = ((TypeConverterAccess) columnAccess).typeConverterDefinition.getDbTypeName(); + } else if (columnAccess instanceof ModelContainerAccess) { + typeName = ModelUtils.getModelContainerType(manager, referencedTableClassName); + } else { + if (isModelContainer || isModel) { + typeName = ModelUtils.getModelContainerType(manager, referencedTableClassName); + statement = ModelUtils.getVariable(isModelContainerAdapter) + ".getInstance(" + statement + ", " + referencedTableClassName + ".class)"; + } else { + typeName = referencedTableClassName; + } + } + + codeBuilder.addStatement("$T $L = $L", typeName, + finalAccessStatement, statement); + } + return finalAccessStatement; + } + + String getForeignKeyReferenceAccess(boolean isModelContainerAdapter, String statement) { + if (columnAccess instanceof TypeConverterAccess || + columnAccess instanceof ModelContainerAccess || + isModelContainerAdapter) { + return getRefName(); + } else { + return statement; + } + } + + public String getRefName() { + return "ref" + elementName; + } + + public List getForeignKeyReferenceDefinitionList() { + checkNeedsReferences(); + return foreignKeyReferenceDefinitionList; + } + + protected abstract void checkNeedsReferences (); +} diff --git a/dbflow-processor/src/main/java/com/raizlabs/android/dbflow/processor/definition/column/ExternalForeignKeyColumnDefinition.java b/dbflow-processor/src/main/java/com/raizlabs/android/dbflow/processor/definition/column/ExternalForeignKeyColumnDefinition.java new file mode 100644 index 000000000..c2271659d --- /dev/null +++ b/dbflow-processor/src/main/java/com/raizlabs/android/dbflow/processor/definition/column/ExternalForeignKeyColumnDefinition.java @@ -0,0 +1,104 @@ +package com.raizlabs.android.dbflow.processor.definition.column; + +import com.raizlabs.android.dbflow.annotation.ExternalForeignKey; +import com.raizlabs.android.dbflow.annotation.ForeignKeyReference; +import com.raizlabs.android.dbflow.annotation.Table; +import com.raizlabs.android.dbflow.processor.definition.TableDefinition; +import com.raizlabs.android.dbflow.processor.model.ProcessorManager; +import com.squareup.javapoet.ClassName; +import com.squareup.javapoet.ParameterizedTypeName; +import com.squareup.javapoet.TypeName; + +import java.util.List; + +import javax.lang.model.element.Element; +import javax.lang.model.element.TypeElement; +import javax.lang.model.type.MirroredTypeException; + +public class ExternalForeignKeyColumnDefinition extends BaseForeignKeyColumnDefinition { + public ClassName referencedDatabaseClassName; + + public ExternalForeignKeyColumnDefinition(ProcessorManager manager, TableDefinition tableDefinition, Element typeElement, boolean isPackagePrivate) { + super(manager, tableDefinition, typeElement, isPackagePrivate); + + TypeElement referencedTableElement = null; + ExternalForeignKey extForeignKey = typeElement.getAnnotation(ExternalForeignKey.class); + + try { + extForeignKey.tableClass(); + } catch (MirroredTypeException mte) { + referencedTableElement = manager.getElements().getTypeElement(mte.getTypeMirror().toString()); + referencedTableClassName = ClassName.get(referencedTableElement); + } + + // hopefully intentionally left blank + if (referencedTableClassName.equals(TypeName.OBJECT)) { + if (elementTypeName instanceof ParameterizedTypeName) { + List args = ((ParameterizedTypeName) elementTypeName).typeArguments; + if (args.size() > 0) { + referencedTableClassName = ClassName.bestGuess(args.get(0).toString()); + isModelContainer = true; + } + } else { + referencedTableClassName = ClassName.bestGuess(elementTypeName.toString()); + } + } else if (elementTypeName instanceof ParameterizedTypeName) { + isModelContainer = true; + } + + if (referencedTableElement != null) { + Table referencedTable = referencedTableElement.getAnnotation(Table.class); + + if (referencedTable != null) { + try { + referencedTable.database(); + } catch (MirroredTypeException mte) { + referencedDatabaseClassName = ClassName.get(manager.getElements().getTypeElement(mte.getTypeMirror().toString())); + } + } + } + + if (referencedDatabaseClassName == null) { + // The table is in a database module. So, we have to rely on the user + // giving us hints about the database and the foreign reference keys. + try { + extForeignKey.databaseClass(); + } catch (MirroredTypeException mte) { + referencedDatabaseClassName = ClassName.get(manager.getElements().getTypeElement(mte.getTypeMirror().toString())); + } + } + + ForeignKeyReference[] references = extForeignKey.references(); + if (references.length == 0) { + // TODO This should be an error. We need to have references! + // no references specified we will delegate references call to post-evaluation + needsReferences = true; + } else { + for (ForeignKeyReference reference : references) { + ForeignKeyReferenceDefinition referenceDefinition = + new ForeignKeyReferenceDefinition(manager, elementName, reference, columnAccess, this); + foreignKeyReferenceDefinitionList.add(referenceDefinition); + } + } + } + + @Override + protected void checkNeedsReferences() { + if (needsReferences) { + System.err.println ("==== " + referencedTableClassName); + System.err.println ("==== " + referencedDatabaseClassName); + + TableDefinition referencedTableDefinition = manager.getTableDefinition(referencedDatabaseClassName, referencedTableClassName); + List primaryColumns = referencedTableDefinition.getPrimaryColumnDefinitions(); + + for (ColumnDefinition primaryColumn : primaryColumns) { + ForeignKeyReferenceDefinition foreignKeyReferenceDefinition = + new ForeignKeyReferenceDefinition(manager, elementName, primaryColumn, columnAccess, this); + + foreignKeyReferenceDefinitionList.add(foreignKeyReferenceDefinition); + } + + needsReferences = false; + } + } +} diff --git a/dbflow-processor/src/main/java/com/raizlabs/android/dbflow/processor/definition/method/ExternalForeignKeyContainerMethod.java b/dbflow-processor/src/main/java/com/raizlabs/android/dbflow/processor/definition/method/ExternalForeignKeyContainerMethod.java new file mode 100644 index 000000000..4fa5e1982 --- /dev/null +++ b/dbflow-processor/src/main/java/com/raizlabs/android/dbflow/processor/definition/method/ExternalForeignKeyContainerMethod.java @@ -0,0 +1,45 @@ +package com.raizlabs.android.dbflow.processor.definition.method; + +import com.raizlabs.android.dbflow.processor.ClassNames; +import com.raizlabs.android.dbflow.processor.definition.TableDefinition; +import com.raizlabs.android.dbflow.processor.definition.column.ColumnDefinition; +import com.raizlabs.android.dbflow.processor.utils.ModelUtils; +import com.squareup.javapoet.CodeBlock; +import com.squareup.javapoet.MethodSpec; +import com.squareup.javapoet.ParameterizedTypeName; + +import javax.lang.model.element.Modifier; + +/** + * Description: Writes a Model into a ForeignKeyContainer for convenience. + */ +public class ExternalForeignKeyContainerMethod implements MethodDefinition { + + private final TableDefinition tableDefinition; + + public ExternalForeignKeyContainerMethod(TableDefinition tableDefinition) { + this.tableDefinition = tableDefinition; + } + + + @Override + public MethodSpec getMethodSpec() { + + CodeBlock.Builder codeBuilder = CodeBlock.builder(); + codeBuilder.addStatement("$T $L = new $T<>($T.class)", ClassNames.EXTERNAL_FOREIGN_KEY_CONTAINER, + ModelUtils.getVariable(true), ClassNames.EXTERNAL_FOREIGN_KEY_CONTAINER, tableDefinition.elementClassName); + for (ColumnDefinition columnDefinition : tableDefinition.getPrimaryColumnDefinitions()) { + codeBuilder.add(columnDefinition.getForeignKeyContainerMethod(tableDefinition.getPropertyClassName())); + } + codeBuilder.addStatement("return $L", ModelUtils.getVariable(true)); + + + return MethodSpec.methodBuilder("toExternalForeignKeyContainer") + .addAnnotation(Override.class) + .addModifiers(Modifier.PUBLIC, Modifier.FINAL) + .addParameter(tableDefinition.elementClassName, ModelUtils.getVariable(false)) + .addCode(codeBuilder.build()) + .returns(ParameterizedTypeName.get(ClassNames.EXTERNAL_FOREIGN_KEY_CONTAINER, tableDefinition.elementClassName)) + .build(); + } +} diff --git a/dbflow/src/androidTest/java/com/raizlabs/android/dbflow/test/structure/externalforeignkey/ExternalForeignKeyTest.java b/dbflow/src/androidTest/java/com/raizlabs/android/dbflow/test/structure/externalforeignkey/ExternalForeignKeyTest.java new file mode 100644 index 000000000..7bb931bf5 --- /dev/null +++ b/dbflow/src/androidTest/java/com/raizlabs/android/dbflow/test/structure/externalforeignkey/ExternalForeignKeyTest.java @@ -0,0 +1,33 @@ +package com.raizlabs.android.dbflow.test.structure.externalforeignkey; + +import com.raizlabs.android.dbflow.sql.language.Delete; +import com.raizlabs.android.dbflow.sql.language.Select; +import com.raizlabs.android.dbflow.test.FlowTestCase; + +import static com.raizlabs.android.dbflow.test.structure.foreignkey.ForeignModel_Table.name; + +public class ExternalForeignKeyTest extends FlowTestCase { + public void testExternalForeignKey () { + Delete.tables(ForeignParentModel.class, ForeignModel.class); + + ForeignParentModel parentModel = new ForeignParentModel(); + parentModel.setName("Test"); + parentModel.save(); + + ForeignModel foreignModel = new ForeignModel(); + foreignModel.setForeignParentModel(parentModel); + foreignModel.setName("Test"); + foreignModel.save(); + + ForeignModel retrieved = + new Select() + .from(ForeignModel.class) + .where (name.is("Test")) + .querySingle(); + + assertNotNull(retrieved); + assertNotNull(retrieved.foreignParentModel); + assertNotNull(retrieved.foreignParentModel.toModel()); + assertEquals(retrieved.foreignParentModel.toModel(), foreignModel.foreignParentModel.toModel()); + } +} diff --git a/dbflow/src/androidTest/java/com/raizlabs/android/dbflow/test/structure/externalforeignkey/ForeignModel.java b/dbflow/src/androidTest/java/com/raizlabs/android/dbflow/test/structure/externalforeignkey/ForeignModel.java new file mode 100644 index 000000000..90ddc1beb --- /dev/null +++ b/dbflow/src/androidTest/java/com/raizlabs/android/dbflow/test/structure/externalforeignkey/ForeignModel.java @@ -0,0 +1,17 @@ +package com.raizlabs.android.dbflow.test.structure.externalforeignkey; + +import com.raizlabs.android.dbflow.annotation.ExternalForeignKey; +import com.raizlabs.android.dbflow.annotation.Table; +import com.raizlabs.android.dbflow.config.FlowManager; +import com.raizlabs.android.dbflow.structure.container.ExternalForeignKeyContainer; +import com.raizlabs.android.dbflow.test.structure.TestModel1; + +@Table(database=TestDatabase1.class) +public class ForeignModel extends TestModel1 { + @ExternalForeignKey + ExternalForeignKeyContainer foreignParentModel; + + public void setForeignParentModel(ForeignParentModel foreignParentModel) { + this.foreignParentModel = FlowManager.getContainerAdapter(ForeignParentModel.class).toExternalForeignKeyContainer(foreignParentModel); + } +} diff --git a/dbflow/src/androidTest/java/com/raizlabs/android/dbflow/test/structure/externalforeignkey/ForeignParentModel.java b/dbflow/src/androidTest/java/com/raizlabs/android/dbflow/test/structure/externalforeignkey/ForeignParentModel.java new file mode 100644 index 000000000..567b636a2 --- /dev/null +++ b/dbflow/src/androidTest/java/com/raizlabs/android/dbflow/test/structure/externalforeignkey/ForeignParentModel.java @@ -0,0 +1,13 @@ +package com.raizlabs.android.dbflow.test.structure.externalforeignkey; + +import com.raizlabs.android.dbflow.annotation.ModelContainer; +import com.raizlabs.android.dbflow.annotation.Table; +import com.raizlabs.android.dbflow.test.structure.TestModel1; + +/** + * Description: + */ +@ModelContainer +@Table(database=TestDatabase2.class) +public class ForeignParentModel extends TestModel1 { +} diff --git a/dbflow/src/androidTest/java/com/raizlabs/android/dbflow/test/structure/externalforeignkey/TestDatabase1.java b/dbflow/src/androidTest/java/com/raizlabs/android/dbflow/test/structure/externalforeignkey/TestDatabase1.java new file mode 100644 index 000000000..66b1a89b7 --- /dev/null +++ b/dbflow/src/androidTest/java/com/raizlabs/android/dbflow/test/structure/externalforeignkey/TestDatabase1.java @@ -0,0 +1,7 @@ +package com.raizlabs.android.dbflow.test.structure.externalforeignkey; + +import com.raizlabs.android.dbflow.annotation.Database; + +@Database(name="externalforeignkey_database1", version=1) +public class TestDatabase1 { +} diff --git a/dbflow/src/androidTest/java/com/raizlabs/android/dbflow/test/structure/externalforeignkey/TestDatabase2.java b/dbflow/src/androidTest/java/com/raizlabs/android/dbflow/test/structure/externalforeignkey/TestDatabase2.java new file mode 100644 index 000000000..be43059ce --- /dev/null +++ b/dbflow/src/androidTest/java/com/raizlabs/android/dbflow/test/structure/externalforeignkey/TestDatabase2.java @@ -0,0 +1,7 @@ +package com.raizlabs.android.dbflow.test.structure.externalforeignkey; + +import com.raizlabs.android.dbflow.annotation.Database; + +@Database(name="externalforeignkey_database2", version=1) +public class TestDatabase2 { +} diff --git a/dbflow/src/main/java/com/raizlabs/android/dbflow/structure/container/ExternalForeignKeyContainer.java b/dbflow/src/main/java/com/raizlabs/android/dbflow/structure/container/ExternalForeignKeyContainer.java new file mode 100644 index 000000000..51b816504 --- /dev/null +++ b/dbflow/src/main/java/com/raizlabs/android/dbflow/structure/container/ExternalForeignKeyContainer.java @@ -0,0 +1,44 @@ +package com.raizlabs.android.dbflow.structure.container; + +import com.raizlabs.android.dbflow.config.FlowManager; +import com.raizlabs.android.dbflow.runtime.FlowContentObserver; +import com.raizlabs.android.dbflow.sql.language.SQLCondition; +import com.raizlabs.android.dbflow.structure.BaseModel; +import com.raizlabs.android.dbflow.structure.Model; + +import java.util.Map; + +public class ExternalForeignKeyContainer extends ForeignKeyContainer { + private final FlowContentObserver observer = new FlowContentObserver(); + + private final FlowContentObserver.OnModelStateChangedListener onModelStateChangedListener = new FlowContentObserver.OnModelStateChangedListener () { + @Override + public void onModelStateChanged(Class table, BaseModel.Action action, SQLCondition[] primaryKeyValues) { + // TODO Delete rows from the table referencing this table. + } + }; + + public ExternalForeignKeyContainer(ModelContainer existingContainer) { + super(existingContainer); + initializeObserver(); + } + + public ExternalForeignKeyContainer(Class table) { + super(table); + initializeObserver(); + } + + public ExternalForeignKeyContainer(Class table, Map data) { + super(table, data); + initializeObserver(); + } + + private void initializeObserver() { + observer.registerForContentChanges(FlowManager.getContext(), getTable()); + observer.addModelChangeListener(onModelStateChangedListener); + } + + public void close() { + observer.unregisterForContentChanges(FlowManager.getContext()); + } +} From 35567d334edf1c40bf173db210c6b054e3ba6c1a Mon Sep 17 00:00:00 2001 From: "James H. Hill" Date: Tue, 2 Feb 2016 21:44:12 -0500 Subject: [PATCH 03/47] Foreign key on primary key failed if column was a model and not a model container --- .../BaseForeignKeyColumnDefinition.java | 1 - .../definition/column/ColumnDefinition.java | 31 ++++-------------- .../column/ForeignKeyColumnDefinition.java | 32 +++++++++++++++++++ 3 files changed, 39 insertions(+), 25 deletions(-) diff --git a/dbflow-processor/src/main/java/com/raizlabs/android/dbflow/processor/definition/column/BaseForeignKeyColumnDefinition.java b/dbflow-processor/src/main/java/com/raizlabs/android/dbflow/processor/definition/column/BaseForeignKeyColumnDefinition.java index 502094c57..a9fa79d48 100644 --- a/dbflow-processor/src/main/java/com/raizlabs/android/dbflow/processor/definition/column/BaseForeignKeyColumnDefinition.java +++ b/dbflow-processor/src/main/java/com/raizlabs/android/dbflow/processor/definition/column/BaseForeignKeyColumnDefinition.java @@ -192,7 +192,6 @@ public CodeBlock getSQLiteStatementMethod(AtomicInteger index, boolean isModelCo } if (saveForeignKeyModel) { - System.err.println ("==== Saving the foreign model!!!!"); builder.addStatement("$L.save()", finalAccessStatement); } diff --git a/dbflow-processor/src/main/java/com/raizlabs/android/dbflow/processor/definition/column/ColumnDefinition.java b/dbflow-processor/src/main/java/com/raizlabs/android/dbflow/processor/definition/column/ColumnDefinition.java index 8f59c7ce0..f73477d09 100644 --- a/dbflow-processor/src/main/java/com/raizlabs/android/dbflow/processor/definition/column/ColumnDefinition.java +++ b/dbflow-processor/src/main/java/com/raizlabs/android/dbflow/processor/definition/column/ColumnDefinition.java @@ -248,8 +248,8 @@ public void addPropertyDefinition(TypeSpec.Builder typeBuilder, TypeName tableCl propParam = ParameterizedTypeName.get(ClassNames.PROPERTY, elementTypeName.box()); } typeBuilder.addField(FieldSpec.builder(propParam, - columnName, Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL) - .initializer("new $T($T.class, $S)", propParam, tableClass, columnName).build()); + columnName, Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL) + .initializer("new $T($T.class, $S)", propParam, tableClass, columnName).build()); } public void addPropertyCase(MethodSpec.Builder methodBuilder) { @@ -272,12 +272,12 @@ public CodeBlock getInsertStatementValuesString() { public CodeBlock getContentValuesStatement(boolean isModelContainerAdapter) { return DefinitionUtils.getContentValuesStatement(containerKeyName, elementName, - columnName, elementTypeName, isModelContainerAdapter, columnAccess, ModelUtils.getVariable(isModelContainerAdapter)).build(); + columnName, elementTypeName, isModelContainerAdapter, columnAccess, ModelUtils.getVariable(isModelContainerAdapter)).build(); } public CodeBlock getSQLiteStatementMethod(AtomicInteger index, boolean isModelContainerAdapter) { return DefinitionUtils.getSQLiteStatementMethod(index, containerKeyName, elementName, - elementTypeName, isModelContainerAdapter, columnAccess, ModelUtils.getVariable(isModelContainerAdapter), isPrimaryKeyAutoIncrement).build(); + elementTypeName, isModelContainerAdapter, columnAccess, ModelUtils.getVariable(isModelContainerAdapter), isPrimaryKeyAutoIncrement).build(); } public CodeBlock getLoadFromCursorMethod(boolean isModelContainerAdapter, boolean putNullForContainerAdapter, @@ -289,7 +289,7 @@ public CodeBlock getLoadFromCursorMethod(boolean isModelContainerAdapter, boolea putDefaultValue = true; } return DefinitionUtils.getLoadFromCursorMethod(containerKeyName, elementName, - elementTypeName, columnName, isModelContainerAdapter, putDefaultValue, columnAccess).build(); + elementTypeName, columnName, isModelContainerAdapter, putDefaultValue, columnAccess).build(); } /** @@ -304,7 +304,7 @@ public CodeBlock getUpdateAutoIncrementMethod(boolean isModelContainerAdapter) { public String setColumnAccessString(CodeBlock formattedAccess, boolean toModelMethod) { return columnAccess.setColumnAccessString(elementTypeName, containerKeyName, elementName, - false, ModelUtils.getVariable(false), formattedAccess, toModelMethod); + false, ModelUtils.getVariable(false), formattedAccess, toModelMethod); } public CodeBlock getToModelMethod() { @@ -361,25 +361,8 @@ public String getPropertyComparisonAccessStatement(boolean isModelContainerAdapt .build().toString(); } } else { - String statement = columnAccess.getColumnAccessString(elementTypeName, containerKeyName, elementName, + return columnAccess.getColumnAccessString(elementTypeName, containerKeyName, elementName, ModelUtils.getVariable(isModelContainerAdapter), isModelContainerAdapter, false); - - if (this instanceof ForeignKeyColumnDefinition && isPrimaryKey - && ((ForeignKeyColumnDefinition) this).isModelContainer) { - ForeignKeyColumnDefinition foreignKeyColumnDefinition = (ForeignKeyColumnDefinition) this; - TableDefinition referenced = manager.getTableDefinition(tableDefinition.databaseDefinition.elementTypeName, - foreignKeyColumnDefinition.referencedTableClassName); - ForeignKeyReferenceDefinition referenceDefinition = foreignKeyColumnDefinition.getForeignKeyReferenceDefinitionList().get(0); - // check for null and retrieve proper value - String method = SQLiteHelper.getModelContainerMethod(referenceDefinition.columnClassName); - if (method == null) { - method = "get"; - } - statement = String - .format("%1s != null ? %1s.%1sValue(%1s.%1s.getContainerKey()) : null", - statement, statement, method, referenced.outputClassName, referenceDefinition.foreignColumnName); - } - return statement; } } diff --git a/dbflow-processor/src/main/java/com/raizlabs/android/dbflow/processor/definition/column/ForeignKeyColumnDefinition.java b/dbflow-processor/src/main/java/com/raizlabs/android/dbflow/processor/definition/column/ForeignKeyColumnDefinition.java index b7f90dde5..2ff8bf362 100644 --- a/dbflow-processor/src/main/java/com/raizlabs/android/dbflow/processor/definition/column/ForeignKeyColumnDefinition.java +++ b/dbflow-processor/src/main/java/com/raizlabs/android/dbflow/processor/definition/column/ForeignKeyColumnDefinition.java @@ -3,6 +3,7 @@ import com.raizlabs.android.dbflow.annotation.ForeignKey; import com.raizlabs.android.dbflow.annotation.ForeignKeyAction; import com.raizlabs.android.dbflow.annotation.ForeignKeyReference; +import com.raizlabs.android.dbflow.processor.SQLiteHelper; import com.raizlabs.android.dbflow.processor.definition.TableDefinition; import com.raizlabs.android.dbflow.processor.model.ProcessorManager; import com.squareup.javapoet.ClassName; @@ -88,4 +89,35 @@ protected void checkNeedsReferences() { } } } + + @Override + public String getPropertyComparisonAccessStatement(boolean isModelContainerAdapter) { + String statement = super.getPropertyComparisonAccessStatement(isModelContainerAdapter); + + if (isPrimaryKey) { + if (isModelContainer) { + TableDefinition referenced = + manager.getTableDefinition ( + tableDefinition.databaseDefinition.elementTypeName, + referencedTableClassName); + + ForeignKeyReferenceDefinition referenceDefinition = getForeignKeyReferenceDefinitionList().get(0); + // check for null and retrieve proper value + String method = SQLiteHelper.getModelContainerMethod(referenceDefinition.columnClassName); + + if (method == null) { + method = "get"; + } + + statement = String + .format("%1s != null ? %1s.%1sValue(%1s.%1s.getContainerKey()) : null", + statement, statement, method, referenced.outputClassName, referenceDefinition.foreignColumnName); + } + else { + statement = String.format ("%s.%s", statement, foreignKeyReferenceDefinitionList.get(0).foreignColumnName); + } + } + + return statement; + } } From a92a9d1644a26a012a66f63e7300f9845ba7025d Mon Sep 17 00:00:00 2001 From: "James H. Hill" Date: Tue, 2 Feb 2016 21:49:19 -0500 Subject: [PATCH 04/47] Removed debug code --- .../definition/column/ExternalForeignKeyColumnDefinition.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/dbflow-processor/src/main/java/com/raizlabs/android/dbflow/processor/definition/column/ExternalForeignKeyColumnDefinition.java b/dbflow-processor/src/main/java/com/raizlabs/android/dbflow/processor/definition/column/ExternalForeignKeyColumnDefinition.java index c2271659d..c3f646cf1 100644 --- a/dbflow-processor/src/main/java/com/raizlabs/android/dbflow/processor/definition/column/ExternalForeignKeyColumnDefinition.java +++ b/dbflow-processor/src/main/java/com/raizlabs/android/dbflow/processor/definition/column/ExternalForeignKeyColumnDefinition.java @@ -85,9 +85,6 @@ public ExternalForeignKeyColumnDefinition(ProcessorManager manager, TableDefinit @Override protected void checkNeedsReferences() { if (needsReferences) { - System.err.println ("==== " + referencedTableClassName); - System.err.println ("==== " + referencedDatabaseClassName); - TableDefinition referencedTableDefinition = manager.getTableDefinition(referencedDatabaseClassName, referencedTableClassName); List primaryColumns = referencedTableDefinition.getPrimaryColumnDefinitions(); From de303756389e432276b1e5001f292f047ddd1bc4 Mon Sep 17 00:00:00 2001 From: "James H. Hill" Date: Tue, 2 Feb 2016 21:55:06 -0500 Subject: [PATCH 05/47] Overrided getSupportedOptions() to handle processor warnings --- .../android/dbflow/processor/DBFlowProcessor.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/dbflow-processor/src/main/java/com/raizlabs/android/dbflow/processor/DBFlowProcessor.java b/dbflow-processor/src/main/java/com/raizlabs/android/dbflow/processor/DBFlowProcessor.java index 3a96c651e..6cb5fdf4c 100644 --- a/dbflow-processor/src/main/java/com/raizlabs/android/dbflow/processor/DBFlowProcessor.java +++ b/dbflow-processor/src/main/java/com/raizlabs/android/dbflow/processor/DBFlowProcessor.java @@ -39,6 +39,14 @@ public class DBFlowProcessor extends AbstractProcessor { private ProcessorManager manager; + @Override + public Set getSupportedOptions() { + Set supportedOptions = new LinkedHashSet<>(); + supportedOptions.add("targetModuleName"); + + return supportedOptions; + } + /** * If the processor class is annotated with {@link * javax.annotation.processing.SupportedAnnotationTypes}, return an unmodifiable set with the From bf4b41583c0c0d9742f63a0d8010f4197f1dce04 Mon Sep 17 00:00:00 2001 From: "James H. Hill" Date: Tue, 2 Feb 2016 22:17:03 -0500 Subject: [PATCH 06/47] Foreign key definition failed with model container --- .../definition/column/ForeignKeyColumnDefinition.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dbflow-processor/src/main/java/com/raizlabs/android/dbflow/processor/definition/column/ForeignKeyColumnDefinition.java b/dbflow-processor/src/main/java/com/raizlabs/android/dbflow/processor/definition/column/ForeignKeyColumnDefinition.java index 2ff8bf362..7dd1365b9 100644 --- a/dbflow-processor/src/main/java/com/raizlabs/android/dbflow/processor/definition/column/ForeignKeyColumnDefinition.java +++ b/dbflow-processor/src/main/java/com/raizlabs/android/dbflow/processor/definition/column/ForeignKeyColumnDefinition.java @@ -110,8 +110,8 @@ public String getPropertyComparisonAccessStatement(boolean isModelContainerAdapt } statement = String - .format("%1s != null ? %1s.%1sValue(%1s.%1s.getContainerKey()) : null", - statement, statement, method, referenced.outputClassName, referenceDefinition.foreignColumnName); + .format("%1s != null ? %1sValue(%1s.%1s.getContainerKey()) : null", + statement, method, referenced.outputClassName, referenceDefinition.foreignColumnName); } else { statement = String.format ("%s.%s", statement, foreignKeyReferenceDefinitionList.get(0).foreignColumnName); From 50e409b1fe8dd0893fa505e5544d82f9469674e8 Mon Sep 17 00:00:00 2001 From: "James H. Hill" Date: Tue, 2 Feb 2016 22:29:48 -0500 Subject: [PATCH 07/47] Reverted change --- .../definition/column/ForeignKeyColumnDefinition.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dbflow-processor/src/main/java/com/raizlabs/android/dbflow/processor/definition/column/ForeignKeyColumnDefinition.java b/dbflow-processor/src/main/java/com/raizlabs/android/dbflow/processor/definition/column/ForeignKeyColumnDefinition.java index 7dd1365b9..2ff8bf362 100644 --- a/dbflow-processor/src/main/java/com/raizlabs/android/dbflow/processor/definition/column/ForeignKeyColumnDefinition.java +++ b/dbflow-processor/src/main/java/com/raizlabs/android/dbflow/processor/definition/column/ForeignKeyColumnDefinition.java @@ -110,8 +110,8 @@ public String getPropertyComparisonAccessStatement(boolean isModelContainerAdapt } statement = String - .format("%1s != null ? %1sValue(%1s.%1s.getContainerKey()) : null", - statement, method, referenced.outputClassName, referenceDefinition.foreignColumnName); + .format("%1s != null ? %1s.%1sValue(%1s.%1s.getContainerKey()) : null", + statement, statement, method, referenced.outputClassName, referenceDefinition.foreignColumnName); } else { statement = String.format ("%s.%s", statement, foreignKeyReferenceDefinitionList.get(0).foreignColumnName); From 6dfd5d6d61dbdc428954dcb8076e4d7a5b762f7c Mon Sep 17 00:00:00 2001 From: "James H. Hill" Date: Tue, 23 Feb 2016 11:25:40 -0500 Subject: [PATCH 08/47] Removed test files --- .../ExternalForeignKeyTest.java | 33 ------------------- .../externalforeignkey/ForeignModel.java | 17 ---------- .../ForeignParentModel.java | 13 -------- .../externalforeignkey/TestDatabase1.java | 7 ---- .../externalforeignkey/TestDatabase2.java | 7 ---- 5 files changed, 77 deletions(-) delete mode 100644 dbflow/src/androidTest/java/com/raizlabs/android/dbflow/test/structure/externalforeignkey/ExternalForeignKeyTest.java delete mode 100644 dbflow/src/androidTest/java/com/raizlabs/android/dbflow/test/structure/externalforeignkey/ForeignModel.java delete mode 100644 dbflow/src/androidTest/java/com/raizlabs/android/dbflow/test/structure/externalforeignkey/ForeignParentModel.java delete mode 100644 dbflow/src/androidTest/java/com/raizlabs/android/dbflow/test/structure/externalforeignkey/TestDatabase1.java delete mode 100644 dbflow/src/androidTest/java/com/raizlabs/android/dbflow/test/structure/externalforeignkey/TestDatabase2.java diff --git a/dbflow/src/androidTest/java/com/raizlabs/android/dbflow/test/structure/externalforeignkey/ExternalForeignKeyTest.java b/dbflow/src/androidTest/java/com/raizlabs/android/dbflow/test/structure/externalforeignkey/ExternalForeignKeyTest.java deleted file mode 100644 index 7bb931bf5..000000000 --- a/dbflow/src/androidTest/java/com/raizlabs/android/dbflow/test/structure/externalforeignkey/ExternalForeignKeyTest.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.raizlabs.android.dbflow.test.structure.externalforeignkey; - -import com.raizlabs.android.dbflow.sql.language.Delete; -import com.raizlabs.android.dbflow.sql.language.Select; -import com.raizlabs.android.dbflow.test.FlowTestCase; - -import static com.raizlabs.android.dbflow.test.structure.foreignkey.ForeignModel_Table.name; - -public class ExternalForeignKeyTest extends FlowTestCase { - public void testExternalForeignKey () { - Delete.tables(ForeignParentModel.class, ForeignModel.class); - - ForeignParentModel parentModel = new ForeignParentModel(); - parentModel.setName("Test"); - parentModel.save(); - - ForeignModel foreignModel = new ForeignModel(); - foreignModel.setForeignParentModel(parentModel); - foreignModel.setName("Test"); - foreignModel.save(); - - ForeignModel retrieved = - new Select() - .from(ForeignModel.class) - .where (name.is("Test")) - .querySingle(); - - assertNotNull(retrieved); - assertNotNull(retrieved.foreignParentModel); - assertNotNull(retrieved.foreignParentModel.toModel()); - assertEquals(retrieved.foreignParentModel.toModel(), foreignModel.foreignParentModel.toModel()); - } -} diff --git a/dbflow/src/androidTest/java/com/raizlabs/android/dbflow/test/structure/externalforeignkey/ForeignModel.java b/dbflow/src/androidTest/java/com/raizlabs/android/dbflow/test/structure/externalforeignkey/ForeignModel.java deleted file mode 100644 index 90ddc1beb..000000000 --- a/dbflow/src/androidTest/java/com/raizlabs/android/dbflow/test/structure/externalforeignkey/ForeignModel.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.raizlabs.android.dbflow.test.structure.externalforeignkey; - -import com.raizlabs.android.dbflow.annotation.ExternalForeignKey; -import com.raizlabs.android.dbflow.annotation.Table; -import com.raizlabs.android.dbflow.config.FlowManager; -import com.raizlabs.android.dbflow.structure.container.ExternalForeignKeyContainer; -import com.raizlabs.android.dbflow.test.structure.TestModel1; - -@Table(database=TestDatabase1.class) -public class ForeignModel extends TestModel1 { - @ExternalForeignKey - ExternalForeignKeyContainer foreignParentModel; - - public void setForeignParentModel(ForeignParentModel foreignParentModel) { - this.foreignParentModel = FlowManager.getContainerAdapter(ForeignParentModel.class).toExternalForeignKeyContainer(foreignParentModel); - } -} diff --git a/dbflow/src/androidTest/java/com/raizlabs/android/dbflow/test/structure/externalforeignkey/ForeignParentModel.java b/dbflow/src/androidTest/java/com/raizlabs/android/dbflow/test/structure/externalforeignkey/ForeignParentModel.java deleted file mode 100644 index 567b636a2..000000000 --- a/dbflow/src/androidTest/java/com/raizlabs/android/dbflow/test/structure/externalforeignkey/ForeignParentModel.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.raizlabs.android.dbflow.test.structure.externalforeignkey; - -import com.raizlabs.android.dbflow.annotation.ModelContainer; -import com.raizlabs.android.dbflow.annotation.Table; -import com.raizlabs.android.dbflow.test.structure.TestModel1; - -/** - * Description: - */ -@ModelContainer -@Table(database=TestDatabase2.class) -public class ForeignParentModel extends TestModel1 { -} diff --git a/dbflow/src/androidTest/java/com/raizlabs/android/dbflow/test/structure/externalforeignkey/TestDatabase1.java b/dbflow/src/androidTest/java/com/raizlabs/android/dbflow/test/structure/externalforeignkey/TestDatabase1.java deleted file mode 100644 index 66b1a89b7..000000000 --- a/dbflow/src/androidTest/java/com/raizlabs/android/dbflow/test/structure/externalforeignkey/TestDatabase1.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.raizlabs.android.dbflow.test.structure.externalforeignkey; - -import com.raizlabs.android.dbflow.annotation.Database; - -@Database(name="externalforeignkey_database1", version=1) -public class TestDatabase1 { -} diff --git a/dbflow/src/androidTest/java/com/raizlabs/android/dbflow/test/structure/externalforeignkey/TestDatabase2.java b/dbflow/src/androidTest/java/com/raizlabs/android/dbflow/test/structure/externalforeignkey/TestDatabase2.java deleted file mode 100644 index be43059ce..000000000 --- a/dbflow/src/androidTest/java/com/raizlabs/android/dbflow/test/structure/externalforeignkey/TestDatabase2.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.raizlabs.android.dbflow.test.structure.externalforeignkey; - -import com.raizlabs.android.dbflow.annotation.Database; - -@Database(name="externalforeignkey_database2", version=1) -public class TestDatabase2 { -} From 0947f8ccfa588c6e68e2992ed45276db30ad92f6 Mon Sep 17 00:00:00 2001 From: "James H. Hill" Date: Wed, 9 Mar 2016 22:41:48 -0500 Subject: [PATCH 09/47] Added missing code for checkNeedsReferences() --- .../column/ExternalForeignKeyColumnDefinition.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/dbflow-processor/src/main/java/com/raizlabs/android/dbflow/processor/definition/column/ExternalForeignKeyColumnDefinition.java b/dbflow-processor/src/main/java/com/raizlabs/android/dbflow/processor/definition/column/ExternalForeignKeyColumnDefinition.java index 29bae1380..08e5d5b28 100644 --- a/dbflow-processor/src/main/java/com/raizlabs/android/dbflow/processor/definition/column/ExternalForeignKeyColumnDefinition.java +++ b/dbflow-processor/src/main/java/com/raizlabs/android/dbflow/processor/definition/column/ExternalForeignKeyColumnDefinition.java @@ -106,5 +106,10 @@ protected void checkNeedsReferences() { needsReferences = false; } + + if (nonModelColumn && foreignKeyReferenceDefinitionList.size() == 1) { + ForeignKeyReferenceDefinition foreignKeyReferenceDefinition = foreignKeyReferenceDefinitionList.get(0); + columnName = foreignKeyReferenceDefinition.columnName; + } } } From 118204abf3b633957178a0e617784b086949b4a3 Mon Sep 17 00:00:00 2001 From: "James H. Hill" Date: Wed, 9 Mar 2016 22:52:00 -0500 Subject: [PATCH 10/47] Removed faulty line of code --- .../definition/column/ExternalForeignKeyColumnDefinition.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/dbflow-processor/src/main/java/com/raizlabs/android/dbflow/processor/definition/column/ExternalForeignKeyColumnDefinition.java b/dbflow-processor/src/main/java/com/raizlabs/android/dbflow/processor/definition/column/ExternalForeignKeyColumnDefinition.java index 08e5d5b28..98418250e 100644 --- a/dbflow-processor/src/main/java/com/raizlabs/android/dbflow/processor/definition/column/ExternalForeignKeyColumnDefinition.java +++ b/dbflow-processor/src/main/java/com/raizlabs/android/dbflow/processor/definition/column/ExternalForeignKeyColumnDefinition.java @@ -107,9 +107,10 @@ protected void checkNeedsReferences() { needsReferences = false; } + /* if (nonModelColumn && foreignKeyReferenceDefinitionList.size() == 1) { ForeignKeyReferenceDefinition foreignKeyReferenceDefinition = foreignKeyReferenceDefinitionList.get(0); columnName = foreignKeyReferenceDefinition.columnName; - } + }*/ } } From 2a450a2f26938affd8b681431bdd31ad7f70f04b Mon Sep 17 00:00:00 2001 From: "James H. Hill" Date: Wed, 9 Mar 2016 23:03:15 -0500 Subject: [PATCH 11/47] Added missing check for external foreign key --- .../android/dbflow/processor/definition/TableDefinition.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dbflow-processor/src/main/java/com/raizlabs/android/dbflow/processor/definition/TableDefinition.java b/dbflow-processor/src/main/java/com/raizlabs/android/dbflow/processor/definition/TableDefinition.java index 58f4f1446..fab3d5198 100644 --- a/dbflow-processor/src/main/java/com/raizlabs/android/dbflow/processor/definition/TableDefinition.java +++ b/dbflow-processor/src/main/java/com/raizlabs/android/dbflow/processor/definition/TableDefinition.java @@ -300,7 +300,7 @@ protected void createColumnDefinitions(TypeElement typeElement) { boolean isInherited = inheritedColumnMap.containsKey(element.getSimpleName().toString()); boolean isInheritedPrimaryKey = inheritedPrimaryKeyMap.containsKey(element.getSimpleName().toString()); - if (element.getAnnotation(Column.class) != null || isForeign || isPrimary + if (element.getAnnotation(Column.class) != null || isForeign || isExternalForeign || isPrimary || isAllFields || isInherited || isInheritedPrimaryKey) { ColumnDefinition columnDefinition; From 36b7fa7a0ce4d485f0727c6971c96e05b1064634 Mon Sep 17 00:00:00 2001 From: "James H. Hill" Date: Mon, 14 Mar 2016 12:23:15 -0400 Subject: [PATCH 12/47] Overrided the newInstance() method --- .../container/ExternalForeignKeyContainer.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/dbflow/src/main/java/com/raizlabs/android/dbflow/structure/container/ExternalForeignKeyContainer.java b/dbflow/src/main/java/com/raizlabs/android/dbflow/structure/container/ExternalForeignKeyContainer.java index 51b816504..333afe301 100644 --- a/dbflow/src/main/java/com/raizlabs/android/dbflow/structure/container/ExternalForeignKeyContainer.java +++ b/dbflow/src/main/java/com/raizlabs/android/dbflow/structure/container/ExternalForeignKeyContainer.java @@ -23,6 +23,16 @@ public ExternalForeignKeyContainer(ModelContainer existingContain initializeObserver(); } + @Override + public BaseModelContainer getInstance(Object inValue, Class columnClass) { + if (inValue instanceof ModelContainer) { + return new ExternalForeignKeyContainer((ModelContainer) inValue); + } else { + return new ExternalForeignKeyContainer(columnClass, (Map) inValue); + } + + } + public ExternalForeignKeyContainer(Class table) { super(table); initializeObserver(); From 9431b138a4ec2cf9a3cc4b144718cbae0e2dafb6 Mon Sep 17 00:00:00 2001 From: "James H. Hill" Date: Sun, 3 Jul 2016 08:13:36 -0400 Subject: [PATCH 13/47] Fixed error preventing Jitpack from working --- .../raizlabs/android/dbflow/annotation/ForeignKeyReference.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dbflow-core/src/main/java/com/raizlabs/android/dbflow/annotation/ForeignKeyReference.java b/dbflow-core/src/main/java/com/raizlabs/android/dbflow/annotation/ForeignKeyReference.java index 5fb380e67..a19400a25 100644 --- a/dbflow-core/src/main/java/com/raizlabs/android/dbflow/annotation/ForeignKeyReference.java +++ b/dbflow-core/src/main/java/com/raizlabs/android/dbflow/annotation/ForeignKeyReference.java @@ -6,7 +6,7 @@ /** * Description: Used inside of {@link ForeignKey#references()}, describes the * local column name, type, and referencing table column name. - *

+ * * Note: the type of the local column must match the * column type of the referenced column. By using a field as a Model object, * you will need to ensure the same types are used. From e483520c28ea1734a829cfce4210ea991b5458ac Mon Sep 17 00:00:00 2001 From: "James H. Hill" Date: Sun, 3 Jul 2016 08:13:58 -0400 Subject: [PATCH 14/47] Merge from master --- .../kotlinextensions/PropertyExtensions.kt | 8 +- .../PropertyMethodExtensions.kt | 32 +-- .../kotlinextensions/QueryExtensions.kt | 88 ++++---- .../dbflow/list/FlowCursorAdapter.java | 45 ++++ .../android/dbflow/list/FlowCursorLoader.java | 212 ++++++++++++++++++ .../android/dbflow/list/FlowModelLoader.java | 138 ++++++++++++ .../dbflow/list/FlowSimpleCursorAdapter.java | 38 ++++ usage2/KotlinSupport.md | 2 +- usage2/Migration3Guide.md | 2 +- usage2/Models.md | 2 +- usage2/SQLiteWrapperLanguage.md | 2 +- usage2/TypeConverters.md | 2 +- 12 files changed, 502 insertions(+), 69 deletions(-) create mode 100644 dbflow/src/main/java/com/raizlabs/android/dbflow/list/FlowCursorAdapter.java create mode 100644 dbflow/src/main/java/com/raizlabs/android/dbflow/list/FlowCursorLoader.java create mode 100644 dbflow/src/main/java/com/raizlabs/android/dbflow/list/FlowModelLoader.java create mode 100644 dbflow/src/main/java/com/raizlabs/android/dbflow/list/FlowSimpleCursorAdapter.java diff --git a/dbflow-kotlinextensions/src/main/java/com/raizlabs/android/dbflow/kotlinextensions/PropertyExtensions.kt b/dbflow-kotlinextensions/src/main/java/com/raizlabs/android/dbflow/kotlinextensions/PropertyExtensions.kt index 6eb421f1f..c90f568a8 100644 --- a/dbflow-kotlinextensions/src/main/java/com/raizlabs/android/dbflow/kotlinextensions/PropertyExtensions.kt +++ b/dbflow-kotlinextensions/src/main/java/com/raizlabs/android/dbflow/kotlinextensions/PropertyExtensions.kt @@ -29,12 +29,12 @@ val Short.property: ShortProperty val Byte.property: ByteProperty get() = PropertyFactory.from(this) -val T.property: Property +val TModel.property: Property get() = PropertyFactory.from(this) -val ModelQueriable.property: Property +val ModelQueriable.property: Property get() = PropertyFactory.from(this) -inline fun T.propertyString(stringRepresentation: String?): Property { - return PropertyFactory.from(T::class.java, stringRepresentation) +inline fun TModel.propertyString(stringRepresentation: String?): Property { + return PropertyFactory.from(TModel::class.java, stringRepresentation) } \ No newline at end of file diff --git a/dbflow-kotlinextensions/src/main/java/com/raizlabs/android/dbflow/kotlinextensions/PropertyMethodExtensions.kt b/dbflow-kotlinextensions/src/main/java/com/raizlabs/android/dbflow/kotlinextensions/PropertyMethodExtensions.kt index 7e045cd04..d8ea75deb 100644 --- a/dbflow-kotlinextensions/src/main/java/com/raizlabs/android/dbflow/kotlinextensions/PropertyMethodExtensions.kt +++ b/dbflow-kotlinextensions/src/main/java/com/raizlabs/android/dbflow/kotlinextensions/PropertyMethodExtensions.kt @@ -10,47 +10,47 @@ import com.raizlabs.android.dbflow.structure.Model * Description: Provides property methods in via infix functions. */ -infix fun Property.eq(value: T) = this.eq(value) +infix fun Property.eq(value: TModel) = this.eq(value) -infix fun Property.`is`(value: T) = this.`is`(value) +infix fun Property.`is`(value: TModel) = this.`is`(value) -infix fun Property.isNot(value: T) = this.isNot(value) +infix fun Property.isNot(value: TModel) = this.isNot(value) -infix fun Property.notEq(value: T) = this.notEq(value) +infix fun Property.notEq(value: TModel) = this.notEq(value) -infix fun Property.like(value: String) = this.like(value) +infix fun Property.like(value: String) = this.like(value) -infix fun Property.glob(value: String) = this.glob(value) +infix fun Property.glob(value: String) = this.glob(value) -infix fun Property.greaterThan(value: T) = this.greaterThan(value) +infix fun Property.greaterThan(value: TModel) = this.greaterThan(value) -infix fun Property.greaterThanOrEq(value: T) = this.greaterThanOrEq(value) +infix fun Property.greaterThanOrEq(value: TModel) = this.greaterThanOrEq(value) -infix fun Property.lessThan(value: T) = this.lessThan(value) +infix fun Property.lessThan(value: TModel) = this.lessThan(value) -infix fun Property.lessThanOrEq(value: T) = this.lessThanOrEq(value) +infix fun Property.lessThanOrEq(value: TModel) = this.lessThanOrEq(value) -infix fun Property.between(value: T) = this.between(value) +infix fun Property.between(value: TModel) = this.between(value) -infix fun Property.`in`(values: Array): Condition.In { +infix fun Property.`in`(values: Array): Condition.In { return when (values.size) { 1 -> `in`(values[0]) else -> this.`in`(values[0], *values.sliceArray(IntRange(1, values.size))) } } -infix fun Property.notIn(values: Array): Condition.In { +infix fun Property.notIn(values: Array): Condition.In { return when (values.size) { 1 -> notIn(values[0]) else -> this.notIn(values[0], *values.sliceArray(IntRange(1, values.size))) } } -infix fun Property.`in`(values: Collection) = this.`in`(values) +infix fun Property.`in`(values: Collection) = this.`in`(values) -infix fun Property.notIn(values: Collection) = this.notIn(values) +infix fun Property.notIn(values: Collection) = this.notIn(values) -infix fun Property.concatenate(value: T) = this.concatenate(value) +infix fun Property.concatenate(value: TModel) = this.concatenate(value) infix fun IConditional.eq(value: IConditional) = this.eq(value) diff --git a/dbflow-kotlinextensions/src/main/java/com/raizlabs/android/dbflow/kotlinextensions/QueryExtensions.kt b/dbflow-kotlinextensions/src/main/java/com/raizlabs/android/dbflow/kotlinextensions/QueryExtensions.kt index e2340310d..f32f0f8b6 100644 --- a/dbflow-kotlinextensions/src/main/java/com/raizlabs/android/dbflow/kotlinextensions/QueryExtensions.kt +++ b/dbflow-kotlinextensions/src/main/java/com/raizlabs/android/dbflow/kotlinextensions/QueryExtensions.kt @@ -23,33 +23,33 @@ val select: Select inline fun Select.from(): From = from(TModel::class.java) -fun delete(modelClass: KClass): From = SQLite.delete(modelClass.java) +fun delete(modelClass: KClass): From = SQLite.delete(modelClass.java) -infix fun Select.from(modelClass: KClass) = from(modelClass.java) +infix fun Select.from(modelClass: KClass) = from(modelClass.java) -infix fun From.whereExists(where: Where) = where().exists(where) +infix fun From.whereExists(where: Where) = where().exists(where) -infix fun From.where(sqlCondition: SQLCondition) = where(sqlCondition) +infix fun From.where(sqlCondition: SQLCondition) = where(sqlCondition) -infix fun Set.where(sqlCondition: SQLCondition) = where(sqlCondition) +infix fun Set.where(sqlCondition: SQLCondition) = where(sqlCondition) -infix fun Where.and(sqlCondition: SQLCondition) = and(sqlCondition) +infix fun Where.and(sqlCondition: SQLCondition) = and(sqlCondition) -infix fun Where.or(sqlCondition: SQLCondition) = and(sqlCondition) +infix fun Where.or(sqlCondition: SQLCondition) = and(sqlCondition) -infix fun Case.`when`(sqlCondition: SQLCondition) = `when`(sqlCondition) +infix fun Case.`when`(sqlCondition: SQLCondition) = `when`(sqlCondition) -infix fun Case.`when`(property: IProperty<*>) = `when`(property) +infix fun Case.`when`(property: IProperty<*>) = `when`(property) -infix fun Case.`when`(value: T?) = `when`(value) +infix fun Case.`when`(value: TModel?) = `when`(value) -infix fun CaseCondition.then(value: T?) = then(value) +infix fun CaseCondition.then(value: TModel?) = then(value) -infix fun CaseCondition.then(property: IProperty<*>) = then(property) +infix fun CaseCondition.then(property: IProperty<*>) = then(property) -infix fun Case.`else`(value: T?) = _else(value) +infix fun Case.`else`(value: TModel?) = _else(value) -infix fun Case.end(columnName: String) = end(columnName) +infix fun Case.end(columnName: String) = end(columnName) // queriable extensions @@ -65,72 +65,72 @@ val Queriable.hasData: Boolean val Queriable.statement: DatabaseStatement get() = compileStatement() -val ModelQueriable.list: MutableList +val ModelQueriable.list: MutableList get() = queryList() -val ModelQueriable.result: T? +val ModelQueriable.result: TModel? get() = querySingle() -val ModelQueriable.cursorResult: CursorResult +val ModelQueriable.cursorResult: CursorResult get() = queryResults() // async extensions -val ModelQueriable.async: AsyncQuery +val ModelQueriable.async: AsyncQuery get() = async() -infix fun AsyncQuery.list(callback: (QueryTransaction<*>, MutableList?) -> Unit) +infix fun AsyncQuery.list(callback: (QueryTransaction<*>, MutableList?) -> Unit) = queryListResultCallback { queryTransaction, mutableList -> callback(queryTransaction, mutableList) } .execute() -infix fun AsyncQuery.result(callback: (QueryTransaction<*>, T?) -> Unit) +infix fun AsyncQuery.result(callback: (QueryTransaction<*>, TModel?) -> Unit) = querySingleResultCallback { queryTransaction, model -> callback(queryTransaction, model) } .execute() -infix fun AsyncQuery.cursorResult(callback: (QueryTransaction<*>, CursorResult) -> Unit) +infix fun AsyncQuery.cursorResult(callback: (QueryTransaction<*>, CursorResult) -> Unit) = queryResultCallback { queryTransaction, cursorResult -> callback(queryTransaction, cursorResult) } .execute() val BaseModel.async: AsyncModel get() = async() -infix fun AsyncModel.insert(listener: (T) -> Unit) = withListener { listener(it) }.insert() +infix fun AsyncModel.insert(listener: (TModel) -> Unit) = withListener { listener(it) }.insert() -infix fun AsyncModel.update(listener: (T) -> Unit) = withListener { listener(it) }.update() +infix fun AsyncModel.update(listener: (TModel) -> Unit) = withListener { listener(it) }.update() -infix fun AsyncModel.delete(listener: (T) -> Unit) = withListener { listener(it) }.delete() +infix fun AsyncModel.delete(listener: (TModel) -> Unit) = withListener { listener(it) }.delete() -infix fun AsyncModel.save(listener: (T) -> Unit) = withListener { listener(it) }.save() +infix fun AsyncModel.save(listener: (TModel) -> Unit) = withListener { listener(it) }.save() // Transformable methods -infix fun Transformable.groupBy(nameAlias: NameAlias) = groupBy(nameAlias) +infix fun Transformable.groupBy(nameAlias: NameAlias) = groupBy(nameAlias) -infix fun Transformable.groupBy(property: IProperty<*>) = groupBy(property) +infix fun Transformable.groupBy(property: IProperty<*>) = groupBy(property) -infix fun Transformable.orderBy(orderBy: OrderBy) = orderBy(orderBy) +infix fun Transformable.orderBy(orderBy: OrderBy) = orderBy(orderBy) -infix fun Transformable.limit(limit: Int) = limit(limit) +infix fun Transformable.limit(limit: Int) = limit(limit) -infix fun Transformable.offset(offset: Int) = offset(offset) +infix fun Transformable.offset(offset: Int) = offset(offset) -infix fun Transformable.having(sqlCondition: SQLCondition) = having(sqlCondition) +infix fun Transformable.having(sqlCondition: SQLCondition) = having(sqlCondition) // join -infix fun From.innerJoin(joinTable: KClass) = join(joinTable.java, Join.JoinType.INNER) +infix fun From.innerJoin(joinTable: KClass) = join(joinTable.java, Join.JoinType.INNER) -infix fun From.crossJoin(joinTable: KClass) = join(joinTable.java, Join.JoinType.CROSS) +infix fun From.crossJoin(joinTable: KClass) = join(joinTable.java, Join.JoinType.CROSS) -infix fun From.leftOuterJoin(joinTable: KClass) = join(joinTable.java, Join.JoinType.LEFT_OUTER) +infix fun From.leftOuterJoin(joinTable: KClass) = join(joinTable.java, Join.JoinType.LEFT_OUTER) -infix fun Join.on(sqlCondition: SQLCondition) = on(sqlCondition) +infix fun Join.on(sqlCondition: SQLCondition) = on(sqlCondition) // update methods -fun update(modelClass: KClass): Update = SQLite.update(modelClass.java) +fun update(modelClass: KClass): Update = SQLite.update(modelClass.java) -infix fun Update.set(sqlCondition: SQLCondition) = set(sqlCondition) +infix fun Update.set(sqlCondition: SQLCondition) = set(sqlCondition) // delete @@ -141,19 +141,19 @@ inline fun delete(deleteClause: From.() -> Base // insert methods -fun insert(modelClass: KClass) = SQLite.insert(modelClass.java) +fun insert(modelClass: KClass) = SQLite.insert(modelClass.java) -infix fun Insert.orReplace(into: Array, *>>) = orReplace().into(*into) +infix fun Insert.orReplace(into: Array, *>>) = orReplace().into(*into) -infix fun Insert.orRollback(into: Array, *>>) = orRollback().into(*into) +infix fun Insert.orRollback(into: Array, *>>) = orRollback().into(*into) -infix fun Insert.orAbort(into: Array, *>>) = orAbort().into(*into) +infix fun Insert.orAbort(into: Array, *>>) = orAbort().into(*into) -infix fun Insert.orFail(into: Array, *>>) = orFail().into(*into) +infix fun Insert.orFail(into: Array, *>>) = orFail().into(*into) -infix fun Insert.orIgnore(into: Array, *>>) = orIgnore().into(*into) +infix fun Insert.orIgnore(into: Array, *>>) = orIgnore().into(*into) -infix fun Insert.select(from: From<*>) = select(from) +infix fun Insert.select(from: From<*>) = select(from) fun into(vararg pairs: Pair, *>): Array, *>> = pairs diff --git a/dbflow/src/main/java/com/raizlabs/android/dbflow/list/FlowCursorAdapter.java b/dbflow/src/main/java/com/raizlabs/android/dbflow/list/FlowCursorAdapter.java new file mode 100644 index 000000000..c69b4b4e4 --- /dev/null +++ b/dbflow/src/main/java/com/raizlabs/android/dbflow/list/FlowCursorAdapter.java @@ -0,0 +1,45 @@ +package com.raizlabs.android.dbflow.list; + +import android.annotation.TargetApi; +import android.content.Context; +import android.database.Cursor; +import android.widget.CursorAdapter; + +import com.raizlabs.android.dbflow.config.FlowManager; +import com.raizlabs.android.dbflow.structure.Model; +import com.raizlabs.android.dbflow.structure.ModelAdapter; + +/** + * Specialization of CursorAdapter for DBFLow models. + * + * @param + */ +public abstract class FlowCursorAdapter extends CursorAdapter +{ + private final Class modelClass_; + private final ModelAdapter modelAdapter_; + + public FlowCursorAdapter (Context context, Class modelClass, Cursor c, boolean autoRequery) + { + super (context, c, autoRequery); + + this.modelClass_ = modelClass; + this.modelAdapter_ = FlowManager.getModelAdapter (modelClass); + } + + @TargetApi(11) + public FlowCursorAdapter (Context context, Class modelClass, Cursor c, int flags) + { + super (context, c, flags); + + this.modelClass_ = modelClass; + this.modelAdapter_ = FlowManager.getModelAdapter (modelClass); + } + + @Override + public TModel getItem (int position) + { + Cursor cursor = (Cursor) super.getItem (position); + return cursor != null ? this.modelAdapter_.loadFromCursor (cursor) : null; + } +} diff --git a/dbflow/src/main/java/com/raizlabs/android/dbflow/list/FlowCursorLoader.java b/dbflow/src/main/java/com/raizlabs/android/dbflow/list/FlowCursorLoader.java new file mode 100644 index 000000000..86d82ea1c --- /dev/null +++ b/dbflow/src/main/java/com/raizlabs/android/dbflow/list/FlowCursorLoader.java @@ -0,0 +1,212 @@ +package com.raizlabs.android.dbflow.list; + +import android.annotation.TargetApi; +import android.content.AsyncTaskLoader; +import android.content.Context; +import android.database.Cursor; +import android.net.Uri; + +import com.raizlabs.android.dbflow.runtime.FlowContentObserver; +import com.raizlabs.android.dbflow.sql.language.SQLCondition; +import com.raizlabs.android.dbflow.sql.queriable.Queriable; +import com.raizlabs.android.dbflow.structure.BaseModel; +import com.raizlabs.android.dbflow.structure.Model; + +import java.util.Collection; +import java.util.HashSet; + +/** + * Specialization of AsyncTaskLoader for Cursor objects in DBFlow. + */ +@TargetApi (11) +public class FlowCursorLoader extends AsyncTaskLoader +{ + private static final String TAG = "FlowCursorLoader"; + + /// Models to be observed for changes. + private HashSet> mModels = new HashSet<> (); + + /// Queriable operation that the loader executes. + private Queriable mQueriable; + + /// Cursor for the loader. + private Cursor mCursor; + + private final ForceLoadContentObserver mObserver = new ForceLoadContentObserver (); + + private boolean mListening = false; + + /** + * Creates a fully-specified CursorLoader. See {@link android.content.ContentResolver#query(Uri, + * String[], String, String[], String) ContentResolver.query()} for documentation on the meaning + * of the parameters. These will be passed as-is to that call. + */ + public FlowCursorLoader (Context context, Queriable queriable) + { + super (context); + + this.mQueriable = queriable; + } + + @Override + public Cursor loadInBackground () + { + Cursor cursor = this.mQueriable.query (); + + if (cursor != null) + cursor.getCount (); + + return cursor; + } + + @Override + public void deliverResult (Cursor cursor) + { + if (this.isReset ()) + { + // An async query came in while the loader is stopped + if (cursor != null) + cursor.close (); + + return; + } + + Cursor oldCursor = this.mCursor; + this.mCursor = cursor; + + if (this.isStarted ()) + super.deliverResult (cursor); + + if (oldCursor != null && oldCursor != cursor && !oldCursor.isClosed ()) + oldCursor.close (); + + // Now that the result has been delivered, start listening for changes + // to the target models. Doing this at anytime earlier runs the risk of + // listening for changes while we are still loading content. + this.startListeningForChanges (); + } + + /** + * Register the loader for changes to a Flow model. When changes to the model are + * detected, then the loader will automatically reload the content. + * + * @param model + */ + public void registerForContentChanges (Class model) + { + if (this.mModels.contains (model)) + return; + + this.mModels.add (model); + this.mObserver.registerForContentChanges (this.getContext (), model); + } + + @Override + protected void onStartLoading () + { + if (this.mCursor != null) + this.deliverResult (this.mCursor); + + if (this.takeContentChanged () || this.mCursor == null) + this.forceLoad (); + } + + @Override + protected void onStopLoading () + { + // Make sure the loading has stopped. + this.cancelLoad (); + } + + @Override + public void onCanceled (Cursor cursor) + { + if (cursor != null && !cursor.isClosed ()) + cursor.close (); + + this.stopListeningForChanges (); + } + + @Override + protected void onReset () + { + // Ensure the loader is stopped + this.onStopLoading (); + + if (mCursor != null && !mCursor.isClosed ()) + mCursor.close (); + + mCursor = null; + + this.mObserver.unregisterForContentChanges (this.getContext ()); + } + + private void startListeningForChanges () + { + if (!this.mListening) + { + this.mObserver.addModelChangeListener (this.mObserver); + this.mListening = true; + } + } + + private void stopListeningForChanges () + { + if (this.mListening) + { + this.mObserver.removeModelChangeListener (this.mObserver); + this.mListening = false; + } + } + + public Collection> getModels () + { + return this.mModels; + } + + public FlowContentObserver getContentObserver () + { + return this.mObserver; + } + + final class ForceLoadContentObserver extends FlowContentObserver + implements FlowContentObserver.OnModelStateChangedListener + { + private boolean endOfTransaction = false; + + @Override + public boolean deliverSelfNotifications () + { + return false; + } + + @Override + public void onModelStateChanged (Class table, + BaseModel.Action action, + SQLCondition[] primaryKeyValues) + { + if (!this.endOfTransaction) + { + if (action == BaseModel.Action.INSERT || + action == BaseModel.Action.DELETE || + action == BaseModel.Action.UPDATE) + { + onContentChanged (); + } + } + } + + @Override + public void endTransactionAndNotify () + { + // Mark this as the end of a transactions, and pass control to the base class + // to perform the notifications. + this.endOfTransaction = true; + super.endTransactionAndNotify (); + + // Notify the observer the content has changed. + this.endOfTransaction = false; + onContentChanged (); + } + } +} \ No newline at end of file diff --git a/dbflow/src/main/java/com/raizlabs/android/dbflow/list/FlowModelLoader.java b/dbflow/src/main/java/com/raizlabs/android/dbflow/list/FlowModelLoader.java new file mode 100644 index 000000000..64181f8cd --- /dev/null +++ b/dbflow/src/main/java/com/raizlabs/android/dbflow/list/FlowModelLoader.java @@ -0,0 +1,138 @@ +package com.raizlabs.android.dbflow.list; + +import android.annotation.TargetApi; +import android.content.AsyncTaskLoader; +import android.content.Context; +import android.database.Cursor; +import android.net.Uri; + +import com.raizlabs.android.dbflow.config.FlowManager; +import com.raizlabs.android.dbflow.runtime.FlowContentObserver; +import com.raizlabs.android.dbflow.sql.queriable.Queriable; +import com.raizlabs.android.dbflow.structure.Model; +import com.raizlabs.android.dbflow.structure.ModelAdapter; + +/** + * Utility class to be added to DBFlow. + * + * @param + */ +@TargetApi(11) +public class FlowModelLoader extends AsyncTaskLoader +{ + /// Models to be observed for changes. + private final Class mModel; + private final ModelAdapter mModelAdapter; + + /// Queriable operation that the loader executes. + private Queriable mQueriable; + + /// Cursor for the loader. + private TModel mResult; + + private class ForceLoadContentObserver extends FlowContentObserver + { + @Override + public boolean deliverSelfNotifications () + { + return true; + } + + @Override + public void onChange (boolean selfChange) + { + super.onChange (selfChange); + onContentChanged (); + } + + @Override + public void onChange (boolean selfChange, Uri uri) + { + super.onChange (selfChange, uri); + onContentChanged (); + } + } + + private final ForceLoadContentObserver mObserver = new ForceLoadContentObserver (); + + public FlowModelLoader (Context context, Class model, Queriable queriable) + { + super (context); + + this.mQueriable = queriable; + this.mModel = model; + this.mModelAdapter = FlowManager.getModelAdapter (model); + } + + /* Runs on a worker thread */ + @Override + public TModel loadInBackground () + { + Cursor cursor = this.mQueriable.query (); + return cursor != null && cursor.moveToFirst () ? this.mModelAdapter.loadFromCursor (cursor) : null; + } + + /* Runs on the UI thread */ + @Override + public void deliverResult (TModel result) + { + if (this.isReset ()) + return; + + this.mResult = result; + + if (this.isStarted ()) + super.deliverResult (this.mResult); + } + + /** + * Starts an asynchronous load of the contacts list data. When the result is ready the callbacks + * will be called on the UI thread. If a previous load has been completed and is still valid the + * result may be passed to the callbacks immediately. + *

+ * Must be called from the UI thread + */ + @Override + protected void onStartLoading () + { + if (mResult != null) + this.deliverResult (mResult); + + if (this.takeContentChanged () || this.mResult == null) + this.forceLoad (); + + this.mObserver.registerForContentChanges (this.getContext (), this.mModel); + } + + /** + * Must be called from the UI thread + */ + @Override + protected void onStopLoading () + { + this.cancelLoad (); + } + + @Override + public void onCanceled (TModel result) + { + mObserver.unregisterForContentChanges (this.getContext ()); + } + + @Override + protected void onReset () + { + super.onReset (); + + // Ensure the loader is stopped + onStopLoading (); + + mResult = null; + mObserver.unregisterForContentChanges (this.getContext ()); + } + + public Class getModel () + { + return this.mModel; + } +} \ No newline at end of file diff --git a/dbflow/src/main/java/com/raizlabs/android/dbflow/list/FlowSimpleCursorAdapter.java b/dbflow/src/main/java/com/raizlabs/android/dbflow/list/FlowSimpleCursorAdapter.java new file mode 100644 index 000000000..d95085782 --- /dev/null +++ b/dbflow/src/main/java/com/raizlabs/android/dbflow/list/FlowSimpleCursorAdapter.java @@ -0,0 +1,38 @@ +package com.raizlabs.android.dbflow.list; + + +import android.annotation.TargetApi; +import android.content.Context; +import android.database.Cursor; +import android.widget.SimpleCursorAdapter; + +import com.raizlabs.android.dbflow.config.FlowManager; +import com.raizlabs.android.dbflow.structure.Model; +import com.raizlabs.android.dbflow.structure.ModelAdapter; + +/** + * Utility class to be added to DBFlow. + * + * @param + */ +public class FlowSimpleCursorAdapter extends SimpleCursorAdapter +{ + private final Class modelClass_; + private final ModelAdapter modelAdapter_; + + @TargetApi (11) + public FlowSimpleCursorAdapter (Context context, Class modelClass, int layout, Cursor c, String[] from, int[] to, int flags) + { + super (context, layout, c, from, to, flags); + + this.modelClass_ = modelClass; + this.modelAdapter_ = FlowManager.getModelAdapter (modelClass); + } + + @Override + public TModel getItem (int position) + { + Cursor cursor = (Cursor) super.getItem (position); + return cursor != null ? this.modelAdapter_.loadFromCursor (cursor) : null; + } +} diff --git a/usage2/KotlinSupport.md b/usage2/KotlinSupport.md index 73770a786..7eb3b6312 100644 --- a/usage2/KotlinSupport.md +++ b/usage2/KotlinSupport.md @@ -187,7 +187,7 @@ items.processInTransactionAsync({ it, databaseWrapper -> it.delete(databaseWrapp ``` -The extension method on `Collection` allows you to perform this on all +The extension method on `Collection` allows you to perform this on all collections from your Table! If you wish to easily do them _synchronously_ then use: diff --git a/usage2/Migration3Guide.md b/usage2/Migration3Guide.md index dd2c606c6..edfcaebfc 100644 --- a/usage2/Migration3Guide.md +++ b/usage2/Migration3Guide.md @@ -449,7 +449,7 @@ Perhaps the most significant external change to this library is making queries, ### Property Properties replace `String` column names generated in the "$Table" classes. They also match exact case to the column name. They have methods that generate `Condition` that drastically simplify queries. (Please note the `Condition` class has moved to the `.language` package). -Properties are represented by the interface `IProperty` which are subclassed into `Property`, `Method`, and the primitive properties (`IntProperty`, `CharProperty`, etc). +Properties are represented by the interface `IProperty` which are subclassed into `Property`, `Method`, and the primitive properties (`IntProperty`, `CharProperty`, etc). Properties can also be represented by values via the `PropertyFactory` class, enabling values to appear first in queries: diff --git a/usage2/Models.md b/usage2/Models.md index 2276e008c..6ed8f1143 100644 --- a/usage2/Models.md +++ b/usage2/Models.md @@ -45,7 +45,7 @@ Columns have a wide-range of supported types in the `Model` classes: 5. `Model`/`ModelContainer`/`ForeignKeyContainer` as fields, but only as `@PrimaryKey` and/or `@ForeignKey` **Unsupported Types**: - 1. `List` : List columns are not supported and not generally proper for a relational database. However, you can get away with a non-generic `List` column via a `TypeConverter`. But again, avoid this if you can. + 1. `List` : List columns are not supported and not generally proper for a relational database. However, you can get away with a non-generic `List` column via a `TypeConverter`. But again, avoid this if you can. 2. Anything that is generically typed (even with an associated `TypeConverter`), **except** `ModelContainer` and `ForeignKeyContainer` fields. If you need to include the field, subclass the generic object and provide a `TypeConverter`. ## Inherited Columns diff --git a/usage2/SQLiteWrapperLanguage.md b/usage2/SQLiteWrapperLanguage.md index a1f81345d..93bd506ef 100644 --- a/usage2/SQLiteWrapperLanguage.md +++ b/usage2/SQLiteWrapperLanguage.md @@ -269,7 +269,7 @@ Delete.tables(MyTable1.class, MyTable2.class); // Delete using query SQLite.delete(MyTable.class) - .where(DeviceObject_Table.carrier.is("T-MOBILE")) + .where(DeviceObject_Table.carrier.is("TModel-MOBILE")) .and(DeviceObject_Table.device.is("Samsung-Galaxy-S5")) .async() .execute(); diff --git a/usage2/TypeConverters.md b/usage2/TypeConverters.md index d98881f52..cd54407d1 100644 --- a/usage2/TypeConverters.md +++ b/usage2/TypeConverters.md @@ -12,7 +12,7 @@ When building out `Model` classes, you may wish to provide a different type of ` `TypeConverter` do _not_ support: 1. Any Parameterized fields _except_ `ForeignKeyContainer` and `ModelContainer` fields. - 2. `List`, `Map`, etc. Best way to fix this is to create a separate table [relationship](/usage2/Relationships.md) + 2. `List`, `Map`, etc. Best way to fix this is to create a separate table [relationship](/usage2/Relationships.md) 3. Conversion from one type-converter to another (i.e `JSONObject` to `Date`). The first parameter of `TypeConverter` is the value of the type as if it was a primitive/boxed type. 4. Conversion from custom type to `Model`, or `Model` to a supported type. 5. The custom class _must_ map to a non-complex field such as `String`, numbers, `char`/`Character` or `Blob` From 1e05a47b1e24e5166878955bf9b133444dbfe6e2 Mon Sep 17 00:00:00 2001 From: "James H. Hill" Date: Sun, 3 Jul 2016 20:14:17 -0400 Subject: [PATCH 15/47] Fixed build errors --- .../android/dbflow/annotation/ForeignKeyReference.java | 2 +- dbflow-kotlinextensions/build.gradle | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/dbflow-core/src/main/java/com/raizlabs/android/dbflow/annotation/ForeignKeyReference.java b/dbflow-core/src/main/java/com/raizlabs/android/dbflow/annotation/ForeignKeyReference.java index a19400a25..f41612fa3 100644 --- a/dbflow-core/src/main/java/com/raizlabs/android/dbflow/annotation/ForeignKeyReference.java +++ b/dbflow-core/src/main/java/com/raizlabs/android/dbflow/annotation/ForeignKeyReference.java @@ -6,7 +6,7 @@ /** * Description: Used inside of {@link ForeignKey#references()}, describes the * local column name, type, and referencing table column name. - * + * * Note: the type of the local column must match the * column type of the referenced column. By using a field as a Model object, * you will need to ensure the same types are used. diff --git a/dbflow-kotlinextensions/build.gradle b/dbflow-kotlinextensions/build.gradle index b37bd4a1b..799f3fa94 100644 --- a/dbflow-kotlinextensions/build.gradle +++ b/dbflow-kotlinextensions/build.gradle @@ -29,6 +29,9 @@ android { sourceSets { main.java.srcDirs += 'src/main/kotlin' } + lintOptions { + abortOnError false + } } dependencies { From ccdb83b772dc181161d1759ccdce8d6ddd0dcd76 Mon Sep 17 00:00:00 2001 From: "James H. Hill" Date: Sun, 3 Jul 2016 22:46:39 -0400 Subject: [PATCH 16/47] Fixed build error --- .../raizlabs/android/dbflow/annotation/ForeignKeyReference.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dbflow-core/src/main/java/com/raizlabs/android/dbflow/annotation/ForeignKeyReference.java b/dbflow-core/src/main/java/com/raizlabs/android/dbflow/annotation/ForeignKeyReference.java index 5fb380e67..a19400a25 100644 --- a/dbflow-core/src/main/java/com/raizlabs/android/dbflow/annotation/ForeignKeyReference.java +++ b/dbflow-core/src/main/java/com/raizlabs/android/dbflow/annotation/ForeignKeyReference.java @@ -6,7 +6,7 @@ /** * Description: Used inside of {@link ForeignKey#references()}, describes the * local column name, type, and referencing table column name. - *

+ * * Note: the type of the local column must match the * column type of the referenced column. By using a field as a Model object, * you will need to ensure the same types are used. From 49d3993477fe7e36bab024e0d76f44ea2de90abf Mon Sep 17 00:00:00 2001 From: "James H. Hill" Date: Sun, 3 Jul 2016 23:25:38 -0400 Subject: [PATCH 17/47] Fixed compilation errors --- .../raizlabs/android/dbflow/annotation/ForeignKeyReference.java | 2 +- .../dbflow/processor/definition/column/ColumnDefinition.java | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/dbflow-core/src/main/java/com/raizlabs/android/dbflow/annotation/ForeignKeyReference.java b/dbflow-core/src/main/java/com/raizlabs/android/dbflow/annotation/ForeignKeyReference.java index a19400a25..f41612fa3 100644 --- a/dbflow-core/src/main/java/com/raizlabs/android/dbflow/annotation/ForeignKeyReference.java +++ b/dbflow-core/src/main/java/com/raizlabs/android/dbflow/annotation/ForeignKeyReference.java @@ -6,7 +6,7 @@ /** * Description: Used inside of {@link ForeignKey#references()}, describes the * local column name, type, and referencing table column name. - * + * * Note: the type of the local column must match the * column type of the referenced column. By using a field as a Model object, * you will need to ensure the same types are used. diff --git a/dbflow-processor/src/main/java/com/raizlabs/android/dbflow/processor/definition/column/ColumnDefinition.java b/dbflow-processor/src/main/java/com/raizlabs/android/dbflow/processor/definition/column/ColumnDefinition.java index dc396c13b..1121ef45e 100644 --- a/dbflow-processor/src/main/java/com/raizlabs/android/dbflow/processor/definition/column/ColumnDefinition.java +++ b/dbflow-processor/src/main/java/com/raizlabs/android/dbflow/processor/definition/column/ColumnDefinition.java @@ -359,7 +359,6 @@ public String getColumnAccessString(boolean isModelContainerAdapter, boolean isS /** * @param isModelContainerAdapter * @param codeBuilder - * @return A string without any type conversion for this field. */ public void appendPropertyComparisonAccessStatement(boolean isModelContainerAdapter, CodeBlock.Builder codeBuilder) { codeBuilder.add("\nclause.and($T.$L.eq(", tableDefinition.getPropertyClassName(), columnName); From e3b8ecb32a21f60aab92345e4aab4380079ed1ae Mon Sep 17 00:00:00 2001 From: "James H. Hill" Date: Thu, 7 Jul 2016 11:15:12 -0400 Subject: [PATCH 18/47] Switch to AsyncTaskLoader in Android support library --- dbflow/build.gradle | 3 +-- .../com/raizlabs/android/dbflow/list/FlowCursorLoader.java | 3 ++- .../com/raizlabs/android/dbflow/list/FlowModelLoader.java | 5 +++-- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/dbflow/build.gradle b/dbflow/build.gradle index ed5695b38..1d6e79fc0 100644 --- a/dbflow/build.gradle +++ b/dbflow/build.gradle @@ -29,8 +29,7 @@ android { dependencies { compile project("${dbflow_project_prefix}dbflow-core") compile "com.android.support:support-annotations:23.1.1" - - + compile 'com.android.support:support-v4:23.1.1' } apply from: '../android-artifacts.gradle' diff --git a/dbflow/src/main/java/com/raizlabs/android/dbflow/list/FlowCursorLoader.java b/dbflow/src/main/java/com/raizlabs/android/dbflow/list/FlowCursorLoader.java index 86d82ea1c..f6a11e805 100644 --- a/dbflow/src/main/java/com/raizlabs/android/dbflow/list/FlowCursorLoader.java +++ b/dbflow/src/main/java/com/raizlabs/android/dbflow/list/FlowCursorLoader.java @@ -1,11 +1,12 @@ package com.raizlabs.android.dbflow.list; import android.annotation.TargetApi; -import android.content.AsyncTaskLoader; import android.content.Context; import android.database.Cursor; import android.net.Uri; +import android.support.v4.content.AsyncTaskLoader; + import com.raizlabs.android.dbflow.runtime.FlowContentObserver; import com.raizlabs.android.dbflow.sql.language.SQLCondition; import com.raizlabs.android.dbflow.sql.queriable.Queriable; diff --git a/dbflow/src/main/java/com/raizlabs/android/dbflow/list/FlowModelLoader.java b/dbflow/src/main/java/com/raizlabs/android/dbflow/list/FlowModelLoader.java index 64181f8cd..ebd2c47b5 100644 --- a/dbflow/src/main/java/com/raizlabs/android/dbflow/list/FlowModelLoader.java +++ b/dbflow/src/main/java/com/raizlabs/android/dbflow/list/FlowModelLoader.java @@ -1,11 +1,12 @@ package com.raizlabs.android.dbflow.list; import android.annotation.TargetApi; -import android.content.AsyncTaskLoader; import android.content.Context; import android.database.Cursor; import android.net.Uri; +import android.support.v4.content.AsyncTaskLoader; + import com.raizlabs.android.dbflow.config.FlowManager; import com.raizlabs.android.dbflow.runtime.FlowContentObserver; import com.raizlabs.android.dbflow.sql.queriable.Queriable; @@ -18,7 +19,7 @@ * @param */ @TargetApi(11) -public class FlowModelLoader extends AsyncTaskLoader +public class FlowModelLoader extends AsyncTaskLoader { /// Models to be observed for changes. private final Class mModel; From 536a5bbe05d47d943c264b7a9834045c0da59b1b Mon Sep 17 00:00:00 2001 From: "James H. Hill" Date: Thu, 7 Jul 2016 12:21:21 -0400 Subject: [PATCH 19/47] Added missing dependency --- dbflow-processor/build.gradle | 1 + 1 file changed, 1 insertion(+) diff --git a/dbflow-processor/build.gradle b/dbflow-processor/build.gradle index 3dcff8d05..768c5d3d0 100644 --- a/dbflow-processor/build.gradle +++ b/dbflow-processor/build.gradle @@ -11,6 +11,7 @@ dependencies { compile project("${dbflow_project_prefix}dbflow-core") compile 'com.squareup:javapoet:1.7.0' compile 'com.google.auto.service:auto-service:1.0-rc2' + compile group: 'com.google.guava', name: 'guava', version: '19.0' } apply from: '../java-artifacts.gradle' From 36b144d10c03a3d73f835645812c8deb1ee1b5c4 Mon Sep 17 00:00:00 2001 From: "James H. Hill" Date: Thu, 7 Jul 2016 12:55:07 -0400 Subject: [PATCH 20/47] Fixed build issues with API version --- dbflow-processor/build.gradle | 2 +- .../dbflow/processor/definition/TableDefinition.java | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/dbflow-processor/build.gradle b/dbflow-processor/build.gradle index 768c5d3d0..b0fdda920 100644 --- a/dbflow-processor/build.gradle +++ b/dbflow-processor/build.gradle @@ -11,7 +11,7 @@ dependencies { compile project("${dbflow_project_prefix}dbflow-core") compile 'com.squareup:javapoet:1.7.0' compile 'com.google.auto.service:auto-service:1.0-rc2' - compile group: 'com.google.guava', name: 'guava', version: '19.0' + compile 'com.google.guava:guava:19.0' } apply from: '../java-artifacts.gradle' diff --git a/dbflow-processor/src/main/java/com/raizlabs/android/dbflow/processor/definition/TableDefinition.java b/dbflow-processor/src/main/java/com/raizlabs/android/dbflow/processor/definition/TableDefinition.java index d2ba35a72..72838a1bd 100644 --- a/dbflow-processor/src/main/java/com/raizlabs/android/dbflow/processor/definition/TableDefinition.java +++ b/dbflow-processor/src/main/java/com/raizlabs/android/dbflow/processor/definition/TableDefinition.java @@ -139,7 +139,7 @@ public TableDefinition(ProcessorManager manager, TypeElement element) { if (table != null) { this.tableName = table.name(); - if (tableName == null || tableName.isEmpty()) { + if (tableName == null || tableName.length () == 0) { tableName = element.getSimpleName().toString(); } @@ -679,7 +679,7 @@ public void writeAdapter(ProcessingEnvironment processingEnvironment) throws IOE .returns(ClassNames.BASE_PROPERTY) .build()); - if (!updateConflictActionName.isEmpty()) { + if (updateConflictActionName.length () != 0) { typeBuilder.addMethod(MethodSpec.methodBuilder("getUpdateOnConflictAction") .addAnnotation(Override.class) .addModifiers(Modifier.PUBLIC, Modifier.FINAL) @@ -688,7 +688,7 @@ public void writeAdapter(ProcessingEnvironment processingEnvironment) throws IOE .build()); } - if (!insertConflictActionName.isEmpty()) { + if (insertConflictActionName.length () != 0) { typeBuilder.addMethod(MethodSpec.methodBuilder("getInsertOnConflictAction") .addAnnotation(Override.class) .addModifiers(Modifier.PUBLIC, Modifier.FINAL) From 63fe2200e7f0975fa8c32fccfbcd58f796401a12 Mon Sep 17 00:00:00 2001 From: "James H. Hill" Date: Thu, 21 Jul 2016 12:06:46 -0400 Subject: [PATCH 21/47] Fixed issues in implementation --- .../android/dbflow/list/FlowCursorAdapter.java | 2 +- .../raizlabs/android/dbflow/list/FlowCursorLoader.java | 6 +++--- .../android/dbflow/list/FlowSimpleCursorAdapter.java | 10 +++++----- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/dbflow/src/main/java/com/raizlabs/android/dbflow/list/FlowCursorAdapter.java b/dbflow/src/main/java/com/raizlabs/android/dbflow/list/FlowCursorAdapter.java index c69b4b4e4..dec6dbadc 100644 --- a/dbflow/src/main/java/com/raizlabs/android/dbflow/list/FlowCursorAdapter.java +++ b/dbflow/src/main/java/com/raizlabs/android/dbflow/list/FlowCursorAdapter.java @@ -17,7 +17,7 @@ public abstract class FlowCursorAdapter extends CursorAdapter { private final Class modelClass_; - private final ModelAdapter modelAdapter_; + private final ModelAdapter modelAdapter_; public FlowCursorAdapter (Context context, Class modelClass, Cursor c, boolean autoRequery) { diff --git a/dbflow/src/main/java/com/raizlabs/android/dbflow/list/FlowCursorLoader.java b/dbflow/src/main/java/com/raizlabs/android/dbflow/list/FlowCursorLoader.java index f6a11e805..2be793306 100644 --- a/dbflow/src/main/java/com/raizlabs/android/dbflow/list/FlowCursorLoader.java +++ b/dbflow/src/main/java/com/raizlabs/android/dbflow/list/FlowCursorLoader.java @@ -4,7 +4,6 @@ import android.content.Context; import android.database.Cursor; import android.net.Uri; - import android.support.v4.content.AsyncTaskLoader; import com.raizlabs.android.dbflow.runtime.FlowContentObserver; @@ -131,8 +130,9 @@ public void onCanceled (Cursor cursor) @Override protected void onReset () { - // Ensure the loader is stopped - this.onStopLoading (); + super.onReset (); + + this.startLoading (); if (mCursor != null && !mCursor.isClosed ()) mCursor.close (); diff --git a/dbflow/src/main/java/com/raizlabs/android/dbflow/list/FlowSimpleCursorAdapter.java b/dbflow/src/main/java/com/raizlabs/android/dbflow/list/FlowSimpleCursorAdapter.java index d95085782..8151028ff 100644 --- a/dbflow/src/main/java/com/raizlabs/android/dbflow/list/FlowSimpleCursorAdapter.java +++ b/dbflow/src/main/java/com/raizlabs/android/dbflow/list/FlowSimpleCursorAdapter.java @@ -17,22 +17,22 @@ */ public class FlowSimpleCursorAdapter extends SimpleCursorAdapter { - private final Class modelClass_; - private final ModelAdapter modelAdapter_; + private final Class mModel; + private final ModelAdapter mModelAdapter; @TargetApi (11) public FlowSimpleCursorAdapter (Context context, Class modelClass, int layout, Cursor c, String[] from, int[] to, int flags) { super (context, layout, c, from, to, flags); - this.modelClass_ = modelClass; - this.modelAdapter_ = FlowManager.getModelAdapter (modelClass); + this.mModel = modelClass; + this.mModelAdapter = FlowManager.getModelAdapter (modelClass); } @Override public TModel getItem (int position) { Cursor cursor = (Cursor) super.getItem (position); - return cursor != null ? this.modelAdapter_.loadFromCursor (cursor) : null; + return cursor != null ? this.mModelAdapter.loadFromCursor (cursor) : null; } } From 008dc04073bc5e8318d80e2c02f9ef8701073179 Mon Sep 17 00:00:00 2001 From: "James H. Hill" Date: Thu, 21 Jul 2016 12:07:28 -0400 Subject: [PATCH 22/47] Loaders for single model queries --- .../dbflow/single/FlowModelLoader.java | 23 +++ .../dbflow/single/FlowModelViewLoader.java | 28 +++ .../dbflow/single/FlowQueryModelLoader.java | 26 +++ .../dbflow/single/FlowSingleModelLoader.java | 167 ++++++++++++++++++ 4 files changed, 244 insertions(+) create mode 100644 dbflow/src/main/java/com/raizlabs/android/dbflow/single/FlowModelLoader.java create mode 100644 dbflow/src/main/java/com/raizlabs/android/dbflow/single/FlowModelViewLoader.java create mode 100644 dbflow/src/main/java/com/raizlabs/android/dbflow/single/FlowQueryModelLoader.java create mode 100644 dbflow/src/main/java/com/raizlabs/android/dbflow/single/FlowSingleModelLoader.java diff --git a/dbflow/src/main/java/com/raizlabs/android/dbflow/single/FlowModelLoader.java b/dbflow/src/main/java/com/raizlabs/android/dbflow/single/FlowModelLoader.java new file mode 100644 index 000000000..91b4fb216 --- /dev/null +++ b/dbflow/src/main/java/com/raizlabs/android/dbflow/single/FlowModelLoader.java @@ -0,0 +1,23 @@ +package com.raizlabs.android.dbflow.single; + +import android.annotation.TargetApi; +import android.content.Context; + +import com.raizlabs.android.dbflow.config.FlowManager; +import com.raizlabs.android.dbflow.sql.queriable.Queriable; +import com.raizlabs.android.dbflow.structure.Model; + +/** + * Load a single model from the database. + * + * @param + */ +@TargetApi(11) +public class FlowModelLoader + extends FlowSingleModelLoader +{ + public FlowModelLoader (Context context, Class model, Queriable queriable) + { + super (context, model, FlowManager.getModelAdapter (model), queriable); + } +} \ No newline at end of file diff --git a/dbflow/src/main/java/com/raizlabs/android/dbflow/single/FlowModelViewLoader.java b/dbflow/src/main/java/com/raizlabs/android/dbflow/single/FlowModelViewLoader.java new file mode 100644 index 000000000..1903c76f8 --- /dev/null +++ b/dbflow/src/main/java/com/raizlabs/android/dbflow/single/FlowModelViewLoader.java @@ -0,0 +1,28 @@ +package com.raizlabs.android.dbflow.single; + +import android.annotation.TargetApi; +import android.content.Context; + +import com.raizlabs.android.dbflow.config.FlowManager; +import com.raizlabs.android.dbflow.sql.queriable.Queriable; +import com.raizlabs.android.dbflow.structure.BaseModelView; +import com.raizlabs.android.dbflow.structure.InstanceAdapter; +import com.raizlabs.android.dbflow.structure.Model; + +/** + * Utility class to be added to DBFlow. + * + * @param + */ +@TargetApi(11) +public class FlowModelViewLoader > + extends FlowSingleModelLoader +{ + public FlowModelViewLoader (Context context, + Class model, + Class modelView, + Queriable queriable) + { + super (context, model, (InstanceAdapter) FlowManager.getModelViewAdapter (modelView), queriable); + } +} \ No newline at end of file diff --git a/dbflow/src/main/java/com/raizlabs/android/dbflow/single/FlowQueryModelLoader.java b/dbflow/src/main/java/com/raizlabs/android/dbflow/single/FlowQueryModelLoader.java new file mode 100644 index 000000000..79e4a250d --- /dev/null +++ b/dbflow/src/main/java/com/raizlabs/android/dbflow/single/FlowQueryModelLoader.java @@ -0,0 +1,26 @@ +package com.raizlabs.android.dbflow.single; + +import android.annotation.TargetApi; +import android.content.Context; + +import com.raizlabs.android.dbflow.config.FlowManager; +import com.raizlabs.android.dbflow.sql.queriable.Queriable; +import com.raizlabs.android.dbflow.structure.BaseQueryModel; + +/** + * Utility class to be added to DBFlow. + * + * @param + */ +@TargetApi(11) +public class FlowQueryModelLoader + extends FlowSingleModelLoader +{ + public FlowQueryModelLoader (Context context, + Class model, + Queriable queriable) + { + super (context, model, FlowManager.getQueryModelAdapter (model), queriable); + this.setObserveModel (false); + } +} \ No newline at end of file diff --git a/dbflow/src/main/java/com/raizlabs/android/dbflow/single/FlowSingleModelLoader.java b/dbflow/src/main/java/com/raizlabs/android/dbflow/single/FlowSingleModelLoader.java new file mode 100644 index 000000000..a43969436 --- /dev/null +++ b/dbflow/src/main/java/com/raizlabs/android/dbflow/single/FlowSingleModelLoader.java @@ -0,0 +1,167 @@ +package com.raizlabs.android.dbflow.single; + +import android.annotation.TargetApi; +import android.content.Context; +import android.database.Cursor; +import android.net.Uri; +import android.support.v4.content.AsyncTaskLoader; + +import com.raizlabs.android.dbflow.runtime.FlowContentObserver; +import com.raizlabs.android.dbflow.sql.queriable.Queriable; +import com.raizlabs.android.dbflow.structure.InstanceAdapter; +import com.raizlabs.android.dbflow.structure.Model; + +import java.util.HashSet; + +/** + * Utility class to be added to DBFlow. + * + * @param + */ +@TargetApi(11) +public abstract class FlowSingleModelLoader + extends AsyncTaskLoader +{ + /// Models to be observed for changes. + private final Class mModel; + private final InstanceAdapter mAdapter; + + /// Queriable operation that the loader executes. + private Queriable mQueriable; + + /// Cursor for the loader. + private TModel mResult; + + private boolean mObserveModel = true; + + private static final String TAG = "FlowSingleModelLoader"; + + protected HashSet mModels = new HashSet<> (); + + private class ForceLoadContentObserver extends FlowContentObserver + { + @Override + public boolean deliverSelfNotifications () + { + return true; + } + + @Override + public void onChange (boolean selfChange) + { + super.onChange (selfChange); + + onContentChanged (); + } + + @Override + public void onChange (boolean selfChange, Uri uri) + { + super.onChange (selfChange, uri); + + onContentChanged (); + } + } + + protected final FlowContentObserver mObserver = new ForceLoadContentObserver (); + + protected FlowSingleModelLoader (Context context, + Class model, + InstanceAdapter adapter, + Queriable queriable) + { + super (context); + + this.mQueriable = queriable; + this.mModel = model; + this.mAdapter = adapter; + } + + /* Runs on a worker thread */ + @Override + public TModel loadInBackground () + { + Cursor cursor = this.mQueriable.query (); + + if (cursor == null || !cursor.moveToFirst ()) + return null; + + TModel model = this.mAdapter.newInstance (); + this.mAdapter.loadFromCursor (cursor, model); + + return model; + } + + /* Runs on the UI thread */ + @Override + public void deliverResult (TModel result) + { + this.mResult = result; + + if (this.isStarted ()) + super.deliverResult (result); + } + + /** + * Starts an asynchronous load of the contacts list data. When the result is ready the callbacks + * will be called on the UI thread. If a previous load has been completed and is still valid the + * result may be passed to the callbacks immediately. + *

+ * Must be called from the UI thread + */ + @Override + protected void onStartLoading () + { + if (mResult != null) + this.deliverResult (mResult); + + // Start watching for changes to the model. + if (this.mObserveModel) + this.registerForContentChanges (this.mModel); + + if (this.takeContentChanged () || this.mResult == null) + this.forceLoad (); + } + + /** + * Must be called from the UI thread + */ + @Override + protected void onStopLoading () + { + this.cancelLoad (); + } + + @Override + protected void onReset () + { + super.onReset (); + + // Ensure the loader is stopped + this.onStopLoading (); + + if (this.mResult != null) + this.mResult = null; + + // Unregister the loader for content changes. + this.mObserver.unregisterForContentChanges (this.getContext ()); + } + + public Class getModel () + { + return this.mModel; + } + + public void setObserveModel (boolean observeModel) + { + this.mObserveModel = observeModel; + } + + public void registerForContentChanges (Class model) + { + if (this.mModels.contains (model)) + return; + + this.mObserver.registerForContentChanges (this.getContext (), model); + } +} \ No newline at end of file From a7105b4d5bb37ec1252b23be18abe82bbe460a7e Mon Sep 17 00:00:00 2001 From: "James H. Hill" Date: Thu, 4 Aug 2016 14:18:52 -0400 Subject: [PATCH 23/47] Relocated file --- .../android/dbflow/list/FlowModelLoader.java | 139 ------------------ 1 file changed, 139 deletions(-) delete mode 100644 dbflow/src/main/java/com/raizlabs/android/dbflow/list/FlowModelLoader.java diff --git a/dbflow/src/main/java/com/raizlabs/android/dbflow/list/FlowModelLoader.java b/dbflow/src/main/java/com/raizlabs/android/dbflow/list/FlowModelLoader.java deleted file mode 100644 index ebd2c47b5..000000000 --- a/dbflow/src/main/java/com/raizlabs/android/dbflow/list/FlowModelLoader.java +++ /dev/null @@ -1,139 +0,0 @@ -package com.raizlabs.android.dbflow.list; - -import android.annotation.TargetApi; -import android.content.Context; -import android.database.Cursor; -import android.net.Uri; - -import android.support.v4.content.AsyncTaskLoader; - -import com.raizlabs.android.dbflow.config.FlowManager; -import com.raizlabs.android.dbflow.runtime.FlowContentObserver; -import com.raizlabs.android.dbflow.sql.queriable.Queriable; -import com.raizlabs.android.dbflow.structure.Model; -import com.raizlabs.android.dbflow.structure.ModelAdapter; - -/** - * Utility class to be added to DBFlow. - * - * @param - */ -@TargetApi(11) -public class FlowModelLoader extends AsyncTaskLoader -{ - /// Models to be observed for changes. - private final Class mModel; - private final ModelAdapter mModelAdapter; - - /// Queriable operation that the loader executes. - private Queriable mQueriable; - - /// Cursor for the loader. - private TModel mResult; - - private class ForceLoadContentObserver extends FlowContentObserver - { - @Override - public boolean deliverSelfNotifications () - { - return true; - } - - @Override - public void onChange (boolean selfChange) - { - super.onChange (selfChange); - onContentChanged (); - } - - @Override - public void onChange (boolean selfChange, Uri uri) - { - super.onChange (selfChange, uri); - onContentChanged (); - } - } - - private final ForceLoadContentObserver mObserver = new ForceLoadContentObserver (); - - public FlowModelLoader (Context context, Class model, Queriable queriable) - { - super (context); - - this.mQueriable = queriable; - this.mModel = model; - this.mModelAdapter = FlowManager.getModelAdapter (model); - } - - /* Runs on a worker thread */ - @Override - public TModel loadInBackground () - { - Cursor cursor = this.mQueriable.query (); - return cursor != null && cursor.moveToFirst () ? this.mModelAdapter.loadFromCursor (cursor) : null; - } - - /* Runs on the UI thread */ - @Override - public void deliverResult (TModel result) - { - if (this.isReset ()) - return; - - this.mResult = result; - - if (this.isStarted ()) - super.deliverResult (this.mResult); - } - - /** - * Starts an asynchronous load of the contacts list data. When the result is ready the callbacks - * will be called on the UI thread. If a previous load has been completed and is still valid the - * result may be passed to the callbacks immediately. - *

- * Must be called from the UI thread - */ - @Override - protected void onStartLoading () - { - if (mResult != null) - this.deliverResult (mResult); - - if (this.takeContentChanged () || this.mResult == null) - this.forceLoad (); - - this.mObserver.registerForContentChanges (this.getContext (), this.mModel); - } - - /** - * Must be called from the UI thread - */ - @Override - protected void onStopLoading () - { - this.cancelLoad (); - } - - @Override - public void onCanceled (TModel result) - { - mObserver.unregisterForContentChanges (this.getContext ()); - } - - @Override - protected void onReset () - { - super.onReset (); - - // Ensure the loader is stopped - onStopLoading (); - - mResult = null; - mObserver.unregisterForContentChanges (this.getContext ()); - } - - public Class getModel () - { - return this.mModel; - } -} \ No newline at end of file From 1508e0009f749f17a148a65d9ae421dbc734a167 Mon Sep 17 00:00:00 2001 From: "James H. Hill" Date: Thu, 4 Aug 2016 14:19:03 -0400 Subject: [PATCH 24/47] Added support for Travis CI --- .travis.yml | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 000000000..e30e43217 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,44 @@ +language: android +sudo: false + +env: + global: + - ANDROID_BUILD_TOOLS_VERSION=23.0.3 + - ADB_INSTALL_TIMEOUT=10 + + matrix: + - ANDROID_TARGET=android-23 ANDROID_ABI=armeabi-v7a + +android: + components: + # Use the latest revision of Android SDK Tools + - platform-tools + - tools + + # The BuildTools version used by your project + - build-tools-$ANDROID_BUILD_TOOLS_VERSION + + # The SDK version used to compile your project + - $ANDROID_TARGET + + # Additional components + - extra-google-m2repository + - extra-android-m2repository + + # Specify the system image to run emulator during tests + - sys-img-$ANDROID_ABI-$ANDROID_TARGET + +before_script: + # Create and start emulator + - chmod +x gradlew + - pip install --user codecov + - echo no | android create avd --force -n test -t $ANDROID_TARGET --abi $ANDROID_ABI + - emulator -avd test -no-skin -no-audio -no-window & + - android-wait-for-emulator + - adb shell input keyevent 82 & + +script: + - ./gradlew build connectedCheck -PdisablePreDex + +after_success: + - codecov \ No newline at end of file From 464ba50e2021f04cc61917b5e8b0ac8f58141bf2 Mon Sep 17 00:00:00 2001 From: "James H. Hill" Date: Sun, 28 Aug 2016 13:53:38 -0400 Subject: [PATCH 25/47] Moved Travis-CI config to different branch --- .travis.yml | 44 -------------------------------------------- 1 file changed, 44 deletions(-) delete mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index e30e43217..000000000 --- a/.travis.yml +++ /dev/null @@ -1,44 +0,0 @@ -language: android -sudo: false - -env: - global: - - ANDROID_BUILD_TOOLS_VERSION=23.0.3 - - ADB_INSTALL_TIMEOUT=10 - - matrix: - - ANDROID_TARGET=android-23 ANDROID_ABI=armeabi-v7a - -android: - components: - # Use the latest revision of Android SDK Tools - - platform-tools - - tools - - # The BuildTools version used by your project - - build-tools-$ANDROID_BUILD_TOOLS_VERSION - - # The SDK version used to compile your project - - $ANDROID_TARGET - - # Additional components - - extra-google-m2repository - - extra-android-m2repository - - # Specify the system image to run emulator during tests - - sys-img-$ANDROID_ABI-$ANDROID_TARGET - -before_script: - # Create and start emulator - - chmod +x gradlew - - pip install --user codecov - - echo no | android create avd --force -n test -t $ANDROID_TARGET --abi $ANDROID_ABI - - emulator -avd test -no-skin -no-audio -no-window & - - android-wait-for-emulator - - adb shell input keyevent 82 & - -script: - - ./gradlew build connectedCheck -PdisablePreDex - -after_success: - - codecov \ No newline at end of file From f5a5b13473f1f7974e1326f7f9e3ea7719de1879 Mon Sep 17 00:00:00 2001 From: "James H. Hill" Date: Sun, 28 Aug 2016 14:03:12 -0400 Subject: [PATCH 26/47] Moved ExternalForeignKey annotation to its own branch --- .../dbflow/annotation/ExternalForeignKey.java | 41 ------------------- 1 file changed, 41 deletions(-) delete mode 100644 dbflow-core/src/main/java/com/raizlabs/android/dbflow/annotation/ExternalForeignKey.java diff --git a/dbflow-core/src/main/java/com/raizlabs/android/dbflow/annotation/ExternalForeignKey.java b/dbflow-core/src/main/java/com/raizlabs/android/dbflow/annotation/ExternalForeignKey.java deleted file mode 100644 index a6460a523..000000000 --- a/dbflow-core/src/main/java/com/raizlabs/android/dbflow/annotation/ExternalForeignKey.java +++ /dev/null @@ -1,41 +0,0 @@ -package com.raizlabs.android.dbflow.annotation; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * Description: - */ -@Retention(RetentionPolicy.SOURCE) -@Target(ElementType.FIELD) -public @interface ExternalForeignKey { - /** - * @return When this column is a {@link ExternalForeignKey} and a Model, returning true with save the model - * before adding the fields to save as a foreign key. If false, we expect the field to not change - * and must save the model manually outside of the ModelAdapter. This also applies to ModelContainer objects - * as foreign key fields. - */ - boolean saveForeignKeyModel() default true; - - /** - * @return Required table class that this reference points to. - */ - Class tableClass() default Object.class; - - /** - * @return Optional database class that owns the tableClass. This field is necessary if - * the table is in a database that is not defined in the current application, such as - * a module. - */ - Class databaseClass() default Object.class; - - /** - * Defines explicit references for a composite {@link ExternalForeignKey} definition. This is no required - * if the table is imported from a module. - * - * @return the set of explicit references if you wish to have different values than default generated. - */ - ForeignKeyReference[] references() default {}; -} From d983e5f98434af6b8094bc5e7443ade5d48da899 Mon Sep 17 00:00:00 2001 From: "James H. Hill" Date: Sun, 28 Aug 2016 14:10:32 -0400 Subject: [PATCH 27/47] Added documentation; fixed spacing issues --- .../dbflow/list/FlowCursorAdapter.java | 3 +- .../android/dbflow/list/FlowCursorLoader.java | 310 +++++++++--------- .../dbflow/list/FlowSimpleCursorAdapter.java | 5 +- 3 files changed, 160 insertions(+), 158 deletions(-) diff --git a/dbflow/src/main/java/com/raizlabs/android/dbflow/list/FlowCursorAdapter.java b/dbflow/src/main/java/com/raizlabs/android/dbflow/list/FlowCursorAdapter.java index dec6dbadc..7aeed082d 100644 --- a/dbflow/src/main/java/com/raizlabs/android/dbflow/list/FlowCursorAdapter.java +++ b/dbflow/src/main/java/com/raizlabs/android/dbflow/list/FlowCursorAdapter.java @@ -10,7 +10,8 @@ import com.raizlabs.android.dbflow.structure.ModelAdapter; /** - * Specialization of CursorAdapter for DBFLow models. + * Specialization of CursorAdapter for DBFLow models. The getItem() method + * returns a model element instead of a Cursor object. * * @param */ diff --git a/dbflow/src/main/java/com/raizlabs/android/dbflow/list/FlowCursorLoader.java b/dbflow/src/main/java/com/raizlabs/android/dbflow/list/FlowCursorLoader.java index 2be793306..40ed3bf8a 100644 --- a/dbflow/src/main/java/com/raizlabs/android/dbflow/list/FlowCursorLoader.java +++ b/dbflow/src/main/java/com/raizlabs/android/dbflow/list/FlowCursorLoader.java @@ -18,196 +18,196 @@ /** * Specialization of AsyncTaskLoader for Cursor objects in DBFlow. */ -@TargetApi (11) +@TargetApi(11) public class FlowCursorLoader extends AsyncTaskLoader { - private static final String TAG = "FlowCursorLoader"; + private static final String TAG = "FlowCursorLoader"; - /// Models to be observed for changes. - private HashSet> mModels = new HashSet<> (); + /// Models to be observed for changes. + private HashSet> mModels = new HashSet<> (); - /// Queriable operation that the loader executes. - private Queriable mQueriable; + /// Queriable operation that the loader executes. + private Queriable mQueriable; - /// Cursor for the loader. - private Cursor mCursor; + /// Cursor for the loader. + private Cursor mCursor; - private final ForceLoadContentObserver mObserver = new ForceLoadContentObserver (); + private final ForceLoadContentObserver mObserver = new ForceLoadContentObserver (); - private boolean mListening = false; + private boolean mListening = false; - /** - * Creates a fully-specified CursorLoader. See {@link android.content.ContentResolver#query(Uri, - * String[], String, String[], String) ContentResolver.query()} for documentation on the meaning - * of the parameters. These will be passed as-is to that call. - */ - public FlowCursorLoader (Context context, Queriable queriable) - { - super (context); + /** + * Creates a fully-specified CursorLoader. See {@link android.content.ContentResolver#query(Uri, + * String[], String, String[], String) ContentResolver.query()} for documentation on the meaning + * of the parameters. These will be passed as-is to that call. + */ + public FlowCursorLoader (Context context, Queriable queriable) + { + super (context); - this.mQueriable = queriable; - } + this.mQueriable = queriable; + } - @Override - public Cursor loadInBackground () - { - Cursor cursor = this.mQueriable.query (); + @Override + public Cursor loadInBackground () + { + Cursor cursor = this.mQueriable.query (); - if (cursor != null) - cursor.getCount (); + if (cursor != null) + cursor.getCount (); - return cursor; - } + return cursor; + } - @Override - public void deliverResult (Cursor cursor) - { - if (this.isReset ()) + @Override + public void deliverResult (Cursor cursor) { - // An async query came in while the loader is stopped - if (cursor != null) - cursor.close (); + if (this.isReset ()) + { + // An async query came in while the loader is stopped + if (cursor != null) + cursor.close (); + + return; + } + + Cursor oldCursor = this.mCursor; + this.mCursor = cursor; + + if (this.isStarted ()) + super.deliverResult (cursor); + + if (oldCursor != null && oldCursor != cursor && !oldCursor.isClosed ()) + oldCursor.close (); - return; + // Now that the result has been delivered, start listening for changes + // to the target models. Doing this at anytime earlier runs the risk of + // listening for changes while we are still loading content. + this.startListeningForChanges (); } - Cursor oldCursor = this.mCursor; - this.mCursor = cursor; - - if (this.isStarted ()) - super.deliverResult (cursor); - - if (oldCursor != null && oldCursor != cursor && !oldCursor.isClosed ()) - oldCursor.close (); - - // Now that the result has been delivered, start listening for changes - // to the target models. Doing this at anytime earlier runs the risk of - // listening for changes while we are still loading content. - this.startListeningForChanges (); - } - - /** - * Register the loader for changes to a Flow model. When changes to the model are - * detected, then the loader will automatically reload the content. - * - * @param model - */ - public void registerForContentChanges (Class model) - { - if (this.mModels.contains (model)) - return; - - this.mModels.add (model); - this.mObserver.registerForContentChanges (this.getContext (), model); - } - - @Override - protected void onStartLoading () - { - if (this.mCursor != null) - this.deliverResult (this.mCursor); - - if (this.takeContentChanged () || this.mCursor == null) - this.forceLoad (); - } - - @Override - protected void onStopLoading () - { - // Make sure the loading has stopped. - this.cancelLoad (); - } - - @Override - public void onCanceled (Cursor cursor) - { - if (cursor != null && !cursor.isClosed ()) - cursor.close (); - - this.stopListeningForChanges (); - } - - @Override - protected void onReset () - { - super.onReset (); - - this.startLoading (); - - if (mCursor != null && !mCursor.isClosed ()) - mCursor.close (); - - mCursor = null; - - this.mObserver.unregisterForContentChanges (this.getContext ()); - } - - private void startListeningForChanges () - { - if (!this.mListening) + /** + * Register the loader for changes to a Flow model. When changes to the model are + * detected, then the loader will automatically reload the content. + * + * @param model + */ + public void registerForContentChanges (Class model) { - this.mObserver.addModelChangeListener (this.mObserver); - this.mListening = true; + if (this.mModels.contains (model)) + return; + + this.mModels.add (model); + this.mObserver.registerForContentChanges (this.getContext (), model); } - } - private void stopListeningForChanges () - { - if (this.mListening) + @Override + protected void onStartLoading () { - this.mObserver.removeModelChangeListener (this.mObserver); - this.mListening = false; + if (this.mCursor != null) + this.deliverResult (this.mCursor); + + if (this.takeContentChanged () || this.mCursor == null) + this.forceLoad (); } - } - public Collection> getModels () - { - return this.mModels; - } + @Override + protected void onStopLoading () + { + // Make sure the loading has stopped. + this.cancelLoad (); + } - public FlowContentObserver getContentObserver () - { - return this.mObserver; - } + @Override + public void onCanceled (Cursor cursor) + { + if (cursor != null && !cursor.isClosed ()) + cursor.close (); - final class ForceLoadContentObserver extends FlowContentObserver - implements FlowContentObserver.OnModelStateChangedListener - { - private boolean endOfTransaction = false; + this.stopListeningForChanges (); + } @Override - public boolean deliverSelfNotifications () + protected void onReset () { - return false; + super.onReset (); + + this.startLoading (); + + if (mCursor != null && !mCursor.isClosed ()) + mCursor.close (); + + mCursor = null; + + this.mObserver.unregisterForContentChanges (this.getContext ()); } - @Override - public void onModelStateChanged (Class table, - BaseModel.Action action, - SQLCondition[] primaryKeyValues) + private void startListeningForChanges () { - if (!this.endOfTransaction) - { - if (action == BaseModel.Action.INSERT || - action == BaseModel.Action.DELETE || - action == BaseModel.Action.UPDATE) + if (!this.mListening) { - onContentChanged (); + this.mObserver.addModelChangeListener (this.mObserver); + this.mListening = true; } - } } - @Override - public void endTransactionAndNotify () + private void stopListeningForChanges () + { + if (this.mListening) + { + this.mObserver.removeModelChangeListener (this.mObserver); + this.mListening = false; + } + } + + public Collection> getModels () + { + return this.mModels; + } + + public FlowContentObserver getContentObserver () { - // Mark this as the end of a transactions, and pass control to the base class - // to perform the notifications. - this.endOfTransaction = true; - super.endTransactionAndNotify (); - - // Notify the observer the content has changed. - this.endOfTransaction = false; - onContentChanged (); + return this.mObserver; + } + + final class ForceLoadContentObserver extends FlowContentObserver + implements FlowContentObserver.OnModelStateChangedListener + { + private boolean endOfTransaction = false; + + @Override + public boolean deliverSelfNotifications () + { + return false; + } + + @Override + public void onModelStateChanged (Class table, + BaseModel.Action action, + SQLCondition[] primaryKeyValues) + { + if (!this.endOfTransaction) + { + if (action == BaseModel.Action.INSERT || + action == BaseModel.Action.DELETE || + action == BaseModel.Action.UPDATE) + { + onContentChanged (); + } + } + } + + @Override + public void endTransactionAndNotify () + { + // Mark this as the end of a transactions, and pass control to the base class + // to perform the notifications. + this.endOfTransaction = true; + super.endTransactionAndNotify (); + + // Notify the observer the content has changed. + this.endOfTransaction = false; + onContentChanged (); + } } - } } \ No newline at end of file diff --git a/dbflow/src/main/java/com/raizlabs/android/dbflow/list/FlowSimpleCursorAdapter.java b/dbflow/src/main/java/com/raizlabs/android/dbflow/list/FlowSimpleCursorAdapter.java index 8151028ff..baf805afe 100644 --- a/dbflow/src/main/java/com/raizlabs/android/dbflow/list/FlowSimpleCursorAdapter.java +++ b/dbflow/src/main/java/com/raizlabs/android/dbflow/list/FlowSimpleCursorAdapter.java @@ -11,7 +11,8 @@ import com.raizlabs.android.dbflow.structure.ModelAdapter; /** - * Utility class to be added to DBFlow. + * Specialization of SimpleCursorAdapter designed for DBFlow. The getItem() method + * return a model element instead of a Cursor element. * * @param */ @@ -20,7 +21,7 @@ public class FlowSimpleCursorAdapter extends SimpleCursor private final Class mModel; private final ModelAdapter mModelAdapter; - @TargetApi (11) + @TargetApi(11) public FlowSimpleCursorAdapter (Context context, Class modelClass, int layout, Cursor c, String[] from, int[] to, int flags) { super (context, layout, c, from, to, flags); From 9632cd8d2fdbd05a571fc59888f881956a1547bb Mon Sep 17 00:00:00 2001 From: "James H. Hill" Date: Sun, 28 Aug 2016 14:30:05 -0400 Subject: [PATCH 28/47] Fixed format --- .../dbflow/single/FlowModelLoader.java | 11 +- .../dbflow/single/FlowModelViewLoader.java | 17 +- .../dbflow/single/FlowQueryModelLoader.java | 18 +- .../dbflow/single/FlowSingleModelLoader.java | 252 +++++++++--------- 4 files changed, 143 insertions(+), 155 deletions(-) diff --git a/dbflow/src/main/java/com/raizlabs/android/dbflow/single/FlowModelLoader.java b/dbflow/src/main/java/com/raizlabs/android/dbflow/single/FlowModelLoader.java index 91b4fb216..562dde928 100644 --- a/dbflow/src/main/java/com/raizlabs/android/dbflow/single/FlowModelLoader.java +++ b/dbflow/src/main/java/com/raizlabs/android/dbflow/single/FlowModelLoader.java @@ -14,10 +14,9 @@ */ @TargetApi(11) public class FlowModelLoader - extends FlowSingleModelLoader -{ - public FlowModelLoader (Context context, Class model, Queriable queriable) - { - super (context, model, FlowManager.getModelAdapter (model), queriable); - } + extends FlowSingleModelLoader { + + public FlowModelLoader (Context context, Class model, Queriable queriable) { + super (context, model, FlowManager.getModelAdapter (model), queriable); + } } \ No newline at end of file diff --git a/dbflow/src/main/java/com/raizlabs/android/dbflow/single/FlowModelViewLoader.java b/dbflow/src/main/java/com/raizlabs/android/dbflow/single/FlowModelViewLoader.java index 1903c76f8..1d4396f6c 100644 --- a/dbflow/src/main/java/com/raizlabs/android/dbflow/single/FlowModelViewLoader.java +++ b/dbflow/src/main/java/com/raizlabs/android/dbflow/single/FlowModelViewLoader.java @@ -10,19 +10,16 @@ import com.raizlabs.android.dbflow.structure.Model; /** - * Utility class to be added to DBFlow. + * Load a single DBFlow model from a ViewModel. * * @param */ @TargetApi(11) public class FlowModelViewLoader > - extends FlowSingleModelLoader -{ - public FlowModelViewLoader (Context context, - Class model, - Class modelView, - Queriable queriable) - { - super (context, model, (InstanceAdapter) FlowManager.getModelViewAdapter (modelView), queriable); - } + extends FlowSingleModelLoader { + + @SuppressWarnings ("unchecked") + public FlowModelViewLoader (Context context, Class model, Class modelView, Queriable queriable) { + super (context, model, (InstanceAdapter) FlowManager.getModelViewAdapter (modelView), queriable); + } } \ No newline at end of file diff --git a/dbflow/src/main/java/com/raizlabs/android/dbflow/single/FlowQueryModelLoader.java b/dbflow/src/main/java/com/raizlabs/android/dbflow/single/FlowQueryModelLoader.java index 79e4a250d..15087fd0a 100644 --- a/dbflow/src/main/java/com/raizlabs/android/dbflow/single/FlowQueryModelLoader.java +++ b/dbflow/src/main/java/com/raizlabs/android/dbflow/single/FlowQueryModelLoader.java @@ -8,19 +8,17 @@ import com.raizlabs.android.dbflow.structure.BaseQueryModel; /** - * Utility class to be added to DBFlow. + * Load a single DBFlow model from a QueryModel. * * @param */ @TargetApi(11) public class FlowQueryModelLoader - extends FlowSingleModelLoader -{ - public FlowQueryModelLoader (Context context, - Class model, - Queriable queriable) - { - super (context, model, FlowManager.getQueryModelAdapter (model), queriable); - this.setObserveModel (false); - } + extends FlowSingleModelLoader { + + public FlowQueryModelLoader (Context context, Class model, Queriable queriable) { + super (context, model, FlowManager.getQueryModelAdapter (model), queriable); + + this.setObserveModel (false); + } } \ No newline at end of file diff --git a/dbflow/src/main/java/com/raizlabs/android/dbflow/single/FlowSingleModelLoader.java b/dbflow/src/main/java/com/raizlabs/android/dbflow/single/FlowSingleModelLoader.java index a43969436..924f011b9 100644 --- a/dbflow/src/main/java/com/raizlabs/android/dbflow/single/FlowSingleModelLoader.java +++ b/dbflow/src/main/java/com/raizlabs/android/dbflow/single/FlowSingleModelLoader.java @@ -14,154 +14,148 @@ import java.util.HashSet; /** - * Utility class to be added to DBFlow. + * Abstract class for all DBFlow Loader classes that return a single + * model element. * * @param */ @TargetApi(11) public abstract class FlowSingleModelLoader - extends AsyncTaskLoader -{ - /// Models to be observed for changes. - private final Class mModel; - private final InstanceAdapter mAdapter; + extends AsyncTaskLoader { - /// Queriable operation that the loader executes. - private Queriable mQueriable; + /// Model type being loaded. + private final Class mModel; - /// Cursor for the loader. - private TModel mResult; + /// Adapter for converting cursor into target model. + private final InstanceAdapter mAdapter; - private boolean mObserveModel = true; + /// Queriable operation that the loader executes. + private Queriable mQueriable; - private static final String TAG = "FlowSingleModelLoader"; + /// Cursor for the loader. + private TModel mResult; - protected HashSet mModels = new HashSet<> (); + /// Observe changes to the model. + private boolean mObserveModel = true; - private class ForceLoadContentObserver extends FlowContentObserver - { + /// Collection of models to be observed. + protected HashSet mModels = new HashSet<> (); + + private class ForceLoadContentObserver extends FlowContentObserver { + @Override + public boolean deliverSelfNotifications () { + return true; + } + + @Override + public void onChange (boolean selfChange) { + super.onChange (selfChange); + + onContentChanged (); + } + + @Override + public void onChange (boolean selfChange, Uri uri) { + super.onChange (selfChange, uri); + + onContentChanged (); + } + } + + protected final FlowContentObserver mObserver = new ForceLoadContentObserver (); + + protected FlowSingleModelLoader (Context context, Class model, InstanceAdapter adapter, Queriable queriable) { + super (context); + + this.mQueriable = queriable; + this.mModel = model; + this.mAdapter = adapter; + } + + /* Runs on a worker thread */ @Override - public boolean deliverSelfNotifications () - { - return true; + public TModel loadInBackground () { + Cursor cursor = this.mQueriable.query (); + + if (cursor == null || !cursor.moveToFirst ()) { + return null; + } + + TModel model = this.mAdapter.newInstance (); + this.mAdapter.loadFromCursor (cursor, model); + + return model; } + /* Runs on the UI thread */ @Override - public void onChange (boolean selfChange) - { - super.onChange (selfChange); + public void deliverResult (TModel result) { + this.mResult = result; - onContentChanged (); + if (this.isStarted ()) { + super.deliverResult (result); + } } + /** + * Starts an asynchronous load of the contacts list data. When the result is ready the callbacks + * will be called on the UI thread. If a previous load has been completed and is still valid the + * result may be passed to the callbacks immediately. + *

+ * Must be called from the UI thread + */ @Override - public void onChange (boolean selfChange, Uri uri) - { - super.onChange (selfChange, uri); + protected void onStartLoading () { + if (mResult != null) { + this.deliverResult (mResult); + } + + // Start watching for changes to the model. + if (this.mObserveModel) { + this.registerForContentChanges (this.mModel); + } + + if (this.takeContentChanged () || this.mResult == null) { + this.forceLoad (); + } + } + + /** + * Must be called from the UI thread + */ + @Override + protected void onStopLoading () { + this.cancelLoad (); + } + + @Override + protected void onReset () { + super.onReset (); + + // Ensure the loader is stopped + this.onStopLoading (); + + if (this.mResult != null) { + this.mResult = null; + } + + // Unregister the loader for content changes. + this.mObserver.unregisterForContentChanges (this.getContext ()); + } + + public Class getModel () { + return this.mModel; + } + + public void setObserveModel (boolean observeModel) { + this.mObserveModel = observeModel; + } + + public void registerForContentChanges (Class model) { + if (this.mModels.contains (model)) { + return; + } - onContentChanged (); + this.mObserver.registerForContentChanges (this.getContext (), model); } - } - - protected final FlowContentObserver mObserver = new ForceLoadContentObserver (); - - protected FlowSingleModelLoader (Context context, - Class model, - InstanceAdapter adapter, - Queriable queriable) - { - super (context); - - this.mQueriable = queriable; - this.mModel = model; - this.mAdapter = adapter; - } - - /* Runs on a worker thread */ - @Override - public TModel loadInBackground () - { - Cursor cursor = this.mQueriable.query (); - - if (cursor == null || !cursor.moveToFirst ()) - return null; - - TModel model = this.mAdapter.newInstance (); - this.mAdapter.loadFromCursor (cursor, model); - - return model; - } - - /* Runs on the UI thread */ - @Override - public void deliverResult (TModel result) - { - this.mResult = result; - - if (this.isStarted ()) - super.deliverResult (result); - } - - /** - * Starts an asynchronous load of the contacts list data. When the result is ready the callbacks - * will be called on the UI thread. If a previous load has been completed and is still valid the - * result may be passed to the callbacks immediately. - *

- * Must be called from the UI thread - */ - @Override - protected void onStartLoading () - { - if (mResult != null) - this.deliverResult (mResult); - - // Start watching for changes to the model. - if (this.mObserveModel) - this.registerForContentChanges (this.mModel); - - if (this.takeContentChanged () || this.mResult == null) - this.forceLoad (); - } - - /** - * Must be called from the UI thread - */ - @Override - protected void onStopLoading () - { - this.cancelLoad (); - } - - @Override - protected void onReset () - { - super.onReset (); - - // Ensure the loader is stopped - this.onStopLoading (); - - if (this.mResult != null) - this.mResult = null; - - // Unregister the loader for content changes. - this.mObserver.unregisterForContentChanges (this.getContext ()); - } - - public Class getModel () - { - return this.mModel; - } - - public void setObserveModel (boolean observeModel) - { - this.mObserveModel = observeModel; - } - - public void registerForContentChanges (Class model) - { - if (this.mModels.contains (model)) - return; - - this.mObserver.registerForContentChanges (this.getContext (), model); - } } \ No newline at end of file From 7d79b78c0eed704c47005a959a50177c7a685d0b Mon Sep 17 00:00:00 2001 From: "James H. Hill" Date: Sun, 28 Aug 2016 14:31:57 -0400 Subject: [PATCH 29/47] Fixed format --- .../android/dbflow/list/FlowCursorLoader.java | 97 ++++++++----------- 1 file changed, 40 insertions(+), 57 deletions(-) diff --git a/dbflow/src/main/java/com/raizlabs/android/dbflow/list/FlowCursorLoader.java b/dbflow/src/main/java/com/raizlabs/android/dbflow/list/FlowCursorLoader.java index 40ed3bf8a..145e58160 100644 --- a/dbflow/src/main/java/com/raizlabs/android/dbflow/list/FlowCursorLoader.java +++ b/dbflow/src/main/java/com/raizlabs/android/dbflow/list/FlowCursorLoader.java @@ -19,10 +19,7 @@ * Specialization of AsyncTaskLoader for Cursor objects in DBFlow. */ @TargetApi(11) -public class FlowCursorLoader extends AsyncTaskLoader -{ - private static final String TAG = "FlowCursorLoader"; - +public class FlowCursorLoader extends AsyncTaskLoader { /// Models to be observed for changes. private HashSet> mModels = new HashSet<> (); @@ -41,32 +38,30 @@ public class FlowCursorLoader extends AsyncTaskLoader * String[], String, String[], String) ContentResolver.query()} for documentation on the meaning * of the parameters. These will be passed as-is to that call. */ - public FlowCursorLoader (Context context, Queriable queriable) - { + public FlowCursorLoader (Context context, Queriable queriable) { super (context); this.mQueriable = queriable; } @Override - public Cursor loadInBackground () - { + public Cursor loadInBackground () { Cursor cursor = this.mQueriable.query (); - if (cursor != null) + if (cursor != null) { cursor.getCount (); + } return cursor; } @Override - public void deliverResult (Cursor cursor) - { - if (this.isReset ()) - { + public void deliverResult (Cursor cursor) { + if (this.isReset ()) { // An async query came in while the loader is stopped - if (cursor != null) + if (cursor != null) { cursor.close (); + } return; } @@ -74,11 +69,13 @@ public void deliverResult (Cursor cursor) Cursor oldCursor = this.mCursor; this.mCursor = cursor; - if (this.isStarted ()) + if (this.isStarted ()) { super.deliverResult (cursor); + } - if (oldCursor != null && oldCursor != cursor && !oldCursor.isClosed ()) + if (oldCursor != null && oldCursor != cursor && !oldCursor.isClosed ()) { oldCursor.close (); + } // Now that the result has been delivered, start listening for changes // to the target models. Doing this at anytime earlier runs the risk of @@ -92,114 +89,100 @@ public void deliverResult (Cursor cursor) * * @param model */ - public void registerForContentChanges (Class model) - { - if (this.mModels.contains (model)) + public void registerForContentChanges (Class model) { + if (this.mModels.contains (model)) { return; + } this.mModels.add (model); this.mObserver.registerForContentChanges (this.getContext (), model); } @Override - protected void onStartLoading () - { - if (this.mCursor != null) + protected void onStartLoading () { + if (this.mCursor != null) { this.deliverResult (this.mCursor); + } - if (this.takeContentChanged () || this.mCursor == null) + if (this.takeContentChanged () || this.mCursor == null) { this.forceLoad (); + } } @Override - protected void onStopLoading () - { + protected void onStopLoading () { // Make sure the loading has stopped. this.cancelLoad (); } @Override - public void onCanceled (Cursor cursor) - { - if (cursor != null && !cursor.isClosed ()) + public void onCanceled (Cursor cursor) { + if (cursor != null && !cursor.isClosed ()) { cursor.close (); + } this.stopListeningForChanges (); } @Override - protected void onReset () - { + protected void onReset () { super.onReset (); this.startLoading (); - if (mCursor != null && !mCursor.isClosed ()) + if (mCursor != null && !mCursor.isClosed ()) { mCursor.close (); + } mCursor = null; this.mObserver.unregisterForContentChanges (this.getContext ()); } - private void startListeningForChanges () - { - if (!this.mListening) - { + private void startListeningForChanges () { + if (!this.mListening) { this.mObserver.addModelChangeListener (this.mObserver); this.mListening = true; } } - private void stopListeningForChanges () - { - if (this.mListening) - { + private void stopListeningForChanges () { + if (this.mListening) { this.mObserver.removeModelChangeListener (this.mObserver); this.mListening = false; } } - public Collection> getModels () - { + public Collection> getModels () { return this.mModels; } - public FlowContentObserver getContentObserver () - { + public FlowContentObserver getContentObserver () { return this.mObserver; } final class ForceLoadContentObserver extends FlowContentObserver - implements FlowContentObserver.OnModelStateChangedListener - { + implements FlowContentObserver.OnModelStateChangedListener { private boolean endOfTransaction = false; @Override - public boolean deliverSelfNotifications () - { + public boolean deliverSelfNotifications () { return false; } @Override public void onModelStateChanged (Class table, BaseModel.Action action, - SQLCondition[] primaryKeyValues) - { - if (!this.endOfTransaction) - { - if (action == BaseModel.Action.INSERT || - action == BaseModel.Action.DELETE || - action == BaseModel.Action.UPDATE) - { + SQLCondition[] primaryKeyValues) { + if (!this.endOfTransaction) { + if (action == BaseModel.Action.INSERT || action == BaseModel.Action.DELETE || action == BaseModel.Action.UPDATE) { onContentChanged (); } } } @Override - public void endTransactionAndNotify () - { + public void endTransactionAndNotify () { // Mark this as the end of a transactions, and pass control to the base class // to perform the notifications. this.endOfTransaction = true; From aa85b794266e73539ebe36fbadbcdd4725940bc3 Mon Sep 17 00:00:00 2001 From: "James H. Hill" Date: Sun, 28 Aug 2016 14:33:42 -0400 Subject: [PATCH 30/47] Removed unused variables; fixed formatting --- .../dbflow/list/FlowCursorAdapter.java | 23 +++++++------------ 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/dbflow/src/main/java/com/raizlabs/android/dbflow/list/FlowCursorAdapter.java b/dbflow/src/main/java/com/raizlabs/android/dbflow/list/FlowCursorAdapter.java index 7aeed082d..c85a0fd4e 100644 --- a/dbflow/src/main/java/com/raizlabs/android/dbflow/list/FlowCursorAdapter.java +++ b/dbflow/src/main/java/com/raizlabs/android/dbflow/list/FlowCursorAdapter.java @@ -15,32 +15,25 @@ * * @param */ -public abstract class FlowCursorAdapter extends CursorAdapter -{ - private final Class modelClass_; - private final ModelAdapter modelAdapter_; +public abstract class FlowCursorAdapter extends CursorAdapter { + private final ModelAdapter mModelAdapter_; - public FlowCursorAdapter (Context context, Class modelClass, Cursor c, boolean autoRequery) - { + public FlowCursorAdapter (Context context, Class modelClass, Cursor c, boolean autoRequery) { super (context, c, autoRequery); - this.modelClass_ = modelClass; - this.modelAdapter_ = FlowManager.getModelAdapter (modelClass); + this.mModelAdapter_ = FlowManager.getModelAdapter (modelClass); } @TargetApi(11) - public FlowCursorAdapter (Context context, Class modelClass, Cursor c, int flags) - { + public FlowCursorAdapter (Context context, Class modelClass, Cursor c, int flags) { super (context, c, flags); - this.modelClass_ = modelClass; - this.modelAdapter_ = FlowManager.getModelAdapter (modelClass); + this.mModelAdapter_ = FlowManager.getModelAdapter (modelClass); } @Override - public TModel getItem (int position) - { + public TModel getItem (int position) { Cursor cursor = (Cursor) super.getItem (position); - return cursor != null ? this.modelAdapter_.loadFromCursor (cursor) : null; + return cursor != null ? this.mModelAdapter_.loadFromCursor (cursor) : null; } } From 344a9a5947c428076236bf99e442431c6c735e28 Mon Sep 17 00:00:00 2001 From: "James H. Hill" Date: Mon, 28 Nov 2016 22:20:45 -0500 Subject: [PATCH 31/47] Fixed build error --- .../android/dbflow/processor/definition/TableDefinition.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/dbflow-processor/src/main/java/com/raizlabs/android/dbflow/processor/definition/TableDefinition.java b/dbflow-processor/src/main/java/com/raizlabs/android/dbflow/processor/definition/TableDefinition.java index 72838a1bd..32f8d3ff1 100644 --- a/dbflow-processor/src/main/java/com/raizlabs/android/dbflow/processor/definition/TableDefinition.java +++ b/dbflow-processor/src/main/java/com/raizlabs/android/dbflow/processor/definition/TableDefinition.java @@ -5,7 +5,6 @@ import com.raizlabs.android.dbflow.annotation.Column; import com.raizlabs.android.dbflow.annotation.ConflictAction; import com.raizlabs.android.dbflow.annotation.ContainerKey; -import com.raizlabs.android.dbflow.annotation.ExternalForeignKey; import com.raizlabs.android.dbflow.annotation.ForeignKey; import com.raizlabs.android.dbflow.annotation.IndexGroup; import com.raizlabs.android.dbflow.annotation.InheritedColumn; @@ -339,7 +338,6 @@ protected void createColumnDefinitions(TypeElement typeElement) { boolean isPackagePrivateNotInSamePackage = isPackagePrivate && !ElementUtility.isInSamePackage(manager, element, this.element); boolean isForeign = element.getAnnotation(ForeignKey.class) != null; - boolean isExternalForeign = element.getAnnotation(ExternalForeignKey.class) != null; boolean isPrimary = element.getAnnotation(PrimaryKey.class) != null; boolean isInherited = inheritedColumnMap.containsKey(element.getSimpleName().toString()); boolean isInheritedPrimaryKey = inheritedPrimaryKeyMap.containsKey(element.getSimpleName().toString()); From a1b948505a42e47ca8317f07b2c55980427b9978 Mon Sep 17 00:00:00 2001 From: "James H. Hill" Date: Wed, 30 Nov 2016 19:13:57 -0500 Subject: [PATCH 32/47] Fixed build errors related to updates to raizlabs/develop --- .../android/dbflow/list/FlowCursorLoader.java | 13 +++++++------ .../android/dbflow/single/FlowModelLoader.java | 2 +- .../android/dbflow/single/FlowModelViewLoader.java | 6 +++--- .../dbflow/single/FlowSingleModelLoader.java | 12 ++++++------ 4 files changed, 17 insertions(+), 16 deletions(-) diff --git a/dbflow/src/main/java/com/raizlabs/android/dbflow/list/FlowCursorLoader.java b/dbflow/src/main/java/com/raizlabs/android/dbflow/list/FlowCursorLoader.java index 145e58160..d47588d4d 100644 --- a/dbflow/src/main/java/com/raizlabs/android/dbflow/list/FlowCursorLoader.java +++ b/dbflow/src/main/java/com/raizlabs/android/dbflow/list/FlowCursorLoader.java @@ -1,10 +1,12 @@ package com.raizlabs.android.dbflow.list; import android.annotation.TargetApi; +import android.content.AsyncTaskLoader; import android.content.Context; import android.database.Cursor; import android.net.Uri; -import android.support.v4.content.AsyncTaskLoader; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; import com.raizlabs.android.dbflow.runtime.FlowContentObserver; import com.raizlabs.android.dbflow.sql.language.SQLCondition; @@ -19,7 +21,8 @@ * Specialization of AsyncTaskLoader for Cursor objects in DBFlow. */ @TargetApi(11) -public class FlowCursorLoader extends AsyncTaskLoader { +public class FlowCursorLoader extends AsyncTaskLoader +{ /// Models to be observed for changes. private HashSet> mModels = new HashSet<> (); @@ -161,7 +164,7 @@ public FlowContentObserver getContentObserver () { return this.mObserver; } - final class ForceLoadContentObserver extends FlowContentObserver + private final class ForceLoadContentObserver extends FlowContentObserver implements FlowContentObserver.OnModelStateChangedListener { private boolean endOfTransaction = false; @@ -171,9 +174,7 @@ public boolean deliverSelfNotifications () { } @Override - public void onModelStateChanged (Class table, - BaseModel.Action action, - SQLCondition[] primaryKeyValues) { + public void onModelStateChanged (@Nullable Class table, BaseModel.Action action, @NonNull SQLCondition[] primaryKeyValues) { if (!this.endOfTransaction) { if (action == BaseModel.Action.INSERT || action == BaseModel.Action.DELETE || action == BaseModel.Action.UPDATE) { onContentChanged (); diff --git a/dbflow/src/main/java/com/raizlabs/android/dbflow/single/FlowModelLoader.java b/dbflow/src/main/java/com/raizlabs/android/dbflow/single/FlowModelLoader.java index 562dde928..579a964f2 100644 --- a/dbflow/src/main/java/com/raizlabs/android/dbflow/single/FlowModelLoader.java +++ b/dbflow/src/main/java/com/raizlabs/android/dbflow/single/FlowModelLoader.java @@ -14,7 +14,7 @@ */ @TargetApi(11) public class FlowModelLoader - extends FlowSingleModelLoader { + extends FlowSingleModelLoader { public FlowModelLoader (Context context, Class model, Queriable queriable) { super (context, model, FlowManager.getModelAdapter (model), queriable); diff --git a/dbflow/src/main/java/com/raizlabs/android/dbflow/single/FlowModelViewLoader.java b/dbflow/src/main/java/com/raizlabs/android/dbflow/single/FlowModelViewLoader.java index 1d4396f6c..3f9ef4c88 100644 --- a/dbflow/src/main/java/com/raizlabs/android/dbflow/single/FlowModelViewLoader.java +++ b/dbflow/src/main/java/com/raizlabs/android/dbflow/single/FlowModelViewLoader.java @@ -15,11 +15,11 @@ * @param */ @TargetApi(11) -public class FlowModelViewLoader > - extends FlowSingleModelLoader { +public class FlowModelViewLoader + extends FlowSingleModelLoader { @SuppressWarnings ("unchecked") public FlowModelViewLoader (Context context, Class model, Class modelView, Queriable queriable) { - super (context, model, (InstanceAdapter) FlowManager.getModelViewAdapter (modelView), queriable); + super (context, model, (InstanceAdapter) FlowManager.getModelViewAdapter (modelView), queriable); } } \ No newline at end of file diff --git a/dbflow/src/main/java/com/raizlabs/android/dbflow/single/FlowSingleModelLoader.java b/dbflow/src/main/java/com/raizlabs/android/dbflow/single/FlowSingleModelLoader.java index 924f011b9..db61f4bea 100644 --- a/dbflow/src/main/java/com/raizlabs/android/dbflow/single/FlowSingleModelLoader.java +++ b/dbflow/src/main/java/com/raizlabs/android/dbflow/single/FlowSingleModelLoader.java @@ -1,10 +1,10 @@ package com.raizlabs.android.dbflow.single; import android.annotation.TargetApi; +import android.content.AsyncTaskLoader; import android.content.Context; import android.database.Cursor; import android.net.Uri; -import android.support.v4.content.AsyncTaskLoader; import com.raizlabs.android.dbflow.runtime.FlowContentObserver; import com.raizlabs.android.dbflow.sql.queriable.Queriable; @@ -20,14 +20,14 @@ * @param */ @TargetApi(11) -public abstract class FlowSingleModelLoader - extends AsyncTaskLoader { - +public abstract class FlowSingleModelLoader + extends AsyncTaskLoader +{ /// Model type being loaded. private final Class mModel; /// Adapter for converting cursor into target model. - private final InstanceAdapter mAdapter; + private final InstanceAdapter mAdapter; /// Queriable operation that the loader executes. private Queriable mQueriable; @@ -64,7 +64,7 @@ public void onChange (boolean selfChange, Uri uri) { protected final FlowContentObserver mObserver = new ForceLoadContentObserver (); - protected FlowSingleModelLoader (Context context, Class model, InstanceAdapter adapter, Queriable queriable) { + protected FlowSingleModelLoader (Context context, Class model, InstanceAdapter adapter, Queriable queriable) { super (context); this.mQueriable = queriable; From 56392adc07d98a8322f618b74b4b6bdca21b4dc7 Mon Sep 17 00:00:00 2001 From: "James H. Hill" Date: Wed, 30 Nov 2016 19:25:37 -0500 Subject: [PATCH 33/47] Fixed merge conflicts --- .../kotlinextensions/PropertyExtensions.kt | 8 - .../PropertyMethodExtensions.kt | 39 - .../kotlinextensions/QueryExtensions.kt | 112 --- .../definition/ModelContainerDefinition.java | 109 --- .../processor/definition/TableDefinition.java | 702 ------------------ .../column/ForeignKeyColumnDefinition.java | 586 --------------- .../column/ForeignKeyReferenceDefinition.java | 209 ------ .../ExternalForeignKeyContainerMethod.java | 45 -- .../dbflow/single/FlowQueryModelLoader.java | 2 +- .../container/ForeignKeyContainer.java | 147 ---- 10 files changed, 1 insertion(+), 1958 deletions(-) delete mode 100644 dbflow-processor/src/main/java/com/raizlabs/android/dbflow/processor/definition/ModelContainerDefinition.java delete mode 100644 dbflow-processor/src/main/java/com/raizlabs/android/dbflow/processor/definition/TableDefinition.java delete mode 100644 dbflow-processor/src/main/java/com/raizlabs/android/dbflow/processor/definition/column/ForeignKeyColumnDefinition.java delete mode 100644 dbflow-processor/src/main/java/com/raizlabs/android/dbflow/processor/definition/column/ForeignKeyReferenceDefinition.java delete mode 100644 dbflow-processor/src/main/java/com/raizlabs/android/dbflow/processor/definition/method/ExternalForeignKeyContainerMethod.java delete mode 100644 dbflow/src/main/java/com/raizlabs/android/dbflow/structure/container/ForeignKeyContainer.java diff --git a/dbflow-kotlinextensions/src/main/java/com/raizlabs/android/dbflow/kotlinextensions/PropertyExtensions.kt b/dbflow-kotlinextensions/src/main/java/com/raizlabs/android/dbflow/kotlinextensions/PropertyExtensions.kt index 5f48a4a2c..4ea1829a7 100644 --- a/dbflow-kotlinextensions/src/main/java/com/raizlabs/android/dbflow/kotlinextensions/PropertyExtensions.kt +++ b/dbflow-kotlinextensions/src/main/java/com/raizlabs/android/dbflow/kotlinextensions/PropertyExtensions.kt @@ -2,7 +2,6 @@ package com.raizlabs.android.dbflow.kotlinextensions import com.raizlabs.android.dbflow.sql.language.property.* import com.raizlabs.android.dbflow.sql.queriable.ModelQueriable -import com.raizlabs.android.dbflow.structure.Model /** * Description: Provides some very nice Property class extensions. @@ -29,17 +28,10 @@ val Short.property: ShortProperty val Byte.property: ByteProperty get() = PropertyFactory.from(this) -<<<<<<< HEAD -val TModel.property: Property - get() = PropertyFactory.from(this) - -val ModelQueriable.property: Property -======= val T.property: Property get() = PropertyFactory.from(this) val ModelQueriable.property: Property ->>>>>>> raizlabs/develop get() = PropertyFactory.from(this) inline fun TModel.propertyString(stringRepresentation: String?): Property { diff --git a/dbflow-kotlinextensions/src/main/java/com/raizlabs/android/dbflow/kotlinextensions/PropertyMethodExtensions.kt b/dbflow-kotlinextensions/src/main/java/com/raizlabs/android/dbflow/kotlinextensions/PropertyMethodExtensions.kt index e3bcdda53..a46cf68be 100644 --- a/dbflow-kotlinextensions/src/main/java/com/raizlabs/android/dbflow/kotlinextensions/PropertyMethodExtensions.kt +++ b/dbflow-kotlinextensions/src/main/java/com/raizlabs/android/dbflow/kotlinextensions/PropertyMethodExtensions.kt @@ -9,32 +9,6 @@ import com.raizlabs.android.dbflow.structure.Model /** * Description: Provides property methods in via infix functions. */ - -<<<<<<< HEAD -infix fun Property.eq(value: TModel) = this.eq(value) - -infix fun Property.`is`(value: TModel) = this.`is`(value) - -infix fun Property.isNot(value: TModel) = this.isNot(value) - -infix fun Property.notEq(value: TModel) = this.notEq(value) - -infix fun Property.like(value: String) = this.like(value) - -infix fun Property.glob(value: String) = this.glob(value) - -infix fun Property.greaterThan(value: TModel) = this.greaterThan(value) - -infix fun Property.greaterThanOrEq(value: TModel) = this.greaterThanOrEq(value) - -infix fun Property.lessThan(value: TModel) = this.lessThan(value) - -infix fun Property.lessThanOrEq(value: TModel) = this.lessThanOrEq(value) - -infix fun Property.between(value: TModel) = this.between(value) - -infix fun Property.`in`(values: Array): Condition.In { -======= infix fun Property.eq(value: T) = this.eq(value) infix fun Property.`is`(value: T) = this.`is`(value) @@ -58,37 +32,24 @@ infix fun Property.lessThanOrEq(value: T) = this.lessThanOrEq(value infix fun Property.between(value: T) = this.between(value) infix fun Property.`in`(values: Array): Condition.In { ->>>>>>> raizlabs/develop return when (values.size) { 1 -> `in`(values[0]) else -> this.`in`(values[0], *values.sliceArray(IntRange(1, values.size))) } } -<<<<<<< HEAD -infix fun Property.notIn(values: Array): Condition.In { -======= infix fun Property.notIn(values: Array): Condition.In { ->>>>>>> raizlabs/develop return when (values.size) { 1 -> notIn(values[0]) else -> this.notIn(values[0], *values.sliceArray(IntRange(1, values.size))) } } -<<<<<<< HEAD -infix fun Property.`in`(values: Collection) = this.`in`(values) - -infix fun Property.notIn(values: Collection) = this.notIn(values) - -infix fun Property.concatenate(value: TModel) = this.concatenate(value) -======= infix fun Property.`in`(values: Collection) = this.`in`(values) infix fun Property.notIn(values: Collection) = this.notIn(values) infix fun Property.concatenate(value: T) = this.concatenate(value) ->>>>>>> raizlabs/develop infix fun IConditional.eq(value: IConditional) = this.eq(value) diff --git a/dbflow-kotlinextensions/src/main/java/com/raizlabs/android/dbflow/kotlinextensions/QueryExtensions.kt b/dbflow-kotlinextensions/src/main/java/com/raizlabs/android/dbflow/kotlinextensions/QueryExtensions.kt index 35daad385..303a4be26 100644 --- a/dbflow-kotlinextensions/src/main/java/com/raizlabs/android/dbflow/kotlinextensions/QueryExtensions.kt +++ b/dbflow-kotlinextensions/src/main/java/com/raizlabs/android/dbflow/kotlinextensions/QueryExtensions.kt @@ -22,35 +22,6 @@ val select: Select inline fun Select.from(): From = from(T::class.java) -<<<<<<< HEAD -fun delete(modelClass: KClass): From = SQLite.delete(modelClass.java) - -infix fun Select.from(modelClass: KClass) = from(modelClass.java) - -infix fun From.whereExists(where: Where) = where().exists(where) - -infix fun From.where(sqlCondition: SQLCondition) = where(sqlCondition) - -infix fun Set.where(sqlCondition: SQLCondition) = where(sqlCondition) - -infix fun Where.and(sqlCondition: SQLCondition) = and(sqlCondition) - -infix fun Where.or(sqlCondition: SQLCondition) = and(sqlCondition) - -infix fun Case.`when`(sqlCondition: SQLCondition) = `when`(sqlCondition) - -infix fun Case.`when`(property: IProperty<*>) = `when`(property) - -infix fun Case.`when`(value: TModel?) = `when`(value) - -infix fun CaseCondition.then(value: TModel?) = then(value) - -infix fun CaseCondition.then(property: IProperty<*>) = then(property) - -infix fun Case.`else`(value: TModel?) = _else(value) - -infix fun Case.end(columnName: String) = end(columnName) -======= fun delete(modelClass: KClass): From = SQLite.delete(modelClass.java) infix fun Select.from(modelClass: KClass): From = from(modelClass.java) @@ -78,7 +49,6 @@ infix fun CaseCondition.then(property: IProperty<*>): Case = the infix fun Case.`else`(value: T?) = _else(value) infix fun Case.end(columnName: String) = end(columnName) ->>>>>>> raizlabs/develop // queriable extensions @@ -94,15 +64,6 @@ val Queriable.hasData: Boolean val Queriable.statement: DatabaseStatement get() = compileStatement() -<<<<<<< HEAD -val ModelQueriable.list: MutableList - get() = queryList() - -val ModelQueriable.result: TModel? - get() = querySingle() - -val ModelQueriable.cursorResult: CursorResult -======= val ModelQueriable.list: MutableList get() = queryList() @@ -110,25 +71,10 @@ val ModelQueriable.result: T? get() = querySingle() val ModelQueriable.cursorResult: CursorResult ->>>>>>> raizlabs/develop get() = queryResults() // async extensions -<<<<<<< HEAD -val ModelQueriable.async: AsyncQuery - get() = async() - -infix fun AsyncQuery.list(callback: (QueryTransaction<*>, MutableList?) -> Unit) - = queryListResultCallback { queryTransaction, mutableList -> callback(queryTransaction, mutableList) } - .execute() - -infix fun AsyncQuery.result(callback: (QueryTransaction<*>, TModel?) -> Unit) - = querySingleResultCallback { queryTransaction, model -> callback(queryTransaction, model) } - .execute() - -infix fun AsyncQuery.cursorResult(callback: (QueryTransaction<*>, CursorResult) -> Unit) -======= val ModelQueriable.async: AsyncQuery get() = async() @@ -141,52 +87,12 @@ infix fun AsyncQuery.result(callback: (QueryTransaction<*>, T?) -> .execute() infix fun AsyncQuery.cursorResult(callback: (QueryTransaction<*>, CursorResult) -> Unit) ->>>>>>> raizlabs/develop = queryResultCallback { queryTransaction, cursorResult -> callback(queryTransaction, cursorResult) } .execute() val BaseModel.async: AsyncModel get() = async() -<<<<<<< HEAD -infix fun AsyncModel.insert(listener: (TModel) -> Unit) = withListener { listener(it) }.insert() - -infix fun AsyncModel.update(listener: (TModel) -> Unit) = withListener { listener(it) }.update() - -infix fun AsyncModel.delete(listener: (TModel) -> Unit) = withListener { listener(it) }.delete() - -infix fun AsyncModel.save(listener: (TModel) -> Unit) = withListener { listener(it) }.save() - -// Transformable methods - -infix fun Transformable.groupBy(nameAlias: NameAlias) = groupBy(nameAlias) - -infix fun Transformable.groupBy(property: IProperty<*>) = groupBy(property) - -infix fun Transformable.orderBy(orderBy: OrderBy) = orderBy(orderBy) - -infix fun Transformable.limit(limit: Int) = limit(limit) - -infix fun Transformable.offset(offset: Int) = offset(offset) - -infix fun Transformable.having(sqlCondition: SQLCondition) = having(sqlCondition) - -// join - -infix fun From.innerJoin(joinTable: KClass) = join(joinTable.java, Join.JoinType.INNER) - -infix fun From.crossJoin(joinTable: KClass) = join(joinTable.java, Join.JoinType.CROSS) - -infix fun From.leftOuterJoin(joinTable: KClass) = join(joinTable.java, Join.JoinType.LEFT_OUTER) - -infix fun Join.on(sqlCondition: SQLCondition) = on(sqlCondition) - -// update methods - -fun update(modelClass: KClass): Update = SQLite.update(modelClass.java) - -infix fun Update.set(sqlCondition: SQLCondition) = set(sqlCondition) -======= infix fun AsyncModel.insert(listener: (T) -> Unit) = withListener { listener(it) }.insert() infix fun AsyncModel.update(listener: (T) -> Unit) = withListener { listener(it) }.update() @@ -224,8 +130,6 @@ infix fun Join.on(sqlCondition: SQLCondition) = on(sqlC fun update(modelClass: KClass): Update = SQLite.update(modelClass.java) infix fun Update.set(sqlCondition: SQLCondition) = set(sqlCondition) ->>>>>>> raizlabs/develop - // delete @@ -235,21 +139,6 @@ inline fun delete(deleteClause: From.() -> BaseModelQueriab // insert methods -<<<<<<< HEAD -fun insert(modelClass: KClass) = SQLite.insert(modelClass.java) - -infix fun Insert.orReplace(into: Array, *>>) = orReplace().into(*into) - -infix fun Insert.orRollback(into: Array, *>>) = orRollback().into(*into) - -infix fun Insert.orAbort(into: Array, *>>) = orAbort().into(*into) - -infix fun Insert.orFail(into: Array, *>>) = orFail().into(*into) - -infix fun Insert.orIgnore(into: Array, *>>) = orIgnore().into(*into) - -infix fun Insert.select(from: From<*>) = select(from) -======= fun insert(modelClass: KClass) = SQLite.insert(modelClass.java) infix fun Insert.orReplace(into: Array, *>>) = orReplace().into(*into) @@ -263,7 +152,6 @@ infix fun Insert.orFail(into: Array, *>>) = o infix fun Insert.orIgnore(into: Array, *>>) = orIgnore().into(*into) infix fun Insert.select(from: From<*>) = select(from) ->>>>>>> raizlabs/develop fun into(vararg pairs: Pair, *>): Array, *>> = pairs diff --git a/dbflow-processor/src/main/java/com/raizlabs/android/dbflow/processor/definition/ModelContainerDefinition.java b/dbflow-processor/src/main/java/com/raizlabs/android/dbflow/processor/definition/ModelContainerDefinition.java deleted file mode 100644 index 1d1455efe..000000000 --- a/dbflow-processor/src/main/java/com/raizlabs/android/dbflow/processor/definition/ModelContainerDefinition.java +++ /dev/null @@ -1,109 +0,0 @@ -package com.raizlabs.android.dbflow.processor.definition; - -import com.raizlabs.android.dbflow.annotation.ModelContainer; -import com.raizlabs.android.dbflow.processor.ClassNames; -import com.raizlabs.android.dbflow.processor.definition.column.ColumnDefinition; -import com.raizlabs.android.dbflow.processor.definition.method.BindToContentValuesMethod; -import com.raizlabs.android.dbflow.processor.definition.method.BindToStatementMethod; -import com.raizlabs.android.dbflow.processor.definition.method.CustomTypeConverterPropertyMethod; -import com.raizlabs.android.dbflow.processor.definition.method.ExistenceMethod; -import com.raizlabs.android.dbflow.processor.definition.method.ExternalForeignKeyContainerMethod; -import com.raizlabs.android.dbflow.processor.definition.method.ForeignKeyContainerMethod; -import com.raizlabs.android.dbflow.processor.definition.method.LoadFromCursorMethod; -import com.raizlabs.android.dbflow.processor.definition.method.MethodDefinition; -import com.raizlabs.android.dbflow.processor.definition.method.PrimaryConditionMethod; -import com.raizlabs.android.dbflow.processor.definition.method.ToModelMethod; -import com.raizlabs.android.dbflow.processor.model.ProcessorManager; -import com.squareup.javapoet.CodeBlock; -import com.squareup.javapoet.MethodSpec; -import com.squareup.javapoet.ParameterizedTypeName; -import com.squareup.javapoet.TypeName; -import com.squareup.javapoet.TypeSpec; - -import javax.lang.model.element.Modifier; -import javax.lang.model.element.TypeElement; - -/** - * Description: Used in writing model container adapters - */ -public class ModelContainerDefinition extends BaseDefinition { - - public static final String DBFLOW_MODEL_CONTAINER_TAG = "Container"; - - private MethodDefinition[] methods; - public TableDefinition tableDefinition; - - public ModelContainerDefinition(TypeElement classElement, ProcessorManager manager) { - super(classElement, manager); - } - - public void prepareForWrite() { - ModelContainer containerKey = typeElement.getAnnotation(ModelContainer.class); - if (containerKey != null) { - tableDefinition = manager.getTableDefinition(manager.getDatabase(elementTypeName), elementTypeName); - - if (tableDefinition == null) { - manager.logError("Could not find a table definition for " + elementClassName + " ensure" + - "that you have added a @Table definition for it."); - return; - } - setOutputClassName(tableDefinition.databaseDefinition.classSeparator + DBFLOW_MODEL_CONTAINER_TAG); - - boolean putDefaultValue = containerKey.putDefault(); - - methods = new MethodDefinition[]{ - new BindToContentValuesMethod(tableDefinition, true, true, tableDefinition.implementsContentValuesListener), - new BindToContentValuesMethod(tableDefinition, false, true, tableDefinition.implementsContentValuesListener), - new BindToStatementMethod(tableDefinition, true, true), - new BindToStatementMethod(tableDefinition, false, true), - new ExistenceMethod(tableDefinition, true), - new PrimaryConditionMethod(tableDefinition, true), - new ToModelMethod(tableDefinition), - new LoadFromCursorMethod(tableDefinition, true, tableDefinition.implementsLoadFromCursorListener, putDefaultValue), - new ForeignKeyContainerMethod(tableDefinition) - }; - } - } - - public TypeName getDatabaseName() { - return tableDefinition.databaseTypeName; - } - - @Override - protected TypeName getExtendsClass() { - return ParameterizedTypeName.get(ClassNames.MODEL_CONTAINER_ADAPTER, elementClassName); - } - - @Override - public void onWriteDefinition(TypeSpec.Builder typeBuilder) { - - CustomTypeConverterPropertyMethod customTypeConverterPropertyMethod = new CustomTypeConverterPropertyMethod(tableDefinition); - customTypeConverterPropertyMethod.addToType(typeBuilder); - - CodeBlock.Builder constructorCode = CodeBlock.builder(); - constructorCode.addStatement("super(databaseDefinition)"); - - for (ColumnDefinition columnDefinition : tableDefinition.columnDefinitions) { - constructorCode.addStatement("$L.put($S, $T.class)", "columnMap", columnDefinition.columnName, - columnDefinition.erasedTypeName); - } - customTypeConverterPropertyMethod.addCode(constructorCode); - - typeBuilder.addMethod(MethodSpec.constructorBuilder() - .addParameter(ClassNames.DATABASE_HOLDER, "holder") - .addParameter(ClassNames.BASE_DATABASE_DEFINITION_CLASSNAME, "databaseDefinition") - .addCode(constructorCode.build()) - .addModifiers(Modifier.PUBLIC).build()); - - InternalAdapterHelper.writeGetModelClass(typeBuilder, elementClassName); - InternalAdapterHelper.writeGetTableName(typeBuilder, tableDefinition.tableName); - - for (MethodDefinition method : methods) { - MethodSpec methodSpec = method.getMethodSpec(); - if (methodSpec != null) { - typeBuilder.addMethod(methodSpec); - } - } - } - -} diff --git a/dbflow-processor/src/main/java/com/raizlabs/android/dbflow/processor/definition/TableDefinition.java b/dbflow-processor/src/main/java/com/raizlabs/android/dbflow/processor/definition/TableDefinition.java deleted file mode 100644 index 32f8d3ff1..000000000 --- a/dbflow-processor/src/main/java/com/raizlabs/android/dbflow/processor/definition/TableDefinition.java +++ /dev/null @@ -1,702 +0,0 @@ -package com.raizlabs.android.dbflow.processor.definition; - -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; -import com.raizlabs.android.dbflow.annotation.Column; -import com.raizlabs.android.dbflow.annotation.ConflictAction; -import com.raizlabs.android.dbflow.annotation.ContainerKey; -import com.raizlabs.android.dbflow.annotation.ForeignKey; -import com.raizlabs.android.dbflow.annotation.IndexGroup; -import com.raizlabs.android.dbflow.annotation.InheritedColumn; -import com.raizlabs.android.dbflow.annotation.InheritedPrimaryKey; -import com.raizlabs.android.dbflow.annotation.ModelCacheField; -import com.raizlabs.android.dbflow.annotation.ModelContainer; -import com.raizlabs.android.dbflow.annotation.MultiCacheField; -import com.raizlabs.android.dbflow.annotation.OneToMany; -import com.raizlabs.android.dbflow.annotation.PrimaryKey; -import com.raizlabs.android.dbflow.annotation.Table; -import com.raizlabs.android.dbflow.annotation.UniqueGroup; -import com.raizlabs.android.dbflow.processor.ClassNames; -import com.raizlabs.android.dbflow.processor.ProcessorUtils; -import com.raizlabs.android.dbflow.processor.definition.column.ColumnDefinition; -import com.raizlabs.android.dbflow.processor.definition.column.ContainerKeyDefinition; -import com.raizlabs.android.dbflow.processor.definition.column.ForeignKeyColumnDefinition; -import com.raizlabs.android.dbflow.processor.definition.method.BindToContentValuesMethod; -import com.raizlabs.android.dbflow.processor.definition.method.BindToStatementMethod; -import com.raizlabs.android.dbflow.processor.definition.method.CreationQueryMethod; -import com.raizlabs.android.dbflow.processor.definition.method.CustomTypeConverterPropertyMethod; -import com.raizlabs.android.dbflow.processor.definition.method.ExistenceMethod; -import com.raizlabs.android.dbflow.processor.definition.method.InsertStatementQueryMethod; -import com.raizlabs.android.dbflow.processor.definition.method.LoadFromCursorMethod; -import com.raizlabs.android.dbflow.processor.definition.method.MethodDefinition; -import com.raizlabs.android.dbflow.processor.definition.method.OneToManyDeleteMethod; -import com.raizlabs.android.dbflow.processor.definition.method.OneToManySaveMethod; -import com.raizlabs.android.dbflow.processor.definition.method.PrimaryConditionMethod; -import com.raizlabs.android.dbflow.processor.model.ProcessorManager; -import com.raizlabs.android.dbflow.processor.utils.ElementUtility; -import com.raizlabs.android.dbflow.processor.utils.ModelUtils; -import com.raizlabs.android.dbflow.processor.utils.StringUtils; -import com.raizlabs.android.dbflow.processor.validator.ColumnValidator; -import com.raizlabs.android.dbflow.processor.validator.OneToManyValidator; -import com.raizlabs.android.dbflow.sql.QueryBuilder; -import com.squareup.javapoet.ArrayTypeName; -import com.squareup.javapoet.ClassName; -import com.squareup.javapoet.CodeBlock; -import com.squareup.javapoet.FieldSpec; -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.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.atomic.AtomicInteger; - -import javax.annotation.processing.ProcessingEnvironment; -import javax.lang.model.element.Element; -import javax.lang.model.element.ExecutableElement; -import javax.lang.model.element.Modifier; -import javax.lang.model.element.TypeElement; -import javax.lang.model.type.MirroredTypeException; - -/** - * Description: Used in writing ModelAdapters - */ -public class TableDefinition extends BaseTableDefinition { - - public static final String DBFLOW_TABLE_TAG = "Table"; - - public static final String DBFLOW_TABLE_ADAPTER = "Adapter"; - - public String tableName; - - public String adapterName; - - public TypeName databaseTypeName; - - public String insertConflictActionName; - - public String updateConflictActionName; - - public String primaryKeyConflictActionName; - - public List primaryColumnDefinitions; - public List foreignKeyDefinitions; - public List uniqueGroupsDefinitions; - public List indexGroupsDefinitions; - - public ColumnDefinition autoIncrementDefinition; - - public boolean hasAutoIncrement = false; - public boolean hasRowID = false; - - public boolean implementsContentValuesListener = false; - - public boolean implementsSqlStatementListener = false; - - public boolean implementsLoadFromCursorListener = false; - - private final MethodDefinition[] methods; - - public boolean cachingEnabled = false; - public int cacheSize; - public String customCacheFieldName; - public String customMultiCacheFieldName; - - public boolean allFields = false; - public boolean useIsForPrivateBooleans; - - public final Map mColumnMap = Maps.newHashMap(); - - public Map> columnUniqueMap = Maps.newHashMap(); - - public List oneToManyDefinitions = new ArrayList<>(); - public List containerKeyDefinitions = new ArrayList<>(); - - public Map inheritedColumnMap = new HashMap<>(); - public List inheritedFieldNameList = new ArrayList<>(); - public Map inheritedPrimaryKeyMap = new HashMap<>(); - - public ModelContainerDefinition modelContainerDefinition; - - public TableDefinition(ProcessorManager manager, TypeElement element) { - super(element, manager); - - primaryColumnDefinitions = new ArrayList<>(); - foreignKeyDefinitions = new ArrayList<>(); - uniqueGroupsDefinitions = new ArrayList<>(); - indexGroupsDefinitions = new ArrayList<>(); - - Table table = element.getAnnotation(Table.class); - if (table != null) { - this.tableName = table.name(); - - if (tableName == null || tableName.length () == 0) { - tableName = element.getSimpleName().toString(); - } - - try { - table.database(); - } catch (MirroredTypeException mte) { - databaseTypeName = TypeName.get(mte.getTypeMirror()); - } - - cachingEnabled = table.cachingEnabled(); - cacheSize = table.cacheSize(); - - orderedCursorLookUp = table.orderedCursorLookUp(); - assignDefaultValuesFromCursor = table.assignDefaultValuesFromCursor(); - - allFields = table.allFields(); - useIsForPrivateBooleans = table.useBooleanGetterSetters(); - - manager.addModelToDatabase(elementClassName, databaseTypeName); - - - InheritedColumn[] inheritedColumns = table.inheritedColumns(); - for (InheritedColumn inheritedColumn : inheritedColumns) { - if (inheritedFieldNameList.contains(inheritedColumn.fieldName())) { - manager.logError("A duplicate inherited column with name %1s was found for %1s", inheritedColumn.fieldName(), tableName); - } - inheritedFieldNameList.add(inheritedColumn.fieldName()); - inheritedColumnMap.put(inheritedColumn.fieldName(), inheritedColumn); - } - - InheritedPrimaryKey[] inheritedPrimaryKeys = table.inheritedPrimaryKeys(); - for (InheritedPrimaryKey inheritedColumn : inheritedPrimaryKeys) { - if (inheritedFieldNameList.contains(inheritedColumn.fieldName())) { - manager.logError("A duplicate inherited column with name %1s was found for %1s", inheritedColumn.fieldName(), tableName); - } - inheritedFieldNameList.add(inheritedColumn.fieldName()); - inheritedPrimaryKeyMap.put(inheritedColumn.fieldName(), inheritedColumn); - } - - implementsLoadFromCursorListener = ProcessorUtils.implementsClass(manager.getProcessingEnvironment(), - ClassNames.LOAD_FROM_CURSOR_LISTENER.toString(), element); - - implementsContentValuesListener = ProcessorUtils.implementsClass(manager.getProcessingEnvironment(), - ClassNames.CONTENT_VALUES_LISTENER.toString(), element); - - implementsSqlStatementListener = ProcessorUtils.implementsClass(manager.getProcessingEnvironment(), - ClassNames.SQLITE_STATEMENT_LISTENER.toString(), element); - } - - if (element.getAnnotation(ModelContainer.class) != null) { - modelContainerDefinition = new ModelContainerDefinition(element, manager); - } - - methods = new MethodDefinition[] - { - new BindToContentValuesMethod(this, true, false, implementsContentValuesListener), - new BindToContentValuesMethod(this, false, false, implementsContentValuesListener), - new BindToStatementMethod(this, true, false), - new BindToStatementMethod(this, false, false), - new InsertStatementQueryMethod(this, true), - new InsertStatementQueryMethod(this, false), - new CreationQueryMethod(this), - new LoadFromCursorMethod(this, false, implementsLoadFromCursorListener, false), - new ExistenceMethod(this, false), - new PrimaryConditionMethod(this, false), - new OneToManyDeleteMethod(this, false, false), - new OneToManyDeleteMethod(this, false, true), - new OneToManySaveMethod(this, false, OneToManySaveMethod.METHOD_SAVE, false), - new OneToManySaveMethod(this, false, OneToManySaveMethod.METHOD_INSERT, false), - new OneToManySaveMethod(this, false, OneToManySaveMethod.METHOD_UPDATE, false), - new OneToManySaveMethod(this, false, OneToManySaveMethod.METHOD_SAVE, true), - new OneToManySaveMethod(this, false, OneToManySaveMethod.METHOD_INSERT, true), - new OneToManySaveMethod(this, false, OneToManySaveMethod.METHOD_UPDATE, true) - }; - } - - @Override - public void prepareForWrite() { - columnDefinitions = new ArrayList<>(); - mColumnMap.clear(); - classElementLookUpMap.clear(); - autoIncrementDefinition = null; - primaryColumnDefinitions.clear(); - uniqueGroupsDefinitions.clear(); - indexGroupsDefinitions.clear(); - foreignKeyDefinitions.clear(); - columnUniqueMap.clear(); - containerKeyDefinitions.clear(); - oneToManyDefinitions.clear(); - customCacheFieldName = null; - customMultiCacheFieldName = null; - - Table table = element.getAnnotation(Table.class); - if (table != null) { - databaseDefinition = manager.getDatabaseHolderDefinition(databaseTypeName).getDatabaseDefinition(); - if (databaseDefinition == null) { - manager.logError("DatabaseDefinition was null for : " + tableName + " for db type: " + databaseTypeName); - } - - setOutputClassName(databaseDefinition.classSeparator + DBFLOW_TABLE_TAG); - this.adapterName = getModelClassName() + databaseDefinition.classSeparator + DBFLOW_TABLE_ADAPTER; - - - // globular default - ConflictAction insertConflict = table.insertConflict(); - if (insertConflict.equals(ConflictAction.NONE) && !databaseDefinition.insertConflict.equals(ConflictAction.NONE)) { - insertConflict = databaseDefinition.insertConflict; - } - - ConflictAction updateConflict = table.updateConflict(); - if (updateConflict.equals(ConflictAction.NONE) && !databaseDefinition.updateConflict.equals(ConflictAction.NONE)) { - updateConflict = databaseDefinition.updateConflict; - } - - ConflictAction primaryKeyConflict = table.primaryKeyConflict(); - - insertConflictActionName = insertConflict.equals(ConflictAction.NONE) ? "" - : insertConflict.name(); - updateConflictActionName = updateConflict.equals(ConflictAction.NONE) ? "" - : updateConflict.name(); - primaryKeyConflictActionName = primaryKeyConflict.equals(ConflictAction.NONE) ? "" - : primaryKeyConflict.name(); - - - createColumnDefinitions(typeElement); - - UniqueGroup[] groups = table.uniqueColumnGroups(); - Set uniqueNumbersSet = new HashSet<>(); - for (UniqueGroup uniqueGroup : groups) { - if (uniqueNumbersSet.contains(uniqueGroup.groupNumber())) { - manager.logError("A duplicate unique group with number %1s was found for %1s", uniqueGroup.groupNumber(), tableName); - } - UniqueGroupsDefinition definition = new UniqueGroupsDefinition(manager, uniqueGroup); - for (ColumnDefinition columnDefinition : getColumnDefinitions()) { - if (columnDefinition.uniqueGroups.contains(definition.number)) { - definition.addColumnDefinition(columnDefinition); - } - } - uniqueGroupsDefinitions.add(definition); - uniqueNumbersSet.add(uniqueGroup.groupNumber()); - } - - IndexGroup[] indexGroups = table.indexGroups(); - uniqueNumbersSet = new HashSet<>(); - for (IndexGroup indexGroup : indexGroups) { - if (uniqueNumbersSet.contains(indexGroup.number())) { - manager.logError(TableDefinition.class, "A duplicate unique index number %1s was found for %1s", indexGroup.number(), elementName); - } - IndexGroupsDefinition definition = new IndexGroupsDefinition(manager, this, indexGroup); - for (ColumnDefinition columnDefinition : getColumnDefinitions()) { - if (columnDefinition.indexGroups.contains(definition.indexNumber)) { - definition.columnDefinitionList.add(columnDefinition); - } - } - indexGroupsDefinitions.add(definition); - uniqueNumbersSet.add(indexGroup.number()); - } - } - - if (modelContainerDefinition != null) { - modelContainerDefinition.prepareForWrite(); - } - } - - @Override - public boolean hasAutoIncrement() { - return hasAutoIncrement; - } - - @Override - public boolean hasRowID() { - return hasRowID; - } - - @Override - public ColumnDefinition getAutoIncrementColumn() { - return autoIncrementDefinition; - } - - @Override - protected void createColumnDefinitions(TypeElement typeElement) { - List elements = ElementUtility.getAllElements(typeElement, manager); - - for (Element element : elements) { - classElementLookUpMap.put(element.getSimpleName().toString(), element); - } - - ColumnValidator columnValidator = new ColumnValidator(); - OneToManyValidator oneToManyValidator = new OneToManyValidator(); - AtomicInteger integer = new AtomicInteger(0); - for (Element element : elements) { - // no private static or final fields for all columns, or any inherited columns here. - boolean isAllFields = ElementUtility.isValidAllFields(allFields, element); - - // package private, will generate helper - boolean isPackagePrivate = ElementUtility.isPackagePrivate(element); - boolean isPackagePrivateNotInSamePackage = isPackagePrivate && !ElementUtility.isInSamePackage(manager, element, this.element); - - boolean isForeign = element.getAnnotation(ForeignKey.class) != null; - boolean isPrimary = element.getAnnotation(PrimaryKey.class) != null; - boolean isInherited = inheritedColumnMap.containsKey(element.getSimpleName().toString()); - boolean isInheritedPrimaryKey = inheritedPrimaryKeyMap.containsKey(element.getSimpleName().toString()); - if (element.getAnnotation(Column.class) != null || isForeign || isPrimary - || isAllFields || isInherited || isInheritedPrimaryKey) { - - ColumnDefinition columnDefinition; - if (isInheritedPrimaryKey) { - InheritedPrimaryKey inherited = inheritedPrimaryKeyMap.get(element.getSimpleName().toString()); - columnDefinition = new ColumnDefinition(manager, element, this, isPackagePrivateNotInSamePackage, - inherited.column(), inherited.primaryKey()); - } else if (isInherited) { - InheritedColumn inherited = inheritedColumnMap.get(element.getSimpleName().toString()); - columnDefinition = new ColumnDefinition(manager, element, this, isPackagePrivateNotInSamePackage, - inherited.column(), null); - } else if (isForeign) { - columnDefinition = new ForeignKeyColumnDefinition(manager, this, - element, isPackagePrivateNotInSamePackage); - } else { - columnDefinition = new ColumnDefinition(manager, element, - this, isPackagePrivateNotInSamePackage); - } - - if (columnValidator.validate(manager, columnDefinition)) { - columnDefinitions.add(columnDefinition); - mColumnMap.put(columnDefinition.columnName, columnDefinition); - if (columnDefinition.isPrimaryKey) { - primaryColumnDefinitions.add(columnDefinition); - } else if (columnDefinition.isPrimaryKeyAutoIncrement()) { - autoIncrementDefinition = columnDefinition; - hasAutoIncrement = true; - } else if (columnDefinition.isRowId) { - autoIncrementDefinition = columnDefinition; - hasRowID = true; - } - - if (columnDefinition instanceof ForeignKeyColumnDefinition) { - foreignKeyDefinitions.add((ForeignKeyColumnDefinition) columnDefinition); - } - - if (!columnDefinition.uniqueGroups.isEmpty()) { - List groups = columnDefinition.uniqueGroups; - for (int group : groups) { - List groupList = columnUniqueMap.get(group); - if (groupList == null) { - groupList = new ArrayList<>(); - columnUniqueMap.put(group, groupList); - } - if (!groupList.contains(columnDefinition)) { - groupList.add(columnDefinition); - } - } - } - - if (isPackagePrivate) { - packagePrivateList.add(columnDefinition); - } - } - } else if (element.getAnnotation(OneToMany.class) != null) { - OneToManyDefinition oneToManyDefinition = new OneToManyDefinition((ExecutableElement) element, manager); - if (oneToManyValidator.validate(manager, oneToManyDefinition)) { - oneToManyDefinitions.add(oneToManyDefinition); - } - } else if (element.getAnnotation(ContainerKey.class) != null) { - ContainerKeyDefinition containerKeyDefinition = new ContainerKeyDefinition(element, manager, this, isPackagePrivateNotInSamePackage); - containerKeyDefinitions.add(containerKeyDefinition); - } else if (element.getAnnotation(ModelCacheField.class) != null) { - if (!element.getModifiers().contains(Modifier.PUBLIC)) { - manager.logError("ModelCacheField must be public from: " + typeElement); - } - if (!element.getModifiers().contains(Modifier.STATIC)) { - manager.logError("ModelCacheField must be static from: " + typeElement); - } - if (!StringUtils.isNullOrEmpty(customCacheFieldName)) { - manager.logError("ModelCacheField can only be declared once from: " + typeElement); - } else { - customCacheFieldName = element.getSimpleName().toString(); - } - } else if (element.getAnnotation(MultiCacheField.class) != null) { - if (!element.getModifiers().contains(Modifier.PUBLIC)) { - manager.logError("MultiCacheField must be public from: " + typeElement); - } - if (!element.getModifiers().contains(Modifier.STATIC)) { - manager.logError("MultiCacheField must be static from: " + typeElement); - } - if (!StringUtils.isNullOrEmpty(customMultiCacheFieldName)) { - manager.logError("MultiCacheField can only be declared once from: " + typeElement); - } else { - customMultiCacheFieldName = element.getSimpleName().toString(); - } - } - } - - } - - public ColumnDefinition getAutoIncrementPrimaryKey() { - return autoIncrementDefinition; - } - - @Override - public List getPrimaryColumnDefinitions() { - if (getAutoIncrementPrimaryKey() != null) { - return Lists.newArrayList(getAutoIncrementPrimaryKey()); - } else { - return primaryColumnDefinitions; - } - } - - public ClassName getAdapterClassName() { - return ClassName.get(packageName, adapterName); - } - - @Override - public ClassName getPropertyClassName() { - return outputClassName; - } - - @Override - public void onWriteDefinition(TypeSpec.Builder typeBuilder) { - - FieldSpec.Builder propertyConverter = FieldSpec.builder(ClassNames.PROPERTY_CONVERTER, "PROPERTY_CONVERTER", Modifier.FINAL, Modifier.PUBLIC, Modifier.STATIC) - .initializer(CodeBlock.builder() - .add("new $T(){ \n", ClassNames.PROPERTY_CONVERTER) - .add("public $T fromName(String columnName) {\n", ClassNames.IPROPERTY) - .add("return $L.getProperty(columnName); \n}\n}", getPropertyClassName()) - .build()); - typeBuilder.addField(propertyConverter.build()); - - MethodSpec.Builder getPropertyForNameMethod = MethodSpec.methodBuilder("getProperty") - .addModifiers(Modifier.PUBLIC, Modifier.STATIC) - .addParameter(String.class, "columnName") - .returns(ClassNames.BASE_PROPERTY); - - MethodSpec.Builder getAllColumnPropertiesMethod = MethodSpec.methodBuilder("getAllColumnProperties") - .addModifiers(Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL) - .returns(ArrayTypeName.of(ClassNames.IPROPERTY)); - CodeBlock.Builder getPropertiesBuilder = CodeBlock.builder(); - - getPropertyForNameMethod.addStatement("columnName = $T.quoteIfNeeded(columnName)", ClassName.get(QueryBuilder.class)); - - getPropertyForNameMethod.beginControlFlow("switch ($L) ", "columnName"); - for (int i = 0; i < columnDefinitions.size(); i++) { - if (i > 0) { - getPropertiesBuilder.add(","); - } - ColumnDefinition columnDefinition = columnDefinitions.get(i); - columnDefinition.addPropertyDefinition(typeBuilder, elementClassName); - columnDefinition.addPropertyCase(getPropertyForNameMethod); - columnDefinition.addColumnName(getPropertiesBuilder); - - } - getPropertyForNameMethod.beginControlFlow("default: "); - getPropertyForNameMethod.addStatement("throw new $T($S)", IllegalArgumentException.class, - "Invalid column name passed. Ensure you are calling the correct table's column"); - getPropertyForNameMethod.endControlFlow(); - getPropertyForNameMethod.endControlFlow(); - - getAllColumnPropertiesMethod.addStatement("return new $T[]{$L}", ClassNames.IPROPERTY, getPropertiesBuilder.build().toString()); - typeBuilder.addMethod(getAllColumnPropertiesMethod.build()); - - // add index properties here - for (IndexGroupsDefinition indexGroupsDefinition : indexGroupsDefinitions) { - typeBuilder.addField(indexGroupsDefinition.getFieldSpec()); - } - - typeBuilder.addMethod(getPropertyForNameMethod.build()); - } - - public void writeAdapter(ProcessingEnvironment processingEnvironment) throws IOException { - - TypeSpec.Builder typeBuilder = TypeSpec.classBuilder(adapterName) - .addModifiers(Modifier.PUBLIC, Modifier.FINAL) - .superclass(ParameterizedTypeName.get(ClassNames.MODEL_ADAPTER, elementClassName)); - InternalAdapterHelper.writeGetModelClass(typeBuilder, elementClassName); - InternalAdapterHelper.writeGetTableName(typeBuilder, tableName); - - if (hasAutoIncrement || hasRowID) { - InternalAdapterHelper.writeUpdateAutoIncrement(typeBuilder, elementClassName, - autoIncrementDefinition, false); - - typeBuilder.addMethod(MethodSpec.methodBuilder("getAutoIncrementingId") - .addAnnotation(Override.class) - .addModifiers(Modifier.PUBLIC, Modifier.FINAL) - .addParameter(elementClassName, ModelUtils.getVariable(false)) - .addStatement("return $L", autoIncrementDefinition.getColumnAccessString(false, false)) - .returns(ClassName.get(Number.class)).build()); - - typeBuilder.addMethod(MethodSpec.methodBuilder("getAutoIncrementingColumnName") - .addAnnotation(Override.class) - .addModifiers(Modifier.PUBLIC, Modifier.FINAL) - .addStatement("return $S", QueryBuilder.stripQuotes(autoIncrementDefinition.columnName)) - .returns(ClassName.get(String.class)).build()); - } - - typeBuilder.addMethod(MethodSpec.methodBuilder("getAllColumnProperties") - .addAnnotation(Override.class) - .addModifiers(Modifier.PUBLIC, Modifier.FINAL) - .addStatement("return $T.getAllColumnProperties()", outputClassName) - .returns(ArrayTypeName.of(ClassNames.IPROPERTY)).build()); - - if (cachingEnabled) { - - // TODO: pass in model cache loaders. - - boolean singlePrimaryKey = getPrimaryColumnDefinitions().size() == 1; - typeBuilder.addMethod(MethodSpec.methodBuilder("createSingleModelLoader") - .addAnnotation(Override.class) - .addModifiers(Modifier.PUBLIC, Modifier.FINAL) - .addStatement("return new $T<>(getModelClass())", - singlePrimaryKey ? ClassNames.SINGLE_KEY_CACHEABLE_MODEL_LOADER : - ClassNames.CACHEABLE_MODEL_LOADER) - .returns(ClassNames.SINGLE_MODEL_LOADER).build()); - - typeBuilder.addMethod(MethodSpec.methodBuilder("createListModelLoader") - .addAnnotation(Override.class) - .addModifiers(Modifier.PUBLIC, Modifier.FINAL) - .addStatement("return new $T<>(getModelClass())", - singlePrimaryKey ? ClassNames.SINGLE_KEY_CACHEABLE_LIST_MODEL_LOADER : - ClassNames.CACHEABLE_LIST_MODEL_LOADER) - .returns(ClassNames.LIST_MODEL_LOADER).build()); - - typeBuilder.addMethod(MethodSpec.methodBuilder("createListModelSaver") - .addAnnotation(Override.class) - .addModifiers(Modifier.PUBLIC, Modifier.FINAL) - .addStatement("return new $T<>(getModelSaver())", ClassNames.CACHEABLE_LIST_MODEL_SAVER) - .returns(ParameterizedTypeName.get(ClassNames.CACHEABLE_LIST_MODEL_SAVER, - elementClassName, - ParameterizedTypeName.get(ClassNames.MODEL_ADAPTER, elementTypeName))).build()); - - typeBuilder.addMethod(MethodSpec.methodBuilder("cachingEnabled") - .addAnnotation(Override.class) - .addModifiers(Modifier.PUBLIC, Modifier.FINAL) - .addStatement("return $L", true) - .returns(TypeName.BOOLEAN).build()); - - List primaries = primaryColumnDefinitions; - if (primaries == null || primaries.isEmpty()) { - primaries = Lists.newArrayList(autoIncrementDefinition); - } - InternalAdapterHelper.writeGetCachingId(typeBuilder, elementClassName, primaries, false); - - MethodSpec.Builder cachingbuilder = MethodSpec.methodBuilder("createCachingColumns") - .addAnnotation(Override.class) - .addModifiers(Modifier.PUBLIC, Modifier.FINAL); - String columns = "return new String[]{"; - for (int i = 0; i < primaries.size(); i++) { - ColumnDefinition column = primaries.get(i); - if (i > 0) { - columns += ","; - } - columns += "\"" + QueryBuilder.quoteIfNeeded(column.columnName) + "\""; - } - columns += "}"; - - cachingbuilder.addStatement(columns) - .returns(ArrayTypeName.of(ClassName.get(String.class))); - - typeBuilder.addMethod(cachingbuilder.build()); - - if (cacheSize != Table.DEFAULT_CACHE_SIZE) { - typeBuilder.addMethod(MethodSpec.methodBuilder("getCacheSize") - .addAnnotation(Override.class) - .addModifiers(Modifier.PUBLIC, Modifier.FINAL) - .addStatement("return $L", cacheSize) - .returns(TypeName.INT).build()); - } - - if (!StringUtils.isNullOrEmpty(customCacheFieldName)) { - typeBuilder.addMethod(MethodSpec.methodBuilder("createModelCache") - .addAnnotation(Override.class) - .addModifiers(Modifier.PUBLIC, Modifier.FINAL) - .addStatement("return $T.$L", elementClassName, customCacheFieldName) - .returns(ParameterizedTypeName.get(ClassNames.MODEL_CACHE, elementClassName, WildcardTypeName.subtypeOf(Object.class))).build()); - } - - if (!StringUtils.isNullOrEmpty(customMultiCacheFieldName)) { - typeBuilder.addMethod(MethodSpec.methodBuilder("getCacheConverter") - .addAnnotation(Override.class) - .addModifiers(Modifier.PUBLIC, Modifier.FINAL) - .addStatement("return $T.$L", elementClassName, customMultiCacheFieldName) - .returns(ParameterizedTypeName.get(ClassNames.MULTI_KEY_CACHE_CONVERTER, WildcardTypeName.subtypeOf(Object.class))).build()); - } - - MethodSpec.Builder reloadMethod = MethodSpec.methodBuilder("reloadRelationships") - .addAnnotation(Override.class) - .addParameter(elementClassName, ModelUtils.getVariable(false)) - .addParameter(ClassNames.CURSOR, LoadFromCursorMethod.PARAM_CURSOR) - .addModifiers(Modifier.PUBLIC, Modifier.FINAL); - CodeBlock.Builder loadStatements = CodeBlock.builder(); - AtomicInteger noIndex = new AtomicInteger(-1); - for (ColumnDefinition foreignColumn : foreignKeyDefinitions) { - CodeBlock.Builder codeBuilder = foreignColumn.getLoadFromCursorMethod(false, false, - false, noIndex).toBuilder(); - if (!foreignColumn.elementTypeName.isPrimitive()) { - codeBuilder.nextControlFlow("else"); - codeBuilder.addStatement(foreignColumn.setColumnAccessString(CodeBlock.builder().add("null").build(), false)); - codeBuilder.endControlFlow(); - } - loadStatements.add(codeBuilder.build()); - } - reloadMethod.addCode(loadStatements.build()); - typeBuilder.addMethod(reloadMethod.build()); - } - - CustomTypeConverterPropertyMethod customTypeConverterPropertyMethod = new CustomTypeConverterPropertyMethod(this); - customTypeConverterPropertyMethod.addToType(typeBuilder); - - CodeBlock.Builder constructorCode = CodeBlock.builder(); - constructorCode.addStatement("super(databaseDefinition)"); - customTypeConverterPropertyMethod.addCode(constructorCode); - - typeBuilder.addMethod(MethodSpec.constructorBuilder() - .addParameter(ClassNames.DATABASE_HOLDER, "holder") - .addParameter(ClassNames.BASE_DATABASE_DEFINITION_CLASSNAME, "databaseDefinition") - .addCode(constructorCode.build()) - .addModifiers(Modifier.PUBLIC).build()); - - for (MethodDefinition methodDefinition : methods) { - MethodSpec spec = methodDefinition.getMethodSpec(); - if (spec != null) { - typeBuilder.addMethod(spec); - } - } - - typeBuilder.addMethod(MethodSpec.methodBuilder("newInstance") - .addAnnotation(Override.class) - .addModifiers(Modifier.PUBLIC, Modifier.FINAL) - .addStatement("return new $T()", elementClassName) - .returns(elementClassName) - .build()); - - typeBuilder.addMethod(MethodSpec.methodBuilder("getProperty") - .addAnnotation(Override.class) - .addParameter(ClassName.get(String.class), "name") - .addModifiers(Modifier.PUBLIC, Modifier.FINAL) - .addStatement("return $T.getProperty($L)", outputClassName, "name") - .returns(ClassNames.BASE_PROPERTY) - .build()); - - if (updateConflictActionName.length () != 0) { - typeBuilder.addMethod(MethodSpec.methodBuilder("getUpdateOnConflictAction") - .addAnnotation(Override.class) - .addModifiers(Modifier.PUBLIC, Modifier.FINAL) - .addStatement("return $T.$L", ClassNames.CONFLICT_ACTION, updateConflictActionName) - .returns(ClassNames.CONFLICT_ACTION) - .build()); - } - - if (insertConflictActionName.length () != 0) { - typeBuilder.addMethod(MethodSpec.methodBuilder("getInsertOnConflictAction") - .addAnnotation(Override.class) - .addModifiers(Modifier.PUBLIC, Modifier.FINAL) - .addStatement("return $T.$L", ClassNames.CONFLICT_ACTION, insertConflictActionName) - .returns(ClassNames.CONFLICT_ACTION).build()); - } - - - JavaFile.Builder javaFileBuilder = JavaFile.builder(packageName, typeBuilder.build()); - javaFileBuilder.build().writeTo(processingEnvironment.getFiler()); - - } -} diff --git a/dbflow-processor/src/main/java/com/raizlabs/android/dbflow/processor/definition/column/ForeignKeyColumnDefinition.java b/dbflow-processor/src/main/java/com/raizlabs/android/dbflow/processor/definition/column/ForeignKeyColumnDefinition.java deleted file mode 100644 index 5c6730e43..000000000 --- a/dbflow-processor/src/main/java/com/raizlabs/android/dbflow/processor/definition/column/ForeignKeyColumnDefinition.java +++ /dev/null @@ -1,586 +0,0 @@ -package com.raizlabs.android.dbflow.processor.definition.column; - -import com.raizlabs.android.dbflow.annotation.Column; -import com.raizlabs.android.dbflow.annotation.ForeignKey; -import com.raizlabs.android.dbflow.annotation.ForeignKeyAction; -import com.raizlabs.android.dbflow.annotation.ForeignKeyReference; -import com.raizlabs.android.dbflow.processor.ClassNames; -import com.raizlabs.android.dbflow.processor.ProcessorUtils; -import com.raizlabs.android.dbflow.processor.SQLiteHelper; -import com.raizlabs.android.dbflow.processor.definition.TableDefinition; -import com.raizlabs.android.dbflow.processor.definition.method.BindToContentValuesMethod; -import com.raizlabs.android.dbflow.processor.definition.method.BindToStatementMethod; -import com.raizlabs.android.dbflow.processor.definition.method.LoadFromCursorMethod; -import com.raizlabs.android.dbflow.processor.model.ProcessorManager; -import com.raizlabs.android.dbflow.processor.utils.ModelUtils; -import com.raizlabs.android.dbflow.processor.utils.StringUtils; -import com.raizlabs.android.dbflow.sql.QueryBuilder; -import com.squareup.javapoet.ClassName; -import com.squareup.javapoet.CodeBlock; -import com.squareup.javapoet.FieldSpec; -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.util.ArrayList; -import java.util.List; -import java.util.concurrent.atomic.AtomicInteger; - -import javax.lang.model.element.Element; -import javax.lang.model.element.Modifier; -import javax.lang.model.element.TypeElement; -import javax.lang.model.type.DeclaredType; -import javax.lang.model.type.MirroredTypeException; -import javax.lang.model.type.TypeMirror; -import javax.lang.model.util.Types; - -/** - * Description: - */ -public class ForeignKeyColumnDefinition extends ColumnDefinition { - - public final List foreignKeyReferenceDefinitionList = new ArrayList<>(); - - public final TableDefinition tableDefinition; - - public ClassName referencedTableClassName; - - public ForeignKeyAction onDelete; - public ForeignKeyAction onUpdate; - - public boolean isModelContainer; - public boolean isForeignKeyContainer; - - public boolean isModel; - - public boolean needsReferences; - - public boolean nonModelColumn; - - public boolean saveForeignKeyModel; - - public ForeignKeyColumnDefinition(ProcessorManager manager, TableDefinition tableDefinition, - Element typeElement, boolean isPackagePrivate) { - super(manager, typeElement, tableDefinition, isPackagePrivate); - this.tableDefinition = tableDefinition; - - ForeignKey foreignKey = typeElement.getAnnotation(ForeignKey.class); - onUpdate = foreignKey.onUpdate(); - onDelete = foreignKey.onDelete(); - - try { - foreignKey.tableClass(); - } catch (MirroredTypeException mte) { - referencedTableClassName = ClassName.get(manager.getElements().getTypeElement(mte.getTypeMirror().toString())); - } - - TypeElement erasedElement = manager.getElements().getTypeElement( - manager.getTypeUtils().erasure(typeElement.asType()).toString()); - - // hopefully intentionally left blank - if (referencedTableClassName.equals(TypeName.OBJECT)) { - if (elementTypeName instanceof ParameterizedTypeName) { - List args = ((ParameterizedTypeName) elementTypeName).typeArguments; - if (args.size() > 0) { - referencedTableClassName = ClassName.bestGuess(args.get(0).toString()); - isModelContainer = true; - } - } else { - if (ProcessorUtils.implementsClass(manager.getProcessingEnvironment(), - ClassNames.MODEL_CONTAINER.toString(), erasedElement)) { - Types types = manager.getTypeUtils(); - - DeclaredType superContainer = null; - DeclaredType modelContainer = manager.getTypeUtils().getDeclaredType(manager.getElements().getTypeElement(ClassNames.MODEL_CONTAINER.toString()), - types.getWildcardType(manager.getElements() - .getTypeElement(ClassNames.MODEL.toString()).asType(), null), - types.getWildcardType(null, null)); - for (TypeMirror superType : types.directSupertypes(erasedElement.asType())) { - if (types.isAssignable(superType, modelContainer)) { - superContainer = (DeclaredType) superType; - } - } - - if (superContainer != null) { - List typeArgs = superContainer.getTypeArguments(); - referencedTableClassName = ClassName.get(manager.getElements() - .getTypeElement(typeArgs.get(0).toString())); - isModelContainer = true; - } - } - - if (referencedTableClassName == null || referencedTableClassName.equals(ClassName.OBJECT)) { - referencedTableClassName = ClassName.bestGuess(elementTypeName.toString()); - } - } - } - - if (referencedTableClassName == null) { - manager.logError("Referenced was null for %1s within %1s", typeElement, elementTypeName); - } - - isModel = ProcessorUtils.implementsClass(manager.getProcessingEnvironment(), ClassNames.MODEL.toString(), erasedElement); - isModelContainer = isModelContainer || ProcessorUtils.implementsClass(manager.getProcessingEnvironment(), ClassNames.MODEL_CONTAINER.toString(), erasedElement); - isForeignKeyContainer = isModelContainer && ProcessorUtils.implementsClass(manager.getProcessingEnvironment(), ClassNames.FOREIGN_KEY_CONTAINER.toString(), erasedElement); - - nonModelColumn = !isModel && !isModelContainer; - - saveForeignKeyModel = foreignKey.saveForeignKeyModel(); - - // we need to recheck for this instance - if (columnAccess instanceof TypeConverterAccess) { - if (typeElement.getModifiers().contains(Modifier.PRIVATE)) { - boolean useIs = elementTypeName.box().equals(TypeName.BOOLEAN.box()) - && tableDefinition.useIsForPrivateBooleans; - columnAccess = new PrivateColumnAccess(typeElement.getAnnotation(Column.class), useIs); - } else { - columnAccess = new SimpleColumnAccess(); - } - } - - ForeignKeyReference[] references = foreignKey.references(); - if (references.length == 0) { - // no references specified we will delegate references call to post-evaluation - needsReferences = true; - } else { - for (ForeignKeyReference reference : references) { - ForeignKeyReferenceDefinition referenceDefinition = new ForeignKeyReferenceDefinition(manager, elementName, reference, columnAccess, this); - // TODO: add validation - foreignKeyReferenceDefinitionList.add(referenceDefinition); - } - - if (nonModelColumn && foreignKeyReferenceDefinitionList.size() == 1) { - ForeignKeyReferenceDefinition foreignKeyReferenceDefinition = foreignKeyReferenceDefinitionList.get(0); - columnName = foreignKeyReferenceDefinition.columnName; - } - } - } - - @Override - public void addPropertyDefinition(TypeSpec.Builder typeBuilder, TypeName tableClassName) { - checkNeedsReferences(); - for (ForeignKeyReferenceDefinition reference : foreignKeyReferenceDefinitionList) { - TypeName propParam; - if (reference.columnClassName.isPrimitive() && !reference.columnClassName.equals(TypeName.BOOLEAN)) { - propParam = ClassName.get(ClassNames.PROPERTY_PACKAGE, StringUtils.capitalize(reference.columnClassName.toString()) + "Property"); - } else { - propParam = ParameterizedTypeName.get(ClassNames.PROPERTY, reference.columnClassName.box()); - } - typeBuilder.addField(FieldSpec.builder(propParam, reference.columnName, Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL) - .initializer("new $T($T.class, $S)", propParam, tableClassName, reference.columnName).build()); - } - } - - @Override - public void addPropertyCase(MethodSpec.Builder methodBuilder) { - checkNeedsReferences(); - for (ForeignKeyReferenceDefinition reference : foreignKeyReferenceDefinitionList) { - methodBuilder.beginControlFlow("case $S: ", QueryBuilder.quoteIfNeeded(reference.columnName)); - methodBuilder.addStatement("return $L", reference.columnName); - methodBuilder.endControlFlow(); - } - } - - @Override - public void addColumnName(CodeBlock.Builder codeBuilder) { - checkNeedsReferences(); - for (int i = 0; i < foreignKeyReferenceDefinitionList.size(); i++) { - ForeignKeyReferenceDefinition reference = foreignKeyReferenceDefinitionList.get(i); - if (i > 0) { - codeBuilder.add(","); - } - codeBuilder.add(reference.columnName); - } - } - - @Override - public CodeBlock getInsertStatementColumnName() { - checkNeedsReferences(); - CodeBlock.Builder builder = CodeBlock.builder(); - for (int i = 0; i < foreignKeyReferenceDefinitionList.size(); i++) { - if (i > 0) { - builder.add(","); - } - ForeignKeyReferenceDefinition referenceDefinition = foreignKeyReferenceDefinitionList.get(i); - builder.add("$L", QueryBuilder.quote(referenceDefinition.columnName)); - } - return builder.build(); - } - - @Override - public CodeBlock getInsertStatementValuesString() { - checkNeedsReferences(); - CodeBlock.Builder builder = CodeBlock.builder(); - for (int i = 0; i < foreignKeyReferenceDefinitionList.size(); i++) { - if (i > 0) { - builder.add(","); - } - builder.add("?"); - } - return builder.build(); - } - - @Override - public CodeBlock getCreationName() { - checkNeedsReferences(); - CodeBlock.Builder builder = CodeBlock.builder(); - for (int i = 0; i < foreignKeyReferenceDefinitionList.size(); i++) { - if (i > 0) { - builder.add(" ,"); - } - ForeignKeyReferenceDefinition referenceDefinition = foreignKeyReferenceDefinitionList.get(i); - builder.add(referenceDefinition.getCreationStatement()); - } - return builder.build(); - } - - @Override - public String getPrimaryKeyName() { - checkNeedsReferences(); - CodeBlock.Builder builder = CodeBlock.builder(); - for (int i = 0; i < foreignKeyReferenceDefinitionList.size(); i++) { - if (i > 0) { - builder.add(" ,"); - } - ForeignKeyReferenceDefinition referenceDefinition = foreignKeyReferenceDefinitionList.get(i); - builder.add(referenceDefinition.getPrimaryKeyName()); - } - return builder.build().toString(); - } - - @Override - public CodeBlock getContentValuesStatement(boolean isModelContainerAdapter) { - if (nonModelColumn) { - return super.getContentValuesStatement(isModelContainerAdapter); - } else { - checkNeedsReferences(); - CodeBlock.Builder builder = CodeBlock.builder(); - String statement = columnAccess - .getColumnAccessString(elementTypeName, elementName, elementName, - ModelUtils.getVariable(isModelContainerAdapter), isModelContainerAdapter, false); - String finalAccessStatement = getFinalAccessStatement(builder, isModelContainerAdapter, statement); - builder.beginControlFlow("if ($L != null)", finalAccessStatement); - - if (saveForeignKeyModel) { - builder.addStatement("$L.save()", finalAccessStatement); - } - - CodeBlock.Builder elseBuilder = CodeBlock.builder(); - for (ForeignKeyReferenceDefinition referenceDefinition : foreignKeyReferenceDefinitionList) { - builder.add(referenceDefinition.getContentValuesStatement(isModelContainerAdapter)); - elseBuilder.addStatement("$L.putNull($S)", BindToContentValuesMethod.PARAM_CONTENT_VALUES, QueryBuilder.quote(referenceDefinition.columnName)); - } - - builder.nextControlFlow("else") - .add(elseBuilder.build()) - .endControlFlow(); - return builder.build(); - } - } - - @Override - public CodeBlock getSQLiteStatementMethod(AtomicInteger index, boolean isModelContainerAdapter) { - if (nonModelColumn) { - return super.getSQLiteStatementMethod(index, isModelContainerAdapter); - } else { - checkNeedsReferences(); - CodeBlock.Builder builder = CodeBlock.builder(); - String statement = columnAccess - .getColumnAccessString(elementTypeName, elementName, elementName, - ModelUtils.getVariable(isModelContainerAdapter), isModelContainerAdapter, true); - String finalAccessStatement = getFinalAccessStatement(builder, isModelContainerAdapter, statement); - builder.beginControlFlow("if ($L != null)", finalAccessStatement); - - if (saveForeignKeyModel) { - builder.addStatement("$L.save()", finalAccessStatement); - } - - CodeBlock.Builder elseBuilder = CodeBlock.builder(); - for (int i = 0; i < foreignKeyReferenceDefinitionList.size(); i++) { - if (i > 0) { - index.incrementAndGet(); - } - ForeignKeyReferenceDefinition referenceDefinition = foreignKeyReferenceDefinitionList.get(i); - builder.add(referenceDefinition.getSQLiteStatementMethod(index, isModelContainerAdapter)); - elseBuilder.addStatement("$L.bindNull($L)", BindToStatementMethod.PARAM_STATEMENT, index.intValue() + " + " + BindToStatementMethod.PARAM_START); - } - - builder.nextControlFlow("else") - .add(elseBuilder.build()) - .endControlFlow(); - return builder.build(); - } - } - - @Override - public CodeBlock getLoadFromCursorMethod(boolean isModelContainerAdapter, boolean putNullForContainerAdapter, - boolean endNonPrimitiveIf, AtomicInteger index) { - if (nonModelColumn) { - return super.getLoadFromCursorMethod(isModelContainerAdapter, putNullForContainerAdapter, endNonPrimitiveIf, index); - } else { - checkNeedsReferences(); - CodeBlock.Builder builder = CodeBlock.builder() - .add("//// Only load model if references match, for efficiency\n"); - CodeBlock.Builder ifNullBuilder = CodeBlock.builder() - .add("if ("); - CodeBlock.Builder selectBuilder = CodeBlock.builder(); - - // used for foreignkey containers only. - String foreignKeyContainerRefName = "ref" + columnName; - - for (int i = 0; i < foreignKeyReferenceDefinitionList.size(); i++) { - if (i > 0) { - index.incrementAndGet(); - } - ForeignKeyReferenceDefinition referenceDefinition = foreignKeyReferenceDefinitionList.get(i); - - String indexName; - if (!tableDefinition.orderedCursorLookUp || index.intValue() == -1) { - indexName = "index" + referenceDefinition.columnName; - builder.addStatement("int $L = $L.getColumnIndex($S)", indexName, LoadFromCursorMethod.PARAM_CURSOR, referenceDefinition.columnName); - } else { - indexName = index.intValue() + ""; - } - if (i > 0) { - ifNullBuilder.add(" && "); - } - - if (!tableDefinition.orderedCursorLookUp || index.intValue() == -1) { - ifNullBuilder.add("$L != -1 && !$L.isNull($L)", indexName, LoadFromCursorMethod.PARAM_CURSOR, indexName); - } else { - ifNullBuilder.add("!$L.isNull($L)", LoadFromCursorMethod.PARAM_CURSOR, indexName); - } - - CodeBlock loadFromCursorBlock = CodeBlock.builder().add("$L.$L($L)", LoadFromCursorMethod.PARAM_CURSOR, - DefinitionUtils.getLoadFromCursorMethodString(referenceDefinition.columnClassName, - referenceDefinition.columnAccess), indexName).build(); - ClassName generatedTableRef = ClassName.get(referencedTableClassName.packageName(), referencedTableClassName.simpleName() - + tableDefinition.databaseDefinition.fieldRefSeparator + TableDefinition.DBFLOW_TABLE_TAG); - if (!isForeignKeyContainer) { - selectBuilder.add("\n.and($L.$L.eq($L))", generatedTableRef, - referenceDefinition.foreignColumnName, loadFromCursorBlock); - } else { - selectBuilder.add("\n$L.put($S, $L);", foreignKeyContainerRefName, referenceDefinition.foreignColumnName, - loadFromCursorBlock); - } - } - ifNullBuilder.add(")"); - builder.beginControlFlow(ifNullBuilder.build().toString()); - - CodeBlock.Builder initializer = CodeBlock.builder(); - - if (isForeignKeyContainer) { - - builder.addStatement("$T $L = new $T($T.class)", - elementTypeName, - foreignKeyContainerRefName, - elementTypeName, referencedTableClassName); - - builder.add(selectBuilder.build()).add("\n"); - - initializer.add(foreignKeyContainerRefName); - } else { - initializer.add("new $T().from($T.class).where()", ClassNames.SELECT, referencedTableClassName) - .add(selectBuilder.build()); - if (!isModelContainerAdapter && !isModelContainer) { - initializer.add(".querySingle()"); - } else { - if (isModelContainerAdapter) { - initializer.add(".queryModelContainer($L.getInstance($L.newDataInstance(), $T.class)).getData()", ModelUtils.getVariable(true), - ModelUtils.getVariable(true), referencedTableClassName); - } else { - initializer.add(".queryModelContainer(new $T($T.class))", elementTypeName, referencedTableClassName); - } - } - } - - builder.addStatement(columnAccess.setColumnAccessString(elementTypeName, elementName, elementName, - isModelContainerAdapter, ModelUtils.getVariable(isModelContainerAdapter), initializer.build(), false)); - - boolean putDefaultValue = putNullForContainerAdapter; - if (putContainerDefaultValue != putDefaultValue && isModelContainerAdapter) { - putDefaultValue = putContainerDefaultValue; - } - if (putDefaultValue && tableDefinition.assignDefaultValuesFromCursor) { - builder.nextControlFlow("else"); - builder.addStatement("$L.putDefault($S)", ModelUtils.getVariable(true), columnName); - } - if (endNonPrimitiveIf || !tableDefinition.assignDefaultValuesFromCursor) { - builder.endControlFlow(); - } - return builder.build(); - } - } - - @Override - public CodeBlock getToModelMethod() { - checkNeedsReferences(); - if (nonModelColumn) { - return super.getToModelMethod(); - } else { - CodeBlock.Builder builder = CodeBlock.builder(); - String statement = columnAccess - .getColumnAccessString(elementTypeName, elementName, elementName, - ModelUtils.getVariable(true), true, true); - String finalAccessStatement = getFinalAccessStatement(builder, true, statement); - - builder.beginControlFlow("if ($L != null)", finalAccessStatement); - if (!isModelContainer) { - CodeBlock.Builder modelContainerRetrieval = CodeBlock.builder(); - modelContainerRetrieval.add("$L.getContainerAdapter($T.class).toModel($L)", ClassNames.FLOW_MANAGER, - referencedTableClassName, finalAccessStatement); - builder.addStatement(columnAccess.setColumnAccessString(elementTypeName, elementName, elementName, - false, ModelUtils.getVariable(false), modelContainerRetrieval.build(), true)); - } else { - builder.addStatement(columnAccess.setColumnAccessString(elementTypeName, elementName, elementName, - false, ModelUtils.getVariable(false), CodeBlock.builder().add("new $T($L)", - elementTypeName, finalAccessStatement).build(), true)); - } - builder.endControlFlow(); - return builder.build(); - } - } - - @Override - public CodeBlock getForeignKeyContainerMethod(ClassName tableClassName) { - if (nonModelColumn) { - return super.getForeignKeyContainerMethod(tableClassName); - } else { - String access = columnAccess.getColumnAccessString(elementTypeName, containerKeyName, elementName, - ModelUtils.getVariable(false), false, false); - CodeBlock.Builder builder = CodeBlock.builder(); - CodeBlock.Builder elseBuilder = CodeBlock.builder(); - builder.beginControlFlow("if ($L != null)", access); - for (ForeignKeyReferenceDefinition referenceDefinition : foreignKeyReferenceDefinitionList) { - builder.add(referenceDefinition.getForeignKeyContainerMethod(tableClassName)); - elseBuilder.addStatement("$L.putDefault($T.$L)", ModelUtils.getVariable(true), tableClassName, referenceDefinition.columnName); - } - builder.nextControlFlow("else"); - builder.add(elseBuilder.build()); - builder.endControlFlow(); - return builder.build(); - } - } - - @Override - public void appendPropertyComparisonAccessStatement(boolean isModelContainerAdapter, CodeBlock.Builder codeBuilder) { - if (nonModelColumn || columnAccess instanceof TypeConverterAccess) { - super.appendPropertyComparisonAccessStatement(isModelContainerAdapter, codeBuilder); - } else { - String origStatement = getColumnAccessString(isModelContainerAdapter, false); - if (isPrimaryKey) { - TableDefinition referenced = manager.getTableDefinition(tableDefinition.databaseDefinition.elementTypeName, - referencedTableClassName); - String statement = ""; - String variableName = "container" + elementName; - TypeName typeName = elementTypeName; - if (isModelContainerAdapter) { - typeName = ParameterizedTypeName.get(ClassNames.MODEL_CONTAINER, elementTypeName, WildcardTypeName.subtypeOf(Object.class)); - } - codeBuilder.addStatement("\n$T $L = ($T) $L", typeName, variableName, typeName, origStatement); - codeBuilder.beginControlFlow("if ($L != null)", variableName); - CodeBlock.Builder elseBuilder = CodeBlock.builder(); - for (ForeignKeyReferenceDefinition referenceDefinition : getForeignKeyReferenceDefinitionList()) { - if (isModelContainer || isModelContainerAdapter) { - // check for null and retrieve proper value - String method = SQLiteHelper.getModelContainerMethod(referenceDefinition.columnClassName); - if (method == null) { - method = "get"; - } - statement = String - .format("%1s.%1sValue(%1s.%1s.getContainerKey())", variableName, method, referenced.outputClassName, referenceDefinition.foreignColumnName); - } else if (isModel) { - statement = referenceDefinition.getPrimaryReferenceString(isModelContainerAdapter); - } else { - statement = origStatement; - } - codeBuilder.addStatement("clause.and($T.$L.eq($L))", tableDefinition.getPropertyClassName(), referenceDefinition.columnName, statement); - elseBuilder.addStatement("clause.and($T.$L.eq(($T) $L))", tableDefinition.getPropertyClassName(), referenceDefinition.columnName, referenceDefinition.columnClassName, DefinitionUtils.getDefaultValueString(referenceDefinition.columnClassName)); - } - codeBuilder.nextControlFlow("else"); - codeBuilder.add(elseBuilder.build()); - codeBuilder.endControlFlow(); - } - } - } - - String getFinalAccessStatement(CodeBlock.Builder codeBuilder, boolean isModelContainerAdapter, String statement) { - String finalAccessStatement = statement; - if (columnAccess instanceof TypeConverterAccess || - columnAccess instanceof ModelContainerAccess || - isModelContainerAdapter) { - finalAccessStatement = getRefName(); - - TypeName typeName; - if (columnAccess instanceof TypeConverterAccess) { - typeName = ((TypeConverterAccess) columnAccess).typeConverterDefinition.getDbTypeName(); - } else if (columnAccess instanceof ModelContainerAccess) { - typeName = ModelUtils.getModelContainerType(manager, referencedTableClassName); - } else { - if (isModelContainer || isModel) { - typeName = ModelUtils.getModelContainerType(manager, referencedTableClassName); - statement = ModelUtils.getVariable(isModelContainerAdapter) + ".getInstance(" + statement + ", " + referencedTableClassName + ".class)"; - } else { - typeName = referencedTableClassName; - } - } - - codeBuilder.addStatement("$T $L = $L", typeName, - finalAccessStatement, statement); - } - return finalAccessStatement; - } - - String getForeignKeyReferenceAccess(boolean isModelContainerAdapter, String statement) { - if (columnAccess instanceof TypeConverterAccess || - columnAccess instanceof ModelContainerAccess || - isModelContainerAdapter) { - return getRefName(); - } else { - return statement; - } - } - - public String getRefName() { - return "ref" + elementName; - } - - public List getForeignKeyReferenceDefinitionList() { - checkNeedsReferences(); - return foreignKeyReferenceDefinitionList; - } - - /** - * If {@link ForeignKey} has no {@link ForeignKeyReference}s, we use the primary key the referenced - * table. We do this post-evaluation so all of the {@link TableDefinition} can be generated. - */ - private void checkNeedsReferences() { - TableDefinition referencedTableDefinition = manager.getTableDefinition(tableDefinition.databaseTypeName, referencedTableClassName); - if (referencedTableDefinition == null) { - manager.logError(ForeignKeyColumnDefinition.class, - "Could not find the referenced table definition %1s from %1s. Ensure it exists in the same" + - "database %1s", referencedTableClassName, tableDefinition.tableName, tableDefinition.databaseTypeName); - } else { - if (needsReferences) { - List primaryColumns = referencedTableDefinition.getPrimaryColumnDefinitions(); - for (ColumnDefinition primaryColumn : primaryColumns) { - ForeignKeyReferenceDefinition foreignKeyReferenceDefinition = - new ForeignKeyReferenceDefinition(manager, elementName, primaryColumn, - columnAccess, this, primaryColumns.size()); - foreignKeyReferenceDefinitionList.add(foreignKeyReferenceDefinition); - } - if (nonModelColumn) { - columnName = foreignKeyReferenceDefinitionList.get(0).columnName; - } - needsReferences = false; - } - - if (nonModelColumn && foreignKeyReferenceDefinitionList.size() == 1) { - ForeignKeyReferenceDefinition foreignKeyReferenceDefinition = foreignKeyReferenceDefinitionList.get(0); - columnName = foreignKeyReferenceDefinition.columnName; - } - } - } -} \ No newline at end of file diff --git a/dbflow-processor/src/main/java/com/raizlabs/android/dbflow/processor/definition/column/ForeignKeyReferenceDefinition.java b/dbflow-processor/src/main/java/com/raizlabs/android/dbflow/processor/definition/column/ForeignKeyReferenceDefinition.java deleted file mode 100644 index 83e9b70ac..000000000 --- a/dbflow-processor/src/main/java/com/raizlabs/android/dbflow/processor/definition/column/ForeignKeyReferenceDefinition.java +++ /dev/null @@ -1,209 +0,0 @@ -package com.raizlabs.android.dbflow.processor.definition.column; - -import com.raizlabs.android.dbflow.annotation.ForeignKeyReference; -import com.raizlabs.android.dbflow.processor.model.ProcessorManager; -import com.raizlabs.android.dbflow.processor.utils.ElementUtility; -import com.raizlabs.android.dbflow.processor.utils.ModelUtils; -import com.raizlabs.android.dbflow.sql.QueryBuilder; -import com.squareup.javapoet.ClassName; -import com.squareup.javapoet.CodeBlock; -import com.squareup.javapoet.TypeName; - -import java.util.concurrent.atomic.AtomicInteger; - -import javax.lang.model.element.TypeElement; -import javax.lang.model.type.MirroredTypeException; -import javax.lang.model.type.TypeMirror; - -/** - * Description: - */ -public class ForeignKeyReferenceDefinition { - - private final ProcessorManager manager; - private final String foreignKeyFieldName; - - public final String columnName; - public final String foreignColumnName; - public final TypeName columnClassName; - - private boolean isReferencedFieldPrivate; - private boolean isReferencedFieldPackagePrivate; - - public BaseColumnAccess columnAccess; - - private final BaseColumnAccess tableColumnAccess; - private final ForeignKeyColumnDefinition foreignKeyColumnDefinition; - - private final BaseColumnAccess simpleColumnAccess; - - public ForeignKeyReferenceDefinition(ProcessorManager manager, String foreignKeyFieldName, - ColumnDefinition referencedColumn, - BaseColumnAccess tableColumnAccess, - ForeignKeyColumnDefinition foreignKeyColumnDefinition, int referenceCount) { - this.manager = manager; - this.foreignKeyColumnDefinition = foreignKeyColumnDefinition; - this.tableColumnAccess = tableColumnAccess; - this.foreignKeyFieldName = foreignKeyFieldName; - - if (!foreignKeyColumnDefinition.isPrimaryKey && !foreignKeyColumnDefinition.isPrimaryKeyAutoIncrement() && !foreignKeyColumnDefinition.isRowId - || referenceCount > 0) { - columnName = foreignKeyFieldName + "_" + referencedColumn.columnName; - } else { - columnName = foreignKeyFieldName; - } - foreignColumnName = referencedColumn.columnName; - columnClassName = referencedColumn.elementTypeName; - - if (referencedColumn.columnAccess instanceof WrapperColumnAccess) { - isReferencedFieldPrivate = (((WrapperColumnAccess) referencedColumn.columnAccess).existingColumnAccess instanceof PrivateColumnAccess); - isReferencedFieldPackagePrivate = ((WrapperColumnAccess) referencedColumn.columnAccess).existingColumnAccess instanceof PackagePrivateAccess; - } else { - isReferencedFieldPrivate = (referencedColumn.columnAccess instanceof PrivateColumnAccess); - - // fix here to ensure we can access it otherwise we generate helper - boolean isPackagePrivate = ElementUtility.isPackagePrivate(referencedColumn.element); - boolean isPackagePrivateNotInSamePackage = isPackagePrivate && !ElementUtility.isInSamePackage(manager, referencedColumn.element, foreignKeyColumnDefinition.element); - - isReferencedFieldPackagePrivate = referencedColumn.columnAccess instanceof PackagePrivateAccess - || isPackagePrivateNotInSamePackage; - } - if (isReferencedFieldPrivate && !foreignKeyColumnDefinition.isModelContainer) { - columnAccess = new PrivateColumnAccess(referencedColumn.column, false); - } else if (isReferencedFieldPackagePrivate && !foreignKeyColumnDefinition.isModelContainer) { - columnAccess = new PackagePrivateAccess(referencedColumn.packageName, - foreignKeyColumnDefinition.tableDefinition.databaseDefinition.classSeparator, - ClassName.get((TypeElement) referencedColumn.element.getEnclosingElement()).simpleName()); - PackagePrivateAccess.putElement(((PackagePrivateAccess) columnAccess).helperClassName, foreignColumnName); - } else { - if (foreignKeyColumnDefinition.isModelContainer) { - columnAccess = new ModelContainerAccess(tableColumnAccess, foreignColumnName); - } else { - columnAccess = new SimpleColumnAccess(); - } - } - - simpleColumnAccess = new SimpleColumnAccess(columnAccess instanceof PackagePrivateAccess); - } - - public ForeignKeyReferenceDefinition(ProcessorManager manager, String foreignKeyFieldName, - ForeignKeyReference foreignKeyReference, BaseColumnAccess tableColumnAccess, - ForeignKeyColumnDefinition foreignKeyColumnDefinition) { - this.manager = manager; - this.tableColumnAccess = tableColumnAccess; - this.foreignKeyColumnDefinition = foreignKeyColumnDefinition; - this.foreignKeyFieldName = foreignKeyFieldName; - - columnName = foreignKeyReference.columnName(); - foreignColumnName = foreignKeyReference.foreignKeyColumnName(); - - TypeMirror columnClass = null; - try { - foreignKeyReference.columnType(); - } catch (MirroredTypeException mte) { - columnClass = mte.getTypeMirror(); - } - columnClassName = TypeName.get(columnClass); - isReferencedFieldPrivate = foreignKeyReference.referencedFieldIsPrivate(); - isReferencedFieldPackagePrivate = foreignKeyReference.referencedFieldIsPackagePrivate(); - if (isReferencedFieldPrivate && !foreignKeyColumnDefinition.isModelContainer) { - columnAccess = new PrivateColumnAccess(foreignKeyReference); - } else if (isReferencedFieldPackagePrivate && !foreignKeyColumnDefinition.isModelContainer) { - columnAccess = new PackagePrivateAccess(foreignKeyColumnDefinition.referencedTableClassName.packageName(), - foreignKeyColumnDefinition.tableDefinition.databaseDefinition.classSeparator, - foreignKeyColumnDefinition.referencedTableClassName.simpleName()); - PackagePrivateAccess.putElement(((PackagePrivateAccess) columnAccess).helperClassName, foreignColumnName); - } else { - if (foreignKeyColumnDefinition.isModelContainer) { - columnAccess = new ModelContainerAccess(tableColumnAccess, foreignColumnName); - } else { - columnAccess = new SimpleColumnAccess(); - } - } - - simpleColumnAccess = new SimpleColumnAccess(columnAccess instanceof PackagePrivateAccess); - } - - CodeBlock getCreationStatement() { - return DefinitionUtils.getCreationStatement(columnClassName, null, columnName).build(); - } - - String getPrimaryKeyName() { - return QueryBuilder.quote(columnName); - } - - CodeBlock getContentValuesStatement(boolean isModelContainerAdapter) { - // fix its access here. - String shortAccess = tableColumnAccess.getShortAccessString(foreignKeyColumnDefinition.elementClassName, foreignKeyFieldName, isModelContainerAdapter, false); - shortAccess = foreignKeyColumnDefinition.getForeignKeyReferenceAccess(isModelContainerAdapter, shortAccess); - - String columnShortAccess = getShortColumnAccess(isModelContainerAdapter, false, shortAccess); - - String combined; - if (!(columnAccess instanceof PackagePrivateAccess)) { - combined = shortAccess + (isModelContainerAdapter ? "" : ".") + columnShortAccess; - } else { - combined = columnShortAccess; - } - return DefinitionUtils.getContentValuesStatement(columnShortAccess, combined, - columnName, columnClassName, isModelContainerAdapter, simpleColumnAccess, - getForeignKeyColumnVariable(isModelContainerAdapter), null, - foreignKeyColumnDefinition.tableDefinition.outputClassName).build(); - } - - public String getPrimaryReferenceString(boolean isModelContainerAdapter) { - String shortAccess = tableColumnAccess.getShortAccessString(foreignKeyColumnDefinition.elementClassName, foreignKeyFieldName, isModelContainerAdapter, false); - shortAccess = foreignKeyColumnDefinition.getForeignKeyReferenceAccess(isModelContainerAdapter, shortAccess); - String columnShortAccess = getShortColumnAccess(isModelContainerAdapter, false, shortAccess); - String combined; - if (!(columnAccess instanceof PackagePrivateAccess)) { - combined = ModelUtils.getVariable(isModelContainerAdapter) + "." + shortAccess + (isModelContainerAdapter ? "" : ".") + columnShortAccess; - } else { - combined = columnShortAccess; - } - return combined; - } - - CodeBlock getSQLiteStatementMethod(AtomicInteger index, boolean isModelContainerAdapter) { - String shortAccess = tableColumnAccess.getShortAccessString(foreignKeyColumnDefinition.elementClassName, foreignKeyFieldName, isModelContainerAdapter, true); - shortAccess = foreignKeyColumnDefinition.getForeignKeyReferenceAccess(isModelContainerAdapter, shortAccess); - - String columnShortAccess = getShortColumnAccess(isModelContainerAdapter, true, shortAccess); - String combined = shortAccess + (isModelContainerAdapter ? "" : ".") + columnShortAccess; - return DefinitionUtils.getSQLiteStatementMethod( - index, columnShortAccess, combined, - columnClassName, isModelContainerAdapter, simpleColumnAccess, - getForeignKeyColumnVariable(isModelContainerAdapter), false, null).build(); - } - - CodeBlock getForeignKeyContainerMethod(ClassName tableClassName) { - - String access = getShortColumnAccess(false, false, tableColumnAccess.getShortAccessString(foreignKeyColumnDefinition.elementClassName, foreignKeyFieldName, false, false)); - if (foreignKeyColumnDefinition.isModelContainer) { - access = foreignKeyColumnDefinition.getColumnAccessString(false, false) + "." + access; - } else if (foreignKeyColumnDefinition.isModel && !isReferencedFieldPackagePrivate) { - access = foreignKeyColumnDefinition.getColumnAccessString(false, false) + "." + access; - } - - CodeBlock.Builder codeBuilder = CodeBlock.builder(); - codeBuilder.addStatement("$L.put($T.$L, $L)", ModelUtils.getVariable(true), tableClassName, columnName, access); - return codeBuilder.build(); - } - - private String getForeignKeyColumnVariable(boolean isModelContainerAdapter) { - return isModelContainerAdapter ? foreignKeyColumnDefinition.getRefName() : ModelUtils.getVariable(isModelContainerAdapter); - } - - private String getShortColumnAccess(boolean isModelContainerAdapter, boolean isSqliteMethod, String shortAccess) { - if (isModelContainerAdapter) { - return foreignColumnName; - } else { - if (columnAccess instanceof PackagePrivateAccess) { - return columnAccess.getColumnAccessString(columnClassName, foreignColumnName, "", ModelUtils.getVariable(isModelContainerAdapter) + "." + shortAccess, isModelContainerAdapter, isSqliteMethod); - } else { - return columnAccess.getShortAccessString(columnClassName, foreignColumnName, isModelContainerAdapter, isSqliteMethod); - } - } - } - -} \ No newline at end of file diff --git a/dbflow-processor/src/main/java/com/raizlabs/android/dbflow/processor/definition/method/ExternalForeignKeyContainerMethod.java b/dbflow-processor/src/main/java/com/raizlabs/android/dbflow/processor/definition/method/ExternalForeignKeyContainerMethod.java deleted file mode 100644 index 4fa5e1982..000000000 --- a/dbflow-processor/src/main/java/com/raizlabs/android/dbflow/processor/definition/method/ExternalForeignKeyContainerMethod.java +++ /dev/null @@ -1,45 +0,0 @@ -package com.raizlabs.android.dbflow.processor.definition.method; - -import com.raizlabs.android.dbflow.processor.ClassNames; -import com.raizlabs.android.dbflow.processor.definition.TableDefinition; -import com.raizlabs.android.dbflow.processor.definition.column.ColumnDefinition; -import com.raizlabs.android.dbflow.processor.utils.ModelUtils; -import com.squareup.javapoet.CodeBlock; -import com.squareup.javapoet.MethodSpec; -import com.squareup.javapoet.ParameterizedTypeName; - -import javax.lang.model.element.Modifier; - -/** - * Description: Writes a Model into a ForeignKeyContainer for convenience. - */ -public class ExternalForeignKeyContainerMethod implements MethodDefinition { - - private final TableDefinition tableDefinition; - - public ExternalForeignKeyContainerMethod(TableDefinition tableDefinition) { - this.tableDefinition = tableDefinition; - } - - - @Override - public MethodSpec getMethodSpec() { - - CodeBlock.Builder codeBuilder = CodeBlock.builder(); - codeBuilder.addStatement("$T $L = new $T<>($T.class)", ClassNames.EXTERNAL_FOREIGN_KEY_CONTAINER, - ModelUtils.getVariable(true), ClassNames.EXTERNAL_FOREIGN_KEY_CONTAINER, tableDefinition.elementClassName); - for (ColumnDefinition columnDefinition : tableDefinition.getPrimaryColumnDefinitions()) { - codeBuilder.add(columnDefinition.getForeignKeyContainerMethod(tableDefinition.getPropertyClassName())); - } - codeBuilder.addStatement("return $L", ModelUtils.getVariable(true)); - - - return MethodSpec.methodBuilder("toExternalForeignKeyContainer") - .addAnnotation(Override.class) - .addModifiers(Modifier.PUBLIC, Modifier.FINAL) - .addParameter(tableDefinition.elementClassName, ModelUtils.getVariable(false)) - .addCode(codeBuilder.build()) - .returns(ParameterizedTypeName.get(ClassNames.EXTERNAL_FOREIGN_KEY_CONTAINER, tableDefinition.elementClassName)) - .build(); - } -} diff --git a/dbflow/src/main/java/com/raizlabs/android/dbflow/single/FlowQueryModelLoader.java b/dbflow/src/main/java/com/raizlabs/android/dbflow/single/FlowQueryModelLoader.java index 15087fd0a..bd271e39a 100644 --- a/dbflow/src/main/java/com/raizlabs/android/dbflow/single/FlowQueryModelLoader.java +++ b/dbflow/src/main/java/com/raizlabs/android/dbflow/single/FlowQueryModelLoader.java @@ -14,7 +14,7 @@ */ @TargetApi(11) public class FlowQueryModelLoader - extends FlowSingleModelLoader { + extends FlowSingleModelLoader { public FlowQueryModelLoader (Context context, Class model, Queriable queriable) { super (context, model, FlowManager.getQueryModelAdapter (model), queriable); diff --git a/dbflow/src/main/java/com/raizlabs/android/dbflow/structure/container/ForeignKeyContainer.java b/dbflow/src/main/java/com/raizlabs/android/dbflow/structure/container/ForeignKeyContainer.java deleted file mode 100644 index 01035b224..000000000 --- a/dbflow/src/main/java/com/raizlabs/android/dbflow/structure/container/ForeignKeyContainer.java +++ /dev/null @@ -1,147 +0,0 @@ -package com.raizlabs.android.dbflow.structure.container; - -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; - -import com.raizlabs.android.dbflow.sql.language.Select; -import com.raizlabs.android.dbflow.structure.Model; - -import java.util.Iterator; -import java.util.LinkedHashMap; -import java.util.Map; - -/** - * Description: Holds onto {@link com.raizlabs.android.dbflow.annotation.ForeignKey} data so the {@link - * com.raizlabs.android.dbflow.structure.Model} can lazy-load the foreign key data. Overrides most {@link - * com.raizlabs.android.dbflow.structure.Model} methods to save the associated model data instead of its actual - * underlying data, which in this case is just the primary keys. Any {@link com.raizlabs.android.dbflow.structure.Model} - * method will force this object to load the referenced Model from the DB to interact with. - */ -public class ForeignKeyContainer extends SimpleModelContainer> { - - private TModel relationshipModel; - - /** - * Constructs a new instance with the specified table. - * - * @param table The table to associate the container with - */ - public ForeignKeyContainer(Class table) { - this(table, new LinkedHashMap()); - } - - /** - * Constructs a new instance with table and default data. - * - * @param table The table to associate the container with - * @param data The data to store in this container - */ - @SuppressWarnings("unchecked") - public ForeignKeyContainer(Class table, Map data) { - super(table, data); - } - - public ForeignKeyContainer(@NonNull ModelContainer existingContainer) { - super(existingContainer); - } - - @NonNull - @Override - public Map newDataInstance() { - return new LinkedHashMap<>(); - } - - @Override - @SuppressWarnings("unchecked") - public BaseModelContainer getInstance(Object inValue, Class columnClass) { - if (inValue instanceof ModelContainer) { - return new ForeignKeyContainer((ModelContainer) inValue); - } else { - return new ForeignKeyContainer(columnClass, (Map) inValue); - } - } - - @Override - public boolean containsValue(String key) { - Map data = getData(); - return data != null && data.containsKey(key) && data.get(key) != null; - } - - @Override - public Object getValue(String key) { - Map data = getData(); - return data != null ? data.get(key) : null; - } - - @Override - public void put(String columnName, Object value) { - getData().put(columnName, value); - } - - @Override - public void setModel(TModel model) { - super.setModel(model); - - Map data = getData(); - if (data == null) { - data = new LinkedHashMap<>(); - setData(data); - } - } - - @Nullable - @Override - public Iterator iterator() { - return data != null ? data.keySet().iterator() : null; - } - - /** - * Attempts to load the model from the DB using a {@link Select} query. This should be preferred over - * {@link #toModel()} since this will load the relationship from the DB using it's underlying data. - * - * @return the result of running a primary where query on the contained data. - */ - @Nullable - public TModel load() { - if (relationshipModel == null && getData() != null) { - relationshipModel = new Select().from(modelAdapter.getModelClass()).where(modelContainerAdapter.getPrimaryConditionClause(this)).querySingle(); - } - return relationshipModel; - } - - /** - * @return forces a reload of the underlying model and returns it. - */ - @Nullable - public TModel reload() { - relationshipModel = null; - return load(); - } - - @Override - public void save() { - throw new InvalidMethodCallException("Cannot call save() on a foreign key container. Call load() and then save() instead"); - } - - @Override - public void delete() { - throw new InvalidMethodCallException("Cannot call delete() on a foreign key container. Call load() and then delete() instead"); - } - - @Override - public void update() { - throw new InvalidMethodCallException("Cannot call update() on a foreign key container. Call load() and then update() instead"); - } - - @Override - public void insert() { - throw new InvalidMethodCallException("Cannot call insert() on a foreign key container. Call load() and then insert() instead"); - } - - private static class InvalidMethodCallException extends RuntimeException { - - public InvalidMethodCallException(String detailMessage) { - super(detailMessage); - } - } -} From 34acd05abda24f44ae37fd102433d1a8be2c9e3d Mon Sep 17 00:00:00 2001 From: "James H. Hill" Date: Wed, 30 Nov 2016 20:10:09 -0500 Subject: [PATCH 34/47] Fixed merge conflicts --- .../test/container/ForeignInteractionModel.java | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/dbflow-tests/src/test/java/com/raizlabs/android/dbflow/test/container/ForeignInteractionModel.java b/dbflow-tests/src/test/java/com/raizlabs/android/dbflow/test/container/ForeignInteractionModel.java index 9080fd087..c34cf8f83 100644 --- a/dbflow-tests/src/test/java/com/raizlabs/android/dbflow/test/container/ForeignInteractionModel.java +++ b/dbflow-tests/src/test/java/com/raizlabs/android/dbflow/test/container/ForeignInteractionModel.java @@ -16,16 +16,6 @@ public class ForeignInteractionModel extends TestModel1 { @Column @ForeignKey( -<<<<<<< HEAD - onDelete = ForeignKeyAction.CASCADE, - onUpdate = ForeignKeyAction.CASCADE, - references = { - @ForeignKeyReference(columnName = "testmodel_id", foreignKeyColumnName = "name", columnType = String.class), - @ForeignKeyReference(columnName = "testmodel_type", foreignKeyColumnName = "type", columnType = String.class) - }, - saveForeignKeyModel = true) - ForeignKeyContainer testModel1; -======= onDelete = ForeignKeyAction.CASCADE, onUpdate = ForeignKeyAction.CASCADE, references = @@ -39,7 +29,6 @@ public class ForeignInteractionModel extends TestModel1 { columnType = String.class)} ) ParentModel testModel1; ->>>>>>> raizlabs/develop public TestModel1 getTestModel1() { return testModel1 != null ? testModel1 : null; From 02129820643ff76fc7034ac25f60613ad44bad17 Mon Sep 17 00:00:00 2001 From: "James H. Hill" Date: Wed, 30 Nov 2016 20:11:43 -0500 Subject: [PATCH 35/47] Fixed merge conflicts --- usage2/KotlinSupport.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/usage2/KotlinSupport.md b/usage2/KotlinSupport.md index 90dc8df74..8d0defe28 100644 --- a/usage2/KotlinSupport.md +++ b/usage2/KotlinSupport.md @@ -187,11 +187,7 @@ items.processInTransactionAsync({ it, databaseWrapper -> it.delete(databaseWrapp ``` -<<<<<<< HEAD -The extension method on `Collection` allows you to perform this on all -======= The extension method on `Collection` allows you to perform this on all ->>>>>>> raizlabs/develop collections from your Table! If you wish to easily do them _synchronously_ then use: From d1a52cbdb1f8db81285b160a1aa4108ae17c4467 Mon Sep 17 00:00:00 2001 From: "James H. Hill" Date: Wed, 30 Nov 2016 20:12:40 -0500 Subject: [PATCH 36/47] Fixed merge conflicts --- usage2/Models.md | 5 ----- usage2/TypeConverters.md | 5 ----- 2 files changed, 10 deletions(-) diff --git a/usage2/Models.md b/usage2/Models.md index 3d5661432..f48853b45 100644 --- a/usage2/Models.md +++ b/usage2/Models.md @@ -55,13 +55,8 @@ Columns have a wide-range of supported types in the `Model` classes: 5. `Model` as fields, but only as `@PrimaryKey` and/or `@ForeignKey` **Unsupported Types**: -<<<<<<< HEAD - 1. `List` : List columns are not supported and not generally proper for a relational database. However, you can get away with a non-generic `List` column via a `TypeConverter`. But again, avoid this if you can. - 2. Anything that is generically typed (even with an associated `TypeConverter`), **except** `ModelContainer` and `ForeignKeyContainer` fields. If you need to include the field, subclass the generic object and provide a `TypeConverter`. -======= 1. `List` : List columns are not supported and not generally proper for a relational database. However, you can get away with a non-generic `List` column via a `TypeConverter`. But again, avoid this if you can. 2. Anything that is generically typed (even with an associated `TypeConverter`). If you need to include the field, subclass the generic object and provide a `TypeConverter`. ->>>>>>> raizlabs/develop ## Inherited Columns diff --git a/usage2/TypeConverters.md b/usage2/TypeConverters.md index d1924c629..809c5c657 100644 --- a/usage2/TypeConverters.md +++ b/usage2/TypeConverters.md @@ -11,13 +11,8 @@ When building out `Model` classes, you may wish to provide a different type of ` 8. `ForeignKeyContainer` as `@ForeignKey` `TypeConverter` do _not_ support: -<<<<<<< HEAD - 1. Any Parameterized fields _except_ `ForeignKeyContainer` and `ModelContainer` fields. - 2. `List`, `Map`, etc. Best way to fix this is to create a separate table [relationship](/usage2/Relationships.md) -======= 1. Any Parameterized fields. 2. `List`, `Map`, etc. Best way to fix this is to create a separate table [relationship](/usage2/Relationships.md) ->>>>>>> raizlabs/develop 3. Conversion from one type-converter to another (i.e `JSONObject` to `Date`). The first parameter of `TypeConverter` is the value of the type as if it was a primitive/boxed type. 4. Conversion from custom type to `Model`, or `Model` to a supported type. 5. The custom class _must_ map to a non-complex field such as `String`, numbers, `char`/`Character` or `Blob` From fd72253980d0c86a5cfb7cec5c120588d06e7ec8 Mon Sep 17 00:00:00 2001 From: "James H. Hill" Date: Thu, 1 Dec 2016 09:22:54 -0500 Subject: [PATCH 37/47] Removed obsolete file --- .../raizlabs/android/dbflow/SecondModel.java | 19 ------------------- 1 file changed, 19 deletions(-) delete mode 100644 app/src/main/java/com/raizlabs/android/dbflow/SecondModel.java diff --git a/app/src/main/java/com/raizlabs/android/dbflow/SecondModel.java b/app/src/main/java/com/raizlabs/android/dbflow/SecondModel.java deleted file mode 100644 index 43ed68118..000000000 --- a/app/src/main/java/com/raizlabs/android/dbflow/SecondModel.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.raizlabs.android.dbflow; - -import com.raizlabs.android.dbflow.annotation.ForeignKey; -import com.raizlabs.android.dbflow.annotation.PrimaryKey; -import com.raizlabs.android.dbflow.annotation.Table; -import com.raizlabs.android.dbflow.structure.BaseModel; -import com.raizlabs.android.dbflow.structure.container.ForeignKeyContainer; - -/** - * Description: - */ -@Table(database = SecondAppDatabase.class) -public class SecondModel extends BaseModel { - @PrimaryKey - String name; - - @ForeignKey - ForeignKeyContainer secondModel; -} From 0554ec45360c605bd88f6df4eb536882e1d02e82 Mon Sep 17 00:00:00 2001 From: "James H. Hill" Date: Thu, 1 Dec 2016 09:34:22 -0500 Subject: [PATCH 38/47] Fixed formatting issues --- .../dbflow/list/FlowCursorAdapter.java | 20 ++-- .../android/dbflow/list/FlowCursorLoader.java | 99 ++++++++++--------- .../dbflow/list/FlowSimpleCursorAdapter.java | 17 ++-- .../dbflow/single/FlowModelLoader.java | 4 +- .../dbflow/single/FlowModelViewLoader.java | 6 +- .../dbflow/single/FlowQueryModelLoader.java | 6 +- .../dbflow/single/FlowSingleModelLoader.java | 74 +++++++------- 7 files changed, 112 insertions(+), 114 deletions(-) diff --git a/dbflow/src/main/java/com/raizlabs/android/dbflow/list/FlowCursorAdapter.java b/dbflow/src/main/java/com/raizlabs/android/dbflow/list/FlowCursorAdapter.java index c85a0fd4e..e2b9f299a 100644 --- a/dbflow/src/main/java/com/raizlabs/android/dbflow/list/FlowCursorAdapter.java +++ b/dbflow/src/main/java/com/raizlabs/android/dbflow/list/FlowCursorAdapter.java @@ -16,24 +16,24 @@ * @param */ public abstract class FlowCursorAdapter extends CursorAdapter { - private final ModelAdapter mModelAdapter_; + private final ModelAdapter mModelAdapter; - public FlowCursorAdapter (Context context, Class modelClass, Cursor c, boolean autoRequery) { - super (context, c, autoRequery); + public FlowCursorAdapter(Context context, Class modelClass, Cursor c, boolean autoRequery) { + super(context, c, autoRequery); - this.mModelAdapter_ = FlowManager.getModelAdapter (modelClass); + this.mModelAdapter = FlowManager.getModelAdapter(modelClass); } @TargetApi(11) - public FlowCursorAdapter (Context context, Class modelClass, Cursor c, int flags) { - super (context, c, flags); + public FlowCursorAdapter(Context context, Class modelClass, Cursor c, int flags) { + super(context, c, flags); - this.mModelAdapter_ = FlowManager.getModelAdapter (modelClass); + this.mModelAdapter = FlowManager.getModelAdapter(modelClass); } @Override - public TModel getItem (int position) { - Cursor cursor = (Cursor) super.getItem (position); - return cursor != null ? this.mModelAdapter_.loadFromCursor (cursor) : null; + public TModel getItem(int position) { + Cursor cursor = (Cursor) super.getItem(position); + return cursor != null ? this.mModelAdapter.loadFromCursor(cursor) : null; } } diff --git a/dbflow/src/main/java/com/raizlabs/android/dbflow/list/FlowCursorLoader.java b/dbflow/src/main/java/com/raizlabs/android/dbflow/list/FlowCursorLoader.java index d47588d4d..7fc7e05c0 100644 --- a/dbflow/src/main/java/com/raizlabs/android/dbflow/list/FlowCursorLoader.java +++ b/dbflow/src/main/java/com/raizlabs/android/dbflow/list/FlowCursorLoader.java @@ -21,10 +21,9 @@ * Specialization of AsyncTaskLoader for Cursor objects in DBFlow. */ @TargetApi(11) -public class FlowCursorLoader extends AsyncTaskLoader -{ +public class FlowCursorLoader extends AsyncTaskLoader { /// Models to be observed for changes. - private HashSet> mModels = new HashSet<> (); + private final HashSet> mModels = new HashSet<>(); /// Queriable operation that the loader executes. private Queriable mQueriable; @@ -32,7 +31,9 @@ public class FlowCursorLoader extends AsyncTaskLoader /// Cursor for the loader. private Cursor mCursor; - private final ForceLoadContentObserver mObserver = new ForceLoadContentObserver (); + /// The observer that triggers the loader to reload anytime if it receives + /// notification of a change. + private final ForceLoadContentObserver mObserver = new ForceLoadContentObserver(); private boolean mListening = false; @@ -41,29 +42,29 @@ public class FlowCursorLoader extends AsyncTaskLoader * String[], String, String[], String) ContentResolver.query()} for documentation on the meaning * of the parameters. These will be passed as-is to that call. */ - public FlowCursorLoader (Context context, Queriable queriable) { - super (context); + public FlowCursorLoader(Context context, Queriable queriable) { + super(context); this.mQueriable = queriable; } @Override - public Cursor loadInBackground () { - Cursor cursor = this.mQueriable.query (); + public Cursor loadInBackground() { + Cursor cursor = this.mQueriable.query(); if (cursor != null) { - cursor.getCount (); + cursor.getCount(); } return cursor; } @Override - public void deliverResult (Cursor cursor) { - if (this.isReset ()) { + public void deliverResult(Cursor cursor) { + if (this.isReset()) { // An async query came in while the loader is stopped if (cursor != null) { - cursor.close (); + cursor.close(); } return; @@ -72,18 +73,18 @@ public void deliverResult (Cursor cursor) { Cursor oldCursor = this.mCursor; this.mCursor = cursor; - if (this.isStarted ()) { - super.deliverResult (cursor); + if (this.isStarted()) { + super.deliverResult(cursor); } - if (oldCursor != null && oldCursor != cursor && !oldCursor.isClosed ()) { - oldCursor.close (); + if (oldCursor != null && oldCursor != cursor && !oldCursor.isClosed()) { + oldCursor.close(); } // Now that the result has been delivered, start listening for changes // to the target models. Doing this at anytime earlier runs the risk of // listening for changes while we are still loading content. - this.startListeningForChanges (); + this.startListeningForChanges(); } /** @@ -92,75 +93,75 @@ public void deliverResult (Cursor cursor) { * * @param model */ - public void registerForContentChanges (Class model) { - if (this.mModels.contains (model)) { + public void registerForContentChanges(Class model) { + if (this.mModels.contains(model)) { return; } - this.mModels.add (model); - this.mObserver.registerForContentChanges (this.getContext (), model); + this.mModels.add(model); + this.mObserver.registerForContentChanges(this.getContext(), model); } @Override - protected void onStartLoading () { + protected void onStartLoading() { if (this.mCursor != null) { - this.deliverResult (this.mCursor); + this.deliverResult(this.mCursor); } - if (this.takeContentChanged () || this.mCursor == null) { - this.forceLoad (); + if (this.takeContentChanged() || this.mCursor == null) { + this.forceLoad(); } } @Override - protected void onStopLoading () { + protected void onStopLoading() { // Make sure the loading has stopped. - this.cancelLoad (); + this.cancelLoad(); } @Override - public void onCanceled (Cursor cursor) { - if (cursor != null && !cursor.isClosed ()) { - cursor.close (); + public void onCanceled(Cursor cursor) { + if (cursor != null && !cursor.isClosed()) { + cursor.close(); } - this.stopListeningForChanges (); + this.stopListeningForChanges(); } @Override - protected void onReset () { - super.onReset (); + protected void onReset() { + super.onReset(); - this.startLoading (); + this.startLoading(); - if (mCursor != null && !mCursor.isClosed ()) { - mCursor.close (); + if (mCursor != null && !mCursor.isClosed()) { + mCursor.close(); } mCursor = null; - this.mObserver.unregisterForContentChanges (this.getContext ()); + this.mObserver.unregisterForContentChanges(this.getContext()); } - private void startListeningForChanges () { + private void startListeningForChanges() { if (!this.mListening) { - this.mObserver.addModelChangeListener (this.mObserver); + this.mObserver.addModelChangeListener(this.mObserver); this.mListening = true; } } - private void stopListeningForChanges () { + private void stopListeningForChanges() { if (this.mListening) { - this.mObserver.removeModelChangeListener (this.mObserver); + this.mObserver.removeModelChangeListener(this.mObserver); this.mListening = false; } } - public Collection> getModels () { + public Collection> getModels() { return this.mModels; } - public FlowContentObserver getContentObserver () { + public FlowContentObserver getContentObserver() { return this.mObserver; } @@ -169,29 +170,29 @@ private final class ForceLoadContentObserver extends FlowContentObserver private boolean endOfTransaction = false; @Override - public boolean deliverSelfNotifications () { + public boolean deliverSelfNotifications() { return false; } @Override - public void onModelStateChanged (@Nullable Class table, BaseModel.Action action, @NonNull SQLCondition[] primaryKeyValues) { + public void onModelStateChanged(@Nullable Class table, BaseModel.Action action, @NonNull SQLCondition[] primaryKeyValues) { if (!this.endOfTransaction) { if (action == BaseModel.Action.INSERT || action == BaseModel.Action.DELETE || action == BaseModel.Action.UPDATE) { - onContentChanged (); + onContentChanged(); } } } @Override - public void endTransactionAndNotify () { + public void endTransactionAndNotify() { // Mark this as the end of a transactions, and pass control to the base class // to perform the notifications. this.endOfTransaction = true; - super.endTransactionAndNotify (); + super.endTransactionAndNotify(); // Notify the observer the content has changed. this.endOfTransaction = false; - onContentChanged (); + onContentChanged(); } } } \ No newline at end of file diff --git a/dbflow/src/main/java/com/raizlabs/android/dbflow/list/FlowSimpleCursorAdapter.java b/dbflow/src/main/java/com/raizlabs/android/dbflow/list/FlowSimpleCursorAdapter.java index baf805afe..eb783f7a7 100644 --- a/dbflow/src/main/java/com/raizlabs/android/dbflow/list/FlowSimpleCursorAdapter.java +++ b/dbflow/src/main/java/com/raizlabs/android/dbflow/list/FlowSimpleCursorAdapter.java @@ -16,24 +16,21 @@ * * @param */ -public class FlowSimpleCursorAdapter extends SimpleCursorAdapter -{ +public class FlowSimpleCursorAdapter extends SimpleCursorAdapter { private final Class mModel; private final ModelAdapter mModelAdapter; @TargetApi(11) - public FlowSimpleCursorAdapter (Context context, Class modelClass, int layout, Cursor c, String[] from, int[] to, int flags) - { - super (context, layout, c, from, to, flags); + public FlowSimpleCursorAdapter(Context context, Class modelClass, int layout, Cursor c, String[] from, int[] to, int flags) { + super(context, layout, c, from, to, flags); this.mModel = modelClass; - this.mModelAdapter = FlowManager.getModelAdapter (modelClass); + this.mModelAdapter = FlowManager.getModelAdapter(modelClass); } @Override - public TModel getItem (int position) - { - Cursor cursor = (Cursor) super.getItem (position); - return cursor != null ? this.mModelAdapter.loadFromCursor (cursor) : null; + public TModel getItem(int position) { + Cursor cursor = (Cursor) super.getItem(position); + return cursor != null ? this.mModelAdapter.loadFromCursor(cursor) : null; } } diff --git a/dbflow/src/main/java/com/raizlabs/android/dbflow/single/FlowModelLoader.java b/dbflow/src/main/java/com/raizlabs/android/dbflow/single/FlowModelLoader.java index 579a964f2..3cd47e806 100644 --- a/dbflow/src/main/java/com/raizlabs/android/dbflow/single/FlowModelLoader.java +++ b/dbflow/src/main/java/com/raizlabs/android/dbflow/single/FlowModelLoader.java @@ -16,7 +16,7 @@ public class FlowModelLoader extends FlowSingleModelLoader { - public FlowModelLoader (Context context, Class model, Queriable queriable) { - super (context, model, FlowManager.getModelAdapter (model), queriable); + public FlowModelLoader(Context context, Class model, Queriable queriable) { + super(context, model, FlowManager.getModelAdapter(model), queriable); } } \ No newline at end of file diff --git a/dbflow/src/main/java/com/raizlabs/android/dbflow/single/FlowModelViewLoader.java b/dbflow/src/main/java/com/raizlabs/android/dbflow/single/FlowModelViewLoader.java index 3f9ef4c88..35d280215 100644 --- a/dbflow/src/main/java/com/raizlabs/android/dbflow/single/FlowModelViewLoader.java +++ b/dbflow/src/main/java/com/raizlabs/android/dbflow/single/FlowModelViewLoader.java @@ -18,8 +18,8 @@ public class FlowModelViewLoader extends FlowSingleModelLoader { - @SuppressWarnings ("unchecked") - public FlowModelViewLoader (Context context, Class model, Class modelView, Queriable queriable) { - super (context, model, (InstanceAdapter) FlowManager.getModelViewAdapter (modelView), queriable); + @SuppressWarnings("unchecked") + public FlowModelViewLoader(Context context, Class model, Class modelView, Queriable queriable) { + super(context, model, (InstanceAdapter) FlowManager.getModelViewAdapter(modelView), queriable); } } \ No newline at end of file diff --git a/dbflow/src/main/java/com/raizlabs/android/dbflow/single/FlowQueryModelLoader.java b/dbflow/src/main/java/com/raizlabs/android/dbflow/single/FlowQueryModelLoader.java index bd271e39a..33302b5b3 100644 --- a/dbflow/src/main/java/com/raizlabs/android/dbflow/single/FlowQueryModelLoader.java +++ b/dbflow/src/main/java/com/raizlabs/android/dbflow/single/FlowQueryModelLoader.java @@ -16,9 +16,9 @@ public class FlowQueryModelLoader extends FlowSingleModelLoader { - public FlowQueryModelLoader (Context context, Class model, Queriable queriable) { - super (context, model, FlowManager.getQueryModelAdapter (model), queriable); + public FlowQueryModelLoader(Context context, Class model, Queriable queriable) { + super(context, model, FlowManager.getQueryModelAdapter(model), queriable); - this.setObserveModel (false); + this.setObserveModel(false); } } \ No newline at end of file diff --git a/dbflow/src/main/java/com/raizlabs/android/dbflow/single/FlowSingleModelLoader.java b/dbflow/src/main/java/com/raizlabs/android/dbflow/single/FlowSingleModelLoader.java index db61f4bea..ab604408e 100644 --- a/dbflow/src/main/java/com/raizlabs/android/dbflow/single/FlowSingleModelLoader.java +++ b/dbflow/src/main/java/com/raizlabs/android/dbflow/single/FlowSingleModelLoader.java @@ -21,8 +21,7 @@ */ @TargetApi(11) public abstract class FlowSingleModelLoader - extends AsyncTaskLoader -{ + extends AsyncTaskLoader { /// Model type being loaded. private final Class mModel; @@ -39,33 +38,33 @@ public abstract class FlowSingleModelLoader private boolean mObserveModel = true; /// Collection of models to be observed. - protected HashSet mModels = new HashSet<> (); + private final HashSet> mModels = new HashSet<>(); private class ForceLoadContentObserver extends FlowContentObserver { @Override - public boolean deliverSelfNotifications () { + public boolean deliverSelfNotifications() { return true; } @Override - public void onChange (boolean selfChange) { - super.onChange (selfChange); + public void onChange(boolean selfChange) { + super.onChange(selfChange); - onContentChanged (); + onContentChanged(); } @Override - public void onChange (boolean selfChange, Uri uri) { - super.onChange (selfChange, uri); + public void onChange(boolean selfChange, Uri uri) { + super.onChange(selfChange, uri); - onContentChanged (); + onContentChanged(); } } - protected final FlowContentObserver mObserver = new ForceLoadContentObserver (); + private final FlowContentObserver mObserver = new ForceLoadContentObserver(); - protected FlowSingleModelLoader (Context context, Class model, InstanceAdapter adapter, Queriable queriable) { - super (context); + protected FlowSingleModelLoader(Context context, Class model, InstanceAdapter adapter, Queriable queriable) { + super(context); this.mQueriable = queriable; this.mModel = model; @@ -74,26 +73,26 @@ protected FlowSingleModelLoader (Context context, Class model, InstanceA /* Runs on a worker thread */ @Override - public TModel loadInBackground () { - Cursor cursor = this.mQueriable.query (); + public TModel loadInBackground() { + Cursor cursor = this.mQueriable.query(); - if (cursor == null || !cursor.moveToFirst ()) { + if (cursor == null || !cursor.moveToFirst()) { return null; } - TModel model = this.mAdapter.newInstance (); - this.mAdapter.loadFromCursor (cursor, model); + TModel model = this.mAdapter.newInstance(); + this.mAdapter.loadFromCursor(cursor, model); return model; } /* Runs on the UI thread */ @Override - public void deliverResult (TModel result) { + public void deliverResult(TModel result) { this.mResult = result; - if (this.isStarted ()) { - super.deliverResult (result); + if (this.isStarted()) { + super.deliverResult(result); } } @@ -105,18 +104,18 @@ public void deliverResult (TModel result) { * Must be called from the UI thread */ @Override - protected void onStartLoading () { + protected void onStartLoading() { if (mResult != null) { - this.deliverResult (mResult); + this.deliverResult(mResult); } // Start watching for changes to the model. if (this.mObserveModel) { - this.registerForContentChanges (this.mModel); + this.registerForContentChanges(this.mModel); } - if (this.takeContentChanged () || this.mResult == null) { - this.forceLoad (); + if (this.takeContentChanged() || this.mResult == null) { + this.forceLoad(); } } @@ -124,38 +123,39 @@ protected void onStartLoading () { * Must be called from the UI thread */ @Override - protected void onStopLoading () { - this.cancelLoad (); + protected void onStopLoading() { + this.cancelLoad(); } @Override - protected void onReset () { - super.onReset (); + protected void onReset() { + super.onReset(); // Ensure the loader is stopped - this.onStopLoading (); + this.onStopLoading(); if (this.mResult != null) { this.mResult = null; } // Unregister the loader for content changes. - this.mObserver.unregisterForContentChanges (this.getContext ()); + this.mObserver.unregisterForContentChanges(this.getContext()); } - public Class getModel () { + public Class getModel() { return this.mModel; } - public void setObserveModel (boolean observeModel) { + public void setObserveModel(boolean observeModel) { this.mObserveModel = observeModel; } - public void registerForContentChanges (Class model) { - if (this.mModels.contains (model)) { + public void registerForContentChanges(Class model) { + if (this.mModels.contains(model)) { return; } - this.mObserver.registerForContentChanges (this.getContext (), model); + this.mModels.add(model); + this.mObserver.registerForContentChanges(this.getContext(), model); } } \ No newline at end of file From 8d7296527d99577be8ee2fb574f71124d084dddf Mon Sep 17 00:00:00 2001 From: "James H. Hill" Date: Thu, 1 Dec 2016 09:36:44 -0500 Subject: [PATCH 39/47] For some reason, lintOptions was added to the build config --- dbflow-kotlinextensions/build.gradle | 3 --- 1 file changed, 3 deletions(-) diff --git a/dbflow-kotlinextensions/build.gradle b/dbflow-kotlinextensions/build.gradle index 8bac4e9bd..49be378f4 100644 --- a/dbflow-kotlinextensions/build.gradle +++ b/dbflow-kotlinextensions/build.gradle @@ -27,9 +27,6 @@ android { sourceSets { main.java.srcDirs += 'src/main/kotlin' } - lintOptions { - abortOnError false - } } dependencies { From d0191910dd2a8c0a93c420437c2ffca4f095de2e Mon Sep 17 00:00:00 2001 From: "James H. Hill" Date: Thu, 1 Dec 2016 09:40:58 -0500 Subject: [PATCH 40/47] PropertyExtensions was changed during the merge; this file should not have been modified --- .../android/dbflow/kotlinextensions/PropertyExtensions.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dbflow-kotlinextensions/src/main/java/com/raizlabs/android/dbflow/kotlinextensions/PropertyExtensions.kt b/dbflow-kotlinextensions/src/main/java/com/raizlabs/android/dbflow/kotlinextensions/PropertyExtensions.kt index 4ea1829a7..08e173095 100644 --- a/dbflow-kotlinextensions/src/main/java/com/raizlabs/android/dbflow/kotlinextensions/PropertyExtensions.kt +++ b/dbflow-kotlinextensions/src/main/java/com/raizlabs/android/dbflow/kotlinextensions/PropertyExtensions.kt @@ -34,6 +34,6 @@ val T.property: Property val ModelQueriable.property: Property get() = PropertyFactory.from(this) -inline fun TModel.propertyString(stringRepresentation: String?): Property { - return PropertyFactory.from(TModel::class.java, stringRepresentation) +inline fun T.propertyString(stringRepresentation: String?): Property { + return PropertyFactory.from(T::class.java, stringRepresentation) } \ No newline at end of file From aff9722b69d7e561a8ce92fc3a4fc582c7076f69 Mon Sep 17 00:00:00 2001 From: "James H. Hill" Date: Thu, 1 Dec 2016 09:46:28 -0500 Subject: [PATCH 41/47] Removed obsolete file --- .../android/dbflow/processor/ClassNames.java | 117 ------------------ 1 file changed, 117 deletions(-) delete mode 100644 dbflow-processor/src/main/java/com/raizlabs/android/dbflow/processor/ClassNames.java diff --git a/dbflow-processor/src/main/java/com/raizlabs/android/dbflow/processor/ClassNames.java b/dbflow-processor/src/main/java/com/raizlabs/android/dbflow/processor/ClassNames.java deleted file mode 100644 index 7df666377..000000000 --- a/dbflow-processor/src/main/java/com/raizlabs/android/dbflow/processor/ClassNames.java +++ /dev/null @@ -1,117 +0,0 @@ -package com.raizlabs.android.dbflow.processor; - -import com.raizlabs.android.dbflow.annotation.ConflictAction; -import com.squareup.javapoet.ClassName; - -/** - * Description: The static FQCN string file to assist in providing class names for imports and more in the Compiler - */ -public class ClassNames { - - - public static final String BASE_PACKAGE = "com.raizlabs.android.dbflow"; - public static final String FLOW_MANAGER_PACKAGE = BASE_PACKAGE + ".config"; - public static final String DATABASE_HOLDER_STATIC_CLASS_NAME = "GeneratedDatabaseHolder"; - public static final String CONVERTER = BASE_PACKAGE + ".converter"; - public static final String STRUCTURE = BASE_PACKAGE + ".structure"; - public static final String DATABASE = STRUCTURE + ".database"; - public static final String CONTAINER = STRUCTURE + ".container"; - public static final String SQL = BASE_PACKAGE + ".sql"; - public static final String LANGUAGE = SQL + ".language"; - public static final String QUERIABLE = SQL + ".queriable"; - public static final String PROPERTY_PACKAGE = LANGUAGE + ".property"; - public static final String CONFIG = BASE_PACKAGE + ".config"; - public static final String BUILDER = SQL + ".builder"; - public static final String MIGRATION_PACKAGE = SQL + ".migration"; - public static final String LISTENER = STRUCTURE + ".listener"; - public static final String RUNTIME = BASE_PACKAGE + ".runtime"; - public static final String TRANSACTION = RUNTIME + ".transaction"; - public static final String DATABASE_TRANSACTION = DATABASE + ".transaction"; - public static final String PROCESS = TRANSACTION + ".process"; - public static final String SAVEABLE = SQL + ".saveable"; - - public static final ClassName DATABASE_HOLDER = ClassName.get(CONFIG, "DatabaseHolder"); - public static final ClassName FLOW_MANAGER = ClassName.get(CONFIG, "FlowManager"); - public static final ClassName BASE_DATABASE_DEFINITION_CLASSNAME = ClassName.get(CONFIG, "DatabaseDefinition"); - - public static final ClassName URI = ClassName.get("android.net", "Uri"); - public static final ClassName URI_MATCHER = ClassName.get("android.content", "UriMatcher"); - public static final ClassName CURSOR = ClassName.get("android.database", "Cursor"); - public static final ClassName DATABASE_UTILS = ClassName.get("android.database", "DatabaseUtils"); - public static final ClassName CONTENT_VALUES = ClassName.get("android.content", "ContentValues"); - public static final ClassName CONTENT_URIS = ClassName.get("android.content", "ContentUris"); - - public static final ClassName MODEL_ADAPTER = ClassName.get(STRUCTURE, "ModelAdapter"); - public static final ClassName QUERY_MODEL_ADAPTER = ClassName.get(STRUCTURE, "QueryModelAdapter"); - public static final ClassName MODEL = ClassName.get(STRUCTURE, "Model"); - public static final ClassName MODEL_VIEW_ADAPTER = ClassName.get(STRUCTURE, "ModelViewAdapter"); - public static final ClassName MODEL_VIEW = ClassName.get(STRUCTURE, "BaseModelView"); - - public static final ClassName FLOW_SQLITE_OPEN_HELPER = ClassName.get(DATABASE, "FlowSQLiteOpenHelper"); - public static final ClassName DATABASE_STATEMENT = ClassName.get(DATABASE, "DatabaseStatement"); - public static final ClassName OPEN_HELPER = ClassName.get(DATABASE, "OpenHelper"); - - public static final ClassName CONDITION_QUERY_BUILDER = ClassName.get(BUILDER, "ConditionQueryBuilder"); - public static final ClassName CONDITION = ClassName.get(BUILDER, "Condition"); - - public static final ClassName SQL_UTILS = ClassName.get(SQL, "SqlUtils"); - public static final ClassName QUERY = ClassName.get(SQL, "Query"); - - public static final ClassName TYPE_CONVERTER = ClassName.get(CONVERTER, "TypeConverter"); - public static final ClassName PROCESS_MODEL_INFO = ClassName.get(PROCESS, "ProcessModelInfo"); - - public static final ClassName FLOW_MANAGER_STATIC_INTERFACE = ClassName.get(FLOW_MANAGER_PACKAGE, "DatabaseHolder"); - - public static final ClassName MIGRATION = ClassName.get(MIGRATION_PACKAGE, "Migration"); - - public static final ClassName CONFLICT_ACTION = ClassName.get(ConflictAction.class); - - public static final ClassName CONTENT_VALUES_LISTENER = ClassName.get(LISTENER, "ContentValuesListener"); - public static final ClassName LOAD_FROM_CURSOR_LISTENER = ClassName.get(LISTENER, "LoadFromCursorListener"); - public static final ClassName SQLITE_STATEMENT_LISTENER = ClassName.get(LISTENER, "SQLiteStatementListener"); - - - public static final ClassName DELETE_MODEL_LIST_TRANSACTION = ClassName.get(PROCESS, "DeleteModelListTransaction"); - public static final ClassName SAVE_MODEL_LIST_TRANSACTION = ClassName.get(PROCESS, "SaveModelTransaction"); - public static final ClassName UPDATE_MODEL_LIST_TRANSACTION = ClassName.get(PROCESS, "UpdateModelListTransaction"); - public static final ClassName INSERT_MODEL_LIST_TRANSACTION = ClassName.get(PROCESS, "InsertModelTransaction"); - - public static final ClassName PROPERTY = ClassName.get(PROPERTY_PACKAGE, "Property"); - public static final ClassName IPROPERTY = ClassName.get(PROPERTY_PACKAGE, "IProperty"); - public static final ClassName BASE_PROPERTY = ClassName.get(PROPERTY_PACKAGE, "BaseProperty"); - public static final ClassName INDEX_PROPERTY = ClassName.get(PROPERTY_PACKAGE, "IndexProperty"); - public static final ClassName CONDITION_GROUP = ClassName.get(LANGUAGE, "ConditionGroup"); - public static final ClassName SELECT = ClassName.get(LANGUAGE, "Select"); - public static final ClassName UPDATE = ClassName.get(LANGUAGE, "Update"); - public static final ClassName DELETE = ClassName.get(LANGUAGE, "Delete"); - public static final ClassName METHOD = ClassName.get(LANGUAGE, "Method"); - - public static final ClassName BASE_CONTENT_PROVIDER = ClassName.get(RUNTIME, "BaseContentProvider"); - public static final ClassName PROPERTY_CONVERTER = ClassName.get(RUNTIME + ".BaseContentProvider", "PropertyConverter"); - - public static final ClassName MODEL_CONTAINER_UTILS = ClassName.get(CONTAINER, "ModelContainerUtils"); - public static final ClassName MODEL_CONTAINER = ClassName.get(CONTAINER, "ModelContainer"); - public static final ClassName MODEL_CONTAINER_ADAPTER = ClassName.get(CONTAINER, "ModelContainerAdapter"); - public static final ClassName FOREIGN_KEY_CONTAINER = ClassName.get(CONTAINER, "ForeignKeyContainer"); - public static final ClassName EXTERNAL_FOREIGN_KEY_CONTAINER = ClassName.get(CONTAINER, "ExternalForeignKeyContainer"); - public static final ClassName BASE_MODEL = ClassName.get(STRUCTURE, "BaseModel"); - public static final ClassName MODEL_CACHE = ClassName.get(STRUCTURE + ".cache", "ModelCache"); - public static final ClassName MULTI_KEY_CACHE_CONVERTER = ClassName.get(STRUCTURE + ".cache", "IMultiKeyCacheConverter"); - - public static final ClassName CACHEABLE_MODEL_LOADER = ClassName.get(QUERIABLE, "CacheableModelLoader"); - public static final ClassName SINGLE_MODEL_LOADER = ClassName.get(QUERIABLE, "SingleModelLoader"); - public static final ClassName CACHEABLE_LIST_MODEL_LOADER = ClassName.get(QUERIABLE, "CacheableListModelLoader"); - public static final ClassName LIST_MODEL_LOADER = ClassName.get(QUERIABLE, "ListModelLoader"); - - public static final ClassName DATABASE_WRAPPER = ClassName.get(DATABASE, "DatabaseWrapper"); - - public static final ClassName ORDER_BY = ClassName.get(LANGUAGE, "OrderBy"); - public static final ClassName SQLITE = ClassName.get(LANGUAGE, "SQLite"); - - public static final ClassName UNSAFE_STRING_CONDITION = ClassName.get(LANGUAGE, "UnSafeStringCondition"); - - public static final ClassName CACHEABLE_LIST_MODEL_SAVER = ClassName.get(SAVEABLE, "CacheableListModelSaver"); - - public static final ClassName SINGLE_KEY_CACHEABLE_MODEL_LOADER = ClassName.get(QUERIABLE, "SingleKeyCacheableModelLoader"); - public static final ClassName SINGLE_KEY_CACHEABLE_LIST_MODEL_LOADER = ClassName.get(QUERIABLE, "SingleKeyCacheableListModelLoader"); -} From a613727677fbed3719ec698fd9e341152f5dfca7 Mon Sep 17 00:00:00 2001 From: "James H. Hill" Date: Thu, 1 Dec 2016 11:23:46 -0500 Subject: [PATCH 42/47] Fixed naming convention on class variables --- .../raizlabs/android/dbflow/list/FlowCursorAdapter.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/dbflow/src/main/java/com/raizlabs/android/dbflow/list/FlowCursorAdapter.java b/dbflow/src/main/java/com/raizlabs/android/dbflow/list/FlowCursorAdapter.java index e2b9f299a..4c056837c 100644 --- a/dbflow/src/main/java/com/raizlabs/android/dbflow/list/FlowCursorAdapter.java +++ b/dbflow/src/main/java/com/raizlabs/android/dbflow/list/FlowCursorAdapter.java @@ -16,24 +16,24 @@ * @param */ public abstract class FlowCursorAdapter extends CursorAdapter { - private final ModelAdapter mModelAdapter; + private final ModelAdapter modelAdapter; public FlowCursorAdapter(Context context, Class modelClass, Cursor c, boolean autoRequery) { super(context, c, autoRequery); - this.mModelAdapter = FlowManager.getModelAdapter(modelClass); + this.modelAdapter = FlowManager.getModelAdapter(modelClass); } @TargetApi(11) public FlowCursorAdapter(Context context, Class modelClass, Cursor c, int flags) { super(context, c, flags); - this.mModelAdapter = FlowManager.getModelAdapter(modelClass); + this.modelAdapter = FlowManager.getModelAdapter(modelClass); } @Override public TModel getItem(int position) { Cursor cursor = (Cursor) super.getItem(position); - return cursor != null ? this.mModelAdapter.loadFromCursor(cursor) : null; + return cursor != null ? this.modelAdapter.loadFromCursor(cursor) : null; } } From d7d188eb2c6fb2ccdf1a5afd233a6215e4c9cebd Mon Sep 17 00:00:00 2001 From: "James H. Hill" Date: Thu, 1 Dec 2016 11:25:07 -0500 Subject: [PATCH 43/47] Fixed naming convention on class variables --- .../android/dbflow/list/FlowCursorLoader.java | 54 +++++++++---------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/dbflow/src/main/java/com/raizlabs/android/dbflow/list/FlowCursorLoader.java b/dbflow/src/main/java/com/raizlabs/android/dbflow/list/FlowCursorLoader.java index 7fc7e05c0..25b2f90d9 100644 --- a/dbflow/src/main/java/com/raizlabs/android/dbflow/list/FlowCursorLoader.java +++ b/dbflow/src/main/java/com/raizlabs/android/dbflow/list/FlowCursorLoader.java @@ -23,19 +23,19 @@ @TargetApi(11) public class FlowCursorLoader extends AsyncTaskLoader { /// Models to be observed for changes. - private final HashSet> mModels = new HashSet<>(); + private final HashSet> models = new HashSet<>(); /// Queriable operation that the loader executes. - private Queriable mQueriable; + private Queriable queriable; /// Cursor for the loader. - private Cursor mCursor; + private Cursor cursor; /// The observer that triggers the loader to reload anytime if it receives /// notification of a change. - private final ForceLoadContentObserver mObserver = new ForceLoadContentObserver(); + private final ForceLoadContentObserver observer = new ForceLoadContentObserver(); - private boolean mListening = false; + private boolean listening = false; /** * Creates a fully-specified CursorLoader. See {@link android.content.ContentResolver#query(Uri, @@ -45,12 +45,12 @@ public class FlowCursorLoader extends AsyncTaskLoader { public FlowCursorLoader(Context context, Queriable queriable) { super(context); - this.mQueriable = queriable; + this.queriable = queriable; } @Override public Cursor loadInBackground() { - Cursor cursor = this.mQueriable.query(); + Cursor cursor = this.queriable.query(); if (cursor != null) { cursor.getCount(); @@ -70,8 +70,8 @@ public void deliverResult(Cursor cursor) { return; } - Cursor oldCursor = this.mCursor; - this.mCursor = cursor; + Cursor oldCursor = this.cursor; + this.cursor = cursor; if (this.isStarted()) { super.deliverResult(cursor); @@ -94,21 +94,21 @@ public void deliverResult(Cursor cursor) { * @param model */ public void registerForContentChanges(Class model) { - if (this.mModels.contains(model)) { + if (this.models.contains(model)) { return; } - this.mModels.add(model); - this.mObserver.registerForContentChanges(this.getContext(), model); + this.models.add(model); + this.observer.registerForContentChanges(this.getContext(), model); } @Override protected void onStartLoading() { - if (this.mCursor != null) { - this.deliverResult(this.mCursor); + if (this.cursor != null) { + this.deliverResult(this.cursor); } - if (this.takeContentChanged() || this.mCursor == null) { + if (this.takeContentChanged() || this.cursor == null) { this.forceLoad(); } } @@ -134,35 +134,35 @@ protected void onReset() { this.startLoading(); - if (mCursor != null && !mCursor.isClosed()) { - mCursor.close(); + if (cursor != null && !cursor.isClosed()) { + cursor.close(); } - mCursor = null; + cursor = null; - this.mObserver.unregisterForContentChanges(this.getContext()); + this.observer.unregisterForContentChanges(this.getContext()); } private void startListeningForChanges() { - if (!this.mListening) { - this.mObserver.addModelChangeListener(this.mObserver); - this.mListening = true; + if (!this.listening) { + this.observer.addModelChangeListener(this.observer); + this.listening = true; } } private void stopListeningForChanges() { - if (this.mListening) { - this.mObserver.removeModelChangeListener(this.mObserver); - this.mListening = false; + if (this.listening) { + this.observer.removeModelChangeListener(this.observer); + this.listening = false; } } public Collection> getModels() { - return this.mModels; + return this.models; } public FlowContentObserver getContentObserver() { - return this.mObserver; + return this.observer; } private final class ForceLoadContentObserver extends FlowContentObserver From c97f1b3f72906acb7b685b4cc9e30d51d0bfa58e Mon Sep 17 00:00:00 2001 From: "James H. Hill" Date: Thu, 1 Dec 2016 11:49:38 -0500 Subject: [PATCH 44/47] Fixed refactoring error --- usage2/SQLiteWrapperLanguage.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/usage2/SQLiteWrapperLanguage.md b/usage2/SQLiteWrapperLanguage.md index b2b02c84d..f2d4ade05 100644 --- a/usage2/SQLiteWrapperLanguage.md +++ b/usage2/SQLiteWrapperLanguage.md @@ -269,7 +269,7 @@ Delete.tables(MyTable1.class, MyTable2.class); // Delete using query SQLite.delete(MyTable.class) - .where(DeviceObject_Table.carrier.is("TModel-MOBILE")) + .where(DeviceObject_Table.carrier.is("T-MOBILE")) .and(DeviceObject_Table.device.is("Samsung-Galaxy-S5")) .async() .execute(); From 83ac02d313cbdc5956e495c58fd28b5f8c50d54e Mon Sep 17 00:00:00 2001 From: "James H. Hill" Date: Thu, 1 Dec 2016 11:51:33 -0500 Subject: [PATCH 45/47] Fixed refactoring error --- usage2/Migration3Guide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/usage2/Migration3Guide.md b/usage2/Migration3Guide.md index edfcaebfc..dd2c606c6 100644 --- a/usage2/Migration3Guide.md +++ b/usage2/Migration3Guide.md @@ -449,7 +449,7 @@ Perhaps the most significant external change to this library is making queries, ### Property Properties replace `String` column names generated in the "$Table" classes. They also match exact case to the column name. They have methods that generate `Condition` that drastically simplify queries. (Please note the `Condition` class has moved to the `.language` package). -Properties are represented by the interface `IProperty` which are subclassed into `Property`, `Method`, and the primitive properties (`IntProperty`, `CharProperty`, etc). +Properties are represented by the interface `IProperty` which are subclassed into `Property`, `Method`, and the primitive properties (`IntProperty`, `CharProperty`, etc). Properties can also be represented by values via the `PropertyFactory` class, enabling values to appear first in queries: From 4cd5e395c924e8c1f7f53cf50fa353218df5f645 Mon Sep 17 00:00:00 2001 From: "James H. Hill" Date: Thu, 1 Dec 2016 11:57:02 -0500 Subject: [PATCH 46/47] Fixed naming conventions errors --- .../dbflow/single/FlowSingleModelLoader.java | 42 +++++++++---------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/dbflow/src/main/java/com/raizlabs/android/dbflow/single/FlowSingleModelLoader.java b/dbflow/src/main/java/com/raizlabs/android/dbflow/single/FlowSingleModelLoader.java index ab604408e..ada5eaa04 100644 --- a/dbflow/src/main/java/com/raizlabs/android/dbflow/single/FlowSingleModelLoader.java +++ b/dbflow/src/main/java/com/raizlabs/android/dbflow/single/FlowSingleModelLoader.java @@ -23,19 +23,19 @@ public abstract class FlowSingleModelLoader extends AsyncTaskLoader { /// Model type being loaded. - private final Class mModel; + private final Class model; /// Adapter for converting cursor into target model. - private final InstanceAdapter mAdapter; + private final InstanceAdapter adapter; /// Queriable operation that the loader executes. - private Queriable mQueriable; + private Queriable queriable; /// Cursor for the loader. - private TModel mResult; + private TModel result; /// Observe changes to the model. - private boolean mObserveModel = true; + private boolean observeModel = true; /// Collection of models to be observed. private final HashSet> mModels = new HashSet<>(); @@ -66,22 +66,22 @@ public void onChange(boolean selfChange, Uri uri) { protected FlowSingleModelLoader(Context context, Class model, InstanceAdapter adapter, Queriable queriable) { super(context); - this.mQueriable = queriable; - this.mModel = model; - this.mAdapter = adapter; + this.queriable = queriable; + this.model = model; + this.adapter = adapter; } /* Runs on a worker thread */ @Override public TModel loadInBackground() { - Cursor cursor = this.mQueriable.query(); + Cursor cursor = this.queriable.query(); if (cursor == null || !cursor.moveToFirst()) { return null; } - TModel model = this.mAdapter.newInstance(); - this.mAdapter.loadFromCursor(cursor, model); + TModel model = this.adapter.newInstance(); + this.adapter.loadFromCursor(cursor, model); return model; } @@ -89,7 +89,7 @@ public TModel loadInBackground() { /* Runs on the UI thread */ @Override public void deliverResult(TModel result) { - this.mResult = result; + this.result = result; if (this.isStarted()) { super.deliverResult(result); @@ -105,16 +105,16 @@ public void deliverResult(TModel result) { */ @Override protected void onStartLoading() { - if (mResult != null) { - this.deliverResult(mResult); + if (result != null) { + this.deliverResult(result); } // Start watching for changes to the model. - if (this.mObserveModel) { - this.registerForContentChanges(this.mModel); + if (this.observeModel) { + this.registerForContentChanges(this.model); } - if (this.takeContentChanged() || this.mResult == null) { + if (this.takeContentChanged() || this.result == null) { this.forceLoad(); } } @@ -134,8 +134,8 @@ protected void onReset() { // Ensure the loader is stopped this.onStopLoading(); - if (this.mResult != null) { - this.mResult = null; + if (this.result != null) { + this.result = null; } // Unregister the loader for content changes. @@ -143,11 +143,11 @@ protected void onReset() { } public Class getModel() { - return this.mModel; + return this.model; } public void setObserveModel(boolean observeModel) { - this.mObserveModel = observeModel; + this.observeModel = observeModel; } public void registerForContentChanges(Class model) { From 0067c1ecb75165dccdabc900da27095c4e9b69a8 Mon Sep 17 00:00:00 2001 From: "James H. Hill" Date: Thu, 1 Dec 2016 11:57:44 -0500 Subject: [PATCH 47/47] Fixed naming conventions errors --- .../android/dbflow/single/FlowSingleModelLoader.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dbflow/src/main/java/com/raizlabs/android/dbflow/single/FlowSingleModelLoader.java b/dbflow/src/main/java/com/raizlabs/android/dbflow/single/FlowSingleModelLoader.java index ada5eaa04..0ebf30051 100644 --- a/dbflow/src/main/java/com/raizlabs/android/dbflow/single/FlowSingleModelLoader.java +++ b/dbflow/src/main/java/com/raizlabs/android/dbflow/single/FlowSingleModelLoader.java @@ -38,7 +38,7 @@ public abstract class FlowSingleModelLoader private boolean observeModel = true; /// Collection of models to be observed. - private final HashSet> mModels = new HashSet<>(); + private final HashSet> models = new HashSet<>(); private class ForceLoadContentObserver extends FlowContentObserver { @Override @@ -151,11 +151,11 @@ public void setObserveModel(boolean observeModel) { } public void registerForContentChanges(Class model) { - if (this.mModels.contains(model)) { + if (this.models.contains(model)) { return; } - this.mModels.add(model); + this.models.add(model); this.mObserver.registerForContentChanges(this.getContext(), model); } } \ No newline at end of file