Skip to content

Commit 03c1f9a

Browse files
committed
[ANDROSDK-2183] KtlintFormat and refactor code
1 parent a0d3f0e commit 03c1f9a

File tree

5 files changed

+123
-142
lines changed

5 files changed

+123
-142
lines changed

core/src/androidTest/java/org/hisp/dhis/android/core/configuration/internal/MigrationDatabaseNameHashIntegrationShould.kt

Lines changed: 73 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ class MigrationDatabaseNameHashIntegrationShould {
5555
context,
5656
databaseConfigurationStore,
5757
nameGenerator,
58-
renamer
58+
renamer,
5959
)
6060

6161
// Clean up any existing test files
@@ -76,6 +76,7 @@ class MigrationDatabaseNameHashIntegrationShould {
7676

7777
@Suppress("DEPRECATION")
7878
val oldDbName1 = nameGenerator.getOldDatabaseName(url1, username, false)
79+
7980
@Suppress("DEPRECATION")
8081
val oldDbName2 = nameGenerator.getOldDatabaseName(url2, username, false)
8182

@@ -90,22 +91,24 @@ class MigrationDatabaseNameHashIntegrationShould {
9091

9192
// Create configuration with both accounts pointing to same DB
9293
val configuration = DatabasesConfiguration.builder()
93-
.accounts(listOf(
94-
DatabaseAccount.builder()
95-
.username(username)
96-
.serverUrl(url1)
97-
.databaseName(oldDbName1)
98-
.encrypted(false)
99-
.databaseCreationDate("2024-01-01")
100-
.build(),
101-
DatabaseAccount.builder()
102-
.username(username)
103-
.serverUrl(url2)
104-
.databaseName(oldDbName2)
105-
.encrypted(false)
106-
.databaseCreationDate("2024-01-01")
107-
.build()
108-
))
94+
.accounts(
95+
listOf(
96+
DatabaseAccount.builder()
97+
.username(username)
98+
.serverUrl(url1)
99+
.databaseName(oldDbName1)
100+
.encrypted(false)
101+
.databaseCreationDate("2024-01-01")
102+
.build(),
103+
DatabaseAccount.builder()
104+
.username(username)
105+
.serverUrl(url2)
106+
.databaseName(oldDbName2)
107+
.encrypted(false)
108+
.databaseCreationDate("2024-01-01")
109+
.build(),
110+
),
111+
)
109112
.build()
110113

111114
databaseConfigurationStore.set(configuration)
@@ -166,15 +169,17 @@ class MigrationDatabaseNameHashIntegrationShould {
166169

167170
// Create configuration
168171
val configuration = DatabasesConfiguration.builder()
169-
.accounts(listOf(
170-
DatabaseAccount.builder()
171-
.username(username)
172-
.serverUrl(url)
173-
.databaseName(oldDbName)
174-
.encrypted(false)
175-
.databaseCreationDate("2024-01-01")
176-
.build()
177-
))
172+
.accounts(
173+
listOf(
174+
DatabaseAccount.builder()
175+
.username(username)
176+
.serverUrl(url)
177+
.databaseName(oldDbName)
178+
.encrypted(false)
179+
.databaseCreationDate("2024-01-01")
180+
.build(),
181+
),
182+
)
178183
.build()
179184

180185
databaseConfigurationStore.set(configuration)
@@ -221,21 +226,23 @@ class MigrationDatabaseNameHashIntegrationShould {
221226

222227
// Create configuration with pending import
223228
val configuration = DatabasesConfiguration.builder()
224-
.accounts(listOf(
225-
DatabaseAccount.builder()
226-
.username(username)
227-
.serverUrl(url)
228-
.databaseName(oldDbName)
229-
.encrypted(false)
230-
.databaseCreationDate("2024-01-01")
231-
.importDB(
232-
DatabaseAccountImport.builder()
233-
.status(DatabaseAccountImportStatus.PENDING_TO_IMPORT)
234-
.protectedDbName(oldProtectedName)
235-
.build()
236-
)
237-
.build()
238-
))
229+
.accounts(
230+
listOf(
231+
DatabaseAccount.builder()
232+
.username(username)
233+
.serverUrl(url)
234+
.databaseName(oldDbName)
235+
.encrypted(false)
236+
.databaseCreationDate("2024-01-01")
237+
.importDB(
238+
DatabaseAccountImport.builder()
239+
.status(DatabaseAccountImportStatus.PENDING_TO_IMPORT)
240+
.protectedDbName(oldProtectedName)
241+
.build(),
242+
)
243+
.build(),
244+
),
245+
)
239246
.build()
240247

241248
databaseConfigurationStore.set(configuration)
@@ -272,15 +279,17 @@ class MigrationDatabaseNameHashIntegrationShould {
272279
}
273280

274281
val configuration = DatabasesConfiguration.builder()
275-
.accounts(listOf(
276-
DatabaseAccount.builder()
277-
.username(username)
278-
.serverUrl(url)
279-
.databaseName(newDbName)
280-
.encrypted(false)
281-
.databaseCreationDate("2024-01-01")
282-
.build()
283-
))
282+
.accounts(
283+
listOf(
284+
DatabaseAccount.builder()
285+
.username(username)
286+
.serverUrl(url)
287+
.databaseName(newDbName)
288+
.encrypted(false)
289+
.databaseCreationDate("2024-01-01")
290+
.build(),
291+
),
292+
)
284293
.build()
285294

286295
databaseConfigurationStore.set(configuration)
@@ -306,15 +315,17 @@ class MigrationDatabaseNameHashIntegrationShould {
306315

307316
// Create configuration but NO physical database file
308317
val configuration = DatabasesConfiguration.builder()
309-
.accounts(listOf(
310-
DatabaseAccount.builder()
311-
.username(username)
312-
.serverUrl(url)
313-
.databaseName(oldDbName)
314-
.encrypted(false)
315-
.databaseCreationDate("2024-01-01")
316-
.build()
317-
))
318+
.accounts(
319+
listOf(
320+
DatabaseAccount.builder()
321+
.username(username)
322+
.serverUrl(url)
323+
.databaseName(oldDbName)
324+
.encrypted(false)
325+
.databaseCreationDate("2024-01-01")
326+
.build(),
327+
),
328+
)
318329
.build()
319330

320331
databaseConfigurationStore.set(configuration)
@@ -339,7 +350,7 @@ class MigrationDatabaseNameHashIntegrationShould {
339350
val accounts = listOf(
340351
Triple("https://server1.org", "user1", false),
341352
Triple("https://server2.org", "user2", true),
342-
Triple("https://server3.org", "user3", false)
353+
Triple("https://server3.org", "user3", false),
343354
)
344355

345356
// Create old-format accounts with physical files
@@ -392,7 +403,8 @@ class MigrationDatabaseNameHashIntegrationShould {
392403
// Clean up database files
393404
context.databaseList().forEach { dbName ->
394405
if (dbName.contains("play") || dbName.contains("demo") ||
395-
dbName.contains("server") || dbName.contains("test")) {
406+
dbName.contains("server") || dbName.contains("test")
407+
) {
396408
context.deleteDatabase(dbName)
397409
}
398410
}

core/src/main/java/org/hisp/dhis/android/core/configuration/internal/DatabaseNameGenerator.kt

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,8 @@ internal class DatabaseNameGenerator {
6969
val md = MessageDigest.getInstance("SHA-256")
7070
val digest = md.digest(input.toByteArray())
7171
// First 4 bytes = 8 hex characters
72-
return digest.take(4).joinToString("") {
73-
it.toUByte().toString(16).padStart(2, '0')
72+
return digest.take(HASH_BYTE_COUNT).joinToString("") {
73+
it.toUByte().toString(HEX_RADIX).padStart(HEX_STRING_WIDTH, '0')
7474
}
7575
}
7676

@@ -96,5 +96,8 @@ internal class DatabaseNameGenerator {
9696

9797
companion object {
9898
const val DB_SUFFIX = ".db"
99+
private const val HASH_BYTE_COUNT = 4
100+
private const val HEX_STRING_WIDTH = 2
101+
private const val HEX_RADIX = 16
99102
}
100103
}

core/src/main/java/org/hisp/dhis/android/core/configuration/internal/migration/MigrationDatabaseNameHash.kt

Lines changed: 39 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,8 @@ internal class MigrationDatabaseNameHash(
5757
) {
5858

5959
fun apply() {
60-
val configuration = databaseConfigurationStore.get() ?: return
61-
62-
if (configuration.accounts().isEmpty()) {
60+
val configuration = databaseConfigurationStore.get()
61+
if (configuration == null || configuration.accounts().isEmpty()) {
6362
return
6463
}
6564

@@ -74,13 +73,6 @@ internal class MigrationDatabaseNameHash(
7473

7574
Log.i(TAG, "Starting database name hash migration for ${configuration.accounts().size} accounts")
7675

77-
val collisions = detectCollisions(configuration)
78-
79-
if (collisions.isNotEmpty()) {
80-
Log.w(TAG, "Detected ${collisions.size} database name collisions")
81-
handleCollisions(collisions)
82-
}
83-
8476
val migratedAccounts = configuration.accounts().mapNotNull { account ->
8577
migrateAccount(account)
8678
}
@@ -94,41 +86,12 @@ internal class MigrationDatabaseNameHash(
9486
Log.i(TAG, "Database name hash migration completed successfully")
9587
}
9688

97-
private fun detectCollisions(configuration: DatabasesConfiguration): Map<String, List<DatabaseAccount>> {
98-
return configuration.accounts()
99-
.groupBy { it.databaseName() }
100-
.filterValues { it.size > 1 }
101-
}
102-
103-
/**
104-
* Handles collision scenarios by keeping only the first account's data
105-
* and marking others for re-login.
106-
*
107-
* Strategy:
108-
* - First account in the collision list keeps the database
109-
* - Other accounts will get a new database name (empty database)
110-
* - User will need to sync data again for the other accounts
111-
*/
112-
private fun handleCollisions(collisions: Map<String, List<DatabaseAccount>>) {
113-
collisions.forEach { (dbName, accounts) ->
114-
Log.w(TAG, """
115-
Collision detected for database: $dbName
116-
Affected accounts: ${accounts.size}
117-
${accounts.mapIndexed { index, acc ->
118-
" ${index + 1}. ${acc.username()}@${acc.serverUrl()}"
119-
}.joinToString("\n")}
120-
121-
Resolution: First account keeps data, others will get new empty databases.
122-
""".trimIndent())
123-
}
124-
}
125-
12689
private fun migrateAccount(account: DatabaseAccount): DatabaseAccount? {
12790
val oldDbName = account.databaseName()
12891
val newDbName = nameGenerator.getDatabaseName(
12992
account.serverUrl(),
13093
account.username(),
131-
account.encrypted()
94+
account.encrypted(),
13295
)
13396

13497
return try {
@@ -143,11 +106,14 @@ internal class MigrationDatabaseNameHash(
143106
if (dbRenamed) {
144107
Log.i(TAG, "Successfully migrated account: ${account.username()}@${account.serverUrl()}")
145108
} else {
146-
Log.w(TAG, "Account migrated but database file didn't exist: ${account.username()}@${account.serverUrl()}")
109+
Log.w(
110+
TAG,
111+
"Account migrated but database file didn't exist: ${account.username()}@${account.serverUrl()}",
112+
)
147113
}
148114

149115
updatedAccount
150-
} catch (e: Exception) {
116+
} catch (@Suppress("TooGenericExceptionCaught") e: Exception) {
151117
Log.e(TAG, "Failed to migrate account: ${account.username()}@${account.serverUrl()}", e)
152118
account
153119
}
@@ -159,25 +125,25 @@ internal class MigrationDatabaseNameHash(
159125
*/
160126
private fun renameDatabaseFile(oldDbName: String, newDbName: String): Boolean {
161127
val oldDbFile = context.getDatabasePath(oldDbName)
162-
163-
if (!oldDbFile.exists()) {
164-
Log.d(TAG, "Database file doesn't exist: $oldDbName")
165-
return false
166-
}
167-
168128
val newDbFile = context.getDatabasePath(newDbName)
169-
if (newDbFile.exists()) {
170-
Log.e(TAG, "Target database already exists, skipping rename: $newDbName")
171-
return false
172-
}
173-
174-
val success = databaseRenamer.renameDatabase(oldDbName, newDbName)
175129

176-
if (!success) {
177-
throw IllegalStateException("Failed to rename database from $oldDbName to $newDbName")
130+
return when {
131+
!oldDbFile.exists() -> {
132+
Log.d(TAG, "Database file doesn't exist: $oldDbName")
133+
false
134+
}
135+
newDbFile.exists() -> {
136+
Log.e(TAG, "Target database already exists, skipping rename: $newDbName")
137+
false
138+
}
139+
else -> {
140+
val success = databaseRenamer.renameDatabase(oldDbName, newDbName)
141+
if (!success) {
142+
throw IllegalStateException("Failed to rename database from $oldDbName to $newDbName")
143+
}
144+
true
145+
}
178146
}
179-
180-
return true
181147
}
182148

183149
private fun renameFileResourceDirectories(oldDbName: String, newDbName: String) {
@@ -205,27 +171,27 @@ internal class MigrationDatabaseNameHash(
205171
private fun updateImportDB(
206172
account: DatabaseAccount,
207173
oldDbName: String,
208-
newDbName: String
174+
newDbName: String,
209175
): org.hisp.dhis.android.core.configuration.internal.DatabaseAccountImport? {
210-
val importDB = account.importDB() ?: return null
176+
val importDB = account.importDB()
211177

212-
if (importDB.status() != DatabaseAccountImportStatus.PENDING_TO_IMPORT) {
213-
return null
214-
}
178+
return if (importDB == null || importDB.status() != DatabaseAccountImportStatus.PENDING_TO_IMPORT) {
179+
null
180+
} else {
181+
val oldProtectedName = "$oldDbName.protected"
182+
val newProtectedName = "$newDbName.protected"
215183

216-
val oldProtectedName = "$oldDbName.protected"
217-
val newProtectedName = "$newDbName.protected"
184+
val oldProtectedFile = context.getDatabasePath(oldProtectedName)
185+
val newProtectedFile = context.getDatabasePath(newProtectedName)
218186

219-
val oldProtectedFile = context.getDatabasePath(oldProtectedName)
220-
val newProtectedFile = context.getDatabasePath(newProtectedName)
187+
if (oldProtectedFile.exists()) {
188+
oldProtectedFile.renameTo(newProtectedFile)
189+
}
221190

222-
if (oldProtectedFile.exists()) {
223-
oldProtectedFile.renameTo(newProtectedFile)
191+
importDB.toBuilder()
192+
.protectedDbName(newProtectedName)
193+
.build()
224194
}
225-
226-
return importDB.toBuilder()
227-
.protectedDbName(newProtectedName)
228-
.build()
229195
}
230196

231197
companion object {

0 commit comments

Comments
 (0)