From 40c3352f3b17abb90744de03dd533ff8b0f33931 Mon Sep 17 00:00:00 2001 From: Matte23 Date: Fri, 23 Oct 2020 18:48:40 +0200 Subject: [PATCH] Add base code for multiple server (schools) support --- .../circolapp/data/CircularRepository.kt | 51 ++++++------ .../fragments/CircularLetterFragment.kt | 4 +- .../circolapp/fragments/FavouritesFragment.kt | 4 +- .../circolapp/fragments/RemindersFragment.kt | 4 +- .../underdesk/circolapp/server/DataFetcher.kt | 80 ------------------- .../net/underdesk/circolapp/server/Server.kt | 26 ++++++ .../underdesk/circolapp/server/ServerAPI.kt | 64 +++++++++++++++ .../circolapp/server/curie/CurieServer.kt | 71 ++++++++++++++++ .../server/{ => curie}/pojo/Content.kt | 2 +- .../server/{ => curie}/pojo/Response.kt | 2 +- .../net/underdesk/circolapp/works/PollWork.kt | 4 +- 11 files changed, 200 insertions(+), 112 deletions(-) delete mode 100644 app/src/main/java/net/underdesk/circolapp/server/DataFetcher.kt create mode 100644 app/src/main/java/net/underdesk/circolapp/server/Server.kt create mode 100644 app/src/main/java/net/underdesk/circolapp/server/ServerAPI.kt create mode 100644 app/src/main/java/net/underdesk/circolapp/server/curie/CurieServer.kt rename app/src/main/java/net/underdesk/circolapp/server/{ => curie}/pojo/Content.kt (70%) rename app/src/main/java/net/underdesk/circolapp/server/{ => curie}/pojo/Response.kt (70%) diff --git a/app/src/main/java/net/underdesk/circolapp/data/CircularRepository.kt b/app/src/main/java/net/underdesk/circolapp/data/CircularRepository.kt index d800f31..a2afb41 100644 --- a/app/src/main/java/net/underdesk/circolapp/data/CircularRepository.kt +++ b/app/src/main/java/net/underdesk/circolapp/data/CircularRepository.kt @@ -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, Boolean> { var onlyNewCirculars = listOf() - 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 } } } } diff --git a/app/src/main/java/net/underdesk/circolapp/fragments/CircularLetterFragment.kt b/app/src/main/java/net/underdesk/circolapp/fragments/CircularLetterFragment.kt index 1bf5f2a..b6bcf22 100644 --- a/app/src/main/java/net/underdesk/circolapp/fragments/CircularLetterFragment.kt +++ b/app/src/main/java/net/underdesk/circolapp/fragments/CircularLetterFragment.kt @@ -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) ) ) } diff --git a/app/src/main/java/net/underdesk/circolapp/fragments/FavouritesFragment.kt b/app/src/main/java/net/underdesk/circolapp/fragments/FavouritesFragment.kt index 1e3e335..8119769 100644 --- a/app/src/main/java/net/underdesk/circolapp/fragments/FavouritesFragment.kt +++ b/app/src/main/java/net/underdesk/circolapp/fragments/FavouritesFragment.kt @@ -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) ) ) } diff --git a/app/src/main/java/net/underdesk/circolapp/fragments/RemindersFragment.kt b/app/src/main/java/net/underdesk/circolapp/fragments/RemindersFragment.kt index eadc6fa..28b1c95 100644 --- a/app/src/main/java/net/underdesk/circolapp/fragments/RemindersFragment.kt +++ b/app/src/main/java/net/underdesk/circolapp/fragments/RemindersFragment.kt @@ -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) ) ) } diff --git a/app/src/main/java/net/underdesk/circolapp/server/DataFetcher.kt b/app/src/main/java/net/underdesk/circolapp/server/DataFetcher.kt deleted file mode 100644 index af63e78..0000000 --- a/app/src/main/java/net/underdesk/circolapp/server/DataFetcher.kt +++ /dev/null @@ -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 . - */ - -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 { - 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() - - 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() - )!! - } - } -} diff --git a/app/src/main/java/net/underdesk/circolapp/server/Server.kt b/app/src/main/java/net/underdesk/circolapp/server/Server.kt new file mode 100644 index 0000000..9fa61be --- /dev/null +++ b/app/src/main/java/net/underdesk/circolapp/server/Server.kt @@ -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 . + */ + +package net.underdesk.circolapp.server + +import net.underdesk.circolapp.data.Circular + +abstract class Server { + abstract suspend fun getCircularsFromServer(): Pair, ServerAPI.Companion.Result> + abstract suspend fun newCircularsAvailable(): Pair +} diff --git a/app/src/main/java/net/underdesk/circolapp/server/ServerAPI.kt b/app/src/main/java/net/underdesk/circolapp/server/ServerAPI.kt new file mode 100644 index 0000000..eb1e683 --- /dev/null +++ b/app/src/main/java/net/underdesk/circolapp/server/ServerAPI.kt @@ -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 . + */ + +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, 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() + } + } + } +} diff --git a/app/src/main/java/net/underdesk/circolapp/server/curie/CurieServer.kt b/app/src/main/java/net/underdesk/circolapp/server/curie/CurieServer.kt new file mode 100644 index 0000000..9f9b407 --- /dev/null +++ b/app/src/main/java/net/underdesk/circolapp/server/curie/CurieServer.kt @@ -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, 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() + + 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 { + 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" + } +} diff --git a/app/src/main/java/net/underdesk/circolapp/server/pojo/Content.kt b/app/src/main/java/net/underdesk/circolapp/server/curie/pojo/Content.kt similarity index 70% rename from app/src/main/java/net/underdesk/circolapp/server/pojo/Content.kt rename to app/src/main/java/net/underdesk/circolapp/server/curie/pojo/Content.kt index 1d14914..79fe93f 100644 --- a/app/src/main/java/net/underdesk/circolapp/server/pojo/Content.kt +++ b/app/src/main/java/net/underdesk/circolapp/server/curie/pojo/Content.kt @@ -1,4 +1,4 @@ -package net.underdesk.circolapp.server.pojo +package net.underdesk.circolapp.server.curie.pojo import com.squareup.moshi.JsonClass diff --git a/app/src/main/java/net/underdesk/circolapp/server/pojo/Response.kt b/app/src/main/java/net/underdesk/circolapp/server/curie/pojo/Response.kt similarity index 70% rename from app/src/main/java/net/underdesk/circolapp/server/pojo/Response.kt rename to app/src/main/java/net/underdesk/circolapp/server/curie/pojo/Response.kt index c42c418..08ce81b 100644 --- a/app/src/main/java/net/underdesk/circolapp/server/pojo/Response.kt +++ b/app/src/main/java/net/underdesk/circolapp/server/curie/pojo/Response.kt @@ -1,4 +1,4 @@ -package net.underdesk.circolapp.server.pojo +package net.underdesk.circolapp.server.curie.pojo import com.squareup.moshi.JsonClass diff --git a/app/src/main/java/net/underdesk/circolapp/works/PollWork.kt b/app/src/main/java/net/underdesk/circolapp/works/PollWork.kt index 1563d46..08216bb 100644 --- a/app/src/main/java/net/underdesk/circolapp/works/PollWork.kt +++ b/app/src/main/java/net/underdesk/circolapp/works/PollWork.kt @@ -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()