mirror of
https://github.com/Matte23/circolapp.git
synced 2025-12-06 07:29:10 +00:00
Add base code for multiple server (schools) support
This commit is contained in:
@@ -2,50 +2,49 @@ package net.underdesk.circolapp.data
|
||||
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
import net.underdesk.circolapp.server.DataFetcher
|
||||
import java.io.IOException
|
||||
import net.underdesk.circolapp.server.ServerAPI
|
||||
|
||||
class CircularRepository(
|
||||
val circularDao: CircularDao,
|
||||
private val fetcher: DataFetcher = DataFetcher()
|
||||
private val serverAPI: ServerAPI
|
||||
) {
|
||||
suspend fun updateCirculars(returnNewCirculars: Boolean = true): Pair<List<Circular>, Boolean> {
|
||||
var onlyNewCirculars = listOf<Circular>()
|
||||
|
||||
try {
|
||||
withContext(Dispatchers.IO) {
|
||||
val oldCirculars = circularDao.getCirculars()
|
||||
val newCirculars = fetcher.getCircularsFromServer()
|
||||
if (newCirculars.size != oldCirculars.size) {
|
||||
if (newCirculars.size < oldCirculars.size) {
|
||||
circularDao.deleteAll()
|
||||
}
|
||||
return withContext(Dispatchers.IO) {
|
||||
val result = serverAPI.getCircularsFromServer()
|
||||
if (result.second == ServerAPI.Companion.Result.ERROR)
|
||||
return@withContext Pair(emptyList(), false)
|
||||
|
||||
if (returnNewCirculars) {
|
||||
val oldCircularsSize =
|
||||
if (newCirculars.size < oldCirculars.size) 0 else oldCirculars.size
|
||||
val oldCirculars = circularDao.getCirculars()
|
||||
val newCirculars = result.first
|
||||
|
||||
val circularCount = newCirculars.size - oldCircularsSize
|
||||
onlyNewCirculars = newCirculars.subList(0, circularCount)
|
||||
}
|
||||
|
||||
circularDao.insertAll(newCirculars)
|
||||
if (newCirculars.size != oldCirculars.size) {
|
||||
if (newCirculars.size < oldCirculars.size) {
|
||||
circularDao.deleteAll()
|
||||
}
|
||||
}
|
||||
} catch (exception: IOException) {
|
||||
return Pair(onlyNewCirculars, false)
|
||||
}
|
||||
|
||||
return Pair(onlyNewCirculars, true)
|
||||
if (returnNewCirculars) {
|
||||
val oldCircularsSize =
|
||||
if (newCirculars.size < oldCirculars.size) 0 else oldCirculars.size
|
||||
|
||||
val circularCount = newCirculars.size - oldCircularsSize
|
||||
onlyNewCirculars = newCirculars.subList(0, circularCount)
|
||||
}
|
||||
|
||||
circularDao.insertAll(newCirculars)
|
||||
}
|
||||
Pair(onlyNewCirculars, true)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
@Volatile
|
||||
private var instance: CircularRepository? = null
|
||||
|
||||
fun getInstance(circularDao: CircularDao) =
|
||||
fun getInstance(circularDao: CircularDao, serverAPI: ServerAPI) =
|
||||
instance ?: synchronized(this) {
|
||||
instance ?: CircularRepository(circularDao).also { instance = it }
|
||||
instance ?: CircularRepository(circularDao, serverAPI).also { instance = it }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,6 +34,7 @@ import net.underdesk.circolapp.R
|
||||
import net.underdesk.circolapp.adapters.CircularLetterAdapter
|
||||
import net.underdesk.circolapp.data.AppDatabase
|
||||
import net.underdesk.circolapp.data.CircularRepository
|
||||
import net.underdesk.circolapp.server.ServerAPI
|
||||
import net.underdesk.circolapp.viewmodels.CircularLetterViewModel
|
||||
import net.underdesk.circolapp.viewmodels.CircularLetterViewModelFactory
|
||||
|
||||
@@ -45,7 +46,8 @@ class CircularLetterFragment :
|
||||
private val circularLetterViewModel: CircularLetterViewModel by viewModels {
|
||||
CircularLetterViewModelFactory(
|
||||
CircularRepository.getInstance(
|
||||
AppDatabase.getInstance(requireContext()).circularDao()
|
||||
AppDatabase.getInstance(requireContext()).circularDao(),
|
||||
ServerAPI.getInstance(ServerAPI.Companion.Servers.CURIE)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -31,6 +31,7 @@ import net.underdesk.circolapp.R
|
||||
import net.underdesk.circolapp.adapters.CircularLetterAdapter
|
||||
import net.underdesk.circolapp.data.AppDatabase
|
||||
import net.underdesk.circolapp.data.CircularRepository
|
||||
import net.underdesk.circolapp.server.ServerAPI
|
||||
import net.underdesk.circolapp.viewmodels.FavouritesViewModel
|
||||
import net.underdesk.circolapp.viewmodels.FavouritesViewModelFactory
|
||||
|
||||
@@ -39,7 +40,8 @@ class FavouritesFragment : Fragment(), MainActivity.SearchCallback {
|
||||
private val favouritesViewModel: FavouritesViewModel by viewModels {
|
||||
FavouritesViewModelFactory(
|
||||
CircularRepository.getInstance(
|
||||
AppDatabase.getInstance(requireContext()).circularDao()
|
||||
AppDatabase.getInstance(requireContext()).circularDao(),
|
||||
ServerAPI.getInstance(ServerAPI.Companion.Servers.CURIE)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -31,6 +31,7 @@ import net.underdesk.circolapp.R
|
||||
import net.underdesk.circolapp.adapters.CircularLetterAdapter
|
||||
import net.underdesk.circolapp.data.AppDatabase
|
||||
import net.underdesk.circolapp.data.CircularRepository
|
||||
import net.underdesk.circolapp.server.ServerAPI
|
||||
import net.underdesk.circolapp.viewmodels.RemindersViewModel
|
||||
import net.underdesk.circolapp.viewmodels.RemindersViewModelFactory
|
||||
|
||||
@@ -39,7 +40,8 @@ class RemindersFragment : Fragment(), MainActivity.SearchCallback {
|
||||
private val remindersViewModel: RemindersViewModel by viewModels {
|
||||
RemindersViewModelFactory(
|
||||
CircularRepository.getInstance(
|
||||
AppDatabase.getInstance(requireContext()).circularDao()
|
||||
AppDatabase.getInstance(requireContext()).circularDao(),
|
||||
ServerAPI.getInstance(ServerAPI.Companion.Servers.CURIE)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,80 +0,0 @@
|
||||
/*
|
||||
* Circolapp
|
||||
* Copyright (C) 2019-2020 Matteo Schiff
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package net.underdesk.circolapp.server
|
||||
|
||||
import com.squareup.moshi.Moshi
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
import net.underdesk.circolapp.data.Circular
|
||||
import net.underdesk.circolapp.server.pojo.Response
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.Request
|
||||
import org.jsoup.Jsoup
|
||||
import java.io.IOException
|
||||
|
||||
class DataFetcher {
|
||||
companion object {
|
||||
const val ENDPOINT_URL = "https://www.curiepinerolo.edu.it/wp-json/wp/v2/pages/5958"
|
||||
|
||||
private val moshi = Moshi.Builder().build()
|
||||
private val responseAdapter = moshi.adapter(Response::class.java)
|
||||
private val client = OkHttpClient()
|
||||
}
|
||||
|
||||
@Throws(IOException::class)
|
||||
suspend fun getCircularsFromServer(): List<Circular> {
|
||||
return withContext(Dispatchers.Default) {
|
||||
val json = retrieveDataFromServer()
|
||||
|
||||
val document = Jsoup.parseBodyFragment(json.content.rendered)
|
||||
val htmlList = document.getElementsByTag("ul")[0].getElementsByTag("a")
|
||||
|
||||
val list = ArrayList<Circular>()
|
||||
|
||||
htmlList.forEach { element ->
|
||||
if (element.parents().size == 6) {
|
||||
list.last().attachmentsNames.add(element.text())
|
||||
list.last().attachmentsUrls.add(element.attr("href"))
|
||||
} else if (element.parents().size == 4) {
|
||||
list.add(Circular.generateFromString(element.text(), element.attr("href")))
|
||||
}
|
||||
}
|
||||
list
|
||||
}
|
||||
}
|
||||
|
||||
@Throws(IOException::class)
|
||||
private suspend fun retrieveDataFromServer(): Response {
|
||||
val request = Request.Builder()
|
||||
.url(ENDPOINT_URL)
|
||||
.build()
|
||||
|
||||
return withContext(Dispatchers.IO) {
|
||||
val response = client.newCall(request).execute()
|
||||
|
||||
if (!response.isSuccessful) {
|
||||
throw IOException("HTTP error code: ${response.code})")
|
||||
}
|
||||
|
||||
responseAdapter.fromJson(
|
||||
response.body!!.string()
|
||||
)!!
|
||||
}
|
||||
}
|
||||
}
|
||||
26
app/src/main/java/net/underdesk/circolapp/server/Server.kt
Normal file
26
app/src/main/java/net/underdesk/circolapp/server/Server.kt
Normal file
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Circolapp
|
||||
* Copyright (C) 2019-2020 Matteo Schiff
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package net.underdesk.circolapp.server
|
||||
|
||||
import net.underdesk.circolapp.data.Circular
|
||||
|
||||
abstract class Server {
|
||||
abstract suspend fun getCircularsFromServer(): Pair<List<Circular>, ServerAPI.Companion.Result>
|
||||
abstract suspend fun newCircularsAvailable(): Pair<Boolean, ServerAPI.Companion.Result>
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Circolapp
|
||||
* Copyright (C) 2019-2020 Matteo Schiff
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package net.underdesk.circolapp.server
|
||||
|
||||
import net.underdesk.circolapp.data.Circular
|
||||
import net.underdesk.circolapp.server.curie.CurieServer
|
||||
|
||||
class ServerAPI(
|
||||
private val server: Server
|
||||
) {
|
||||
suspend fun getCircularsFromServer(): Pair<List<Circular>, Result> {
|
||||
val newCircularsAvailable = server.newCircularsAvailable()
|
||||
|
||||
if (newCircularsAvailable.second == Result.ERROR)
|
||||
return Pair(emptyList(), Result.ERROR)
|
||||
|
||||
if (!newCircularsAvailable.first)
|
||||
return Pair(emptyList(), Result.SUCCESS)
|
||||
|
||||
return server.getCircularsFromServer()
|
||||
}
|
||||
|
||||
companion object {
|
||||
enum class Servers {
|
||||
CURIE, PORPORATO
|
||||
}
|
||||
|
||||
enum class Result {
|
||||
SUCCESS, ERROR
|
||||
}
|
||||
|
||||
@Volatile
|
||||
private var instance: ServerAPI? = null
|
||||
|
||||
fun getInstance(server: Servers): ServerAPI {
|
||||
return instance ?: synchronized(this) {
|
||||
instance ?: createServerAPI(server).also { instance = it }
|
||||
}
|
||||
}
|
||||
|
||||
private fun createServerAPI(server: Servers): ServerAPI {
|
||||
return when (server) {
|
||||
Servers.CURIE -> ServerAPI(CurieServer())
|
||||
Servers.PORPORATO -> TODO()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
package net.underdesk.circolapp.server.curie
|
||||
|
||||
import com.squareup.moshi.Moshi
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
import net.underdesk.circolapp.data.Circular
|
||||
import net.underdesk.circolapp.server.Server
|
||||
import net.underdesk.circolapp.server.ServerAPI
|
||||
import net.underdesk.circolapp.server.curie.pojo.Response
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.Request
|
||||
import org.jsoup.Jsoup
|
||||
import java.io.IOException
|
||||
|
||||
class CurieServer : Server() {
|
||||
private val moshi = Moshi.Builder().build()
|
||||
private val responseAdapter = moshi.adapter(Response::class.java)
|
||||
private val client = OkHttpClient()
|
||||
|
||||
override suspend fun getCircularsFromServer(): Pair<List<Circular>, ServerAPI.Companion.Result> {
|
||||
return try {
|
||||
withContext(Dispatchers.Default) {
|
||||
val json = retrieveDataFromServer()
|
||||
|
||||
val document = Jsoup.parseBodyFragment(json.content.rendered)
|
||||
val htmlList = document.getElementsByTag("ul")[0].getElementsByTag("a")
|
||||
|
||||
val list = ArrayList<Circular>()
|
||||
|
||||
htmlList.forEach { element ->
|
||||
if (element.parents().size == 6) {
|
||||
list.last().attachmentsNames.add(element.text())
|
||||
list.last().attachmentsUrls.add(element.attr("href"))
|
||||
} else if (element.parents().size == 4) {
|
||||
list.add(Circular.generateFromString(element.text(), element.attr("href")))
|
||||
}
|
||||
}
|
||||
Pair(list, ServerAPI.Companion.Result.SUCCESS)
|
||||
}
|
||||
} catch (exception: IOException) {
|
||||
Pair(emptyList(), ServerAPI.Companion.Result.ERROR)
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun newCircularsAvailable(): Pair<Boolean, ServerAPI.Companion.Result> {
|
||||
return Pair(true, ServerAPI.Companion.Result.SUCCESS)
|
||||
}
|
||||
|
||||
@Throws(IOException::class)
|
||||
private suspend fun retrieveDataFromServer(): Response {
|
||||
val request = Request.Builder()
|
||||
.url(ENDPOINT_URL)
|
||||
.build()
|
||||
|
||||
return withContext(Dispatchers.IO) {
|
||||
val response = client.newCall(request).execute()
|
||||
|
||||
if (!response.isSuccessful) {
|
||||
throw IOException("HTTP error code: ${response.code})")
|
||||
}
|
||||
|
||||
responseAdapter.fromJson(
|
||||
response.body!!.string()
|
||||
)!!
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val ENDPOINT_URL = "https://www.curiepinerolo.edu.it/wp-json/wp/v2/pages/5958"
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package net.underdesk.circolapp.server.pojo
|
||||
package net.underdesk.circolapp.server.curie.pojo
|
||||
|
||||
import com.squareup.moshi.JsonClass
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package net.underdesk.circolapp.server.pojo
|
||||
package net.underdesk.circolapp.server.curie.pojo
|
||||
|
||||
import com.squareup.moshi.JsonClass
|
||||
|
||||
@@ -36,6 +36,7 @@ import net.underdesk.circolapp.R
|
||||
import net.underdesk.circolapp.data.AppDatabase
|
||||
import net.underdesk.circolapp.data.Circular
|
||||
import net.underdesk.circolapp.data.CircularRepository
|
||||
import net.underdesk.circolapp.server.ServerAPI
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
class PollWork(appContext: Context, workerParams: WorkerParameters) :
|
||||
@@ -85,7 +86,8 @@ class PollWork(appContext: Context, workerParams: WorkerParameters) :
|
||||
|
||||
override suspend fun doWork(): Result = coroutineScope {
|
||||
val circularRepository = CircularRepository.getInstance(
|
||||
AppDatabase.getInstance(applicationContext).circularDao()
|
||||
AppDatabase.getInstance(applicationContext).circularDao(),
|
||||
ServerAPI.getInstance(ServerAPI.Companion.Servers.CURIE)
|
||||
)
|
||||
|
||||
val result = circularRepository.updateCirculars()
|
||||
|
||||
Reference in New Issue
Block a user