/
TaxonomiesManager.kt
112 lines (100 loc) 路 4.57 KB
/
TaxonomiesManager.kt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
package openfoodfacts.github.scrachx.openfood.repositories
import android.content.Context
import android.util.Log
import dagger.hilt.android.qualifiers.ApplicationContext
import io.reactivex.Single
import openfoodfacts.github.scrachx.openfood.BuildConfig
import openfoodfacts.github.scrachx.openfood.utils.Utils
import openfoodfacts.github.scrachx.openfood.utils.isEmpty
import openfoodfacts.github.scrachx.openfood.utils.logDownload
import org.greenrobot.greendao.AbstractDao
import java.io.IOException
import java.net.HttpURLConnection
import java.net.URL
import javax.inject.Inject
import javax.inject.Singleton
@Singleton
class TaxonomiesManager @Inject constructor(
@ApplicationContext private val context: Context
) {
/**
* Get the last modified date of the taxonomy.json file on the server.
*
* @param taxonomy The taxonomy to check
* @return The timestamp of the last changes date of the taxonomy.json on the server
* or [TAXONOMY_NO_INTERNET] if there is no connection to the server.
*/
private fun getLastModifiedDateFromServer(taxonomy: Taxonomy): Single<Long> = Single.fromCallable {
var lastModifiedDate: Long
val taxoUrl = URL(BuildConfig.OFWEBSITE + taxonomy.jsonUrl)
try {
val httpCon = taxoUrl.openConnection() as HttpURLConnection
lastModifiedDate = httpCon.lastModified
httpCon.disconnect()
} catch (e: IOException) {
// Problem
Log.e(LOG_TAG, "Could not get last modified date from server for taxonomy ${taxonomy.name}.", e)
lastModifiedDate = TAXONOMY_NO_INTERNET
}
Log.i(LOG_TAG, "Last modified date for taxonomy \"$taxonomy\" is $lastModifiedDate")
return@fromCallable lastModifiedDate
}
/**
* @param taxonomy
* @param checkUpdate defines if the source of data must be refresh from server if it has been update there.
*
* * If checkUpdate is true (or local database is empty) then load it from the server,
* * else from the local database.
*
* @param dao used to check if locale data is empty
*/
fun <T> getTaxonomyData(
taxonomy: Taxonomy,
checkUpdate: Boolean,
dao: AbstractDao<T, *>,
productRepository: ProductRepository
): Single<List<T>> {
// WARNING: Before "return" all code is executed on MAIN THREAD
val mSettings = context.getSharedPreferences("prefs", 0)
// First check if this taxonomy is to be loaded for this flavor, else return empty list
val isTaxonomyActivated = mSettings.getBoolean(taxonomy.downloadActivatePreferencesId, false)
if (!isTaxonomyActivated) {
return Single.just(emptyList())
}
// If the database scheme changed, this settings should be true
val forceUpdate = mSettings.getBoolean(Utils.FORCE_REFRESH_TAXONOMIES, false)
// If database is empty or we have to force update, download it
return Single.fromCallable { dao.isEmpty() }.flatMap { empty ->
if (empty || forceUpdate) {
// Table is empty, no need check for update, just load taxonomy
download(taxonomy, productRepository)
} else if (checkUpdate) {
// Get local last downloaded time
val localDownloadTime = mSettings.getLong(taxonomy.lastDownloadTimeStampPreferenceId, 0L)
// We need to check for update. Test if file on server is more recent than last download.
checkAndDownloadIfNewer(taxonomy, localDownloadTime, productRepository)
} else Single.just(emptyList())
}
}
private fun <T> download(
taxonomy: Taxonomy,
productRepository: ProductRepository
): Single<List<T>> = getLastModifiedDateFromServer(taxonomy).flatMap { lastMod ->
if (lastMod != TAXONOMY_NO_INTERNET)
logDownload(taxonomy.load(productRepository, lastMod), taxonomy)
else Single.just(emptyList())
}
private fun <T> checkAndDownloadIfNewer(
taxonomy: Taxonomy,
localDownloadTime: Long,
productRepository: ProductRepository
): Single<List<T>> = getLastModifiedDateFromServer(taxonomy).flatMap { lastModRemote ->
if (lastModRemote == 0L || lastModRemote > localDownloadTime)
logDownload(taxonomy.load(productRepository, lastModRemote), taxonomy)
else Single.just(emptyList())
}
companion object {
private const val TAXONOMY_NO_INTERNET = -9999L
private val LOG_TAG = TaxonomiesManager::class.simpleName
}
}