Initial DB calls added
This commit is contained in:
@@ -1,35 +1,188 @@
|
|||||||
package codes.kalar.service
|
package codes.kalar.service
|
||||||
|
|
||||||
|
import codes.kalar.exception.DbElementInsertionException
|
||||||
|
import codes.kalar.exception.DbElementNotFoundException
|
||||||
import codes.kalar.model.CollectionItem
|
import codes.kalar.model.CollectionItem
|
||||||
import kotlinx.coroutines.*
|
import codes.kalar.model.NewCollectionItem
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.json.Json
|
||||||
import java.sql.Connection
|
import java.sql.*
|
||||||
import java.sql.Statement
|
|
||||||
|
|
||||||
class CollectionItemService(private val connection: Connection) {
|
class CollectionItemService(private val connection: Connection) {
|
||||||
var pageOfItems = mutableListOf<CollectionItem>()
|
|
||||||
companion object {
|
companion object {
|
||||||
// TODO add create table statement
|
private const val SELECT_ITEM_BY_TITLE = "SELECT * FROM collection_item WHERE levenshtein(title, ?) <= 5 LIMIT 25 OFFSET ?"
|
||||||
private const val CREATE_COLLECTION_ITEMS_TABLE = "CREATE TABLE IF NOT EXISTS collection_items ("
|
private const val SELECT_ITEM_BY_ID = "SELECT * FROM collection_item WHERE id = ?"
|
||||||
private const val SELECT_ITEM_BY_TITLE = "SELECT * FROM collection_items WHERE title = ? limit 10"
|
private const val INSERT_ITEM = "INSERT INTO collection_item (title, author, publisher, publishing_date, " +
|
||||||
private const val INSERT_ITEM = "INSERT INTO collection_items (name, population) VALUES (?, ?)"
|
"loc_number, dewey_decimal_number, isbn, sort_title, format, language, page_count, categories, " +
|
||||||
private const val UPDATE_ITEM = "UPDATE collection_items SET name = ?, population = ? WHERE id = ?"
|
"description, price_in_cents, cover_image_uri, is_checked_in, is_archived, is_lost, lost_date) " +
|
||||||
private const val DELETE_ITEM = "DELETE FROM collection_items WHERE id = ?"
|
"VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"
|
||||||
|
private const val UPDATE_ITEM_BY_ID = "UPDATE collection_item SET title = ?, author = ?, publisher = ?, " +
|
||||||
|
"publishing_date = ?, loc_number = ?, dewey_decimal_number = ?, isbn = ?, sort_title = ?, format = ?, " +
|
||||||
|
"language = ?, page_count = ?, categories = ?, description = ?, price_in_cents = ?, cover_image_uri = ?, " +
|
||||||
|
"is_checked_in = ?, is_archived = ?, is_lost = ?, lost_date = ? WHERE id = ?"
|
||||||
|
// In the event books are "deleted" erroneously, having a flag set instead of actually removing the entry allows
|
||||||
|
// for quick reversal.
|
||||||
|
private const val ARCHIVE_ITEM_BY_ID = "UPDATE collection_item SET is_archived = true WHERE id = ?"
|
||||||
}
|
}
|
||||||
|
|
||||||
init {
|
suspend fun create(newCollectionItem: NewCollectionItem): Long {
|
||||||
val statement = connection.createStatement()
|
val statement = connection.prepareStatement(INSERT_ITEM,
|
||||||
val tables = connection.metaData.getTables(null, "public", "collection_items", arrayOf("TABLE"))
|
Statement.RETURN_GENERATED_KEYS)
|
||||||
if (!tables.next()) {
|
statement.setString(1, newCollectionItem.title)
|
||||||
statement.executeUpdate(CREATE_COLLECTION_ITEMS_TABLE)
|
statement.setString(2, newCollectionItem.author)
|
||||||
|
statement.setString(3, newCollectionItem.publisher)
|
||||||
|
statement.setString(4, newCollectionItem.publishingDate)
|
||||||
|
statement.setString(5, newCollectionItem.locNumber)
|
||||||
|
statement.setString(6, newCollectionItem.deweyDecimalNumber)
|
||||||
|
statement.setLong(7, newCollectionItem.isbn)
|
||||||
|
statement.setString(8, newCollectionItem.sortTitle)
|
||||||
|
statement.setString(9, newCollectionItem.format)
|
||||||
|
statement.setString(10, newCollectionItem.language)
|
||||||
|
statement.setInt(11, newCollectionItem.pageCount)
|
||||||
|
statement.setString(12, newCollectionItem.categories)
|
||||||
|
statement.setString(13, newCollectionItem.description)
|
||||||
|
statement.setInt(14, newCollectionItem.priceInCents)
|
||||||
|
statement.setString(15, newCollectionItem.coverImageUri)
|
||||||
|
statement.setBoolean(16, newCollectionItem.isCheckedIn)
|
||||||
|
statement.setBoolean(17, newCollectionItem.isArchived)
|
||||||
|
statement.setBoolean(18, newCollectionItem.isLost)
|
||||||
|
statement.setDate(19, Date.valueOf(newCollectionItem.lostDate))
|
||||||
|
try{
|
||||||
|
statement.execute()
|
||||||
|
val key = statement.generatedKeys
|
||||||
|
if (key.next()) {
|
||||||
|
return key.getLong(1)
|
||||||
|
}
|
||||||
|
return -1
|
||||||
|
} catch (cause: SQLException) {
|
||||||
|
throw DbElementInsertionException("Couldn't insert item " +
|
||||||
|
"${newCollectionItem.title} into database. ${cause.message}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun create(collectionItem: CollectionItem) {}
|
suspend fun readByTitle(inputTitle: String, offset: Int = 0): MutableList<String> {
|
||||||
|
val itemList = mutableListOf<String>()
|
||||||
|
// FUZZY SEARCH!!!!
|
||||||
|
val statement = connection.prepareStatement(SELECT_ITEM_BY_TITLE)
|
||||||
|
statement.setString(1, inputTitle)
|
||||||
|
statement.setInt(2, offset * 25)
|
||||||
|
val resultSet = statement.executeQuery()
|
||||||
|
if (!resultSet.next()) {
|
||||||
|
throw DbElementNotFoundException("Could not find collection item.")
|
||||||
|
}
|
||||||
|
while (resultSet.next()) {
|
||||||
|
// Only return non-archived books
|
||||||
|
if (!resultSet.getBoolean("is_archived")) {
|
||||||
|
val collectionItem = createItemFromResult(resultSet)
|
||||||
|
itemList.addLast(Json.encodeToString(collectionItem))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return itemList
|
||||||
|
}
|
||||||
|
|
||||||
suspend fun read(collectionItem: CollectionItem) {}
|
suspend fun readById(id: Long): CollectionItem {
|
||||||
|
val statement = connection.prepareStatement(SELECT_ITEM_BY_ID)
|
||||||
|
statement.setLong(1, id)
|
||||||
|
try {
|
||||||
|
val resultSet = statement.executeQuery()
|
||||||
|
// Only return non-archived books
|
||||||
|
if (resultSet.next() and !resultSet.getBoolean("is_archived")) {
|
||||||
|
return createItemFromResult(resultSet)
|
||||||
|
} else {
|
||||||
|
throw DbElementNotFoundException("Could not find collection item. resultSet: $resultSet")
|
||||||
|
}
|
||||||
|
} catch(cause: SQLException) {
|
||||||
|
throw DbElementNotFoundException("Could not find collection item with id $id")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
suspend fun update(collectionItem: CollectionItem) {}
|
suspend fun update(collectionItem: CollectionItem): Boolean {
|
||||||
|
val statement = connection.prepareStatement(UPDATE_ITEM_BY_ID)
|
||||||
|
try {
|
||||||
|
statement.setString(1, collectionItem.title)
|
||||||
|
statement.setString(2, collectionItem.author)
|
||||||
|
statement.setString(3, collectionItem.publisher)
|
||||||
|
statement.setString(4, collectionItem.publishingDate)
|
||||||
|
statement.setString(5, collectionItem.locNumber)
|
||||||
|
statement.setString(6, collectionItem.deweyDecimalNumber)
|
||||||
|
statement.setLong(7, collectionItem.isbn)
|
||||||
|
statement.setString(8, collectionItem.sortTitle)
|
||||||
|
statement.setString(9, collectionItem.format)
|
||||||
|
statement.setString(10, collectionItem.language)
|
||||||
|
statement.setInt(11, collectionItem.pageCount)
|
||||||
|
statement.setString(12, collectionItem.categories)
|
||||||
|
statement.setString(13, collectionItem.description)
|
||||||
|
statement.setInt(14, collectionItem.priceInCents)
|
||||||
|
statement.setString(15, collectionItem.coverImageUri)
|
||||||
|
statement.setBoolean(16, collectionItem.isCheckedIn)
|
||||||
|
statement.setBoolean(17, collectionItem.isArchived)
|
||||||
|
statement.setBoolean(18, collectionItem.isLost)
|
||||||
|
statement.setDate(19, Date.valueOf(collectionItem.lostDate))
|
||||||
|
statement.setLong(20, collectionItem.id)
|
||||||
|
return statement.execute()
|
||||||
|
} catch (e: SQLException) {
|
||||||
|
throw DbElementInsertionException("${e.message}\ncollectionItem: $collectionItem\n statement: $statement\n ", e)
|
||||||
|
} catch (e: IllegalArgumentException) {
|
||||||
|
throw DbElementInsertionException("${e.message}\ncollectionItem: $collectionItem\n statement: $statement\n ", e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
suspend fun delete(collectionItem: CollectionItem) {}
|
suspend fun delete(id: Long) {
|
||||||
|
val statement = connection.prepareStatement(ARCHIVE_ITEM_BY_ID)
|
||||||
|
try {
|
||||||
|
statement.setLong(1, id)
|
||||||
|
statement.execute()
|
||||||
|
} catch (e: SQLException) {
|
||||||
|
throw DbElementNotFoundException("Could not find collection item with id $id")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun createItemFromResult(resultSet: ResultSet): CollectionItem {
|
||||||
|
try {
|
||||||
|
val id = resultSet.getLong("id")
|
||||||
|
val title = resultSet.getString("title")
|
||||||
|
val author = resultSet.getString("author")
|
||||||
|
val publisher = resultSet.getString("publisher")
|
||||||
|
val publishingDate = resultSet.getDate("publishing_date")
|
||||||
|
val locNumber = resultSet.getString("loc_number")
|
||||||
|
val deweyDecimalNumber = resultSet.getString("dewey_decimal_number")
|
||||||
|
val isbn = resultSet.getLong("isbn")
|
||||||
|
val sortTitle = resultSet.getString("sort_title")
|
||||||
|
val format = resultSet.getString("format")
|
||||||
|
val language = resultSet.getString("language")
|
||||||
|
val pageCount = resultSet.getInt("page_count")
|
||||||
|
val categories = resultSet.getString("categories")
|
||||||
|
val description = resultSet.getString("description")
|
||||||
|
val priceInCents = resultSet.getInt("price_in_cents")
|
||||||
|
val coverImageUri = resultSet.getString("cover_image_uri") ?: ""
|
||||||
|
val isCheckedIn = resultSet.getBoolean("is_checked_in")
|
||||||
|
val isArchived = resultSet.getBoolean("is_archived")
|
||||||
|
val isLost = resultSet.getBoolean("is_lost")
|
||||||
|
val lostDate = resultSet.getDate("lost_date")
|
||||||
|
return CollectionItem(
|
||||||
|
id = id,
|
||||||
|
title = title,
|
||||||
|
author = author,
|
||||||
|
publisher = publisher,
|
||||||
|
publishingDate = publishingDate.toString(),
|
||||||
|
locNumber = locNumber,
|
||||||
|
deweyDecimalNumber = deweyDecimalNumber,
|
||||||
|
isbn = isbn,
|
||||||
|
sortTitle = sortTitle,
|
||||||
|
format = format,
|
||||||
|
language = language,
|
||||||
|
pageCount = pageCount,
|
||||||
|
categories = categories,
|
||||||
|
description = description,
|
||||||
|
priceInCents = priceInCents,
|
||||||
|
coverImageUri = coverImageUri,
|
||||||
|
isCheckedIn = isCheckedIn,
|
||||||
|
isArchived = isArchived,
|
||||||
|
isLost = isLost,
|
||||||
|
lostDate = lostDate.toString()
|
||||||
|
)
|
||||||
|
} catch (cause: NullPointerException) {
|
||||||
|
throw DbElementInsertionException("${cause.message}\nresultSet = ${resultSet.getMetaData()}")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user