[WIP] simplified and fixed the Api system in the database

This commit is contained in:
Faraphel 2024-05-08 21:32:10 +02:00
parent 8c11e18e0d
commit b97fb71f8f
12 changed files with 87 additions and 75 deletions

View file

@ -4,6 +4,18 @@
<value>
<entry key="app">
<State>
<targetSelectedWithDropDown>
<Target>
<type value="QUICK_BOOT_TARGET" />
<deviceKey>
<Key>
<type value="VIRTUAL_DEVICE_PATH" />
<value value="$USER_HOME$/.android/avd/Very_Small_API_34_2.avd" />
</Key>
</deviceKey>
</Target>
</targetSelectedWithDropDown>
<timeTargetWasSelectedWithDropDown value="2024-05-08T19:26:10.029903174Z" />
<runningDeviceTargetsSelectedWithDialog>
<Target>
<type value="RUNNING_DEVICE_TARGET" />

View file

@ -1,9 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="FrameworkDetectionExcludesConfiguration">
<file type="web" url="file://$PROJECT_DIR$" />
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="jbr-17" project-jdk-type="JavaSDK">
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" project-jdk-name="corretto-17" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/build/classes" />
</component>
<component name="ProjectType">

View file

@ -1,6 +1,7 @@
package com.faraphel.tasks_valider.connectivity.task
import com.faraphel.tasks_valider.database.TaskDatabase
import com.faraphel.tasks_valider.database.api.base.BaseApi
import com.google.gson.Gson
import fi.iki.elonen.NanoHTTPD
@ -21,28 +22,30 @@ class TaskServer(
val uri: String = session.uri
// remove the first slash
val daoName: String = uri.substring(1)
// get the matching DAO in the database
TODO("Faraphel: get the correct DAO from the database")
TODO("Faraphel: pass more direct arguments to the API handler ?")
val entityName: String = uri.substring(1)
// get the matching entity API in the database
val entityApi = database.getApiFromName(entityName)
?: return newFixedLengthResponse(
Response.Status.NOT_FOUND,
"text/plain",
"Invalid entity name"
)
// handle the request
when (method) {
return when (method) {
// check if the data is in the database
Method.HEAD -> { TODO() }
Method.HEAD -> entityApi.head(session)
// get the data from the dao
Method.GET -> { TODO() }
Method.GET -> entityApi.get(session)
// insert the data into the database
Method.POST -> { TODO() }
Method.POST -> entityApi.post(session)
// other methods are not allowed
else -> {
return newFixedLengthResponse(
else ->
newFixedLengthResponse(
Response.Status.METHOD_NOT_ALLOWED,
"text/plain",
"Method not allowed"
)
}
// TODO(Faraphel): implement a permission system
}
}

View file

@ -3,6 +3,8 @@ package com.faraphel.tasks_valider.database
import androidx.room.Database
import androidx.room.RoomDatabase
import androidx.room.TypeConverters
import com.faraphel.tasks_valider.database.api.*
import com.faraphel.tasks_valider.database.api.base.BaseApi
import com.faraphel.tasks_valider.database.converters.InstantConverter
import com.faraphel.tasks_valider.database.dao.GroupDao
import com.faraphel.tasks_valider.database.dao.GroupStudentDao
@ -39,12 +41,32 @@ import com.faraphel.tasks_valider.database.entities.TeacherEntity
)
abstract class TaskDatabase : RoomDatabase() {
// entities
abstract fun groupDao(): GroupDao
abstract fun studentDao(): StudentDao
abstract fun teacherDao(): TeacherDao
abstract fun taskDao(): TaskDao
// relations
abstract fun groupStudentDao(): GroupStudentDao
abstract fun taskGroupDao(): TaskGroupDao
// api
private val api: Map<String, BaseApi> = mapOf(
"group" to GroupApi(this.groupDao()),
"student" to StudentApi(this.studentDao()),
"teacher" to TeacherApi(this.teacherDao()),
"task" to TaskApi(this.taskDao()),
"group_student" to GroupStudentApi(this.groupStudentDao()),
"task_group" to TaskGroupApi(this.taskGroupDao()),
)
/**
* get the api for an entity from its name.
* @param name the name of the entity
*/
fun getApiFromName(name: String): BaseApi? {
return this.api[name]
}
}

View file

@ -1,10 +1,7 @@
package com.faraphel.tasks_valider.database.api
import com.faraphel.tasks_valider.database.TaskDatabase
import com.faraphel.tasks_valider.database.api.base.BaseJsonApi
import com.faraphel.tasks_valider.database.dao.GroupDao
import com.faraphel.tasks_valider.database.dao.base.BaseDao
import com.faraphel.tasks_valider.database.entities.GroupEntity
class GroupApi : BaseJsonApi<GroupEntity>() {
override fun getDao(database: TaskDatabase): GroupDao = database.groupDao()
}
class GroupApi(dao: BaseDao<GroupEntity>) : BaseJsonApi<GroupEntity>(dao)

View file

@ -1,10 +1,7 @@
package com.faraphel.tasks_valider.database.api
import com.faraphel.tasks_valider.database.TaskDatabase
import com.faraphel.tasks_valider.database.api.base.BaseJsonApi
import com.faraphel.tasks_valider.database.dao.GroupStudentDao
import com.faraphel.tasks_valider.database.dao.base.BaseDao
import com.faraphel.tasks_valider.database.entities.GroupStudentEntity
class GroupStudentApi : BaseJsonApi<GroupStudentEntity>() {
override fun getDao(database: TaskDatabase): GroupStudentDao = database.groupStudentDao()
}
class GroupStudentApi(dao: BaseDao<GroupStudentEntity>) : BaseJsonApi<GroupStudentEntity>(dao)

View file

@ -1,10 +1,7 @@
package com.faraphel.tasks_valider.database.api
import com.faraphel.tasks_valider.database.TaskDatabase
import com.faraphel.tasks_valider.database.api.base.BaseJsonApi
import com.faraphel.tasks_valider.database.dao.StudentDao
import com.faraphel.tasks_valider.database.dao.base.BaseDao
import com.faraphel.tasks_valider.database.entities.StudentEntity
class StudentApi : BaseJsonApi<StudentEntity>() {
override fun getDao(database: TaskDatabase): StudentDao = database.studentDao()
}
class StudentApi(dao: BaseDao<StudentEntity>) : BaseJsonApi<StudentEntity>(dao)

View file

@ -1,10 +1,7 @@
package com.faraphel.tasks_valider.database.api
import com.faraphel.tasks_valider.database.TaskDatabase
import com.faraphel.tasks_valider.database.api.base.BaseJsonApi
import com.faraphel.tasks_valider.database.dao.TaskDao
import com.faraphel.tasks_valider.database.dao.base.BaseDao
import com.faraphel.tasks_valider.database.entities.TaskEntity
class TaskApi : BaseJsonApi<TaskEntity>() {
override fun getDao(database: TaskDatabase): TaskDao = database.taskDao()
}
class TaskApi(dao: BaseDao<TaskEntity>) : BaseJsonApi<TaskEntity>(dao)

View file

@ -1,10 +1,7 @@
package com.faraphel.tasks_valider.database.api
import com.faraphel.tasks_valider.database.TaskDatabase
import com.faraphel.tasks_valider.database.api.base.BaseJsonApi
import com.faraphel.tasks_valider.database.dao.TaskGroupDao
import com.faraphel.tasks_valider.database.dao.base.BaseDao
import com.faraphel.tasks_valider.database.entities.TaskGroupEntity
class TaskGroupApi : BaseJsonApi<TaskGroupEntity>() {
override fun getDao(database: TaskDatabase): TaskGroupDao = database.taskGroupDao()
}
class TaskGroupApi(dao: BaseDao<TaskGroupEntity>) : BaseJsonApi<TaskGroupEntity>(dao)

View file

@ -1,10 +1,7 @@
package com.faraphel.tasks_valider.database.api
import com.faraphel.tasks_valider.database.TaskDatabase
import com.faraphel.tasks_valider.database.api.base.BaseJsonApi
import com.faraphel.tasks_valider.database.dao.TeacherDao
import com.faraphel.tasks_valider.database.dao.base.BaseDao
import com.faraphel.tasks_valider.database.entities.TeacherEntity
class TeacherApi : BaseJsonApi<TeacherEntity>() {
override fun getDao(database: TaskDatabase): TeacherDao = database.teacherDao()
}
class TeacherApi(dao: BaseDao<TeacherEntity>) : BaseJsonApi<TeacherEntity>(dao)

View file

@ -1,6 +1,5 @@
package com.faraphel.tasks_valider.database.api.base
import com.faraphel.tasks_valider.database.TaskDatabase
import fi.iki.elonen.NanoHTTPD
/**
@ -11,23 +10,23 @@ interface BaseApi {
* Handle the HEAD request
* This is used to check if a data exists in the database
*/
fun head(database: TaskDatabase, session: NanoHTTPD.IHTTPSession): NanoHTTPD.Response
fun head(session: NanoHTTPD.IHTTPSession): NanoHTTPD.Response
/**
* Handle the GET request
* This is used to get data from the database
*/
fun get(database: TaskDatabase, session: NanoHTTPD.IHTTPSession): NanoHTTPD.Response
fun get(session: NanoHTTPD.IHTTPSession): NanoHTTPD.Response
/**
* Handle the POST request
* This is used to insert data into the database
*/
fun post(database: TaskDatabase, session: NanoHTTPD.IHTTPSession): NanoHTTPD.Response
fun post(session: NanoHTTPD.IHTTPSession): NanoHTTPD.Response
/**
* Handle the PUT request
* This is used to delete data from the database
*/
fun delete(database: TaskDatabase, session: NanoHTTPD.IHTTPSession): NanoHTTPD.Response
fun delete(session: NanoHTTPD.IHTTPSession): NanoHTTPD.Response
}

View file

@ -1,8 +1,6 @@
package com.faraphel.tasks_valider.database.api.base
import com.faraphel.tasks_valider.database.TaskDatabase
import com.faraphel.tasks_valider.database.dao.base.BaseDao
import com.faraphel.tasks_valider.database.entities.GroupEntity
import com.faraphel.tasks_valider.database.entities.base.BaseEntity
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
@ -13,32 +11,21 @@ import fi.iki.elonen.NanoHTTPD
* This is preconfigured to handle JSON data.
* @param Entity the entity type to handle
*/
abstract class BaseJsonApi<Entity: BaseEntity> : BaseApi {
abstract class BaseJsonApi<Entity: BaseEntity>(private val dao: BaseDao<Entity>) : BaseApi {
companion object {
private val parser = Gson() ///< The JSON parser
}
/**
* Get the DAO for the entity
* @param database the database to get the DAO from
* @return the DAO for the entity
*/
abstract fun getDao(database: TaskDatabase): BaseDao<Entity>
/**
* Get the type token for the entity
* @return the type token for the entity
*/
private fun getEntityTypeToken(): TypeToken<Entity> = object: TypeToken<Entity>() {}
private val entityTypeToken: TypeToken<Entity> = object: TypeToken<Entity>() {} ///< the type of the managed entity
// Requests
override fun head(database: TaskDatabase, session: NanoHTTPD.IHTTPSession): NanoHTTPD.Response {
override fun head(session: NanoHTTPD.IHTTPSession): NanoHTTPD.Response {
val obj = parser.fromJson<Entity>(
session.inputStream.bufferedReader().readText(),
getEntityTypeToken().type
this.entityTypeToken.type
)
val exists = this.getDao(database).exists(obj)
val exists = this.dao.exists(obj)
return NanoHTTPD.newFixedLengthResponse(
if (exists) NanoHTTPD.Response.Status.OK else NanoHTTPD.Response.Status.NOT_FOUND,
@ -47,17 +34,20 @@ abstract class BaseJsonApi<Entity: BaseEntity> : BaseApi {
)
}
override fun get(database: TaskDatabase, session: NanoHTTPD.IHTTPSession): NanoHTTPD.Response {
override fun get(session: NanoHTTPD.IHTTPSession): NanoHTTPD.Response {
return NanoHTTPD.newFixedLengthResponse(
NanoHTTPD.Response.Status.OK,
"application/json",
parser.toJson(database.groupDao().getAll())
parser.toJson(this.dao.getAll())
)
}
override fun post(database: TaskDatabase, session: NanoHTTPD.IHTTPSession): NanoHTTPD.Response {
val obj = parser.fromJson(session.inputStream.bufferedReader().readText(), GroupEntity::class.java)
val id = database.groupDao().insert(obj)
override fun post(session: NanoHTTPD.IHTTPSession): NanoHTTPD.Response {
val obj = parser.fromJson<Entity>(
session.inputStream.bufferedReader().readText(),
this.entityTypeToken.type
)
val id = this.dao.insert(obj)
return NanoHTTPD.newFixedLengthResponse(
NanoHTTPD.Response.Status.CREATED,
@ -66,9 +56,12 @@ abstract class BaseJsonApi<Entity: BaseEntity> : BaseApi {
)
}
override fun delete(database: TaskDatabase, session: NanoHTTPD.IHTTPSession): NanoHTTPD.Response {
val obj = parser.fromJson(session.inputStream.bufferedReader().readText(), GroupEntity::class.java)
val count = database.groupDao().delete(obj)
override fun delete(session: NanoHTTPD.IHTTPSession): NanoHTTPD.Response {
val obj = parser.fromJson<Entity>(
session.inputStream.bufferedReader().readText(),
this.entityTypeToken.type
)
val count = this.dao.delete(obj)
return NanoHTTPD.newFixedLengthResponse(
if (count > 0) NanoHTTPD.Response.Status.OK else NanoHTTPD.Response.Status.NOT_FOUND,