First commit
This commit is contained in:
40
src/main/kotlin/Main.kt
Normal file
40
src/main/kotlin/Main.kt
Normal file
@@ -0,0 +1,40 @@
|
||||
import io.ktor.serialization.kotlinx.*
|
||||
import io.ktor.serialization.kotlinx.json.*
|
||||
import io.ktor.server.application.*
|
||||
import io.ktor.server.netty.*
|
||||
import io.ktor.server.plugins.calllogging.*
|
||||
import io.ktor.server.plugins.contentnegotiation.*
|
||||
import io.ktor.server.plugins.defaultheaders.*
|
||||
import io.ktor.server.routing.*
|
||||
import io.ktor.server.websocket.*
|
||||
import service.DatabaseFactory
|
||||
//import service.WidgetService
|
||||
import util.JsonMapper
|
||||
import web.index
|
||||
//import web.widget
|
||||
|
||||
fun Application.module() {
|
||||
install(DefaultHeaders)
|
||||
install(CallLogging)
|
||||
install(WebSockets) {
|
||||
contentConverter = KotlinxWebsocketSerializationConverter(JsonMapper.defaultMapper)
|
||||
}
|
||||
|
||||
install(ContentNegotiation) {
|
||||
json(JsonMapper.defaultMapper)
|
||||
}
|
||||
|
||||
DatabaseFactory.connectAndMigrate()
|
||||
|
||||
//val widgetService = WidgetService()
|
||||
|
||||
routing {
|
||||
index()
|
||||
// widget(widgetService)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
EngineMain.main(args)
|
||||
}
|
||||
12
src/main/kotlin/dao/DictTypeDao.kt
Normal file
12
src/main/kotlin/dao/DictTypeDao.kt
Normal file
@@ -0,0 +1,12 @@
|
||||
package dao
|
||||
|
||||
import org.jetbrains.exposed.dao.*
|
||||
import org.jetbrains.exposed.dao.id.EntityID
|
||||
import tables.DictTypes
|
||||
|
||||
class DictTypeDao(id: EntityID<Int>) : IntEntity(id) {
|
||||
companion object : IntEntityClass<DictTypeDao>(DictTypes)
|
||||
|
||||
var shortName by DictTypes.shortName
|
||||
var fullName by DictTypes.fullName
|
||||
}
|
||||
12
src/main/kotlin/dao/DictionaryDao.kt
Normal file
12
src/main/kotlin/dao/DictionaryDao.kt
Normal file
@@ -0,0 +1,12 @@
|
||||
package dao
|
||||
|
||||
import org.jetbrains.exposed.dao.*
|
||||
import org.jetbrains.exposed.dao.id.EntityID
|
||||
import tables.Dictionaries
|
||||
|
||||
class DictionaryDao(id: EntityID<Int>) : IntEntity(id) {
|
||||
companion object : IntEntityClass<DictionaryDao>(Dictionaries)
|
||||
|
||||
var name by Dictionaries.name
|
||||
var fullName by Dictionaries.fullName
|
||||
}
|
||||
12
src/main/kotlin/dao/LanguageDao.kt
Normal file
12
src/main/kotlin/dao/LanguageDao.kt
Normal file
@@ -0,0 +1,12 @@
|
||||
package dao
|
||||
|
||||
import org.jetbrains.exposed.dao.*
|
||||
import org.jetbrains.exposed.dao.id.EntityID
|
||||
import tables.Languages
|
||||
|
||||
class LanguageDao(id: EntityID<Int>) : IntEntity(id) {
|
||||
companion object : IntEntityClass<LanguageDao>(Languages)
|
||||
|
||||
var name by Languages.name
|
||||
var shortName by Languages.shortName
|
||||
}
|
||||
13
src/main/kotlin/dao/PronunciationDao.kt
Normal file
13
src/main/kotlin/dao/PronunciationDao.kt
Normal file
@@ -0,0 +1,13 @@
|
||||
package dao
|
||||
|
||||
import models.Translation
|
||||
import org.jetbrains.exposed.dao.*
|
||||
import org.jetbrains.exposed.dao.id.EntityID
|
||||
import tables.Pronunciations
|
||||
|
||||
class PronunciationDao(id: EntityID<Int>) : IntEntity(id) {
|
||||
companion object : IntEntityClass<PronunciationDao>(Pronunciations)
|
||||
|
||||
var ipa by Pronunciations.ipa
|
||||
var filename by Pronunciations.filename
|
||||
}
|
||||
12
src/main/kotlin/dao/PronunciationTypeDao.kt
Normal file
12
src/main/kotlin/dao/PronunciationTypeDao.kt
Normal file
@@ -0,0 +1,12 @@
|
||||
package dao
|
||||
|
||||
import models.Translation
|
||||
import org.jetbrains.exposed.dao.*
|
||||
import org.jetbrains.exposed.dao.id.EntityID
|
||||
import tables.PronunciationTypes
|
||||
|
||||
class PronunciationTypeDao(id: EntityID<Int>) : IntEntity(id) {
|
||||
companion object : IntEntityClass<PronunciationTypeDao>(PronunciationTypes)
|
||||
|
||||
var name by PronunciationTypes.name
|
||||
}
|
||||
11
src/main/kotlin/dao/SuffixDao.kt
Normal file
11
src/main/kotlin/dao/SuffixDao.kt
Normal file
@@ -0,0 +1,11 @@
|
||||
package dao
|
||||
|
||||
import org.jetbrains.exposed.dao.*
|
||||
import org.jetbrains.exposed.dao.id.EntityID
|
||||
import tables.Suffixes
|
||||
|
||||
class SuffixDao(id: EntityID<Int>) : IntEntity(id) {
|
||||
companion object : IntEntityClass<SuffixDao>(Suffixes)
|
||||
|
||||
var text by Suffixes.text
|
||||
}
|
||||
14
src/main/kotlin/dao/TranslationDao.kt
Normal file
14
src/main/kotlin/dao/TranslationDao.kt
Normal file
@@ -0,0 +1,14 @@
|
||||
package dao
|
||||
|
||||
import models.Translation
|
||||
import org.jetbrains.exposed.dao.*
|
||||
import org.jetbrains.exposed.dao.id.EntityID
|
||||
import tables.Translations
|
||||
|
||||
class TranslationDao(id: EntityID<Int>) : IntEntity(id) {
|
||||
companion object : IntEntityClass<TranslationDao>(Translations)
|
||||
|
||||
var langName1 by Translations.langName1
|
||||
var langName2 by Translations.langName2
|
||||
var direction by Translations.direction
|
||||
}
|
||||
193
src/main/kotlin/db/migration/V1__test_connection.kt
Normal file
193
src/main/kotlin/db/migration/V1__test_connection.kt
Normal file
@@ -0,0 +1,193 @@
|
||||
package db.migration
|
||||
|
||||
import org.flywaydb.core.api.migration.BaseJavaMigration
|
||||
import org.flywaydb.core.api.migration.Context
|
||||
import org.jetbrains.exposed.sql.SchemaUtils
|
||||
import org.jetbrains.exposed.sql.insert
|
||||
import org.jetbrains.exposed.sql.transactions.transaction
|
||||
import kotlin.collections.*
|
||||
import kotliquery.*
|
||||
import de.m3y.kformat.*
|
||||
import de.m3y.kformat.Table.Hints
|
||||
import kotlinx.serialization.json.JsonObject
|
||||
import kotlinx.serialization.json.Json
|
||||
|
||||
val format = Json { encodeDefaults = true }
|
||||
|
||||
data class Dictionary(
|
||||
val id: Int,
|
||||
val lang1Id: Int,
|
||||
val lang2Id: Int,
|
||||
val name: String,
|
||||
val fullName: String)
|
||||
|
||||
data class DictType(
|
||||
val id: Int,
|
||||
val shortName: String,
|
||||
val fullName: String
|
||||
)
|
||||
data class Language(
|
||||
val id: Int,
|
||||
val name: String,
|
||||
val shortName: String
|
||||
)
|
||||
data class Translation(
|
||||
val id: Int,
|
||||
val dictionaryId: Int,
|
||||
val lang1Id: Int,
|
||||
val lang2Id: Int,
|
||||
val lang1Name: String,
|
||||
val lang2Name: String,
|
||||
val direction: Int
|
||||
)
|
||||
|
||||
data class Pronunciation(
|
||||
val id: Int,
|
||||
val typeId: Int,
|
||||
val ipa: String?,
|
||||
val filename: String?
|
||||
)
|
||||
|
||||
data class PronunciationType(
|
||||
val id: Int,
|
||||
val name: String?
|
||||
)
|
||||
data class TermsPronunciation(
|
||||
val termId: Int,
|
||||
val pronunciationId: Int,
|
||||
)
|
||||
|
||||
data class Suffix(
|
||||
val id: Int,
|
||||
val text: String
|
||||
)
|
||||
|
||||
data class Term(
|
||||
val id: Int,
|
||||
val dictionaryId: Int,
|
||||
val string1: String,
|
||||
val string2: String,
|
||||
val suffix1Id: Int?,
|
||||
val suffix2Id: Int?,
|
||||
val typeId: Int?,
|
||||
val member: String?,
|
||||
val order2: Int?,
|
||||
val flags: String?
|
||||
)
|
||||
val toDictionary: (Row) -> Dictionary = { row ->
|
||||
Dictionary(
|
||||
row.int("id"),
|
||||
row.int("lang1_id"),
|
||||
row.int("lang2_id"),
|
||||
row.string("name"),
|
||||
row.string("full_name")
|
||||
)
|
||||
}
|
||||
|
||||
val toDictType: (Row) -> DictType = { row ->
|
||||
DictType(
|
||||
row.int("id"),
|
||||
row.string("short_name"),
|
||||
row.string("full_name")
|
||||
)
|
||||
}
|
||||
val toLanguage: (Row) -> Language = { row ->
|
||||
Language(
|
||||
row.int("id"),
|
||||
row.string("name"),
|
||||
row.string("short_name")
|
||||
)
|
||||
}
|
||||
val toTranslation: (Row) -> Translation = { row ->
|
||||
Translation(
|
||||
row.int("id"),
|
||||
row.int("dictionary_id"),
|
||||
row.int("lang1_id"),
|
||||
row.int("lang2_id"),
|
||||
row.string("lang_name1"),
|
||||
row.string("lang_name2"),
|
||||
row.int("direction"),
|
||||
)
|
||||
}
|
||||
|
||||
val toPronunciation: (Row) -> Pronunciation = { row ->
|
||||
Pronunciation(
|
||||
row.int("id"),
|
||||
row.int("type_id"),
|
||||
row.stringOrNull("ipa"),
|
||||
row.stringOrNull("filename")
|
||||
)
|
||||
}
|
||||
|
||||
val toTermsPronunciation: (Row) -> TermsPronunciation = { row ->
|
||||
TermsPronunciation(
|
||||
row.int("term_id"),
|
||||
row.int("pronunciation_id"),
|
||||
)
|
||||
}
|
||||
|
||||
val toSuffix: (Row) -> Suffix = { row ->
|
||||
Suffix(
|
||||
row.int("id"),
|
||||
row.string("text")
|
||||
)
|
||||
}
|
||||
val toTerm: (Row) -> Term = { row ->
|
||||
Term(
|
||||
row.int("id"),
|
||||
row.int("dictionary_id"),
|
||||
row.string("string1"),
|
||||
row.string("string2"),
|
||||
row.intOrNull("suffix1_id"),
|
||||
row.intOrNull("suffix2_id"),
|
||||
row.intOrNull("type_id"),
|
||||
row.stringOrNull("member"),
|
||||
row.intOrNull("order2"),
|
||||
row.stringOrNull("flags")
|
||||
)
|
||||
}
|
||||
|
||||
object SharedData {
|
||||
var hashDict: Map<Int,Dictionary> = mapOf()
|
||||
var hashDictType: Map<Int,DictType> = mapOf()
|
||||
var hashLang: Map<Int,Language> = mapOf()
|
||||
var hashTransMap: Map<Int,Translation> = mapOf()
|
||||
var hashPron: Map<Int,Pronunciation> = mapOf()
|
||||
var hashSuffix: Map<Int,Suffix> = mapOf()
|
||||
var hashTermPron : Map<Int,TermsPronunciation> = mapOf()
|
||||
var listTerm : List<Term> = listOf()
|
||||
var getListofTerms : (Int) -> List<Term> = {
|
||||
listOf()
|
||||
}
|
||||
}
|
||||
|
||||
class V1__test_connection: BaseJavaMigration() {
|
||||
override fun migrate(context: Context?) {
|
||||
val session = sessionOf("jdbc:postgresql://nuc.lan:5432/dict", "dict_user", "PW4dbdict")
|
||||
val allNameQuery = queryOf("select * from dictionary").map(toDictionary).asList
|
||||
val allDict = session.run(allNameQuery)
|
||||
SharedData.hashDict = allDict.associateBy { it.id }
|
||||
val allDictTypeQuery = queryOf("select * from dict_type").map(toDictType).asList
|
||||
val allDictType = session.run(allDictTypeQuery)
|
||||
SharedData.hashDictType = allDictType.associateBy { it.id }
|
||||
val allTranslationQuery = queryOf("select * from translation").map(toTranslation).asList
|
||||
val allTranslation = session.run(allTranslationQuery)
|
||||
SharedData.hashTransMap = allTranslation.associateBy { it.id }
|
||||
val allLangQuery = queryOf("select * from language").map(toLanguage).asList
|
||||
val allLanguages = session.run(allLangQuery)
|
||||
SharedData.hashLang = allLanguages.associateBy { it.id }
|
||||
val allSuffixQuery = queryOf("select * from suffix").map(toSuffix).asList
|
||||
val allSuffix = session.run(allSuffixQuery)
|
||||
SharedData.hashSuffix = allSuffix.associateBy { it.id }
|
||||
val allPronunciationQuery = queryOf("select * from pronunciation").map(toPronunciation).asList
|
||||
val allPronunciation = session.run(allPronunciationQuery)
|
||||
SharedData.hashPron = allPronunciation.associateBy { it.id }
|
||||
val allTermsPronunciationQuery = queryOf("select * from terms_pronunciations").map(toTermsPronunciation).asList
|
||||
val allTermsPronunciation = session.run(allTermsPronunciationQuery)
|
||||
SharedData.hashTermPron = allTermsPronunciation.associateBy { it.termId }
|
||||
SharedData.getListofTerms = {
|
||||
session.run(queryOf("select * from term WHERE dictionary_id=${it}").map(toTerm).asList)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
53
src/main/kotlin/db/migration/V2__crete_settingsdb.kt
Normal file
53
src/main/kotlin/db/migration/V2__crete_settingsdb.kt
Normal file
@@ -0,0 +1,53 @@
|
||||
package db.migration
|
||||
|
||||
import dao.DictionaryDao
|
||||
import kotlinx.serialization.decodeFromString
|
||||
import tables.*
|
||||
import org.flywaydb.core.api.migration.BaseJavaMigration
|
||||
import org.flywaydb.core.api.migration.Context
|
||||
import org.jetbrains.exposed.dao.id.EntityID
|
||||
import org.jetbrains.exposed.sql.SchemaUtils
|
||||
import org.jetbrains.exposed.sql.insert
|
||||
import org.jetbrains.exposed.sql.transactions.transaction
|
||||
import org.jetbrains.exposed.sql.upsert
|
||||
|
||||
class V2__create_settingsdb: BaseJavaMigration() {
|
||||
override fun migrate(context: Context?) {
|
||||
transaction {
|
||||
SchemaUtils.create(Dictionaries, Languages, Translations, Settings)
|
||||
|
||||
for ((di, lang) in SharedData.hashLang) {
|
||||
Languages.insert {
|
||||
it[id] = lang.id
|
||||
it[name] = lang.name
|
||||
it[shortName] = lang.shortName
|
||||
}
|
||||
}
|
||||
|
||||
for ((di, dict) in SharedData.hashDict) {
|
||||
Dictionaries.insert {
|
||||
it[id] = dict.id
|
||||
it[lang1] = dict.lang1Id
|
||||
it[lang2] = dict.lang2Id
|
||||
it[name] = dict.name
|
||||
it[fullName] = dict.fullName
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
for ((di, trans) in SharedData.hashTransMap) {
|
||||
Translations.insert {
|
||||
it[id] = trans.id
|
||||
it[lang1Id] = trans.lang1Id
|
||||
it[lang2Id] = trans.lang2Id
|
||||
it[dictionaryId] = trans.dictionaryId
|
||||
it[langName1] = trans.lang1Name
|
||||
it[langName2] = trans.lang2Name
|
||||
it[direction] = trans.direction
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
117
src/main/kotlin/db/migration/V3__create_dictionaries.kt
Normal file
117
src/main/kotlin/db/migration/V3__create_dictionaries.kt
Normal file
@@ -0,0 +1,117 @@
|
||||
package db.migration
|
||||
|
||||
import dao.DictionaryDao
|
||||
import kotlinx.serialization.decodeFromString
|
||||
import tables.*
|
||||
import org.flywaydb.core.api.migration.BaseJavaMigration
|
||||
import org.flywaydb.core.api.migration.Context
|
||||
import org.jetbrains.exposed.dao.id.EntityID
|
||||
import org.jetbrains.exposed.sql.Database
|
||||
import org.jetbrains.exposed.sql.SchemaUtils
|
||||
import org.jetbrains.exposed.sql.insert
|
||||
import org.jetbrains.exposed.sql.transactions.transaction
|
||||
import org.jetbrains.exposed.sql.upsert
|
||||
import kotlin.system.exitProcess
|
||||
|
||||
class V3__create_dictionaries: BaseJavaMigration() {
|
||||
override fun migrate(context: Context?) {
|
||||
println(SharedData.hashDict)
|
||||
//exitProcess(0)
|
||||
for ((db_id,dict) in SharedData.hashDict) {
|
||||
|
||||
val db_name = "jdbc:h2:file:/Users/jaro/data/${SharedData.hashLang[dict.lang1Id]?.shortName}-${SharedData.hashLang[dict.lang2Id]?.shortName}"
|
||||
println(db_name)
|
||||
val db = Database.connect(db_name)
|
||||
transaction (db) {
|
||||
SchemaUtils.create(Dictionaries, Languages, Translations, Pronunciations, PronunciationTypes, DictTypes, Suffixes, Terms)
|
||||
|
||||
for ((di, lang) in SharedData.hashLang) {
|
||||
Languages.insert {
|
||||
it[id] = lang.id
|
||||
it[name] = lang.name
|
||||
it[shortName] = lang.shortName
|
||||
}
|
||||
}
|
||||
|
||||
for ((di, d) in SharedData.hashDict) {
|
||||
Dictionaries.insert {
|
||||
it[id] = d.id
|
||||
it[lang1] = d.lang1Id
|
||||
it[lang2] = d.lang2Id
|
||||
it[name] = d.name
|
||||
it[fullName] = d.fullName
|
||||
}
|
||||
}
|
||||
|
||||
for ((di, trans) in SharedData.hashTransMap) {
|
||||
Translations.insert {
|
||||
it[id] = trans.id
|
||||
it[lang1Id] = trans.lang1Id
|
||||
it[lang2Id] = trans.lang2Id
|
||||
it[dictionaryId] = trans.dictionaryId
|
||||
it[langName1] = trans.lang1Name
|
||||
it[langName2] = trans.lang2Name
|
||||
it[direction] = trans.direction
|
||||
}
|
||||
}
|
||||
|
||||
PronunciationTypes.insert {
|
||||
it[id] = 1
|
||||
it[name] = "English"
|
||||
}
|
||||
|
||||
PronunciationTypes.insert {
|
||||
it[id] = 2
|
||||
it[name] = "American english"
|
||||
}
|
||||
|
||||
PronunciationTypes.insert {
|
||||
it[id] = 3
|
||||
it[name] = "Business english"
|
||||
}
|
||||
|
||||
for ((di, pron) in SharedData.hashPron) {
|
||||
Pronunciations.insert {
|
||||
it[id] = pron.id
|
||||
it[typeId] = pron.typeId
|
||||
it[ipa] = pron.ipa
|
||||
it[filename] = pron.filename
|
||||
}
|
||||
}
|
||||
|
||||
for ((di, dt) in SharedData.hashDictType) {
|
||||
DictTypes.insert {
|
||||
it[id] = dt.id
|
||||
it[shortName] = dt.shortName
|
||||
it[fullName] = dt.fullName
|
||||
}
|
||||
}
|
||||
|
||||
for ((di, ss) in SharedData.hashSuffix) {
|
||||
Suffixes.insert {
|
||||
it[id] = ss.id
|
||||
it[text] = ss.text
|
||||
}
|
||||
}
|
||||
|
||||
var dictTerms = SharedData.getListofTerms(db_id)
|
||||
for (t in dictTerms) {
|
||||
Terms.insert {
|
||||
it[id] = t.id
|
||||
it[string1] = t.string1
|
||||
it[string2] = t.string2
|
||||
it[suffix1] = t.suffix1Id
|
||||
it[suffix2] = t.suffix2Id
|
||||
it[type] = t.typeId
|
||||
it[member] = t.member
|
||||
it[order2] = t.order2
|
||||
it[flags] = format.decodeFromString<IntArray?>(t.flags?.toString() ?:"[]")
|
||||
}
|
||||
}
|
||||
dictTerms = listOf()
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
14
src/main/kotlin/models/DictType.kt
Normal file
14
src/main/kotlin/models/DictType.kt
Normal file
@@ -0,0 +1,14 @@
|
||||
package models
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
import org.jetbrains.exposed.sql.Table
|
||||
|
||||
|
||||
|
||||
@Serializable
|
||||
data class DictType(
|
||||
val id: Int,
|
||||
val shortName: String,
|
||||
val fullName: String
|
||||
)
|
||||
|
||||
17
src/main/kotlin/models/Dictionary.kt
Normal file
17
src/main/kotlin/models/Dictionary.kt
Normal file
@@ -0,0 +1,17 @@
|
||||
package models
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
import org.jetbrains.exposed.sql.Table
|
||||
|
||||
|
||||
|
||||
@Serializable
|
||||
data class Dictionary(
|
||||
val id: Int,
|
||||
val lang1Id: Int,
|
||||
val lang2Id: Int,
|
||||
val name: String?,
|
||||
val fullName: String?,
|
||||
val translations: List<Translation> = emptyList()
|
||||
)
|
||||
|
||||
15
src/main/kotlin/models/Language.kt
Normal file
15
src/main/kotlin/models/Language.kt
Normal file
@@ -0,0 +1,15 @@
|
||||
package models
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
import org.jetbrains.exposed.sql.Table
|
||||
|
||||
|
||||
|
||||
@Serializable
|
||||
data class Language(
|
||||
val id: Int,
|
||||
val name: String,
|
||||
val shortName: String
|
||||
)
|
||||
|
||||
|
||||
12
src/main/kotlin/models/Pronunciation.kt
Normal file
12
src/main/kotlin/models/Pronunciation.kt
Normal file
@@ -0,0 +1,12 @@
|
||||
package models
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
import org.jetbrains.exposed.sql.Table
|
||||
|
||||
@Serializable
|
||||
data class Pronunciation(
|
||||
val id: Int,
|
||||
val typeId: Int,
|
||||
val ipa: String?,
|
||||
val filename: String?
|
||||
)
|
||||
10
src/main/kotlin/models/PronunciationType.kt
Normal file
10
src/main/kotlin/models/PronunciationType.kt
Normal file
@@ -0,0 +1,10 @@
|
||||
package models
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
import org.jetbrains.exposed.sql.Table
|
||||
|
||||
@Serializable
|
||||
data class PronunciationType(
|
||||
val id: Int,
|
||||
val name: String?
|
||||
)
|
||||
12
src/main/kotlin/models/Setting.kt
Normal file
12
src/main/kotlin/models/Setting.kt
Normal file
@@ -0,0 +1,12 @@
|
||||
package models
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
import org.jetbrains.exposed.sql.Table
|
||||
|
||||
@Serializable
|
||||
data class Settings(
|
||||
val id: Int,
|
||||
val dictionary: Int?,
|
||||
val lastSearch: String?,
|
||||
)
|
||||
|
||||
11
src/main/kotlin/models/Suffix.kt
Normal file
11
src/main/kotlin/models/Suffix.kt
Normal file
@@ -0,0 +1,11 @@
|
||||
package models
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
import org.jetbrains.exposed.sql.Table
|
||||
|
||||
|
||||
@Serializable
|
||||
data class Suffix(
|
||||
val id: Int,
|
||||
val text: String
|
||||
)
|
||||
20
src/main/kotlin/models/Term.kt
Normal file
20
src/main/kotlin/models/Term.kt
Normal file
@@ -0,0 +1,20 @@
|
||||
package models
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
import kotlinx.serialization.json.JsonObject
|
||||
import org.jetbrains.exposed.sql.Table
|
||||
|
||||
|
||||
@Serializable
|
||||
data class Term(
|
||||
val id: Int,
|
||||
val dictionaryId: Int,
|
||||
val string1: String,
|
||||
val string2: String,
|
||||
val typeId: Int,
|
||||
val suffix1Id: Int,
|
||||
val suffix2Id: Int,
|
||||
val member: String?,
|
||||
val order2: Int,
|
||||
val flags: JsonObject?
|
||||
)
|
||||
17
src/main/kotlin/models/Translation.kt
Normal file
17
src/main/kotlin/models/Translation.kt
Normal file
@@ -0,0 +1,17 @@
|
||||
package models
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
import org.jetbrains.exposed.sql.Table
|
||||
|
||||
|
||||
|
||||
@Serializable
|
||||
data class Translation(
|
||||
val id: Int,
|
||||
val dictionaryId: Int,
|
||||
val lang1Id: Int,
|
||||
val lang2Id: Int,
|
||||
val lang1Name: String?,
|
||||
val lang2Name: String?,
|
||||
val direction: Int
|
||||
)
|
||||
54
src/main/kotlin/service/DatabaseFactory.kt
Normal file
54
src/main/kotlin/service/DatabaseFactory.kt
Normal file
@@ -0,0 +1,54 @@
|
||||
package service
|
||||
|
||||
import com.zaxxer.hikari.HikariConfig
|
||||
import com.zaxxer.hikari.HikariDataSource
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.flywaydb.core.Flyway
|
||||
import org.jetbrains.exposed.sql.Database
|
||||
import org.jetbrains.exposed.sql.transactions.transaction
|
||||
import org.slf4j.LoggerFactory
|
||||
import javax.sql.DataSource
|
||||
|
||||
object DatabaseFactory {
|
||||
|
||||
private val log = LoggerFactory.getLogger(this::class.java)
|
||||
|
||||
fun connectAndMigrate() {
|
||||
log.info("Initialising database")
|
||||
val pool = hikari()
|
||||
Database.connect(pool)
|
||||
runFlyway(pool)
|
||||
}
|
||||
|
||||
private fun hikari(): HikariDataSource {
|
||||
val config = HikariConfig().apply {
|
||||
driverClassName = "org.h2.Driver"
|
||||
jdbcUrl = "jdbc:h2:file:/Users/jaro/data/dict_settings"
|
||||
maximumPoolSize = 3
|
||||
isAutoCommit = false
|
||||
transactionIsolation = "TRANSACTION_REPEATABLE_READ"
|
||||
validate()
|
||||
}
|
||||
return HikariDataSource(config)
|
||||
}
|
||||
|
||||
private fun runFlyway(datasource: DataSource) {
|
||||
val flyway = Flyway.configure().dataSource(datasource).load()
|
||||
try {
|
||||
flyway.info()
|
||||
flyway.migrate()
|
||||
} catch (e: Exception) {
|
||||
log.error("Exception running flyway migration", e)
|
||||
throw e
|
||||
}
|
||||
log.info("Flyway migration has finished")
|
||||
}
|
||||
|
||||
suspend fun <T> dbExec(
|
||||
block: () -> T
|
||||
): T = withContext(Dispatchers.IO) {
|
||||
transaction { block() }
|
||||
}
|
||||
|
||||
}
|
||||
8
src/main/kotlin/tables/DictType.kt
Normal file
8
src/main/kotlin/tables/DictType.kt
Normal file
@@ -0,0 +1,8 @@
|
||||
package tables
|
||||
|
||||
import org.jetbrains.exposed.dao.id.IntIdTable
|
||||
|
||||
object DictTypes : IntIdTable() {
|
||||
val shortName = varchar("short_name", 255)
|
||||
val fullName = varchar("full_name", 255)
|
||||
}
|
||||
10
src/main/kotlin/tables/Dictionary.kt
Normal file
10
src/main/kotlin/tables/Dictionary.kt
Normal file
@@ -0,0 +1,10 @@
|
||||
package tables
|
||||
|
||||
import org.jetbrains.exposed.dao.id.IntIdTable
|
||||
|
||||
object Dictionaries : IntIdTable() {
|
||||
val lang1 = reference("lang1_id", Languages)
|
||||
val lang2 = reference("lang2_id", Languages)
|
||||
val name = varchar("name", 255)
|
||||
val fullName = varchar("full_name", 255)
|
||||
}
|
||||
8
src/main/kotlin/tables/Language.kt
Normal file
8
src/main/kotlin/tables/Language.kt
Normal file
@@ -0,0 +1,8 @@
|
||||
package tables
|
||||
|
||||
import org.jetbrains.exposed.dao.id.IntIdTable
|
||||
|
||||
object Languages : IntIdTable() {
|
||||
val name = varchar("name", 255)
|
||||
val shortName = varchar("short_name", 255)
|
||||
}
|
||||
10
src/main/kotlin/tables/Pronunciation.kt
Normal file
10
src/main/kotlin/tables/Pronunciation.kt
Normal file
@@ -0,0 +1,10 @@
|
||||
package tables
|
||||
|
||||
import org.jetbrains.exposed.dao.id.IntIdTable
|
||||
|
||||
object Pronunciations : IntIdTable() {
|
||||
val typeId = reference("type_id",PronunciationTypes)
|
||||
|
||||
val ipa = varchar("ipa", 255).nullable()
|
||||
val filename = varchar("filename", 255).nullable()
|
||||
}
|
||||
7
src/main/kotlin/tables/PronunciationType.kt
Normal file
7
src/main/kotlin/tables/PronunciationType.kt
Normal file
@@ -0,0 +1,7 @@
|
||||
package tables
|
||||
|
||||
import org.jetbrains.exposed.dao.id.IntIdTable
|
||||
|
||||
object PronunciationTypes : IntIdTable() {
|
||||
val name = varchar("name", 255)
|
||||
}
|
||||
8
src/main/kotlin/tables/Setting.kt
Normal file
8
src/main/kotlin/tables/Setting.kt
Normal file
@@ -0,0 +1,8 @@
|
||||
package tables
|
||||
|
||||
import org.jetbrains.exposed.dao.id.IntIdTable
|
||||
|
||||
object Settings : IntIdTable() {
|
||||
val dictionary = reference("dictionary_id",Dictionaries)
|
||||
val lastSearch = varchar("last_search", 255).nullable()
|
||||
}
|
||||
7
src/main/kotlin/tables/Suffix.kt
Normal file
7
src/main/kotlin/tables/Suffix.kt
Normal file
@@ -0,0 +1,7 @@
|
||||
package tables
|
||||
|
||||
import org.jetbrains.exposed.dao.id.IntIdTable
|
||||
|
||||
object Suffixes : IntIdTable() {
|
||||
val text = varchar("text", 255)
|
||||
}
|
||||
17
src/main/kotlin/tables/Term.kt
Normal file
17
src/main/kotlin/tables/Term.kt
Normal file
@@ -0,0 +1,17 @@
|
||||
package tables
|
||||
|
||||
import org.jetbrains.exposed.dao.id.IntIdTable
|
||||
import org.jetbrains.exposed.sql.json.json
|
||||
import kotlinx.serialization.json.Json
|
||||
import kotlinx.serialization.json.JsonObject
|
||||
import tables.Suffixes
|
||||
object Terms : IntIdTable() {
|
||||
val string1 = varchar("string1", 255)
|
||||
val string2 = varchar("string2", 255)
|
||||
val suffix1 = reference("suffix1_id",Suffixes).nullable()
|
||||
val suffix2 = reference("suffix2_id",Suffixes).nullable()
|
||||
val type = reference("type_id",DictTypes).nullable()
|
||||
val member = varchar("member", 255).nullable()
|
||||
val order2 = integer("order2").nullable()
|
||||
val flags = json<IntArray>("flags", Json.Default).nullable()
|
||||
}
|
||||
13
src/main/kotlin/tables/Translation.kt
Normal file
13
src/main/kotlin/tables/Translation.kt
Normal file
@@ -0,0 +1,13 @@
|
||||
package tables
|
||||
|
||||
import org.jetbrains.exposed.dao.id.IntIdTable
|
||||
|
||||
object Translations : IntIdTable() {
|
||||
val dictionaryId = reference("dictionary_id",Dictionaries)
|
||||
val lang1Id = reference("lang1_id",Languages)
|
||||
val lang2Id = reference("lang2_id",Languages)
|
||||
|
||||
val langName1 = varchar("lang_name1", 255)
|
||||
val langName2 = varchar("lang_name2", 255)
|
||||
val direction = integer("direction")
|
||||
}
|
||||
11
src/main/kotlin/util/JsonMapper.kt
Normal file
11
src/main/kotlin/util/JsonMapper.kt
Normal file
@@ -0,0 +1,11 @@
|
||||
package util
|
||||
|
||||
import kotlinx.serialization.json.Json
|
||||
|
||||
object JsonMapper {
|
||||
|
||||
val defaultMapper = Json {
|
||||
prettyPrint = true
|
||||
}
|
||||
|
||||
}
|
||||
14
src/main/kotlin/web/IndexResource.kt
Normal file
14
src/main/kotlin/web/IndexResource.kt
Normal file
@@ -0,0 +1,14 @@
|
||||
package web
|
||||
|
||||
import io.ktor.http.*
|
||||
import io.ktor.server.response.*
|
||||
import io.ktor.server.routing.*
|
||||
|
||||
fun Route.index() {
|
||||
|
||||
val indexPage = javaClass.getResource("/index.html").readText()
|
||||
|
||||
get("/") {
|
||||
call.respondText(indexPage, ContentType.Text.Html)
|
||||
}
|
||||
}
|
||||
64
src/main/kotlin/web/WidgetResource.kt.old
Normal file
64
src/main/kotlin/web/WidgetResource.kt.old
Normal file
@@ -0,0 +1,64 @@
|
||||
package web
|
||||
|
||||
import io.ktor.http.*
|
||||
import io.ktor.server.request.*
|
||||
import io.ktor.server.response.*
|
||||
import io.ktor.server.routing.*
|
||||
import io.ktor.server.websocket.*
|
||||
import io.ktor.websocket.*
|
||||
import model.NewWidget
|
||||
import service.WidgetService
|
||||
|
||||
fun Route.widget(widgetService: WidgetService) {
|
||||
|
||||
route("/widgets") {
|
||||
|
||||
get {
|
||||
call.respond(widgetService.getAllWidgets())
|
||||
}
|
||||
|
||||
get("/{id}") {
|
||||
val id = call.parameters["id"]?.toInt() ?: throw IllegalStateException("Must provide id")
|
||||
val widget = widgetService.getWidget(id)
|
||||
if (widget == null) call.respond(HttpStatusCode.NotFound)
|
||||
else call.respond(widget)
|
||||
}
|
||||
|
||||
post {
|
||||
val widget = call.receive<NewWidget>()
|
||||
call.respond(HttpStatusCode.Created, widgetService.addWidget(widget))
|
||||
}
|
||||
|
||||
put {
|
||||
val widget = call.receive<NewWidget>()
|
||||
val updated = widgetService.updateWidget(widget)
|
||||
if (updated == null) call.respond(HttpStatusCode.NotFound)
|
||||
else call.respond(HttpStatusCode.OK, updated)
|
||||
}
|
||||
|
||||
delete("/{id}") {
|
||||
val id = call.parameters["id"]?.toInt() ?: throw IllegalStateException("Must provide id")
|
||||
val removed = widgetService.deleteWidget(id)
|
||||
if (removed) call.respond(HttpStatusCode.OK)
|
||||
else call.respond(HttpStatusCode.NotFound)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
webSocket("/updates") {
|
||||
try {
|
||||
widgetService.addChangeListener(this.hashCode()) {
|
||||
sendSerialized(it)
|
||||
}
|
||||
for (frame in incoming) {
|
||||
if (frame.frameType == FrameType.CLOSE) {
|
||||
break
|
||||
} else if (frame is Frame.Text) {
|
||||
call.application.environment.log.info("Received websocket message: {}", frame.readText())
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
widgetService.removeChangeListener(this.hashCode())
|
||||
}
|
||||
}
|
||||
}
|
||||
10
src/main/resources/application.conf
Normal file
10
src/main/resources/application.conf
Normal file
@@ -0,0 +1,10 @@
|
||||
ktor {
|
||||
deployment {
|
||||
port = 8080
|
||||
watch = [ build ]
|
||||
}
|
||||
|
||||
application {
|
||||
modules = [ MainKt.module ]
|
||||
}
|
||||
}
|
||||
53
src/main/resources/index.html
Normal file
53
src/main/resources/index.html
Normal file
@@ -0,0 +1,53 @@
|
||||
<!doctype html>
|
||||
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Kotlin/Ktor/Exposed Starter - It's Working!</title>
|
||||
<meta name="author" content="Ryan Harrison">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1 id="it-s-working-">It's Working!</h1>
|
||||
<p>This starter project creates a new in-memory H2 database with one table for <code>Widget</code> instances. A simple RESTful interface is provided
|
||||
to perform CRUD operations on <code>Widgets</code> alongside a websocket to be notified in real-time of any changes.</p>
|
||||
<h2 id="routes-">Routes:</h2>
|
||||
<p><code>GET /widgets</code> --> get all widgets in the database</p>
|
||||
<p><code>GET /widgets/{id}</code> --> get one widget instance by id (integer)</p>
|
||||
<p><code>POST /widgets</code> --> add a new widget to the database by providing a JSON object (converted to a NewWidget instance).
|
||||
e.g - </p>
|
||||
<pre><code>{
|
||||
<span class="hljs-attr">"name"</span>: <span class="hljs-string">"new widget"</span>,
|
||||
<span class="hljs-attr">"quantity"</span>: <span class="hljs-number">64</span>
|
||||
}
|
||||
</code></pre>
|
||||
<p>returns</p>
|
||||
<pre><code>{
|
||||
<span class="hljs-attr">"id"</span>: <span class="hljs-number">4</span>,
|
||||
<span class="hljs-attr">"name"</span>: <span class="hljs-string">"new widget"</span>,
|
||||
<span class="hljs-attr">"quantity"</span>: <span class="hljs-number">64</span>,
|
||||
<span class="hljs-attr">"dateCreated"</span>: <span class="hljs-number">1519926898</span>
|
||||
}
|
||||
</code></pre>
|
||||
<p><code>PUT /widgets</code> --> update an existing widgets name or quantity. Pass in the id in the JSON request to determine which record to update
|
||||
</p>
|
||||
<p><code>DELETE /widgets/{id}</code> --> delete the widget with the specified id</p>
|
||||
<h2 id="notifications-websocket-">Notifications (WebSocket)</h2>
|
||||
<p>All updates (creates, updates and deletes) to <code>Widget</code> instances are served as notifications through a WebSocket endpoint:</p>
|
||||
<p><code>WS /updates</code> --> returns <code>Notification</code> instances containing the change type, id and entity (if applicable) e.g:</p>
|
||||
<pre><code class="lang-json">{
|
||||
<span class="hljs-attr">"type"</span>: <span class="hljs-string">"CREATE"</span>,
|
||||
<span class="hljs-attr">"id"</span>: <span class="hljs-number">12</span>,
|
||||
<span class="hljs-attr">"entity"</span>: {
|
||||
<span class="hljs-attr">"id"</span>: <span class="hljs-number">12</span>,
|
||||
<span class="hljs-attr">"name"</span>: <span class="hljs-string">"widget1"</span>,
|
||||
<span class="hljs-attr">"quantity"</span>: <span class="hljs-number">5</span>,
|
||||
<span class="hljs-attr">"dateUpdated"</span>: <span class="hljs-number">1533583858169</span>
|
||||
}
|
||||
}
|
||||
</code></pre>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
||||
15
src/main/resources/logback.xml
Normal file
15
src/main/resources/logback.xml
Normal file
@@ -0,0 +1,15 @@
|
||||
<configuration>
|
||||
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder>
|
||||
<pattern>%d{YYYY-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<root level="INFO">
|
||||
<appender-ref ref="STDOUT"/>
|
||||
</root>
|
||||
|
||||
<logger name="Exposed" level="DEBUG" />
|
||||
<logger name="ktor.application" level="TRACE" />
|
||||
|
||||
</configuration>
|
||||
Reference in New Issue
Block a user