/
TaxonomiesManager.kt
113 lines (100 loc) 路 4.52 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
113
package openfoodfacts.github.scrachx.openfood.repositories
import android.content.Context
import android.util.Log
import dagger.hilt.android.qualifiers.ApplicationContext
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Dispatchers.IO
import kotlinx.coroutines.withContext
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 suspend fun <T> getLastModifiedDateFromServer(taxonomy: Taxonomy<T>) = withContext(IO) {
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::class.simpleName}.", e)
lastModifiedDate = TAXONOMY_NO_INTERNET
}
Log.i(LOG_TAG, "Last modified date for taxonomy \"$taxonomy\" is $lastModifiedDate")
return@withContext 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
*/
suspend fun <T> getTaxonomyData(
taxonomy: Taxonomy<T>,
checkUpdate: Boolean,
dao: AbstractDao<T, *>,
productRepository: ProductRepository
): List<T> = withContext(Dispatchers.Default) {
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.getDownloadActivatePreferencesId(), false)
if (!isTaxonomyActivated) return@withContext 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
val empty = dao.isEmpty()
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.getLastDownloadTimeStampPreferenceId(), 0L)
// We need to check for update. Test if file on server is more recent than last download.
checkAndDownloadIfNewer(taxonomy, localDownloadTime, productRepository)
} else emptyList()
}
private suspend fun <T> download(
taxonomy: Taxonomy<T>,
productRepository: ProductRepository
) = withContext(IO) {
val lastMod = getLastModifiedDateFromServer(taxonomy)
return@withContext if (lastMod != TAXONOMY_NO_INTERNET)
taxonomy.load(productRepository, lastMod).also { logDownload(taxonomy) }
else emptyList()
}
private suspend fun <T> checkAndDownloadIfNewer(
taxonomy: Taxonomy<T>,
localDownloadTime: Long,
productRepository: ProductRepository
) = withContext(IO) {
val lastModRemote = getLastModifiedDateFromServer(taxonomy)
if (lastModRemote == 0L || lastModRemote > localDownloadTime)
taxonomy.load(productRepository, lastModRemote).also { logDownload(taxonomy) }
else emptyList()
}
companion object {
private const val TAXONOMY_NO_INTERNET = -9999L
private val LOG_TAG = TaxonomiesManager::class.simpleName
}
}