Http Server / Client communication #7
12 changed files with 87 additions and 75 deletions
|
@ -4,6 +4,18 @@
|
||||||
<value>
|
<value>
|
||||||
<entry key="app">
|
<entry key="app">
|
||||||
<State>
|
<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>
|
<runningDeviceTargetsSelectedWithDialog>
|
||||||
<Target>
|
<Target>
|
||||||
<type value="RUNNING_DEVICE_TARGET" />
|
<type value="RUNNING_DEVICE_TARGET" />
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project version="4">
|
<project version="4">
|
||||||
<component name="ExternalStorageConfigurationManager" enabled="true" />
|
<component name="ExternalStorageConfigurationManager" enabled="true" />
|
||||||
<component name="FrameworkDetectionExcludesConfiguration">
|
<component name="FrameworkDetectionExcludesConfiguration">
|
||||||
<file type="web" url="file://$PROJECT_DIR$" />
|
<file type="web" url="file://$PROJECT_DIR$" />
|
||||||
</component>
|
</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" />
|
<output url="file://$PROJECT_DIR$/build/classes" />
|
||||||
</component>
|
</component>
|
||||||
<component name="ProjectType">
|
<component name="ProjectType">
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package com.faraphel.tasks_valider.connectivity.task
|
package com.faraphel.tasks_valider.connectivity.task
|
||||||
|
|
||||||
import com.faraphel.tasks_valider.database.TaskDatabase
|
import com.faraphel.tasks_valider.database.TaskDatabase
|
||||||
|
import com.faraphel.tasks_valider.database.api.base.BaseApi
|
||||||
import com.google.gson.Gson
|
import com.google.gson.Gson
|
||||||
import fi.iki.elonen.NanoHTTPD
|
import fi.iki.elonen.NanoHTTPD
|
||||||
|
|
||||||
|
@ -21,28 +22,30 @@ class TaskServer(
|
||||||
val uri: String = session.uri
|
val uri: String = session.uri
|
||||||
|
|
||||||
// remove the first slash
|
// remove the first slash
|
||||||
val daoName: String = uri.substring(1)
|
val entityName: String = uri.substring(1)
|
||||||
// get the matching DAO in the database
|
// get the matching entity API in the database
|
||||||
|
val entityApi = database.getApiFromName(entityName)
|
||||||
TODO("Faraphel: get the correct DAO from the database")
|
?: return newFixedLengthResponse(
|
||||||
TODO("Faraphel: pass more direct arguments to the API handler ?")
|
Response.Status.NOT_FOUND,
|
||||||
|
"text/plain",
|
||||||
|
"Invalid entity name"
|
||||||
|
)
|
||||||
|
|
||||||
// handle the request
|
// handle the request
|
||||||
when (method) {
|
return when (method) {
|
||||||
// check if the data is in the database
|
// check if the data is in the database
|
||||||
Method.HEAD -> { TODO() }
|
Method.HEAD -> entityApi.head(session)
|
||||||
// get the data from the dao
|
// get the data from the dao
|
||||||
Method.GET -> { TODO() }
|
Method.GET -> entityApi.get(session)
|
||||||
// insert the data into the database
|
// insert the data into the database
|
||||||
Method.POST -> { TODO() }
|
Method.POST -> entityApi.post(session)
|
||||||
// other methods are not allowed
|
// other methods are not allowed
|
||||||
else -> {
|
else ->
|
||||||
return newFixedLengthResponse(
|
newFixedLengthResponse(
|
||||||
Response.Status.METHOD_NOT_ALLOWED,
|
Response.Status.METHOD_NOT_ALLOWED,
|
||||||
"text/plain",
|
"text/plain",
|
||||||
"Method not allowed"
|
"Method not allowed"
|
||||||
)
|
)
|
||||||
}
|
|
||||||
// TODO(Faraphel): implement a permission system
|
// TODO(Faraphel): implement a permission system
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,8 @@ package com.faraphel.tasks_valider.database
|
||||||
import androidx.room.Database
|
import androidx.room.Database
|
||||||
import androidx.room.RoomDatabase
|
import androidx.room.RoomDatabase
|
||||||
import androidx.room.TypeConverters
|
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.converters.InstantConverter
|
||||||
import com.faraphel.tasks_valider.database.dao.GroupDao
|
import com.faraphel.tasks_valider.database.dao.GroupDao
|
||||||
import com.faraphel.tasks_valider.database.dao.GroupStudentDao
|
import com.faraphel.tasks_valider.database.dao.GroupStudentDao
|
||||||
|
@ -39,12 +41,32 @@ import com.faraphel.tasks_valider.database.entities.TeacherEntity
|
||||||
)
|
)
|
||||||
abstract class TaskDatabase : RoomDatabase() {
|
abstract class TaskDatabase : RoomDatabase() {
|
||||||
// entities
|
// entities
|
||||||
|
|
||||||
abstract fun groupDao(): GroupDao
|
abstract fun groupDao(): GroupDao
|
||||||
abstract fun studentDao(): StudentDao
|
abstract fun studentDao(): StudentDao
|
||||||
abstract fun teacherDao(): TeacherDao
|
abstract fun teacherDao(): TeacherDao
|
||||||
abstract fun taskDao(): TaskDao
|
abstract fun taskDao(): TaskDao
|
||||||
|
|
||||||
// relations
|
|
||||||
abstract fun groupStudentDao(): GroupStudentDao
|
abstract fun groupStudentDao(): GroupStudentDao
|
||||||
abstract fun taskGroupDao(): TaskGroupDao
|
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]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,7 @@
|
||||||
package com.faraphel.tasks_valider.database.api
|
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.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
|
import com.faraphel.tasks_valider.database.entities.GroupEntity
|
||||||
|
|
||||||
class GroupApi : BaseJsonApi<GroupEntity>() {
|
class GroupApi(dao: BaseDao<GroupEntity>) : BaseJsonApi<GroupEntity>(dao)
|
||||||
override fun getDao(database: TaskDatabase): GroupDao = database.groupDao()
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,10 +1,7 @@
|
||||||
package com.faraphel.tasks_valider.database.api
|
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.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
|
import com.faraphel.tasks_valider.database.entities.GroupStudentEntity
|
||||||
|
|
||||||
class GroupStudentApi : BaseJsonApi<GroupStudentEntity>() {
|
class GroupStudentApi(dao: BaseDao<GroupStudentEntity>) : BaseJsonApi<GroupStudentEntity>(dao)
|
||||||
override fun getDao(database: TaskDatabase): GroupStudentDao = database.groupStudentDao()
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,10 +1,7 @@
|
||||||
package com.faraphel.tasks_valider.database.api
|
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.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
|
import com.faraphel.tasks_valider.database.entities.StudentEntity
|
||||||
|
|
||||||
class StudentApi : BaseJsonApi<StudentEntity>() {
|
class StudentApi(dao: BaseDao<StudentEntity>) : BaseJsonApi<StudentEntity>(dao)
|
||||||
override fun getDao(database: TaskDatabase): StudentDao = database.studentDao()
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,10 +1,7 @@
|
||||||
package com.faraphel.tasks_valider.database.api
|
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.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
|
import com.faraphel.tasks_valider.database.entities.TaskEntity
|
||||||
|
|
||||||
class TaskApi : BaseJsonApi<TaskEntity>() {
|
class TaskApi(dao: BaseDao<TaskEntity>) : BaseJsonApi<TaskEntity>(dao)
|
||||||
override fun getDao(database: TaskDatabase): TaskDao = database.taskDao()
|
|
||||||
}
|
|
|
@ -1,10 +1,7 @@
|
||||||
package com.faraphel.tasks_valider.database.api
|
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.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
|
import com.faraphel.tasks_valider.database.entities.TaskGroupEntity
|
||||||
|
|
||||||
class TaskGroupApi : BaseJsonApi<TaskGroupEntity>() {
|
class TaskGroupApi(dao: BaseDao<TaskGroupEntity>) : BaseJsonApi<TaskGroupEntity>(dao)
|
||||||
override fun getDao(database: TaskDatabase): TaskGroupDao = database.taskGroupDao()
|
|
||||||
}
|
|
|
@ -1,10 +1,7 @@
|
||||||
package com.faraphel.tasks_valider.database.api
|
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.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
|
import com.faraphel.tasks_valider.database.entities.TeacherEntity
|
||||||
|
|
||||||
class TeacherApi : BaseJsonApi<TeacherEntity>() {
|
class TeacherApi(dao: BaseDao<TeacherEntity>) : BaseJsonApi<TeacherEntity>(dao)
|
||||||
override fun getDao(database: TaskDatabase): TeacherDao = database.teacherDao()
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
package com.faraphel.tasks_valider.database.api.base
|
package com.faraphel.tasks_valider.database.api.base
|
||||||
|
|
||||||
import com.faraphel.tasks_valider.database.TaskDatabase
|
|
||||||
import fi.iki.elonen.NanoHTTPD
|
import fi.iki.elonen.NanoHTTPD
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -11,23 +10,23 @@ interface BaseApi {
|
||||||
* Handle the HEAD request
|
* Handle the HEAD request
|
||||||
* This is used to check if a data exists in the database
|
* 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
|
* Handle the GET request
|
||||||
* This is used to get data from the database
|
* 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
|
* Handle the POST request
|
||||||
* This is used to insert data into the database
|
* 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
|
* Handle the PUT request
|
||||||
* This is used to delete data from the database
|
* 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
|
||||||
}
|
}
|
|
@ -1,8 +1,6 @@
|
||||||
package com.faraphel.tasks_valider.database.api.base
|
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.dao.base.BaseDao
|
||||||
import com.faraphel.tasks_valider.database.entities.GroupEntity
|
|
||||||
import com.faraphel.tasks_valider.database.entities.base.BaseEntity
|
import com.faraphel.tasks_valider.database.entities.base.BaseEntity
|
||||||
import com.google.gson.Gson
|
import com.google.gson.Gson
|
||||||
import com.google.gson.reflect.TypeToken
|
import com.google.gson.reflect.TypeToken
|
||||||
|
@ -13,32 +11,21 @@ import fi.iki.elonen.NanoHTTPD
|
||||||
* This is preconfigured to handle JSON data.
|
* This is preconfigured to handle JSON data.
|
||||||
* @param Entity the entity type to handle
|
* @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 {
|
companion object {
|
||||||
private val parser = Gson() ///< The JSON parser
|
private val parser = Gson() ///< The JSON parser
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private val entityTypeToken: TypeToken<Entity> = object: TypeToken<Entity>() {} ///< the type of the managed entity
|
||||||
* 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>() {}
|
|
||||||
|
|
||||||
// Requests
|
// Requests
|
||||||
|
|
||||||
override fun head(database: TaskDatabase, session: NanoHTTPD.IHTTPSession): NanoHTTPD.Response {
|
override fun head(session: NanoHTTPD.IHTTPSession): NanoHTTPD.Response {
|
||||||
val obj = parser.fromJson<Entity>(
|
val obj = parser.fromJson<Entity>(
|
||||||
session.inputStream.bufferedReader().readText(),
|
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(
|
return NanoHTTPD.newFixedLengthResponse(
|
||||||
if (exists) NanoHTTPD.Response.Status.OK else NanoHTTPD.Response.Status.NOT_FOUND,
|
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(
|
return NanoHTTPD.newFixedLengthResponse(
|
||||||
NanoHTTPD.Response.Status.OK,
|
NanoHTTPD.Response.Status.OK,
|
||||||
"application/json",
|
"application/json",
|
||||||
parser.toJson(database.groupDao().getAll())
|
parser.toJson(this.dao.getAll())
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun post(database: TaskDatabase, session: NanoHTTPD.IHTTPSession): NanoHTTPD.Response {
|
override fun post(session: NanoHTTPD.IHTTPSession): NanoHTTPD.Response {
|
||||||
val obj = parser.fromJson(session.inputStream.bufferedReader().readText(), GroupEntity::class.java)
|
val obj = parser.fromJson<Entity>(
|
||||||
val id = database.groupDao().insert(obj)
|
session.inputStream.bufferedReader().readText(),
|
||||||
|
this.entityTypeToken.type
|
||||||
|
)
|
||||||
|
val id = this.dao.insert(obj)
|
||||||
|
|
||||||
return NanoHTTPD.newFixedLengthResponse(
|
return NanoHTTPD.newFixedLengthResponse(
|
||||||
NanoHTTPD.Response.Status.CREATED,
|
NanoHTTPD.Response.Status.CREATED,
|
||||||
|
@ -66,9 +56,12 @@ abstract class BaseJsonApi<Entity: BaseEntity> : BaseApi {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun delete(database: TaskDatabase, session: NanoHTTPD.IHTTPSession): NanoHTTPD.Response {
|
override fun delete(session: NanoHTTPD.IHTTPSession): NanoHTTPD.Response {
|
||||||
val obj = parser.fromJson(session.inputStream.bufferedReader().readText(), GroupEntity::class.java)
|
val obj = parser.fromJson<Entity>(
|
||||||
val count = database.groupDao().delete(obj)
|
session.inputStream.bufferedReader().readText(),
|
||||||
|
this.entityTypeToken.type
|
||||||
|
)
|
||||||
|
val count = this.dao.delete(obj)
|
||||||
|
|
||||||
return NanoHTTPD.newFixedLengthResponse(
|
return NanoHTTPD.newFixedLengthResponse(
|
||||||
if (count > 0) NanoHTTPD.Response.Status.OK else NanoHTTPD.Response.Status.NOT_FOUND,
|
if (count > 0) NanoHTTPD.Response.Status.OK else NanoHTTPD.Response.Status.NOT_FOUND,
|
||||||
|
|
Loading…
Reference in a new issue