Refactir SqliteDictionary

This commit is contained in:
Marvin Elsen 2024-10-21 21:13:27 +02:00
parent 1b5c32c320
commit a1a7567bd0
Signed by: marvinelsen
GPG Key ID: 820672408CC318C2
5 changed files with 64 additions and 64 deletions

View File

@ -3,10 +3,10 @@ package com.marvinelsen.willow.domain
interface Dictionary { interface Dictionary {
fun search(query: String, searchMode: SearchMode): List<DictionaryEntry> fun search(query: String, searchMode: SearchMode): List<DictionaryEntry>
fun findWordsBeginning(entry: DictionaryEntry): List<DictionaryEntry> fun findWordsBeginningWith(entry: DictionaryEntry): List<DictionaryEntry>
fun findWordsContaining(entry: DictionaryEntry): List<DictionaryEntry> fun findWordsContaining(entry: DictionaryEntry): List<DictionaryEntry>
fun findCharacters(entry: DictionaryEntry): List<DictionaryEntry> fun findCharactersOf(entry: DictionaryEntry): List<DictionaryEntry>
fun findSentencesContaining(entry: DictionaryEntry): List<Sentence> fun findExampleSentencesFor(entry: DictionaryEntry): List<Sentence>
} }

View File

@ -58,7 +58,7 @@ class SqliteDictionary(private val connection: Connection) : Dictionary {
) )
} }
private val searchSegments = """ private val searchSegmentsRawSql = """
WITH cte(id, segment) AS (VALUES ?) WITH cte(id, segment) AS (VALUES ?)
SELECT entry.traditional, simplified, pinyin_with_tone_marks, pinyin_with_tone_numbers, zhuyin, cedict_definitions, cross_straits_definitions, moe_definitions SELECT entry.traditional, simplified, pinyin_with_tone_marks, pinyin_with_tone_numbers, zhuyin, cedict_definitions, cross_straits_definitions, moe_definitions
FROM entry INNER JOIN cte FROM entry INNER JOIN cte
@ -66,7 +66,7 @@ class SqliteDictionary(private val connection: Connection) : Dictionary {
ORDER BY cte.id ORDER BY cte.id
""".trimIndent() """.trimIndent()
private val findWordsBeginning: PreparedStatement by lazy { private val findWordsBeginningPreparedStatement: PreparedStatement by lazy {
connection.prepareStatement( connection.prepareStatement(
""" """
SELECT traditional, simplified, pinyin_with_tone_marks, pinyin_with_tone_numbers, zhuyin, cedict_definitions, cross_straits_definitions, moe_definitions SELECT traditional, simplified, pinyin_with_tone_marks, pinyin_with_tone_numbers, zhuyin, cedict_definitions, cross_straits_definitions, moe_definitions
@ -77,7 +77,7 @@ class SqliteDictionary(private val connection: Connection) : Dictionary {
) )
} }
private val findWordsContaining: PreparedStatement by lazy { private val findWordsContainingPreparedStatement: PreparedStatement by lazy {
connection.prepareStatement( connection.prepareStatement(
""" """
SELECT traditional, simplified, pinyin_with_tone_marks, pinyin_with_tone_numbers, zhuyin, cedict_definitions, cross_straits_definitions, moe_definitions SELECT traditional, simplified, pinyin_with_tone_marks, pinyin_with_tone_numbers, zhuyin, cedict_definitions, cross_straits_definitions, moe_definitions
@ -88,16 +88,16 @@ class SqliteDictionary(private val connection: Connection) : Dictionary {
) )
} }
private val findCharacters = """ private val findCharactersRawSql = """
WITH cte(id, character, syllable) AS (VALUES ?) WITH cte(id, character, pinyin) AS (VALUES ?)
SELECT traditional, simplified, pinyin_with_tone_marks, pinyin_with_tone_numbers, zhuyin, cedict_definitions, cross_straits_definitions, moe_definitions SELECT traditional, simplified, pinyin_with_tone_marks, pinyin_with_tone_numbers, zhuyin, cedict_definitions, cross_straits_definitions, moe_definitions
FROM entry INNER JOIN cte FROM entry INNER JOIN cte
ON cte.character = entry.traditional ON cte.character = entry.traditional
WHERE cte.syllable = entry.pinyin_with_tone_numbers WHERE cte.pinyin = entry.pinyin_with_tone_numbers
ORDER BY cte.id ORDER BY cte.id
""".trimIndent() """.trimIndent()
private val findSentences: PreparedStatement by lazy { private val findExampleSentencesPreparedStatement: PreparedStatement by lazy {
connection.prepareStatement( connection.prepareStatement(
""" """
SELECT traditional, simplified SELECT traditional, simplified
@ -112,67 +112,69 @@ class SqliteDictionary(private val connection: Connection) : Dictionary {
SearchMode.SIMPLIFIED -> searchSimplified(query) SearchMode.SIMPLIFIED -> searchSimplified(query)
SearchMode.TRADITIONAL -> searchTraditional(query) SearchMode.TRADITIONAL -> searchTraditional(query)
SearchMode.PINYIN -> searchPinyin(query) SearchMode.PINYIN -> searchPinyin(query)
SearchMode.SEGMENTS -> searchSegments(query) SearchMode.SEGMENTS -> searchSegmentsOf(query)
} }
private fun searchSimplified(query: String): List<DictionaryEntry> { private fun searchSimplified(simplified: String): List<DictionaryEntry> {
searchSimplifiedPreparedStatement.setString(1, "$query*") searchSimplifiedPreparedStatement.setString(1, "$simplified*")
val resultSet: ResultSet = searchSimplifiedPreparedStatement.executeQuery() return searchSimplifiedPreparedStatement.executeQuery().use {
it.toListOfDictionaryEntries()
return resultSet.toListOfDictionaryEntries() }
} }
private fun searchTraditional(query: String): List<DictionaryEntry> { private fun searchTraditional(traditional: String): List<DictionaryEntry> {
searchTraditionalPreparedStatement.setString(1, "$query*") searchTraditionalPreparedStatement.setString(1, "$traditional*")
val resultSet: ResultSet = searchTraditionalPreparedStatement.executeQuery() return searchTraditionalPreparedStatement.executeQuery().use {
it.toListOfDictionaryEntries()
return resultSet.toListOfDictionaryEntries() }
} }
private fun searchPinyin(query: String): List<DictionaryEntry> { private fun searchPinyin(pinyin: String): List<DictionaryEntry> {
val sanitizedQuery = query.lowercase().replace(whitespaceRegex, "") val sanitizedPinyin = pinyin.lowercase().replace(whitespaceRegex, "")
searchPinyinPreparedStatement.setString(1, "$sanitizedQuery*") searchPinyinPreparedStatement.setString(1, "$sanitizedPinyin*")
searchPinyinPreparedStatement.setString(2, "$sanitizedQuery*") searchPinyinPreparedStatement.setString(2, "$sanitizedPinyin*")
val resultSet: ResultSet = searchPinyinPreparedStatement.executeQuery() return searchPinyinPreparedStatement.executeQuery().use { resultSet ->
resultSet.toListOfDictionaryEntries()
return resultSet.toListOfDictionaryEntries() }
} }
private fun searchSegments(phrase: String): List<DictionaryEntry> { private fun searchSegmentsOf(phrase: String): List<DictionaryEntry> {
val segments = segmentBs.segment(phrase, SegmentResultHandlers.word()) val segments = segmentBs.segment(phrase, SegmentResultHandlers.word())
val segmentsListString = segments val segmentsListString = segments
.mapIndexed { index, s -> "($index, '$s')" } .mapIndexed { index, segment -> "($index, '$segment')" }
.joinToString(",") .joinToString(",")
val query = searchSegments.replace("?", segmentsListString) val query = searchSegmentsRawSql.replace("?", segmentsListString)
val resultSet: ResultSet = connection.createStatement().executeQuery(query) return connection.createStatement().use { statement ->
statement.executeQuery(query).use { resultSet ->
return resultSet.toListOfDictionaryEntries() resultSet.toListOfDictionaryEntries()
}
}
} }
override fun findWordsContaining(entry: DictionaryEntry): List<DictionaryEntry> { override fun findWordsContaining(entry: DictionaryEntry): List<DictionaryEntry> {
findWordsContaining.setString(1, "_%${entry.traditional}%") findWordsContainingPreparedStatement.setString(1, "_%${entry.traditional}%")
val resultSet: ResultSet = findWordsContaining.executeQuery() return findWordsContainingPreparedStatement.executeQuery().use { resultSet ->
resultSet.toListOfDictionaryEntries()
return resultSet.toListOfDictionaryEntries() }
} }
override fun findWordsBeginning(entry: DictionaryEntry): List<DictionaryEntry> { override fun findWordsBeginningWith(entry: DictionaryEntry): List<DictionaryEntry> {
findWordsBeginning.setString(1, "${entry.traditional}?*") findWordsBeginningPreparedStatement.setString(1, "${entry.traditional}?*")
val resultSet: ResultSet = findWordsBeginning.executeQuery() return findWordsBeginningPreparedStatement.executeQuery().use { resultSet ->
resultSet.toListOfDictionaryEntries()
return resultSet.toListOfDictionaryEntries() }
} }
override fun findCharacters(entry: DictionaryEntry): List<DictionaryEntry> { override fun findCharactersOf(entry: DictionaryEntry): List<DictionaryEntry> {
val pinyinSyllablesWithToneNumbers = entry.pinyinWithToneNumbers val pinyinSyllablesWithToneNumbers = entry.pinyinWithToneNumbers
.lowercase() .lowercase()
.split(" ") .split(" ")
@ -190,19 +192,21 @@ class SqliteDictionary(private val connection: Connection) : Dictionary {
.mapIndexed { index, s -> "($index, '${s.first}', '${s.second}')" } .mapIndexed { index, s -> "($index, '${s.first}', '${s.second}')" }
.joinToString(",") .joinToString(",")
val query = findCharacters.replace("?", queryInput) val query = findCharactersRawSql.replace("?", queryInput)
val resultSet: ResultSet = connection.createStatement().executeQuery(query) return connection.createStatement().use { statement ->
statement.executeQuery(query).use { resultSet ->
return resultSet.toListOfDictionaryEntries() resultSet.toListOfDictionaryEntries()
}
}
} }
override fun findSentencesContaining(entry: DictionaryEntry): List<Sentence> { override fun findExampleSentencesFor(entry: DictionaryEntry): List<Sentence> {
findSentences.setString(1, "_%${entry.traditional}%") findExampleSentencesPreparedStatement.setString(1, "_%${entry.traditional}%")
val resultSet: ResultSet = findSentences.executeQuery() return findExampleSentencesPreparedStatement.executeQuery().use { resultSet ->
resultSet.toListOfSentences()
return resultSet.toListOfSentences() }
} }
} }
@ -219,10 +223,8 @@ private fun ResultSet.toDictionaryEntry() = DictionaryEntry(
) )
private fun ResultSet.toListOfDictionaryEntries() = buildList { private fun ResultSet.toListOfDictionaryEntries() = buildList {
this@toListOfDictionaryEntries.use { while (this@toListOfDictionaryEntries.next()) {
while (it.next()) { add(this@toListOfDictionaryEntries.toDictionaryEntry())
add(it.toDictionaryEntry())
}
} }
} }
@ -232,9 +234,7 @@ private fun ResultSet.toSentence() = Sentence(
) )
private fun ResultSet.toListOfSentences() = buildList { private fun ResultSet.toListOfSentences() = buildList {
this@toListOfSentences.use { while (this@toListOfSentences.next()) {
while (it.next()) { add(this@toListOfSentences.toSentence())
add(it.toSentence())
}
} }
} }

View File

@ -15,6 +15,6 @@ class FindCharacterService(private val dictionary: Dictionary) : Service<Observa
override fun createTask() = task { override fun createTask() = task {
if (!this::entry.isInitialized) error("Entry is not initialized") if (!this::entry.isInitialized) error("Entry is not initialized")
FXCollections.observableList(dictionary.findCharacters(entry.toDomain()).map { it.toFx() }) FXCollections.observableList(dictionary.findCharactersOf(entry.toDomain()).map { it.toFx() })
} }
} }

View File

@ -16,6 +16,6 @@ class FindSentencesService(private val dictionary: Dictionary) : Service<Observa
override fun createTask() = task { override fun createTask() = task {
if (!this::entry.isInitialized) error("Entry is not initialized") if (!this::entry.isInitialized) error("Entry is not initialized")
FXCollections.observableList(dictionary.findSentencesContaining(entry.toDomain()).map { it.toFx() }) FXCollections.observableList(dictionary.findExampleSentencesFor(entry.toDomain()).map { it.toFx() })
} }
} }

View File

@ -15,6 +15,6 @@ class FindWordsBeginningService(private val dictionary: Dictionary) : Service<Ob
override fun createTask() = task { override fun createTask() = task {
if (!this::entry.isInitialized) error("Entry is not initialized") if (!this::entry.isInitialized) error("Entry is not initialized")
FXCollections.observableList(dictionary.findWordsBeginning(entry.toDomain()).map { it.toFx() }) FXCollections.observableList(dictionary.findWordsBeginningWith(entry.toDomain()).map { it.toFx() })
} }
} }