Db Writer initial code
This CL creates the database writer and prepares RoomDatabase
for actual implementation.
This is just the skeleton, database creation will happen
in another CL.
Bug: 32342709
Test: DatabaseWriter.kt
Change-Id: I7ce7b9c938c7ba196c8d0b6fc5f08d76e2001696
diff --git a/flatfoot-common/init.gradle b/flatfoot-common/init.gradle
index baee4f43..5deb735 100644
--- a/flatfoot-common/init.gradle
+++ b/flatfoot-common/init.gradle
@@ -26,7 +26,7 @@
ext.kotlin_version = "1.0.5"
ext.android_gradle_plugin_version = "2.2.1"
ext.auto_common_version = "0.6"
-ext.javapoet_version = "1.7.0"
+ext.javapoet_version = "1.8.0"
ext.compile_testing_version = "0.9"
ext.localize_maven_version = "1.1"
ext.support_lib_version = "25.1.0-SNAPSHOT"
diff --git a/room/compiler/src/main/kotlin/com/android/support/room/ext/javapoet_ext.kt b/room/compiler/src/main/kotlin/com/android/support/room/ext/javapoet_ext.kt
index 4968fd1..3a4c17c 100644
--- a/room/compiler/src/main/kotlin/com/android/support/room/ext/javapoet_ext.kt
+++ b/room/compiler/src/main/kotlin/com/android/support/room/ext/javapoet_ext.kt
@@ -34,6 +34,16 @@
object SupportDbTypeNames {
val DB: ClassName = ClassName.get("com.android.support.db", "SupportSQLiteDatabase")
val SQLITE_STMT : ClassName = ClassName.get("com.android.support.db", "SupportSQLiteStatement")
+ val SQLITE_OPEN_HELPER : ClassName =
+ ClassName.get("com.android.support.db", "SupportSQLiteOpenHelper")
+ val SQLITE_OPEN_HELPER_CALLBACK : ClassName =
+ ClassName.get("com.android.support.db", "SupportSQLiteOpenHelper.Callback")
+ val SQLITE_OPEN_HELPER_FACTORY : ClassName =
+ ClassName.get("com.android.support.db", "SupportSQLiteOpenHelper.Factory")
+ val SQLITE_OPEN_HELPER_CONFIG : ClassName =
+ ClassName.get("com.android.support.db", "SupportSQLiteOpenHelper.Configuration")
+ val SQLITE_OPEN_HELPER_CONFIG_BUILDER : ClassName =
+ ClassName.get("com.android.support.db", "SupportSQLiteOpenHelper.Configuration.Builder")
}
object RoomTypeNames {
@@ -41,6 +51,8 @@
val CURSOR_CONVERTER : ClassName = ClassName.get("com.android.support.room", "CursorConverter")
val ROOM : ClassName = ClassName.get("com.android.support.room", "Room")
val ROOM_DB : ClassName = ClassName.get("com.android.support.room", "RoomDatabase")
+ val ROOM_DB_CONFIG : ClassName = ClassName.get("com.android.support.room",
+ "DatabaseConfiguration")
val INSERTION_ADAPTER : ClassName =
ClassName.get("com.android.support.room", "EntityInsertionAdapter")
}
diff --git a/room/compiler/src/main/kotlin/com/android/support/room/processor/DatabaseProcessor.kt b/room/compiler/src/main/kotlin/com/android/support/room/processor/DatabaseProcessor.kt
index 9694a24..829a987 100644
--- a/room/compiler/src/main/kotlin/com/android/support/room/processor/DatabaseProcessor.kt
+++ b/room/compiler/src/main/kotlin/com/android/support/room/processor/DatabaseProcessor.kt
@@ -24,6 +24,7 @@
import com.google.auto.common.AnnotationMirrors
import com.google.auto.common.MoreElements
import com.google.auto.common.MoreTypes
+import com.squareup.javapoet.TypeName
import javax.lang.model.element.AnnotationMirror
import javax.lang.model.element.AnnotationValue
import javax.lang.model.element.ElementKind
@@ -56,6 +57,11 @@
val allMembers = context.processingEnv.elementUtils.getAllMembers(element)
val daoMethods = allMembers.filter {
it.hasAnyOf(Modifier.ABSTRACT) && it.kind == ElementKind.METHOD
+ }.filterNot {
+ // remove methods that belong to room
+ val containing = it.enclosingElement
+ MoreElements.isType(containing) &&
+ TypeName.get(containing.asType()) == RoomTypeNames.ROOM_DB
}.map {
val executable = MoreElements.asExecutable(it)
// TODO when we add support for non Dao return types (e.g. database), this code needs
@@ -65,6 +71,7 @@
}
return Database(element = element,
+ type = MoreElements.asType(element).asType(),
entities = entities,
daoMethods = daoMethods)
}
diff --git a/room/compiler/src/main/kotlin/com/android/support/room/solver/CodeGenScope.kt b/room/compiler/src/main/kotlin/com/android/support/room/solver/CodeGenScope.kt
index 37ad6ac..cdc838d 100644
--- a/room/compiler/src/main/kotlin/com/android/support/room/solver/CodeGenScope.kt
+++ b/room/compiler/src/main/kotlin/com/android/support/room/solver/CodeGenScope.kt
@@ -54,4 +54,13 @@
}
fun generate() = builder().build().toString()
+
+ /**
+ * copies all variable indices but excludes generated code.
+ */
+ fun fork() : CodeGenScope {
+ val forked = CodeGenScope()
+ forked.tmpVarIndices.putAll(tmpVarIndices)
+ return forked
+ }
}
\ No newline at end of file
diff --git a/room/compiler/src/main/kotlin/com/android/support/room/vo/Database.kt b/room/compiler/src/main/kotlin/com/android/support/room/vo/Database.kt
index 670ab15..e1ee2f8 100644
--- a/room/compiler/src/main/kotlin/com/android/support/room/vo/Database.kt
+++ b/room/compiler/src/main/kotlin/com/android/support/room/vo/Database.kt
@@ -16,10 +16,24 @@
package com.android.support.room.vo
+import com.squareup.javapoet.ClassName
import javax.lang.model.element.Element
+import javax.lang.model.type.TypeMirror
/**
* Holds information about a class annotated with Database.
*/
-data class Database(val element : Element, val entities : List<Entity>,
- val daoMethods : List<DaoMethod>)
\ No newline at end of file
+data class Database(val element : Element,
+ val type : TypeMirror,
+ val entities : List<Entity>,
+ val daoMethods : List<DaoMethod>) {
+ val typeName by lazy { ClassName.get(type) as ClassName }
+
+ val implClassName by lazy {
+ "${typeName.simpleName()}_Impl"
+ }
+
+ val implTypeName by lazy {
+ ClassName.get(typeName.packageName(), implClassName)
+ }
+}
diff --git a/room/compiler/src/main/kotlin/com/android/support/room/writer/DatabaseWriter.kt b/room/compiler/src/main/kotlin/com/android/support/room/writer/DatabaseWriter.kt
new file mode 100644
index 0000000..9ae0510
--- /dev/null
+++ b/room/compiler/src/main/kotlin/com/android/support/room/writer/DatabaseWriter.kt
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.support.room.writer
+
+import com.android.support.room.ext.L
+import com.android.support.room.ext.N
+import com.android.support.room.ext.RoomTypeNames
+import com.android.support.room.ext.SupportDbTypeNames
+import com.android.support.room.solver.CodeGenScope
+import com.android.support.room.vo.Database
+import com.squareup.javapoet.MethodSpec
+import com.squareup.javapoet.ParameterSpec
+import com.squareup.javapoet.TypeSpec
+import javax.lang.model.element.Modifier
+import javax.lang.model.element.Modifier.PUBLIC
+
+/**
+ * Writes implementation of classes that were annotated with @Database.
+ */
+class DatabaseWriter(val database : Database) : ClassWriter(database.implTypeName) {
+ override fun createTypeSpec(): TypeSpec {
+ val builder = TypeSpec.classBuilder(database.implTypeName)
+ builder.apply {
+ addModifiers(PUBLIC)
+ superclass(database.typeName)
+ addMethod(createConstructor())
+ addMethod(createCreateOpenHelper())
+ }
+ return builder.build()
+ }
+
+ private fun createConstructor(): MethodSpec {
+ return MethodSpec.constructorBuilder().apply {
+ addModifiers(Modifier.PUBLIC)
+ val configParam = ParameterSpec.builder(RoomTypeNames.ROOM_DB_CONFIG,
+ "configuration").build()
+ addParameter(configParam)
+ addStatement("super($N)", configParam)
+ }.build()
+ }
+
+ private fun createCreateOpenHelper() : MethodSpec {
+ val scope = CodeGenScope()
+ return MethodSpec.methodBuilder("createOpenHelper").apply {
+ addModifiers(Modifier.PROTECTED)
+ returns(SupportDbTypeNames.SQLITE_OPEN_HELPER)
+
+ val configParam = ParameterSpec.builder(RoomTypeNames.ROOM_DB_CONFIG,
+ "configuration").build()
+ addParameter(configParam)
+
+ val openHelperVar = scope.getTmpVar("_helper")
+ val openHelperCode = scope.fork()
+ SQLiteOpenHelperWriter(database)
+ .write(openHelperVar, configParam, openHelperCode)
+ addCode(openHelperCode.builder().build())
+ addStatement("return $L", openHelperVar)
+ }.build()
+ }
+}
diff --git a/room/compiler/src/main/kotlin/com/android/support/room/writer/SQLiteOpenHelperWriter.kt b/room/compiler/src/main/kotlin/com/android/support/room/writer/SQLiteOpenHelperWriter.kt
new file mode 100644
index 0000000..30de7e7
--- /dev/null
+++ b/room/compiler/src/main/kotlin/com/android/support/room/writer/SQLiteOpenHelperWriter.kt
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.support.room.writer
+
+import com.android.support.room.ext.L
+import com.android.support.room.ext.N
+import com.android.support.room.ext.SupportDbTypeNames
+import com.android.support.room.ext.T
+import com.android.support.room.solver.CodeGenScope
+import com.android.support.room.vo.Database
+import com.squareup.javapoet.FieldSpec
+import com.squareup.javapoet.MethodSpec
+import com.squareup.javapoet.ParameterSpec
+import com.squareup.javapoet.TypeName
+import com.squareup.javapoet.TypeSpec
+import javax.lang.model.element.Modifier.PUBLIC
+
+/**
+ * Create an open helper using SupportSQLiteOpenHelperFactory
+ */
+class SQLiteOpenHelperWriter(val database : Database) {
+ fun write(outVar : String, configuration : ParameterSpec, scope: CodeGenScope) {
+ scope.builder().apply {
+ val sqliteConfigVar = scope.getTmpVar("_sqliteConfig")
+ val callbackVar = scope.getTmpVar("_openCallback")
+ addStatement("final $T $L = $L",
+ SupportDbTypeNames.SQLITE_OPEN_HELPER_CALLBACK,
+ callbackVar, createOpenCallback())
+ // build configuration
+ addStatement(
+ """
+ final $T $L = $T.builder($N.context)
+ .name($N.name)
+ .version($N.version)
+ .callback($L)
+ .build()
+ """.trimIndent(),
+ SupportDbTypeNames.SQLITE_OPEN_HELPER_CONFIG, sqliteConfigVar,
+ SupportDbTypeNames.SQLITE_OPEN_HELPER_CONFIG,
+ configuration, configuration, configuration, callbackVar)
+ addStatement("final $T $N = $N.sqliteOpenHelperFactory.create($L)",
+ SupportDbTypeNames.SQLITE_OPEN_HELPER, outVar,
+ configuration, sqliteConfigVar)
+ }
+ }
+
+ private fun createOpenCallback() : TypeSpec {
+ return TypeSpec.anonymousClassBuilder("").apply {
+ superclass(SupportDbTypeNames.SQLITE_OPEN_HELPER_CALLBACK)
+ addMethod(createOnCreate())
+ addMethod(createOnUpgrade())
+ addMethod(createOnDowngrade())
+ }.build()
+ }
+
+ private fun createOnCreate() : MethodSpec {
+ return MethodSpec.methodBuilder("onCreate").apply {
+ addModifiers(PUBLIC)
+ addParameter(SupportDbTypeNames.DB, "_db")
+ // TODO
+ }.build()
+ }
+
+ private fun createOnUpgrade() : MethodSpec {
+ return MethodSpec.methodBuilder("onUpgrade").apply {
+ addModifiers(PUBLIC)
+ addParameter(SupportDbTypeNames.DB, "_db")
+ addParameter(TypeName.INT, "_oldVersion")
+ addParameter(TypeName.INT, "_newVersion")
+ // TODO
+ }.build()
+ }
+
+ private fun createOnDowngrade() : MethodSpec {
+ return MethodSpec.methodBuilder("onDowngrade").apply {
+ addModifiers(PUBLIC)
+ addParameter(SupportDbTypeNames.DB, "_db")
+ addParameter(TypeName.INT, "_oldVersion")
+ addParameter(TypeName.INT, "_newVersion")
+ // TODO
+ }.build()
+ }
+}
diff --git a/room/compiler/src/test/data/databasewriter/input/ComplexDatabase.java b/room/compiler/src/test/data/databasewriter/input/ComplexDatabase.java
new file mode 100644
index 0000000..0a582b7
--- /dev/null
+++ b/room/compiler/src/test/data/databasewriter/input/ComplexDatabase.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package foo.bar;
+import com.android.support.room.*;
+import java.util.List;
+@Database(entities = {User.class})
+abstract class ComplexDatabase extends RoomDatabase {
+ public ComplexDatabase(DatabaseConfiguration configuration) {
+ super(configuration);
+ }
+}
diff --git a/room/compiler/src/test/data/databasewriter/output/ComplexDatabase.java b/room/compiler/src/test/data/databasewriter/output/ComplexDatabase.java
new file mode 100644
index 0000000..aea0829
--- /dev/null
+++ b/room/compiler/src/test/data/databasewriter/output/ComplexDatabase.java
@@ -0,0 +1,33 @@
+package foo.bar;
+
+import com.android.support.db.SupportSQLiteDatabase;
+import com.android.support.db.SupportSQLiteOpenHelper;
+import com.android.support.db.SupportSQLiteOpenHelper.Callback;
+import com.android.support.db.SupportSQLiteOpenHelper.Configuration;
+import com.android.support.room.DatabaseConfiguration;
+
+public class ComplexDatabase_Impl extends ComplexDatabase {
+ public ComplexDatabase_Impl(DatabaseConfiguration configuration) {
+ super(configuration);
+ }
+
+ protected SupportSQLiteOpenHelper createOpenHelper(DatabaseConfiguration configuration) {
+ final SupportSQLiteOpenHelper.Callback _openCallback = new SupportSQLiteOpenHelper.Callback() {
+ public void onCreate(SupportSQLiteDatabase _db) {
+ }
+
+ public void onUpgrade(SupportSQLiteDatabase _db, int _oldVersion, int _newVersion) {
+ }
+
+ public void onDowngrade(SupportSQLiteDatabase _db, int _oldVersion, int _newVersion) {
+ }
+ };
+ final SupportSQLiteOpenHelper.Configuration _sqliteConfig = SupportSQLiteOpenHelper.Configuration.builder(configuration.context)
+ .name(configuration.name)
+ .version(configuration.version)
+ .callback(_openCallback)
+ .build();
+ final SupportSQLiteOpenHelper _helper = configuration.sqliteOpenHelperFactory.create(_sqliteConfig);
+ return _helper;
+ }
+}
\ No newline at end of file
diff --git a/room/compiler/src/test/kotlin/com/android/support/room/processor/DatabaseProcessorTest.kt b/room/compiler/src/test/kotlin/com/android/support/room/processor/DatabaseProcessorTest.kt
index b772007..89f378a 100644
--- a/room/compiler/src/test/kotlin/com/android/support/room/processor/DatabaseProcessorTest.kt
+++ b/room/compiler/src/test/kotlin/com/android/support/room/processor/DatabaseProcessorTest.kt
@@ -37,7 +37,6 @@
const val DATABASE_PREFIX = """
package foo.bar;
import com.android.support.room.*;
- import com.android.support.db.SupportSQLiteDatabase;
"""
val USER: JavaFileObject = JavaFileObjects.forSourceString("foo.bar.User",
"""
@@ -86,8 +85,8 @@
singleDb("""
@Database(entities = {User.class})
public abstract class MyDb extends RoomDatabase {
- public MyDb(SupportSQLiteDatabase supportDb) {
- super(supportDb);
+ public MyDb(DatabaseConfiguration config) {
+ super(config);
}
abstract UserDao userDao();
}
@@ -102,8 +101,8 @@
singleDb("""
@Database(entities = {User.class, Book.class})
public abstract class MyDb extends RoomDatabase {
- public MyDb(SupportSQLiteDatabase supportDb) {
- super(supportDb);
+ public MyDb(DatabaseConfiguration config) {
+ super(config);
}
abstract UserDao userDao();
abstract BookDao bookDao();
diff --git a/room/compiler/src/test/kotlin/com/android/support/room/writer/DatabaseWriterTest.kt b/room/compiler/src/test/kotlin/com/android/support/room/writer/DatabaseWriterTest.kt
new file mode 100644
index 0000000..d3ca260
--- /dev/null
+++ b/room/compiler/src/test/kotlin/com/android/support/room/writer/DatabaseWriterTest.kt
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.support.room.writer
+
+import com.android.support.room.processor.DatabaseProcessor
+import com.android.support.room.testing.TestProcessor
+import com.google.auto.common.MoreElements
+import com.google.common.truth.Truth
+import com.google.testing.compile.CompileTester
+import com.google.testing.compile.JavaSourcesSubjectFactory
+import loadJavaCode
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+import javax.tools.JavaFileObject
+
+@RunWith(JUnit4::class)
+class DatabaseWriterTest {
+
+ @Test
+ fun simpleDb() {
+ singleDb(
+ loadJavaCode("databasewriter/input/ComplexDatabase.java",
+ "foo.bar.ComplexDatabase")
+ ).compilesWithoutError().and().generatesSources(
+ loadJavaCode("databasewriter/output/ComplexDatabase.java",
+ "foo.bar.ComplexDatabase_Impl")
+ )
+ }
+
+ private fun singleDb(vararg jfo : JavaFileObject): CompileTester {
+ return Truth.assertAbout(JavaSourcesSubjectFactory.javaSources())
+ .that(jfo.toList() + COMMON.USER)
+ .processedWith(TestProcessor.builder()
+ .forAnnotations(com.android.support.room.Database::class)
+ .nextRunHandler { invocation ->
+ val dao = invocation.roundEnv
+ .getElementsAnnotatedWith(
+ com.android.support.room.Database::class.java)
+ .first()
+ val processor = DatabaseProcessor(invocation.context)
+ val db = processor.parse(MoreElements.asType(dao))
+ DatabaseWriter(db).write(invocation.processingEnv)
+ true
+ }
+ .build())
+ }
+}
\ No newline at end of file
diff --git a/room/gradle/wrapper/gradle-wrapper.properties b/room/gradle/wrapper/gradle-wrapper.properties
index d1755f7..a5292b0 100644
--- a/room/gradle/wrapper/gradle-wrapper.properties
+++ b/room/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,6 @@
-#Thu Dec 08 18:53:02 PST 2016
+#Fri Dec 09 13:07:04 PST 2016
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-3.2-all.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-3.2-bin.zip
diff --git a/room/runtime/build.gradle b/room/runtime/build.gradle
index 76992f1..a917757 100644
--- a/room/runtime/build.gradle
+++ b/room/runtime/build.gradle
@@ -49,6 +49,7 @@
dependencies {
compile project(":common")
compile project(":db")
+ compile project(":db-impl")
compile "com.android.support:support-core-utils:$support_lib_version"
testCompile "junit:junit:$junit_version"
diff --git a/room/runtime/src/main/java/com/android/support/room/DatabaseConfiguration.java b/room/runtime/src/main/java/com/android/support/room/DatabaseConfiguration.java
new file mode 100644
index 0000000..7a6431a
--- /dev/null
+++ b/room/runtime/src/main/java/com/android/support/room/DatabaseConfiguration.java
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.support.room;
+
+import android.content.Context;
+
+import com.android.support.db.SupportSQLiteOpenHelper;
+import com.android.support.db.framework.FrameworkSQLiteOpenHelperFactory;
+
+/**
+ * Configuration class for {@link RoomDatabase}.
+ */
+public class DatabaseConfiguration {
+ /**
+ * The factory to use to access the database.
+ */
+ public final SupportSQLiteOpenHelper.Factory sqliteOpenHelperFactory;
+ /**
+ * The context to you.
+ */
+ public final Context context;
+ /**
+ * The name of the database or null if it is in memory.
+ */
+ public final String name;
+ /**
+ * The version of the database.
+ */
+ public final int version;
+
+ private DatabaseConfiguration(Context context, String name, int version,
+ SupportSQLiteOpenHelper.Factory sqliteOpenHelperFactory) {
+ this.sqliteOpenHelperFactory = sqliteOpenHelperFactory;
+ this.context = context;
+ this.name = name;
+ this.version = version;
+ }
+
+ /**
+ * Builder for the RoomDatabase configuration.
+ */
+ public static class Builder {
+ SupportSQLiteOpenHelper.Factory mFactory;
+ Context mContext;
+ String mName;
+ int mVersion = 1;
+
+ /**
+ * Sets the database factory. If not set, it defaults to
+ * {@link FrameworkSQLiteOpenHelperFactory}.
+ *
+ * @param factory The factory to use to access the database.
+ *
+ * @return this
+ */
+ public Builder withOpenHelperFactory(SupportSQLiteOpenHelper.Factory factory) {
+ mFactory = factory;
+ return this;
+ }
+
+ /**
+ * @param name The name of the database.
+ * @return this
+ */
+ public Builder withName(String name) {
+ mName = name;
+ return this;
+ }
+
+ /**
+ * Version of the database, defaults to 1.
+ * @param version The database version to use
+ * @return this
+ */
+ public Builder withVersion(int version) {
+ mVersion = version;
+ return this;
+ }
+
+ /**
+ * Creates a Configuration builder with the given context.
+ * Most of the time, this should be an application context.
+ *
+ * @param context The context to use for the database.
+ */
+ public Builder(Context context) {
+ mContext = context;
+ }
+
+ /**
+ * Creates the {@link RoomDatabase.Configuration} object for the database.
+ *
+ * @return Configuration that can be used to create the RoomDatabase.
+ */
+ public DatabaseConfiguration build() {
+ if (mFactory == null) {
+ mFactory = new FrameworkSQLiteOpenHelperFactory();
+ }
+ return new DatabaseConfiguration(mContext, mName, mVersion, mFactory);
+ }
+ }
+}
diff --git a/room/runtime/src/main/java/com/android/support/room/RoomDatabase.java b/room/runtime/src/main/java/com/android/support/room/RoomDatabase.java
index 650d97f..83af0aa 100644
--- a/room/runtime/src/main/java/com/android/support/room/RoomDatabase.java
+++ b/room/runtime/src/main/java/com/android/support/room/RoomDatabase.java
@@ -19,6 +19,7 @@
import android.database.Cursor;
import com.android.support.db.SupportSQLiteDatabase;
+import com.android.support.db.SupportSQLiteOpenHelper;
import com.android.support.db.SupportSQLiteStatement;
/**
@@ -26,11 +27,38 @@
*/
@SuppressWarnings({"unused", "WeakerAccess"})
public abstract class RoomDatabase {
- private final SupportSQLiteDatabase mDb;
+ private volatile SupportSQLiteDatabase mDatabase;
+ private final SupportSQLiteOpenHelper mOpenHelper;
- public RoomDatabase(SupportSQLiteDatabase supportDb) {
- mDb = supportDb;
+ /**
+ * Creates a RoomDatabase with the given configuration.
+ *
+ * @param configuration The configuration to setup the database.
+ */
+ public RoomDatabase(DatabaseConfiguration configuration) {
+ mOpenHelper = createOpenHelper(configuration);
}
+
+ /**
+ * Returns the SQLite open helper used by this database.
+ *
+ * @return The SQLite open helper used by this database.
+ */
+ public SupportSQLiteOpenHelper getOpenHelper() {
+ return mOpenHelper;
+ }
+
+ /**
+ * Creates the open helper to access the database. Generated class already implements this
+ * method.
+ * Note that this method is called when the RoomDatabase is initialized.
+ *
+ * @param config The configuration of the Room database.
+ *
+ * @return A new SupportSQLiteOpenHelper to be used while connecting to the database.
+ */
+ protected abstract SupportSQLiteOpenHelper createOpenHelper(DatabaseConfiguration config);
+
// Below, there are wrapper methods for SupportSQLiteDatabase. This helps us track which
// methods we are using and also helps unit tests to mock this class without mocking
// all sqlite database methods.
@@ -43,7 +71,7 @@
* @return Result of the query.
*/
public Cursor query(String sql, String[] selectionArgs) {
- return mDb.rawQuery(sql, selectionArgs);
+ return mOpenHelper.getWritableDatabase().rawQuery(sql, selectionArgs);
}
/**
@@ -54,27 +82,27 @@
* @return The compiled query.
*/
public SupportSQLiteStatement compileStatement(String sql) {
- return mDb.compileStatement(sql);
+ return mOpenHelper.getWritableDatabase().compileStatement(sql);
}
/**
* Wrapper for {@link SupportSQLiteDatabase#beginTransaction()}.
*/
public void beginTransaction() {
- mDb.beginTransaction();
+ mOpenHelper.getWritableDatabase().beginTransaction();
}
/**
* Wrapper for {@link SupportSQLiteDatabase#endTransaction()}.
*/
public void endTransaction() {
- mDb.endTransaction();
+ mOpenHelper.getWritableDatabase().endTransaction();
}
/**
* Wrapper for {@link SupportSQLiteDatabase#setTransactionSuccessful()}.
*/
public void setTransactionSuccessful() {
- mDb.setTransactionSuccessful();
+ mOpenHelper.getWritableDatabase().setTransactionSuccessful();
}
}