349 lines
14 KiB
Kotlin
349 lines
14 KiB
Kotlin
package database.table
|
|
|
|
import content.Category
|
|
import database.data.Soundbank
|
|
import database.dbFunctions
|
|
import org.apache.poi.xssf.usermodel.XSSFWorkbook
|
|
import org.tinylog.Logger
|
|
import java.io.File
|
|
import java.sql.Connection
|
|
import java.util.function.Consumer
|
|
|
|
class Table_Soundbank(connection: Connection) : dbFunctions<Soundbank>("soundbank", connection, listOf("index", "Description", "TAG", "Category", "Language", "VoiceType", "Path")) {
|
|
override fun Create() {
|
|
val tabledefinition = "CREATE TABLE IF NOT EXISTS ${super.dbName} (" +
|
|
"`index` INT AUTO_INCREMENT PRIMARY KEY," +
|
|
"Description VARCHAR(1024) NOT NULL," + // Description of the soundbank
|
|
"TAG VARCHAR(45) NOT NULL," + // TAG of the soundbank
|
|
"Category VARCHAR(45) NOT NULL," + // Category of the soundbank
|
|
"Language VARCHAR(45) NOT NULL," + // Language of the soundbank
|
|
"VoiceType VARCHAR(45) NOT NULL," + // VoiceType of the soundbank
|
|
"Path VARCHAR(1024) NOT NULL" + // Path to the sound file
|
|
")"
|
|
super.Create(tabledefinition)
|
|
}
|
|
|
|
override fun Get(cbOK: Consumer<Unit>?, cbFail: Consumer<String>?) {
|
|
List.clear()
|
|
try {
|
|
val statement = connection.createStatement()
|
|
val resultSet = statement?.executeQuery("SELECT * FROM ${super.dbName} ORDER BY Category, Language, VoiceType, TAG")
|
|
while (resultSet?.next() == true) {
|
|
val soundbank = Soundbank(
|
|
resultSet.getLong("index").toUInt(),
|
|
resultSet.getString("Description"),
|
|
resultSet.getString("TAG"),
|
|
resultSet.getString("Category"),
|
|
resultSet.getString("Language"),
|
|
resultSet.getString("VoiceType"),
|
|
resultSet.getString("Path")
|
|
)
|
|
List.add(soundbank)
|
|
}
|
|
cbOK?.accept(Unit)
|
|
} catch (e: Exception) {
|
|
Logger.error("Error fetching soundbanks: ${e.message}" as Any)
|
|
cbFail?.accept("Error fetching ${super.dbName} : ${e.message}")
|
|
}
|
|
}
|
|
|
|
override fun Add(data: Soundbank): Boolean {
|
|
try {
|
|
val statement =
|
|
connection.prepareStatement("INSERT INTO ${super.dbName} (Description, TAG, Category, Language, VoiceType, Path) VALUES (?, ?, ?, ?, ?, ?)")
|
|
statement?.setString(1, data.Description)
|
|
statement?.setString(2, data.TAG)
|
|
statement?.setString(3, data.Category)
|
|
statement?.setString(4, data.Language)
|
|
statement?.setString(5, data.VoiceType)
|
|
statement?.setString(6, data.Path)
|
|
val rowsAffected = statement?.executeUpdate()
|
|
if (rowsAffected != null && rowsAffected > 0) {
|
|
Logger.info("Soundbank added: ${data.Description}" as Any)
|
|
return true
|
|
} else {
|
|
Logger.warn("No soundbank entry added for: ${data.Description}" as Any)
|
|
}
|
|
} catch (e: Exception) {
|
|
Logger.error("Error adding soundbank entry: ${e.message}" as Any)
|
|
}
|
|
return false
|
|
}
|
|
|
|
override fun AddAll(data: ArrayList<Soundbank>): Boolean {
|
|
// use mysql bulk insert
|
|
try {
|
|
connection.autoCommit = false
|
|
val sql =
|
|
"INSERT INTO ${super.dbName} (Description, TAG, Category, Language, VoiceType, Path) VALUES (?, ?, ?, ?, ?, ?)"
|
|
val statement = connection.prepareStatement(sql)
|
|
for (sb in data) {
|
|
statement.setString(1, sb.Description)
|
|
statement.setString(2, sb.TAG)
|
|
statement.setString(3, sb.Category)
|
|
statement.setString(4, sb.Language)
|
|
statement.setString(5, sb.VoiceType)
|
|
statement.setString(6, sb.Path)
|
|
statement.addBatch()
|
|
}
|
|
statement.executeBatch()
|
|
connection.commit()
|
|
Logger.info("Bulk soundbank insert successful: ${data.size} entries" as Any)
|
|
connection.autoCommit = true
|
|
return true
|
|
} catch (e: Exception) {
|
|
Logger.error("Error adding soundbank entries: ${e.message}" as Any)
|
|
}
|
|
return false
|
|
}
|
|
|
|
override fun UpdateByIndex(index: Int, data: Soundbank): Boolean {
|
|
try {
|
|
val statement =
|
|
connection.prepareStatement("UPDATE ${super.dbName} SET Description = ?, TAG = ?, Category = ?, Language = ?, VoiceType = ?, Path = ? WHERE `index` = ?")
|
|
statement?.setString(1, data.Description)
|
|
statement?.setString(2, data.TAG)
|
|
statement?.setString(3, data.Category)
|
|
statement?.setString(4, data.Language)
|
|
statement?.setString(5, data.VoiceType)
|
|
statement?.setString(6, data.Path)
|
|
statement?.setLong(7, index.toLong())
|
|
val rowsAffected = statement?.executeUpdate()
|
|
if (rowsAffected != null && rowsAffected > 0) {
|
|
Logger.info("Soundbank updated at index $index: ${data.Description}" as Any)
|
|
return true
|
|
} else {
|
|
Logger.warn("No soundbank entry updated at index $index for: ${data.Description}" as Any)
|
|
}
|
|
} catch (e: Exception) {
|
|
Logger.error("Error updating soundbank entry at index $index: ${e.message}" as Any)
|
|
}
|
|
return false
|
|
}
|
|
|
|
override fun Resort(): Boolean {
|
|
try {
|
|
val statement = connection.createStatement()
|
|
val tempdb_name = "temp_${super.dbName}"
|
|
|
|
// use a temporary table to reorder the index
|
|
statement?.executeUpdate("CREATE TABLE IF NOT EXISTS $tempdb_name LIKE ${super.dbName}")
|
|
statement?.executeUpdate("TRUNCATE TABLE $tempdb_name")
|
|
statement?.executeUpdate("INSERT INTO $tempdb_name (Description, TAG, Category, Language, VoiceType, Path) SELECT Description, TAG, Category, Language, VoiceType, Path FROM ${super.dbName} ORDER BY Category, Language, VoiceType, TAG ")
|
|
statement?.executeUpdate("TRUNCATE TABLE ${super.dbName}")
|
|
statement?.executeUpdate("INSERT INTO ${super.dbName} (Description, TAG, Category, Language, VoiceType, Path) SELECT Description, TAG, Category, Language, VoiceType, Path FROM $tempdb_name")
|
|
statement?.executeUpdate("DROP TABLE $tempdb_name")
|
|
Logger.info("${super.dbName} table resorted by Description" as Any)
|
|
// reload the local list
|
|
Get()
|
|
return true
|
|
} catch (e: Exception) {
|
|
Logger.error("Error resorting ${super.dbName} table by Description: ${e.message}" as Any)
|
|
}
|
|
return false
|
|
}
|
|
|
|
override fun Import_XLSX(workbook: XSSFWorkbook): Boolean {
|
|
try {
|
|
// check if there is sheet named "Soundbank"
|
|
val sheet =
|
|
workbook.getSheet("Soundbank") ?: throw Exception("No sheet named 'Soundbank' found")
|
|
// check if the sheet contains header named "index", "Description", "TAG", "Category", "Language", "VoiceType", "Path"
|
|
val headerRow = sheet.getRow(0) ?: throw Exception("No header row found")
|
|
val headers =
|
|
arrayOf("Index", "Description", "TAG", "Category", "Language", "VoiceType", "Path")
|
|
for ((colIndex, header) in headers.withIndex()) {
|
|
val cell = headerRow.getCell(colIndex) ?: throw Exception("Header '$header' not found")
|
|
if (cell.stringCellValue != header) throw Exception("Header '$header' not found")
|
|
}
|
|
// clear existing soundbank
|
|
Clear()
|
|
// read each row and insert into database
|
|
val _soundbankList = ArrayList<Soundbank>()
|
|
for (rowIndex in 1..sheet.lastRowNum) {
|
|
val row = sheet.getRow(rowIndex) ?: continue
|
|
val description = row.getCell(1)?.stringCellValue ?: continue
|
|
val tag = row.getCell(2)?.stringCellValue ?: continue
|
|
val category = row.getCell(3)?.stringCellValue ?: continue
|
|
val language = row.getCell(4)?.stringCellValue ?: continue
|
|
val voiceType = row.getCell(5)?.stringCellValue ?: continue
|
|
val path = row.getCell(6)?.stringCellValue ?: continue
|
|
val soundbank = Soundbank(0u, description, tag, category, language, voiceType, path)
|
|
_soundbankList.add(soundbank)
|
|
}
|
|
return AddAll(_soundbankList)
|
|
} catch (e: Exception) {
|
|
Logger.error { "Error importing Soundbank, Msg: ${e.message}" }
|
|
}
|
|
return false
|
|
}
|
|
|
|
override fun Export_XLSX(): XSSFWorkbook? {
|
|
try {
|
|
val statement = connection.createStatement()
|
|
val resultSet = statement?.executeQuery("SELECT * FROM ${super.dbName}")
|
|
val workbook = XSSFWorkbook()
|
|
val sheet = workbook.createSheet("Soundbank")
|
|
val headerRow = sheet.createRow(0)
|
|
val headers =
|
|
arrayOf("Index", "Description", "TAG", "Category", "Language", "VoiceType", "Path")
|
|
for ((colIndex, header) in headers.withIndex()) {
|
|
val cell = headerRow.createCell(colIndex)
|
|
cell.setCellValue(header)
|
|
}
|
|
var rowIndex = 1
|
|
while (resultSet?.next() == true) {
|
|
val row = sheet.createRow(rowIndex++)
|
|
row.createCell(0).setCellValue(resultSet.getString("index"))
|
|
row.createCell(1).setCellValue(resultSet.getString("Description"))
|
|
row.createCell(2).setCellValue(resultSet.getString("TAG"))
|
|
row.createCell(3).setCellValue(resultSet.getString("Category"))
|
|
row.createCell(4).setCellValue(resultSet.getString("Language"))
|
|
row.createCell(5).setCellValue(resultSet.getString("VoiceType"))
|
|
row.createCell(6).setCellValue(resultSet.getString("Path"))
|
|
}
|
|
for (i in 0 until headers.size) {
|
|
sheet.autoSizeColumn(i)
|
|
}
|
|
return workbook
|
|
} catch (e: Exception) {
|
|
Logger.error { "Error exporting Soundbank, Msg: ${e.message}" }
|
|
}
|
|
return null
|
|
}
|
|
|
|
/**
|
|
* Get all distinct airline code tags from soundbank
|
|
* @return a list of distinct airline code tags sorted alphabetically
|
|
*/
|
|
fun Get_AirlineCode_Tags(): List<String> {
|
|
|
|
return List
|
|
.filter { it.Category.equals(Category.Airline_Code.name,true) }
|
|
.distinctBy { it.TAG }
|
|
.map { it.TAG }
|
|
.sorted()
|
|
}
|
|
|
|
/**
|
|
* Get all distinct city tags from soundbank
|
|
* @return a list of distinct city tags sorted alphabetically
|
|
*/
|
|
fun Get_City_Tags(): List<String> {
|
|
return List
|
|
.filter { it.Category.equals(Category.City.name,true) }
|
|
.distinctBy { it.TAG }
|
|
.map { it.TAG }
|
|
.sorted()
|
|
}
|
|
|
|
/**
|
|
* Find City by TAG
|
|
* @param tag the city tag to search for
|
|
* @return a list of Soundbank entries matching the city tag
|
|
*/
|
|
fun Find_City_By_TAG(tag: String) : List<Soundbank> {
|
|
return List
|
|
.filter {it.Category.equals(Category.City.name,true) }
|
|
.filter { it.TAG.equals(tag, true) }
|
|
.distinctBy { it.TAG }
|
|
}
|
|
|
|
/**
|
|
* Find Airline Name by TAG
|
|
* @param tag the airline code tag to search for
|
|
* @return a list of Soundbank entries matching the airline code tag
|
|
*/
|
|
fun Find_AirlineName_By_TAG(tag: String) : List<Soundbank> {
|
|
return List
|
|
.filter {it.Category.equals(Category.Airplane_Name.name,true) }
|
|
.filter { it.TAG.equals(tag, true) }
|
|
.distinctBy { it.TAG }
|
|
}
|
|
|
|
fun Get_Places(): List<Soundbank> {
|
|
return List
|
|
.filter { it.Category.equals(Category.Places.name,true) }
|
|
.distinctBy { it.TAG }
|
|
.sortedBy { it.TAG }
|
|
}
|
|
|
|
fun Get_Shalat() : List<Soundbank> {
|
|
return List
|
|
.filter { it.Category.equals(Category.Shalat.name,true) }
|
|
.distinctBy { it.TAG }
|
|
.sortedBy { it.TAG }
|
|
}
|
|
|
|
fun Get_Sequences() : List<Soundbank> {
|
|
return List
|
|
.filter { it.Category.equals(Category.Sequence.name,true) }
|
|
.distinctBy { it.TAG }
|
|
.sortedBy { it.TAG }
|
|
}
|
|
|
|
fun Get_Reasons() : List<Soundbank> {
|
|
return List
|
|
.filter { it.Category.equals(Category.Reason.name,true) }
|
|
.distinctBy { it.TAG }
|
|
.sortedBy { it.TAG }
|
|
}
|
|
|
|
fun Get_Gates(): List<Soundbank> {
|
|
return List
|
|
.filter { it.Category.equals(Category.Gate.name,true) }
|
|
.distinctBy { it.TAG }
|
|
.sortedBy { it.TAG }
|
|
}
|
|
|
|
fun Get_Compensation(): List<Soundbank> {
|
|
return List
|
|
.filter { it.Category.equals(Category.Compensation.name,true) }
|
|
.distinctBy { it.TAG }
|
|
.sortedBy { it.TAG }
|
|
}
|
|
|
|
fun Get_Greeting() : List<Soundbank> {
|
|
return List
|
|
.filter { it.Category.equals(Category.Greeting.name,true) }
|
|
.distinctBy { it.TAG }
|
|
.sortedBy { it.TAG }
|
|
}
|
|
|
|
fun Get_Procedures(): List<Soundbank> {
|
|
return List
|
|
.filter { it.Category.equals(Category.Procedure.name,true) }
|
|
.distinctBy { it.TAG }
|
|
.sortedBy { it.TAG }
|
|
}
|
|
|
|
class FileCheckResult{
|
|
var validfile = arrayListOf<Soundbank>()
|
|
var invalidfile = arrayListOf<Soundbank>()
|
|
}
|
|
|
|
/**
|
|
* Check Soundbank path files existence
|
|
* @param cb callback with FileCheckResult containing valid and invalid files
|
|
*/
|
|
fun FileCheck(cb: Consumer<FileCheckResult>){
|
|
val result = FileCheckResult()
|
|
// file wav must at least 10 kb
|
|
val validfilesize = 10 * 1024; // 10 KB
|
|
|
|
for (sb in List){
|
|
if (sb.Path.isBlank()) {
|
|
result.invalidfile.add(sb)
|
|
continue
|
|
}
|
|
val file = File(sb.Path)
|
|
if (file.isFile && file.length() >= validfilesize) {
|
|
// file size should at leat 10 kb
|
|
result.validfile.add(sb)
|
|
} else {
|
|
result.invalidfile.add(sb)
|
|
}
|
|
}
|
|
cb.accept(result)
|
|
}
|
|
} |