1 /*
<lambda>null2  * 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.writer
18 
19 import androidx.room.compiler.codegen.CodeLanguage
20 import androidx.room.compiler.codegen.XClassName
21 import androidx.room.compiler.codegen.XTypeSpec
22 import androidx.room.compiler.codegen.compat.XConverters.applyToJavaPoet
23 import androidx.room.compiler.processing.XProcessingEnv.Platform
24 import androidx.room.compiler.processing.util.Source
25 import androidx.room.compiler.processing.util.XTestInvocation
26 import androidx.room.processor.BaseEntityParserTest
27 import javax.lang.model.element.Modifier
28 import org.junit.Test
29 import org.junit.runner.RunWith
30 import org.junit.runners.JUnit4
31 
32 @RunWith(JUnit4::class)
33 class EntityStatementConverterWriterTest : BaseEntityParserTest() {
34     companion object {
35         val OUT_PREFIX =
36             """
37             package foo.bar;
38             import androidx.annotation.NonNull;
39             import androidx.room.util.SQLiteStatementUtil;
40             import androidx.sqlite.SQLiteStatement;
41             import java.lang.SuppressWarnings;
42             import javax.annotation.processing.Generated;
43             @Generated("androidx.room.RoomProcessor")
44             @SuppressWarnings({"unchecked", "deprecation", "removal"})
45             public final class MyContainerClass {
46         """
47                 .trimIndent()
48         const val OUT_SUFFIX = "}"
49     }
50 
51     @Test
52     fun generateSimple() {
53         generateAndMatch(
54             input =
55                 """
56                 @PrimaryKey
57                 private int id;
58                 String name;
59                 String lastName;
60                 int age;
61                 public int getId() { return id; }
62                 public void setId(int id) { this.id = id; }
63                 """
64                     .trimIndent(),
65             output = {
66                 fun stringAdapterCode(out: String, indexVar: String) =
67                     """
68                     if (statement.isNull($indexVar)) {
69                       $out = null;
70                     } else {
71                       $out = statement.getText($indexVar);
72                     }
73                     """
74                         .trimIndent()
75                 """
76                 |private MyEntity __entityStatementConverter_fooBarMyEntity(
77                 |@NonNull final SQLiteStatement statement) {
78                 |  final MyEntity _entity;
79                 |  final int _columnIndexOfId = SQLiteStatementUtil.getColumnIndex(statement, "id");
80                 |  final int _columnIndexOfName = SQLiteStatementUtil.getColumnIndex(statement, "name");
81                 |  final int _columnIndexOfLastName = SQLiteStatementUtil.getColumnIndex(statement, "lastName");
82                 |  final int _columnIndexOfAge = SQLiteStatementUtil.getColumnIndex(statement, "age");
83                 |  _entity = new MyEntity();
84                 |  if (_columnIndexOfId != -1) {
85                 |    final int _tmpId;
86                 |    _tmpId = (int) (statement.getLong(_columnIndexOfId));
87                 |    _entity.setId(_tmpId);
88                 |  }
89                 |  if (_columnIndexOfName != -1) {
90                 |    ${stringAdapterCode("_entity.name", "_columnIndexOfName")}
91                 |  }
92                 |  if (_columnIndexOfLastName != -1) {
93                 |    ${stringAdapterCode("_entity.lastName", "_columnIndexOfLastName")}
94                 |  }
95                 |  if (_columnIndexOfAge != -1) {
96                 |    _entity.age = (int) (statement.getLong(_columnIndexOfAge));
97                 |  }
98                 |  return _entity;
99                 |}
100                 """
101                     .trimMargin()
102             }
103         )
104     }
105 
106     private fun generateAndMatch(
107         input: String,
108         output: (Boolean) -> String,
109     ) {
110         generate(input) {
111             it.assertCompilationResult {
112                 generatedSource(
113                     Source.java(
114                         qName = "foo.bar.MyContainerClass",
115                         code = listOf(OUT_PREFIX, output(it.isKsp), OUT_SUFFIX).joinToString("\n")
116                     )
117                 )
118             }
119         }
120     }
121 
122     private fun generate(input: String, handler: (XTestInvocation) -> Unit) {
123         singleEntity(input) { entity, invocation ->
124             val className = XClassName.get("foo.bar", "MyContainerClass")
125             val writer =
126                 object : TypeWriter(WriterContext(CodeLanguage.JAVA, setOf(Platform.JVM), true)) {
127                     override val packageName = className.packageName
128 
129                     override fun createTypeSpecBuilder(): XTypeSpec.Builder {
130                         getOrCreateFunction(EntityStatementConverterWriter(entity))
131                         return XTypeSpec.classBuilder(className).applyToJavaPoet {
132                             addModifiers(Modifier.PUBLIC)
133                         }
134                     }
135                 }
136             writer.write(invocation.processingEnv)
137             handler(invocation)
138         }
139     }
140 }
141