Skip to content

Commit 130fbc9

Browse files
committed
Improve code style of buildSrc
1 parent b04e701 commit 130fbc9

3 files changed

Lines changed: 113 additions & 69 deletions

File tree

buildSrc/src/main/kotlin/CopyFilesTask.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ abstract class CopyFilesTask @Inject constructor(
3838
abstract val destination: DirectoryProperty
3939

4040
@TaskAction
41+
@Suppress("UndocumentedPublicFunction") // Described by class'es doc
4142
fun copy() {
4243
fs.copy {
4344
from(sources)

buildSrc/src/main/kotlin/GenerateMapsDatabaseTask.kt

Lines changed: 111 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,19 @@ import org.gradle.api.tasks.TaskAction
3131
import org.sqlite.SQLiteDataSource
3232
import java.io.File
3333
import java.sql.Connection
34+
import java.sql.PreparedStatement
3435
import java.sql.Statement
36+
import kotlin.io.extension
37+
import kotlin.io.inputStream
38+
import kotlin.io.nameWithoutExtension
39+
import kotlin.io.writeBytes
40+
import kotlin.use
3541

42+
private const val TABLE_NAME_PLACEHOLDER = "\${TABLE_NAME}"
43+
44+
/**
45+
* Generates maps database from latest Room schema and map-info JSONs.
46+
*/
3647
@CacheableTask
3748
abstract class GenerateMapsDatabaseTask : DefaultTask() {
3849
@get:InputDirectory
@@ -47,6 +58,7 @@ abstract class GenerateMapsDatabaseTask : DefaultTask() {
4758
abstract val outputFile: RegularFileProperty
4859

4960
@TaskAction
61+
@Suppress("UndocumentedPublicFunction") // Described by class'es doc
5062
fun generateMapsDatabase() {
5163
val schemaFile = requireNotNull(
5264
schemaDirectory.asFileTree
@@ -82,21 +94,7 @@ abstract class GenerateMapsDatabaseTask : DefaultTask() {
8294
execute("PRAGMA user_version = ${schema.database.version}")
8395

8496
for (entity in schema.database.entities) {
85-
execute(entity.createSql.replace("\${TABLE_NAME}", entity.tableName))
86-
for (index in entity.indices) {
87-
execute(index.createSql.replace("\${TABLE_NAME}", entity.tableName))
88-
}
89-
if (entity is RoomSchema.Database.Entity.Fts) {
90-
for (triggerCreateSql in entity.contentSyncTriggers) {
91-
// Table name seems to be hard-coded in contentSyncTriggers
92-
if (triggerCreateSql.contains("\${TABLE_NAME}")) {
93-
throw UnsupportedOperationException(
94-
"Table name parameter in contentSyncTriggers: $triggerCreateSql"
95-
)
96-
}
97-
execute(triggerCreateSql)
98-
}
99-
}
97+
createEntity(entity)
10098
}
10199

102100
// To be implemented when a need arises
@@ -105,76 +103,120 @@ abstract class GenerateMapsDatabaseTask : DefaultTask() {
105103
}
106104
}
107105

106+
private fun Statement.createEntity(entity: RoomSchema.Database.Entity) {
107+
execute(entity.createSql.replace(TABLE_NAME_PLACEHOLDER, entity.tableName))
108+
109+
for (index in entity.indices) {
110+
execute(index.createSql.replace(TABLE_NAME_PLACEHOLDER, entity.tableName))
111+
}
112+
113+
if (entity is RoomSchema.Database.Entity.Fts) {
114+
for (triggerCreateSql in entity.contentSyncTriggers) {
115+
// Table name seems to be hard-coded in contentSyncTriggers
116+
if (triggerCreateSql.contains(TABLE_NAME_PLACEHOLDER)) {
117+
throw UnsupportedOperationException(
118+
"Table name parameter in contentSyncTriggers: $triggerCreateSql"
119+
)
120+
}
121+
execute(triggerCreateSql)
122+
}
123+
}
124+
}
125+
108126
@OptIn(ExperimentalSerializationApi::class)
109127
private fun Connection.fillMapInfo(mapInfoFile: File) {
110128
logger.info("Filling data from $mapInfoFile")
111129
val mapInfo = mapInfoFile.inputStream().use { Json.decodeFromStream<MapInfo>(it) }
112130

113-
prepareStatement(
131+
withPreparedStatement(
114132
"INSERT INTO map_info (id, internal_name, floor_width, floor_height, tile_size, levels_num, floors_num) " +
115133
"VALUES (?, ?, ?, ?, ?, ?, ?)"
116-
).use { insertMapInfo ->
117-
with(insertMapInfo) {
118-
setInt(1, mapInfo.id)
119-
setString(2, mapInfo.internalName)
120-
setInt(3, mapInfo.floorWidth)
121-
setInt(4, mapInfo.floorHeight)
122-
setInt(5, mapInfo.tileSize)
123-
setInt(6, mapInfo.zoomLevelsNum)
124-
setInt(7, mapInfo.floors.size)
125-
executeUpdate()
126-
}
134+
) {
135+
setMapInfoParameters(mapInfo)
136+
executeUpdate()
127137
}
128138

129-
prepareStatement(
139+
withPreparedStatement(
130140
"INSERT INTO map_title (map_id, language_id, title) VALUES (?, ?, ?)"
131-
).use { insertMapTitle ->
132-
with(insertMapTitle) {
133-
for ((language, title) in mapInfo.title.toMap()) {
134-
setInt(1, mapInfo.id)
135-
setString(2, language)
136-
setString(3, title)
137-
addBatch()
138-
}
139-
executeBatch()
141+
) {
142+
for ((language, title) in mapInfo.title.toMap()) {
143+
setMapTitleParameters(mapInfo.id, language, title)
144+
addBatch()
140145
}
146+
executeBatch()
141147
}
142148

143-
prepareStatement(
144-
"INSERT INTO marker (map_id, type, floor, x, y) VALUES (?, ?, ?, ?, ?) RETURNING id"
145-
).use { insertMarker ->
146-
prepareStatement(
147-
"INSERT INTO marker_text (marker_id, language_id, title, location, description)" +
148-
"VALUES (?, ?, ?, ?, ?)"
149-
).use { insertMarkerText ->
150-
for (floor in mapInfo.floors) {
151-
for (marker in floor.markers) {
152-
val markerId = with(insertMarker) {
153-
setInt(1, mapInfo.id)
154-
setString(2, marker.type)
155-
setInt(3, floor.floor)
156-
setDouble(4, marker.x.toDouble() / mapInfo.floorWidth)
157-
setDouble(5, marker.y.toDouble() / mapInfo.floorHeight)
158-
executeQuery().use {
159-
check(it.next())
160-
it.getLong("id")
161-
}
162-
}
163-
164-
for ((language, textInfo) in marker.textInfos()) {
165-
with(insertMarkerText) {
166-
setLong(1, markerId)
167-
setString(2, language)
168-
setString(3, textInfo.title)
169-
setString(4, textInfo.location)
170-
setString(5, textInfo.description)
171-
addBatch()
172-
}
173-
}
149+
usePreparedStatements(
150+
"INSERT INTO marker (map_id, type, floor, x, y) VALUES (?, ?, ?, ?, ?) RETURNING id",
151+
"INSERT INTO marker_text (marker_id, language_id, title, location, description)" +
152+
"VALUES (?, ?, ?, ?, ?)"
153+
) { insertMarker, insertMarkerText ->
154+
for (floor in mapInfo.floors) {
155+
for (marker in floor.markers) {
156+
insertMarker.setMarkerParameters(
157+
mapInfo.id, floor.floor, mapInfo.floorWidth, mapInfo.floorHeight, marker
158+
)
159+
val markerId = insertMarker.executeQuery().use {
160+
check(it.next())
161+
it.getLong("id")
162+
}
163+
for ((language, textInfo) in marker.textInfos()) {
164+
insertMarkerText.setMarkerTestParameters(markerId, language, textInfo)
165+
insertMarkerText.addBatch()
174166
}
175167
}
176-
insertMarkerText.executeBatch()
177168
}
169+
insertMarkerText.executeBatch()
178170
}
179171
}
172+
173+
private inline fun Connection.withPreparedStatement(
174+
sql: String, action: PreparedStatement.() -> Unit
175+
) {
176+
prepareStatement(sql).use { it.action() }
177+
}
178+
179+
private inline fun Connection.usePreparedStatements(
180+
sql1: String, sql2: String, block: (PreparedStatement, PreparedStatement) -> Unit
181+
) {
182+
prepareStatement(sql1).use { s1 -> prepareStatement(sql2).use { s2 -> block(s1, s2) } }
183+
}
184+
185+
private fun PreparedStatement.setMapInfoParameters(mapInfo: MapInfo) {
186+
setInt(1, mapInfo.id)
187+
setString(2, mapInfo.internalName)
188+
setInt(3, mapInfo.floorWidth)
189+
setInt(4, mapInfo.floorHeight)
190+
setInt(5, mapInfo.tileSize)
191+
setInt(6, mapInfo.zoomLevelsNum)
192+
setInt(7, mapInfo.floors.size)
193+
}
194+
195+
private fun PreparedStatement.setMapTitleParameters(
196+
mapId: Int, language: String, title: String
197+
) {
198+
setInt(1, mapId)
199+
setString(2, language)
200+
setString(3, title)
201+
}
202+
203+
private fun PreparedStatement.setMarkerParameters(
204+
mapId: Int, floor: Int, floorWidth: Int, floorHeight: Int, marker: MapInfo.Floor.Marker
205+
) {
206+
setInt(1, mapId)
207+
setString(2, marker.type)
208+
setInt(3, floor)
209+
setDouble(4, marker.x.toDouble() / floorWidth)
210+
setDouble(5, marker.y.toDouble() / floorHeight)
211+
}
212+
213+
private fun PreparedStatement.setMarkerTestParameters(
214+
markerId: Long, language: String, textInfo: MapInfo.Floor.Marker.TextInfo
215+
) {
216+
setLong(1, markerId)
217+
setString(2, language)
218+
setString(3, textInfo.title)
219+
setString(4, textInfo.location)
220+
setString(5, textInfo.description)
221+
}
180222
}

buildSrc/src/main/kotlin/RoomSchema.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ internal data class RoomSchema(
8080
}
8181

8282
object EntitySerializer : JsonContentPolymorphicSerializer<Entity>(Entity::class) {
83+
@Suppress("UseIfExpressionInsteadOfWhen") // Follows an official example
8384
override fun selectDeserializer(element: JsonElement) = when {
8485
"ftsVersion" in element.jsonObject -> Entity.Fts.serializer()
8586
else -> Entity.Normal.serializer()

0 commit comments

Comments
 (0)