mirror of
https://github.com/szkolny-eu/szkolny-android.git
synced 2024-11-24 19:04:38 -06:00
[APIv2] Simplify endpoint choosing. Optimize imports.
This commit is contained in:
parent
b35df5ef11
commit
bdc0ceb11d
@ -0,0 +1,80 @@
|
|||||||
|
package pl.szczodrzynski.edziennik.api.v2
|
||||||
|
|
||||||
|
import pl.szczodrzynski.edziennik.api.v2.models.Data
|
||||||
|
import pl.szczodrzynski.edziennik.api.v2.models.Feature
|
||||||
|
import pl.szczodrzynski.edziennik.api.v2.models.LoginMethod
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.modules.api.EndpointTimer
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.modules.api.SYNC_ALWAYS
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.modules.api.SYNC_NEVER
|
||||||
|
|
||||||
|
fun Data.prepare(loginMethods: List<LoginMethod>, features: List<Feature>, featureIds: List<Int>, viewId: Int?) {
|
||||||
|
val data = this
|
||||||
|
|
||||||
|
val possibleLoginMethods = data.loginMethods.toMutableList()
|
||||||
|
|
||||||
|
for (loginMethod in loginMethods) {
|
||||||
|
if (loginMethod.isPossible(profile, loginStore))
|
||||||
|
possibleLoginMethods += loginMethod.loginMethodId
|
||||||
|
}
|
||||||
|
|
||||||
|
//var highestLoginMethod = 0
|
||||||
|
var endpointList = mutableListOf<Feature>()
|
||||||
|
val requiredLoginMethods = mutableListOf<Int>()
|
||||||
|
|
||||||
|
data.targetEndpointIds.clear()
|
||||||
|
data.targetLoginMethodIds.clear()
|
||||||
|
|
||||||
|
// get all endpoints for every feature, only if possible to login and possible/necessary to sync
|
||||||
|
for (featureId in featureIds) {
|
||||||
|
features.filter {
|
||||||
|
it.featureId == featureId // feature ID matches
|
||||||
|
&& possibleLoginMethods.containsAll(it.requiredLoginMethods) // is possible to login
|
||||||
|
&& it.shouldSync?.invoke(data) ?: true // is necessary/possible to sync
|
||||||
|
}.let {
|
||||||
|
endpointList.addAll(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val timestamp = System.currentTimeMillis()
|
||||||
|
|
||||||
|
endpointList = endpointList
|
||||||
|
// sort the endpoint list by feature ID and priority
|
||||||
|
.sortedWith(compareBy(Feature::featureId, Feature::priority))
|
||||||
|
// select only the most important endpoint for each feature
|
||||||
|
.distinctBy { it.featureId }
|
||||||
|
.toMutableList()
|
||||||
|
// add all endpoint IDs and required login methods, filtering using timers
|
||||||
|
.onEach { feature ->
|
||||||
|
feature.endpointIds.forEach { endpoint ->
|
||||||
|
(data.endpointTimers
|
||||||
|
.singleOrNull { it.endpointId == endpoint.first } ?: EndpointTimer(data.profile?.id ?: -1, endpoint.first))
|
||||||
|
.let { timer ->
|
||||||
|
if (timer.nextSync == SYNC_ALWAYS ||
|
||||||
|
(viewId != null && timer.viewId == viewId) ||
|
||||||
|
(timer.nextSync != SYNC_NEVER && timer.nextSync < timestamp)) {
|
||||||
|
data.targetEndpointIds.add(endpoint.first)
|
||||||
|
requiredLoginMethods.add(endpoint.second)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// check every login method for any dependencies
|
||||||
|
for (loginMethodId in requiredLoginMethods) {
|
||||||
|
var requiredLoginMethod: Int? = loginMethodId
|
||||||
|
while (requiredLoginMethod != LOGIN_METHOD_NOT_NEEDED) {
|
||||||
|
loginMethods.singleOrNull { it.loginMethodId == requiredLoginMethod }?.let { loginMethod ->
|
||||||
|
if (requiredLoginMethod != null)
|
||||||
|
data.targetLoginMethodIds.add(requiredLoginMethod!!)
|
||||||
|
requiredLoginMethod = loginMethod.requiredLoginMethod(data.profile, data.loginStore)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// sort and distinct every login method and endpoint
|
||||||
|
data.targetLoginMethodIds = data.targetLoginMethodIds.toHashSet().toMutableList()
|
||||||
|
data.targetLoginMethodIds.sort()
|
||||||
|
|
||||||
|
data.targetEndpointIds = data.targetEndpointIds.toHashSet().toMutableList()
|
||||||
|
data.targetEndpointIds.sort()
|
||||||
|
}
|
@ -7,18 +7,16 @@ package pl.szczodrzynski.edziennik.api.v2.librus
|
|||||||
import android.util.Log
|
import android.util.Log
|
||||||
import pl.szczodrzynski.edziennik.App
|
import pl.szczodrzynski.edziennik.App
|
||||||
import pl.szczodrzynski.edziennik.api.v2.CODE_INTERNAL_LIBRUS_ACCOUNT_410
|
import pl.szczodrzynski.edziennik.api.v2.CODE_INTERNAL_LIBRUS_ACCOUNT_410
|
||||||
import pl.szczodrzynski.edziennik.api.v2.LOGIN_METHOD_NOT_NEEDED
|
|
||||||
import pl.szczodrzynski.edziennik.api.v2.interfaces.EdziennikCallback
|
import pl.szczodrzynski.edziennik.api.v2.interfaces.EdziennikCallback
|
||||||
import pl.szczodrzynski.edziennik.api.v2.interfaces.EdziennikInterface
|
import pl.szczodrzynski.edziennik.api.v2.interfaces.EdziennikInterface
|
||||||
import pl.szczodrzynski.edziennik.api.v2.librus.data.LibrusData
|
import pl.szczodrzynski.edziennik.api.v2.librus.data.LibrusData
|
||||||
import pl.szczodrzynski.edziennik.api.v2.librus.login.LibrusLogin
|
import pl.szczodrzynski.edziennik.api.v2.librus.login.LibrusLogin
|
||||||
import pl.szczodrzynski.edziennik.api.v2.librusLoginMethods
|
import pl.szczodrzynski.edziennik.api.v2.librusLoginMethods
|
||||||
import pl.szczodrzynski.edziennik.api.v2.mobidziennik.MobidziennikFeatures
|
|
||||||
import pl.szczodrzynski.edziennik.api.v2.models.ApiError
|
import pl.szczodrzynski.edziennik.api.v2.models.ApiError
|
||||||
import pl.szczodrzynski.edziennik.api.v2.models.Feature
|
import pl.szczodrzynski.edziennik.api.v2.prepare
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.api.*
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.login.LoginStore
|
import pl.szczodrzynski.edziennik.data.db.modules.login.LoginStore
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.profiles.Profile
|
import pl.szczodrzynski.edziennik.data.db.modules.profiles.Profile
|
||||||
|
import pl.szczodrzynski.edziennik.utils.Utils
|
||||||
|
|
||||||
class Librus(val app: App, val profile: Profile?, val loginStore: LoginStore, val callback: EdziennikCallback) : EdziennikInterface {
|
class Librus(val app: App, val profile: Profile?, val loginStore: LoginStore, val callback: EdziennikCallback) : EdziennikInterface {
|
||||||
companion object {
|
companion object {
|
||||||
@ -27,13 +25,12 @@ class Librus(val app: App, val profile: Profile?, val loginStore: LoginStore, va
|
|||||||
|
|
||||||
val internalErrorList = mutableListOf<Int>()
|
val internalErrorList = mutableListOf<Int>()
|
||||||
val data: DataLibrus
|
val data: DataLibrus
|
||||||
private var cancelled = false
|
|
||||||
|
|
||||||
init {
|
init {
|
||||||
data = DataLibrus(app, profile, loginStore).apply {
|
data = DataLibrus(app, profile, loginStore).apply {
|
||||||
callback = wrapCallback(this@Librus.callback)
|
callback = wrapCallback(this@Librus.callback)
|
||||||
|
satisfyLoginMethods()
|
||||||
}
|
}
|
||||||
data.satisfyLoginMethods()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun completed() {
|
private fun completed() {
|
||||||
@ -50,77 +47,9 @@ class Librus(val app: App, val profile: Profile?, val loginStore: LoginStore, va
|
|||||||
__/ |
|
__/ |
|
||||||
|__*/
|
|__*/
|
||||||
override fun sync(featureIds: List<Int>, viewId: Int?) {
|
override fun sync(featureIds: List<Int>, viewId: Int?) {
|
||||||
val possibleLoginMethods = data.loginMethods.toMutableList()
|
data.prepare(librusLoginMethods, LibrusFeatures, featureIds, viewId)
|
||||||
|
|
||||||
for (loginMethod in librusLoginMethods) {
|
|
||||||
if (loginMethod.isPossible(profile, loginStore))
|
|
||||||
possibleLoginMethods += loginMethod.loginMethodId
|
|
||||||
}
|
|
||||||
|
|
||||||
//var highestLoginMethod = 0
|
|
||||||
var endpointList = mutableListOf<Feature>()
|
|
||||||
val requiredLoginMethods = mutableListOf<Int>()
|
|
||||||
|
|
||||||
data.targetEndpointIds.clear()
|
|
||||||
data.targetLoginMethodIds.clear()
|
|
||||||
|
|
||||||
// get all endpoints for every feature, only if possible to login and possible/necessary to sync
|
|
||||||
for (featureId in featureIds) {
|
|
||||||
LibrusFeatures.filter {
|
|
||||||
it.featureId == featureId // feature ID matches
|
|
||||||
&& possibleLoginMethods.containsAll(it.requiredLoginMethods) // is possible to login
|
|
||||||
&& it.shouldSync?.invoke(data) ?: true // is necessary/possible to sync
|
|
||||||
}.let {
|
|
||||||
endpointList.addAll(it)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val timestamp = System.currentTimeMillis()
|
|
||||||
|
|
||||||
endpointList = endpointList
|
|
||||||
// sort the endpoint list by feature ID and priority
|
|
||||||
.sortedWith(compareBy(Feature::featureId, Feature::priority))
|
|
||||||
// select only the most important endpoint for each feature
|
|
||||||
.distinctBy { it.featureId }
|
|
||||||
.toMutableList()
|
|
||||||
// add all endpoint IDs and required login methods, filtering using timers
|
|
||||||
.onEach { feature ->
|
|
||||||
feature.endpointIds.forEach { endpoint ->
|
|
||||||
(data.endpointTimers
|
|
||||||
.singleOrNull { it.endpointId == endpoint.first } ?: EndpointTimer(data.profile?.id ?: -1, endpoint.first))
|
|
||||||
.let { timer ->
|
|
||||||
if (timer.nextSync == SYNC_ALWAYS ||
|
|
||||||
(viewId != null && timer.viewId == viewId) ||
|
|
||||||
(timer.nextSync != SYNC_NEVER && timer.nextSync < timestamp)) {
|
|
||||||
data.targetEndpointIds.add(endpoint.first)
|
|
||||||
requiredLoginMethods.add(endpoint.second)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// check every login method for any dependencies
|
|
||||||
for (loginMethodId in requiredLoginMethods) {
|
|
||||||
var requiredLoginMethod: Int? = loginMethodId
|
|
||||||
while (requiredLoginMethod != LOGIN_METHOD_NOT_NEEDED) {
|
|
||||||
librusLoginMethods.singleOrNull { it.loginMethodId == requiredLoginMethod }?.let { loginMethod ->
|
|
||||||
if (requiredLoginMethod != null)
|
|
||||||
data.targetLoginMethodIds.add(requiredLoginMethod!!)
|
|
||||||
requiredLoginMethod = loginMethod.requiredLoginMethod(data.profile, data.loginStore)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// sort and distinct every login method and endpoint
|
|
||||||
data.targetLoginMethodIds = data.targetLoginMethodIds.toHashSet().toMutableList()
|
|
||||||
data.targetLoginMethodIds.sort()
|
|
||||||
|
|
||||||
data.targetEndpointIds = data.targetEndpointIds.toHashSet().toMutableList()
|
|
||||||
data.targetEndpointIds.sort()
|
|
||||||
|
|
||||||
Log.d(TAG, "LoginMethod IDs: ${data.targetLoginMethodIds}")
|
Log.d(TAG, "LoginMethod IDs: ${data.targetLoginMethodIds}")
|
||||||
Log.d(TAG, "Endpoint IDs: ${data.targetEndpointIds}")
|
Log.d(TAG, "Endpoint IDs: ${data.targetEndpointIds}")
|
||||||
|
|
||||||
LibrusLogin(data) {
|
LibrusLogin(data) {
|
||||||
LibrusData(data) {
|
LibrusData(data) {
|
||||||
completed()
|
completed()
|
||||||
@ -137,6 +66,7 @@ class Librus(val app: App, val profile: Profile?, val loginStore: LoginStore, va
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun cancel() {
|
override fun cancel() {
|
||||||
|
Utils.d(TAG, "Cancelled")
|
||||||
data.cancel()
|
data.cancel()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,17 +6,14 @@ package pl.szczodrzynski.edziennik.api.v2.mobidziennik
|
|||||||
|
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import pl.szczodrzynski.edziennik.App
|
import pl.szczodrzynski.edziennik.App
|
||||||
import pl.szczodrzynski.edziennik.api.v2.*
|
import pl.szczodrzynski.edziennik.api.v2.CODE_INTERNAL_LIBRUS_ACCOUNT_410
|
||||||
import pl.szczodrzynski.edziennik.api.v2.interfaces.EdziennikCallback
|
import pl.szczodrzynski.edziennik.api.v2.interfaces.EdziennikCallback
|
||||||
import pl.szczodrzynski.edziennik.api.v2.interfaces.EdziennikInterface
|
import pl.szczodrzynski.edziennik.api.v2.interfaces.EdziennikInterface
|
||||||
import pl.szczodrzynski.edziennik.api.v2.librus.LibrusFeatures
|
|
||||||
import pl.szczodrzynski.edziennik.api.v2.mobidziennik.data.MobidziennikData
|
import pl.szczodrzynski.edziennik.api.v2.mobidziennik.data.MobidziennikData
|
||||||
import pl.szczodrzynski.edziennik.api.v2.mobidziennik.login.MobidziennikLogin
|
import pl.szczodrzynski.edziennik.api.v2.mobidziennik.login.MobidziennikLogin
|
||||||
|
import pl.szczodrzynski.edziennik.api.v2.mobidziennikLoginMethods
|
||||||
import pl.szczodrzynski.edziennik.api.v2.models.ApiError
|
import pl.szczodrzynski.edziennik.api.v2.models.ApiError
|
||||||
import pl.szczodrzynski.edziennik.api.v2.models.Feature
|
import pl.szczodrzynski.edziennik.api.v2.prepare
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.api.EndpointTimer
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.api.SYNC_ALWAYS
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.api.SYNC_NEVER
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.login.LoginStore
|
import pl.szczodrzynski.edziennik.data.db.modules.login.LoginStore
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.profiles.Profile
|
import pl.szczodrzynski.edziennik.data.db.modules.profiles.Profile
|
||||||
import pl.szczodrzynski.edziennik.utils.Utils
|
import pl.szczodrzynski.edziennik.utils.Utils
|
||||||
@ -28,13 +25,12 @@ class Mobidziennik(val app: App, val profile: Profile?, val loginStore: LoginSto
|
|||||||
|
|
||||||
val internalErrorList = mutableListOf<Int>()
|
val internalErrorList = mutableListOf<Int>()
|
||||||
val data: DataMobidziennik
|
val data: DataMobidziennik
|
||||||
private var cancelled = false
|
|
||||||
|
|
||||||
init {
|
init {
|
||||||
data = DataMobidziennik(app, profile, loginStore).apply {
|
data = DataMobidziennik(app, profile, loginStore).apply {
|
||||||
callback = wrapCallback(this@Mobidziennik.callback)
|
callback = wrapCallback(this@Mobidziennik.callback)
|
||||||
|
satisfyLoginMethods()
|
||||||
}
|
}
|
||||||
data.satisfyLoginMethods()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun completed() {
|
private fun completed() {
|
||||||
@ -51,77 +47,9 @@ class Mobidziennik(val app: App, val profile: Profile?, val loginStore: LoginSto
|
|||||||
__/ |
|
__/ |
|
||||||
|__*/
|
|__*/
|
||||||
override fun sync(featureIds: List<Int>, viewId: Int?) {
|
override fun sync(featureIds: List<Int>, viewId: Int?) {
|
||||||
val possibleLoginMethods = data.loginMethods.toMutableList()
|
data.prepare(mobidziennikLoginMethods, MobidziennikFeatures, featureIds, viewId)
|
||||||
|
|
||||||
for (loginMethod in mobidziennikLoginMethods) {
|
|
||||||
if (loginMethod.isPossible(profile, loginStore))
|
|
||||||
possibleLoginMethods += loginMethod.loginMethodId
|
|
||||||
}
|
|
||||||
|
|
||||||
//var highestLoginMethod = 0
|
|
||||||
var endpointList = mutableListOf<Feature>()
|
|
||||||
val requiredLoginMethods = mutableListOf<Int>()
|
|
||||||
|
|
||||||
data.targetEndpointIds.clear()
|
|
||||||
data.targetLoginMethodIds.clear()
|
|
||||||
|
|
||||||
// get all endpoints for every feature, only if possible to login and possible/necessary to sync
|
|
||||||
for (featureId in featureIds) {
|
|
||||||
MobidziennikFeatures.filter {
|
|
||||||
it.featureId == featureId // feature ID matches
|
|
||||||
&& possibleLoginMethods.containsAll(it.requiredLoginMethods) // is possible to login
|
|
||||||
&& it.shouldSync?.invoke(data) ?: true // is necessary/possible to sync
|
|
||||||
}.let {
|
|
||||||
endpointList.addAll(it)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val timestamp = System.currentTimeMillis()
|
|
||||||
|
|
||||||
endpointList = endpointList
|
|
||||||
// sort the endpoint list by feature ID and priority
|
|
||||||
.sortedWith(compareBy(Feature::featureId, Feature::priority))
|
|
||||||
// select only the most important endpoint for each feature
|
|
||||||
.distinctBy { it.featureId }
|
|
||||||
.toMutableList()
|
|
||||||
// add all endpoint IDs and required login methods, filtering using timers
|
|
||||||
.onEach { feature ->
|
|
||||||
feature.endpointIds.forEach { endpoint ->
|
|
||||||
(data.endpointTimers
|
|
||||||
.singleOrNull { it.endpointId == endpoint.first } ?: EndpointTimer(data.profile?.id ?: -1, endpoint.first))
|
|
||||||
.let { timer ->
|
|
||||||
if (timer.nextSync == SYNC_ALWAYS ||
|
|
||||||
(viewId != null && timer.viewId == viewId) ||
|
|
||||||
(timer.nextSync != SYNC_NEVER && timer.nextSync < timestamp)) {
|
|
||||||
data.targetEndpointIds.add(endpoint.first)
|
|
||||||
requiredLoginMethods.add(endpoint.second)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// check every login method for any dependencies
|
|
||||||
for (loginMethodId in requiredLoginMethods) {
|
|
||||||
var requiredLoginMethod: Int? = loginMethodId
|
|
||||||
while (requiredLoginMethod != LOGIN_METHOD_NOT_NEEDED) {
|
|
||||||
mobidziennikLoginMethods.singleOrNull { it.loginMethodId == requiredLoginMethod }?.let { loginMethod ->
|
|
||||||
if (requiredLoginMethod != null)
|
|
||||||
data.targetLoginMethodIds.add(requiredLoginMethod!!)
|
|
||||||
requiredLoginMethod = loginMethod.requiredLoginMethod(data.profile, data.loginStore)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// sort and distinct every login method and endpoint
|
|
||||||
data.targetLoginMethodIds = data.targetLoginMethodIds.toHashSet().toMutableList()
|
|
||||||
data.targetLoginMethodIds.sort()
|
|
||||||
|
|
||||||
data.targetEndpointIds = data.targetEndpointIds.toHashSet().toMutableList()
|
|
||||||
data.targetEndpointIds.sort()
|
|
||||||
|
|
||||||
Log.d(TAG, "LoginMethod IDs: ${data.targetLoginMethodIds}")
|
Log.d(TAG, "LoginMethod IDs: ${data.targetLoginMethodIds}")
|
||||||
Log.d(TAG, "Endpoint IDs: ${data.targetEndpointIds}")
|
Log.d(TAG, "Endpoint IDs: ${data.targetEndpointIds}")
|
||||||
|
|
||||||
MobidziennikLogin(data) {
|
MobidziennikLogin(data) {
|
||||||
MobidziennikData(data) {
|
MobidziennikData(data) {
|
||||||
completed()
|
completed()
|
||||||
@ -139,7 +67,7 @@ class Mobidziennik(val app: App, val profile: Profile?, val loginStore: LoginSto
|
|||||||
|
|
||||||
override fun cancel() {
|
override fun cancel() {
|
||||||
Utils.d(TAG, "Cancelled")
|
Utils.d(TAG, "Cancelled")
|
||||||
cancelled = true
|
data.cancel()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun wrapCallback(callback: EdziennikCallback): EdziennikCallback {
|
private fun wrapCallback(callback: EdziennikCallback): EdziennikCallback {
|
||||||
|
@ -2,7 +2,6 @@ package pl.szczodrzynski.edziennik.api.v2.models
|
|||||||
|
|
||||||
import android.util.LongSparseArray
|
import android.util.LongSparseArray
|
||||||
import android.util.SparseArray
|
import android.util.SparseArray
|
||||||
import androidx.core.util.isNotEmpty
|
|
||||||
import com.google.gson.JsonObject
|
import com.google.gson.JsonObject
|
||||||
import im.wangchao.mhttp.Response
|
import im.wangchao.mhttp.Response
|
||||||
import pl.szczodrzynski.edziennik.App
|
import pl.szczodrzynski.edziennik.App
|
||||||
@ -84,18 +83,6 @@ open class Data(val app: App, val profile: Profile?, val loginStore: LoginStore)
|
|||||||
*/
|
*/
|
||||||
var endpointArgs = mutableMapOf<Int, JsonObject>()
|
var endpointArgs = mutableMapOf<Int, JsonObject>()
|
||||||
|
|
||||||
/**
|
|
||||||
* A list of per-endpoint next sync time descriptors.
|
|
||||||
*
|
|
||||||
* [EndpointTimer.nextSync] may be:
|
|
||||||
* - [pl.szczodrzynski.edziennik.data.db.modules.api.SYNC_NEVER] to never sync the endpoint (pretty useless)
|
|
||||||
* - [pl.szczodrzynski.edziennik.data.db.modules.api.SYNC_ALWAYS] to sync the endpoint during every sync
|
|
||||||
* - [pl.szczodrzynski.edziennik.data.db.modules.api.SYNC_IF_EXPLICIT] to sync the endpoint only if the matching
|
|
||||||
* feature ID is in the input set
|
|
||||||
* - [pl.szczodrzynski.edziennik.data.db.modules.api.SYNC_IF_EXPLICIT_OR_ALL] to sync if the matching feature ID
|
|
||||||
* is in the input set OR the sync covers all feature IDs
|
|
||||||
* - a Unix-epoch timestamp (in millis) to sync the endpoint if [System.currentTimeMillis] is greater or equal to this value
|
|
||||||
*/
|
|
||||||
var endpointTimers = mutableListOf<EndpointTimer>()
|
var endpointTimers = mutableListOf<EndpointTimer>()
|
||||||
|
|
||||||
val teacherList = LongSparseArray<Teacher>()
|
val teacherList = LongSparseArray<Teacher>()
|
||||||
@ -148,9 +135,7 @@ open class Data(val app: App, val profile: Profile?, val loginStore: LoginStore)
|
|||||||
val db by lazy { app.db }
|
val db by lazy { app.db }
|
||||||
|
|
||||||
init {
|
init {
|
||||||
|
|
||||||
clear()
|
clear()
|
||||||
|
|
||||||
if (profile != null) {
|
if (profile != null) {
|
||||||
endpointTimers = db.endpointTimerDao().getAllNow(profile.id).toMutableList()
|
endpointTimers = db.endpointTimerDao().getAllNow(profile.id).toMutableList()
|
||||||
db.teacherDao().getAllNow(profileId).toSparseArray(teacherList) { it.id }
|
db.teacherDao().getAllNow(profileId).toSparseArray(teacherList) { it.id }
|
||||||
@ -159,11 +144,6 @@ open class Data(val app: App, val profile: Profile?, val loginStore: LoginStore)
|
|||||||
db.lessonRangeDao().getAllNow(profileId).toSparseArray(lessonRanges) { it.lessonNumber }
|
db.lessonRangeDao().getAllNow(profileId).toSparseArray(lessonRanges) { it.lessonNumber }
|
||||||
db.gradeCategoryDao().getAllNow(profileId).toSparseArray(gradeCategories) { it.categoryId }
|
db.gradeCategoryDao().getAllNow(profileId).toSparseArray(gradeCategories) { it.categoryId }
|
||||||
}
|
}
|
||||||
|
|
||||||
/*val teacher = teachers.byNameFirstLast("Jan Kowalski") ?: Teacher(1, 1, "", "").let {
|
|
||||||
teachers.add(it)
|
|
||||||
}*/
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun clear() {
|
fun clear() {
|
||||||
|
@ -7,19 +7,13 @@ package pl.szczodrzynski.edziennik.api.v2.template
|
|||||||
import android.util.Log
|
import android.util.Log
|
||||||
import pl.szczodrzynski.edziennik.App
|
import pl.szczodrzynski.edziennik.App
|
||||||
import pl.szczodrzynski.edziennik.api.v2.CODE_INTERNAL_LIBRUS_ACCOUNT_410
|
import pl.szczodrzynski.edziennik.api.v2.CODE_INTERNAL_LIBRUS_ACCOUNT_410
|
||||||
import pl.szczodrzynski.edziennik.api.v2.LOGIN_METHOD_NOT_NEEDED
|
|
||||||
import pl.szczodrzynski.edziennik.api.v2.interfaces.EdziennikCallback
|
import pl.szczodrzynski.edziennik.api.v2.interfaces.EdziennikCallback
|
||||||
import pl.szczodrzynski.edziennik.api.v2.interfaces.EdziennikInterface
|
import pl.szczodrzynski.edziennik.api.v2.interfaces.EdziennikInterface
|
||||||
import pl.szczodrzynski.edziennik.api.v2.librus.LibrusFeatures
|
|
||||||
import pl.szczodrzynski.edziennik.api.v2.models.ApiError
|
import pl.szczodrzynski.edziennik.api.v2.models.ApiError
|
||||||
import pl.szczodrzynski.edziennik.api.v2.models.Feature
|
import pl.szczodrzynski.edziennik.api.v2.prepare
|
||||||
import pl.szczodrzynski.edziennik.api.v2.template.data.TemplateData
|
import pl.szczodrzynski.edziennik.api.v2.template.data.TemplateData
|
||||||
import pl.szczodrzynski.edziennik.api.v2.template.login.TemplateLogin
|
import pl.szczodrzynski.edziennik.api.v2.template.login.TemplateLogin
|
||||||
import pl.szczodrzynski.edziennik.api.v2.templateLoginMethods
|
import pl.szczodrzynski.edziennik.api.v2.templateLoginMethods
|
||||||
import pl.szczodrzynski.edziennik.api.v2.vulcan.VulcanFeatures
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.api.EndpointTimer
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.api.SYNC_ALWAYS
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.api.SYNC_NEVER
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.login.LoginStore
|
import pl.szczodrzynski.edziennik.data.db.modules.login.LoginStore
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.profiles.Profile
|
import pl.szczodrzynski.edziennik.data.db.modules.profiles.Profile
|
||||||
import pl.szczodrzynski.edziennik.utils.Utils
|
import pl.szczodrzynski.edziennik.utils.Utils
|
||||||
@ -31,13 +25,12 @@ class Template(val app: App, val profile: Profile?, val loginStore: LoginStore,
|
|||||||
|
|
||||||
val internalErrorList = mutableListOf<Int>()
|
val internalErrorList = mutableListOf<Int>()
|
||||||
val data: DataTemplate
|
val data: DataTemplate
|
||||||
private var cancelled = false
|
|
||||||
|
|
||||||
init {
|
init {
|
||||||
data = DataTemplate(app, profile, loginStore).apply {
|
data = DataTemplate(app, profile, loginStore).apply {
|
||||||
callback = wrapCallback(this@Template.callback)
|
callback = wrapCallback(this@Template.callback)
|
||||||
|
satisfyLoginMethods()
|
||||||
}
|
}
|
||||||
data.satisfyLoginMethods()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun completed() {
|
private fun completed() {
|
||||||
@ -54,77 +47,9 @@ class Template(val app: App, val profile: Profile?, val loginStore: LoginStore,
|
|||||||
__/ |
|
__/ |
|
||||||
|__*/
|
|__*/
|
||||||
override fun sync(featureIds: List<Int>, viewId: Int?) {
|
override fun sync(featureIds: List<Int>, viewId: Int?) {
|
||||||
val possibleLoginMethods = data.loginMethods.toMutableList()
|
data.prepare(templateLoginMethods, TemplateFeatures, featureIds, viewId)
|
||||||
|
|
||||||
for (loginMethod in templateLoginMethods) {
|
|
||||||
if (loginMethod.isPossible(profile, loginStore))
|
|
||||||
possibleLoginMethods += loginMethod.loginMethodId
|
|
||||||
}
|
|
||||||
|
|
||||||
//var highestLoginMethod = 0
|
|
||||||
var endpointList = mutableListOf<Feature>()
|
|
||||||
val requiredLoginMethods = mutableListOf<Int>()
|
|
||||||
|
|
||||||
data.targetEndpointIds.clear()
|
|
||||||
data.targetLoginMethodIds.clear()
|
|
||||||
|
|
||||||
// get all endpoints for every feature, only if possible to login and possible/necessary to sync
|
|
||||||
for (featureId in featureIds) {
|
|
||||||
VulcanFeatures.filter {
|
|
||||||
it.featureId == featureId // feature ID matches
|
|
||||||
&& possibleLoginMethods.containsAll(it.requiredLoginMethods) // is possible to login
|
|
||||||
&& it.shouldSync?.invoke(data) ?: true // is necessary/possible to sync
|
|
||||||
}.let {
|
|
||||||
endpointList.addAll(it)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val timestamp = System.currentTimeMillis()
|
|
||||||
|
|
||||||
endpointList = endpointList
|
|
||||||
// sort the endpoint list by feature ID and priority
|
|
||||||
.sortedWith(compareBy(Feature::featureId, Feature::priority))
|
|
||||||
// select only the most important endpoint for each feature
|
|
||||||
.distinctBy { it.featureId }
|
|
||||||
.toMutableList()
|
|
||||||
// add all endpoint IDs and required login methods, filtering using timers
|
|
||||||
.onEach { feature ->
|
|
||||||
feature.endpointIds.forEach { endpoint ->
|
|
||||||
(data.endpointTimers
|
|
||||||
.singleOrNull { it.endpointId == endpoint.first } ?: EndpointTimer(data.profile?.id ?: -1, endpoint.first))
|
|
||||||
.let { timer ->
|
|
||||||
if (timer.nextSync == SYNC_ALWAYS ||
|
|
||||||
(viewId != null && timer.viewId == viewId) ||
|
|
||||||
(timer.nextSync != SYNC_NEVER && timer.nextSync < timestamp)) {
|
|
||||||
data.targetEndpointIds.add(endpoint.first)
|
|
||||||
requiredLoginMethods.add(endpoint.second)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// check every login method for any dependencies
|
|
||||||
for (loginMethodId in requiredLoginMethods) {
|
|
||||||
var requiredLoginMethod: Int? = loginMethodId
|
|
||||||
while (requiredLoginMethod != LOGIN_METHOD_NOT_NEEDED) {
|
|
||||||
templateLoginMethods.singleOrNull { it.loginMethodId == requiredLoginMethod }?.let { loginMethod ->
|
|
||||||
if (requiredLoginMethod != null)
|
|
||||||
data.targetLoginMethodIds.add(requiredLoginMethod!!)
|
|
||||||
requiredLoginMethod = loginMethod.requiredLoginMethod(data.profile, data.loginStore)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// sort and distinct every login method and endpoint
|
|
||||||
data.targetLoginMethodIds = data.targetLoginMethodIds.toHashSet().toMutableList()
|
|
||||||
data.targetLoginMethodIds.sort()
|
|
||||||
|
|
||||||
data.targetEndpointIds = data.targetEndpointIds.toHashSet().toMutableList()
|
|
||||||
data.targetEndpointIds.sort()
|
|
||||||
|
|
||||||
Log.d(TAG, "LoginMethod IDs: ${data.targetLoginMethodIds}")
|
Log.d(TAG, "LoginMethod IDs: ${data.targetLoginMethodIds}")
|
||||||
Log.d(TAG, "Endpoint IDs: ${data.targetEndpointIds}")
|
Log.d(TAG, "Endpoint IDs: ${data.targetEndpointIds}")
|
||||||
|
|
||||||
TemplateLogin(data) {
|
TemplateLogin(data) {
|
||||||
TemplateData(data) {
|
TemplateData(data) {
|
||||||
completed()
|
completed()
|
||||||
@ -142,7 +67,7 @@ class Template(val app: App, val profile: Profile?, val loginStore: LoginStore,
|
|||||||
|
|
||||||
override fun cancel() {
|
override fun cancel() {
|
||||||
Utils.d(TAG, "Cancelled")
|
Utils.d(TAG, "Cancelled")
|
||||||
cancelled = true
|
data.cancel()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun wrapCallback(callback: EdziennikCallback): EdziennikCallback {
|
private fun wrapCallback(callback: EdziennikCallback): EdziennikCallback {
|
||||||
|
@ -7,18 +7,13 @@ package pl.szczodrzynski.edziennik.api.v2.vulcan
|
|||||||
import android.util.Log
|
import android.util.Log
|
||||||
import pl.szczodrzynski.edziennik.App
|
import pl.szczodrzynski.edziennik.App
|
||||||
import pl.szczodrzynski.edziennik.api.v2.CODE_INTERNAL_LIBRUS_ACCOUNT_410
|
import pl.szczodrzynski.edziennik.api.v2.CODE_INTERNAL_LIBRUS_ACCOUNT_410
|
||||||
import pl.szczodrzynski.edziennik.api.v2.LOGIN_METHOD_NOT_NEEDED
|
|
||||||
import pl.szczodrzynski.edziennik.api.v2.interfaces.EdziennikCallback
|
import pl.szczodrzynski.edziennik.api.v2.interfaces.EdziennikCallback
|
||||||
import pl.szczodrzynski.edziennik.api.v2.interfaces.EdziennikInterface
|
import pl.szczodrzynski.edziennik.api.v2.interfaces.EdziennikInterface
|
||||||
import pl.szczodrzynski.edziennik.api.v2.librus.LibrusFeatures
|
|
||||||
import pl.szczodrzynski.edziennik.api.v2.models.ApiError
|
import pl.szczodrzynski.edziennik.api.v2.models.ApiError
|
||||||
import pl.szczodrzynski.edziennik.api.v2.models.Feature
|
import pl.szczodrzynski.edziennik.api.v2.prepare
|
||||||
import pl.szczodrzynski.edziennik.api.v2.vulcan.data.VulcanData
|
import pl.szczodrzynski.edziennik.api.v2.vulcan.data.VulcanData
|
||||||
import pl.szczodrzynski.edziennik.api.v2.vulcan.login.VulcanLogin
|
import pl.szczodrzynski.edziennik.api.v2.vulcan.login.VulcanLogin
|
||||||
import pl.szczodrzynski.edziennik.api.v2.vulcanLoginMethods
|
import pl.szczodrzynski.edziennik.api.v2.vulcanLoginMethods
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.api.EndpointTimer
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.api.SYNC_ALWAYS
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.api.SYNC_NEVER
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.login.LoginStore
|
import pl.szczodrzynski.edziennik.data.db.modules.login.LoginStore
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.profiles.Profile
|
import pl.szczodrzynski.edziennik.data.db.modules.profiles.Profile
|
||||||
import pl.szczodrzynski.edziennik.utils.Utils
|
import pl.szczodrzynski.edziennik.utils.Utils
|
||||||
@ -30,13 +25,12 @@ class Vulcan(val app: App, val profile: Profile?, val loginStore: LoginStore, va
|
|||||||
|
|
||||||
val internalErrorList = mutableListOf<Int>()
|
val internalErrorList = mutableListOf<Int>()
|
||||||
val data: DataVulcan
|
val data: DataVulcan
|
||||||
private var cancelled = false
|
|
||||||
|
|
||||||
init {
|
init {
|
||||||
data = DataVulcan(app, profile, loginStore).apply {
|
data = DataVulcan(app, profile, loginStore).apply {
|
||||||
callback = wrapCallback(this@Vulcan.callback)
|
callback = wrapCallback(this@Vulcan.callback)
|
||||||
|
satisfyLoginMethods()
|
||||||
}
|
}
|
||||||
data.satisfyLoginMethods()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun completed() {
|
private fun completed() {
|
||||||
@ -53,77 +47,9 @@ class Vulcan(val app: App, val profile: Profile?, val loginStore: LoginStore, va
|
|||||||
__/ |
|
__/ |
|
||||||
|__*/
|
|__*/
|
||||||
override fun sync(featureIds: List<Int>, viewId: Int?) {
|
override fun sync(featureIds: List<Int>, viewId: Int?) {
|
||||||
val possibleLoginMethods = data.loginMethods.toMutableList()
|
data.prepare(vulcanLoginMethods, VulcanFeatures, featureIds, viewId)
|
||||||
|
|
||||||
for (loginMethod in vulcanLoginMethods) {
|
|
||||||
if (loginMethod.isPossible(profile, loginStore))
|
|
||||||
possibleLoginMethods += loginMethod.loginMethodId
|
|
||||||
}
|
|
||||||
|
|
||||||
//var highestLoginMethod = 0
|
|
||||||
var endpointList = mutableListOf<Feature>()
|
|
||||||
val requiredLoginMethods = mutableListOf<Int>()
|
|
||||||
|
|
||||||
data.targetEndpointIds.clear()
|
|
||||||
data.targetLoginMethodIds.clear()
|
|
||||||
|
|
||||||
// get all endpoints for every feature, only if possible to login and possible/necessary to sync
|
|
||||||
for (featureId in featureIds) {
|
|
||||||
VulcanFeatures.filter {
|
|
||||||
it.featureId == featureId // feature ID matches
|
|
||||||
&& possibleLoginMethods.containsAll(it.requiredLoginMethods) // is possible to login
|
|
||||||
&& it.shouldSync?.invoke(data) ?: true // is necessary/possible to sync
|
|
||||||
}.let {
|
|
||||||
endpointList.addAll(it)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val timestamp = System.currentTimeMillis()
|
|
||||||
|
|
||||||
endpointList = endpointList
|
|
||||||
// sort the endpoint list by feature ID and priority
|
|
||||||
.sortedWith(compareBy(Feature::featureId, Feature::priority))
|
|
||||||
// select only the most important endpoint for each feature
|
|
||||||
.distinctBy { it.featureId }
|
|
||||||
.toMutableList()
|
|
||||||
// add all endpoint IDs and required login methods, filtering using timers
|
|
||||||
.onEach { feature ->
|
|
||||||
feature.endpointIds.forEach { endpoint ->
|
|
||||||
(data.endpointTimers
|
|
||||||
.singleOrNull { it.endpointId == endpoint.first } ?: EndpointTimer(data.profile?.id ?: -1, endpoint.first))
|
|
||||||
.let { timer ->
|
|
||||||
if (timer.nextSync == SYNC_ALWAYS ||
|
|
||||||
(viewId != null && timer.viewId == viewId) ||
|
|
||||||
(timer.nextSync != SYNC_NEVER && timer.nextSync < timestamp)) {
|
|
||||||
data.targetEndpointIds.add(endpoint.first)
|
|
||||||
requiredLoginMethods.add(endpoint.second)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// check every login method for any dependencies
|
|
||||||
for (loginMethodId in requiredLoginMethods) {
|
|
||||||
var requiredLoginMethod: Int? = loginMethodId
|
|
||||||
while (requiredLoginMethod != LOGIN_METHOD_NOT_NEEDED) {
|
|
||||||
vulcanLoginMethods.singleOrNull { it.loginMethodId == requiredLoginMethod }?.let { loginMethod ->
|
|
||||||
if (requiredLoginMethod != null)
|
|
||||||
data.targetLoginMethodIds.add(requiredLoginMethod!!)
|
|
||||||
requiredLoginMethod = loginMethod.requiredLoginMethod(data.profile, data.loginStore)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// sort and distinct every login method and endpoint
|
|
||||||
data.targetLoginMethodIds = data.targetLoginMethodIds.toHashSet().toMutableList()
|
|
||||||
data.targetLoginMethodIds.sort()
|
|
||||||
|
|
||||||
data.targetEndpointIds = data.targetEndpointIds.toHashSet().toMutableList()
|
|
||||||
data.targetEndpointIds.sort()
|
|
||||||
|
|
||||||
Log.d(TAG, "LoginMethod IDs: ${data.targetLoginMethodIds}")
|
Log.d(TAG, "LoginMethod IDs: ${data.targetLoginMethodIds}")
|
||||||
Log.d(TAG, "Endpoint IDs: ${data.targetEndpointIds}")
|
Log.d(TAG, "Endpoint IDs: ${data.targetEndpointIds}")
|
||||||
|
|
||||||
VulcanLogin(data) {
|
VulcanLogin(data) {
|
||||||
VulcanData(data) {
|
VulcanData(data) {
|
||||||
completed()
|
completed()
|
||||||
@ -141,7 +67,7 @@ class Vulcan(val app: App, val profile: Profile?, val loginStore: LoginStore, va
|
|||||||
|
|
||||||
override fun cancel() {
|
override fun cancel() {
|
||||||
Utils.d(TAG, "Cancelled")
|
Utils.d(TAG, "Cancelled")
|
||||||
cancelled = true
|
data.cancel()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun wrapCallback(callback: EdziennikCallback): EdziennikCallback {
|
private fun wrapCallback(callback: EdziennikCallback): EdziennikCallback {
|
||||||
|
Loading…
Reference in New Issue
Block a user