1 /*
<lambda>null2  * Copyright (C) 2017 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.writer
18 
19 import androidx.room.ext.L
20 import androidx.room.ext.RoomTypeNames
21 import androidx.room.ext.S
22 import androidx.room.ext.SupportDbTypeNames
23 import androidx.room.solver.CodeGenScope
24 import androidx.room.vo.Entity
25 import androidx.room.vo.FieldWithIndex
26 import com.squareup.javapoet.ClassName
27 import com.squareup.javapoet.MethodSpec
28 import com.squareup.javapoet.ParameterSpec
29 import com.squareup.javapoet.ParameterizedTypeName
30 import com.squareup.javapoet.TypeName
31 import com.squareup.javapoet.TypeSpec
32 import javax.lang.model.element.Modifier.PUBLIC
33 
34 class EntityUpdateAdapterWriter(val entity: Entity, val onConflict: String) {
35     fun createAnonymous(classWriter: ClassWriter, dbParam: String): TypeSpec {
36         @Suppress("RemoveSingleExpressionStringTemplate")
37         return TypeSpec.anonymousClassBuilder("$L", dbParam).apply {
38             superclass(ParameterizedTypeName.get(RoomTypeNames.DELETE_OR_UPDATE_ADAPTER,
39                     entity.typeName)
40             )
41             addMethod(MethodSpec.methodBuilder("createQuery").apply {
42                 addAnnotation(Override::class.java)
43                 returns(ClassName.get("java.lang", "String"))
44                 addModifiers(PUBLIC)
45                 val query = "UPDATE OR $onConflict `${entity.tableName}` SET " +
46                         entity.fields.joinToString(",") { field ->
47                             "`${field.columnName}` = ?"
48                         } + " WHERE " + entity.primaryKey.fields.joinToString(" AND ") {
49                             "`${it.columnName}` = ?"
50                         }
51                 addStatement("return $S", query)
52             }.build())
53             addMethod(MethodSpec.methodBuilder("bind").apply {
54                 val bindScope = CodeGenScope(classWriter)
55                 addAnnotation(Override::class.java)
56                 val stmtParam = "stmt"
57                 addParameter(ParameterSpec.builder(SupportDbTypeNames.SQLITE_STMT,
58                         stmtParam).build())
59                 val valueParam = "value"
60                 addParameter(ParameterSpec.builder(entity.typeName, valueParam).build())
61                 returns(TypeName.VOID)
62                 addModifiers(PUBLIC)
63                 val mappedField = FieldWithIndex.byOrder(entity.fields)
64                 FieldReadWriteWriter.bindToStatement(
65                         ownerVar = valueParam,
66                         stmtParamVar = stmtParam,
67                         fieldsWithIndices = mappedField,
68                         scope = bindScope
69                 )
70                 val pkeyStart = entity.fields.size
71                 val mappedPrimaryKeys = entity.primaryKey.fields.mapIndexed { index, field ->
72                     FieldWithIndex(field = field,
73                             indexVar = "${pkeyStart + index + 1}",
74                             alwaysExists = true)
75                 }
76                 FieldReadWriteWriter.bindToStatement(
77                         ownerVar = valueParam,
78                         stmtParamVar = stmtParam,
79                         fieldsWithIndices = mappedPrimaryKeys,
80                         scope = bindScope
81                 )
82                 addCode(bindScope.builder().build())
83             }.build())
84         }.build()
85     }
86 }
87