Home | History | Annotate | Download | only in vo
      1 /*
      2  * Copyright (C) 2016 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package androidx.room.vo
     18 
     19 import androidx.room.RoomMasterTable
     20 import androidx.room.migration.bundle.DatabaseBundle
     21 import androidx.room.migration.bundle.SchemaBundle
     22 import com.squareup.javapoet.ClassName
     23 import org.apache.commons.codec.digest.DigestUtils
     24 import java.io.File
     25 import javax.lang.model.element.TypeElement
     26 import javax.lang.model.type.TypeMirror
     27 
     28 /**
     29  * Holds information about a class annotated with Database.
     30  */
     31 data class Database(val element: TypeElement,
     32                     val type: TypeMirror,
     33                     val entities: List<Entity>,
     34                     val daoMethods: List<DaoMethod>,
     35                     val version: Int,
     36                     val exportSchema: Boolean,
     37                     val enableForeignKeys: Boolean) {
     38     val typeName: ClassName by lazy { ClassName.get(element) }
     39 
     40     private val implClassName by lazy {
     41         "${typeName.simpleNames().joinToString("_")}_Impl"
     42     }
     43 
     44     val implTypeName: ClassName by lazy {
     45         ClassName.get(typeName.packageName(), implClassName)
     46     }
     47 
     48     val bundle by lazy {
     49         DatabaseBundle(version, identityHash, entities.map(Entity::toBundle),
     50                 listOf(RoomMasterTable.CREATE_QUERY,
     51                         RoomMasterTable.createInsertQuery(identityHash)))
     52     }
     53 
     54     /**
     55      * Create a has that identifies this database definition so that at runtime we can check to
     56      * ensure developer didn't forget to update the version.
     57      */
     58     val identityHash: String by lazy {
     59         val idKey = SchemaIdentityKey()
     60         idKey.appendSorted(entities)
     61         idKey.hash()
     62     }
     63 
     64     val legacyIdentityHash: String by lazy {
     65         val entityDescriptions = entities
     66                 .sortedBy { it.tableName }
     67                 .map { it.createTableQuery }
     68         val indexDescriptions = entities
     69                 .flatMap { entity ->
     70                     entity.indices.map { index ->
     71                         index.createQuery(entity.tableName)
     72                     }
     73                 }
     74         val input = (entityDescriptions + indexDescriptions).joinToString("\\_()_/")
     75         DigestUtils.md5Hex(input)
     76     }
     77 
     78     fun exportSchema(file: File) {
     79         val schemaBundle = SchemaBundle(SchemaBundle.LATEST_FORMAT, bundle)
     80         if (file.exists()) {
     81             val existing = file.inputStream().use {
     82                 SchemaBundle.deserialize(it)
     83             }
     84             if (existing.isSchemaEqual(schemaBundle)) {
     85                 return
     86             }
     87         }
     88         SchemaBundle.serialize(schemaBundle, file)
     89     }
     90 }
     91