Skip to content

Commit

Permalink
Merge branch 'release/0.0.3'
Browse files Browse the repository at this point in the history
  • Loading branch information
sgrimault committed Jun 27, 2019
2 parents 5fb8e2b + f6bfe90 commit cd4d309
Show file tree
Hide file tree
Showing 32 changed files with 1,038 additions and 360 deletions.
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.

buildscript {
ext.kotlin_version = '1.3.31'
ext.kotlin_version = '1.3.40'

repositories {
google()
Expand Down
11 changes: 9 additions & 2 deletions commons/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,16 @@ apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'

version = "0.0.7"
version = "0.1.2"

android {
compileSdkVersion 28

compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}

defaultConfig {
minSdkVersion 21
targetSdkVersion 28
Expand Down Expand Up @@ -40,8 +45,10 @@ dependencies {
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.2.1"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.2.1"

implementation 'com.google.android.material:material:1.0.0'
implementation 'androidx.appcompat:appcompat:1.1.0-beta01'
api 'androidx.room:room-runtime:2.1.0-rc01'
implementation 'androidx.preference:preference:1.0.0'
api 'androidx.room:room-runtime:2.1.0'

testImplementation 'junit:junit:4.12'
testImplementation 'androidx.test:core:1.2.0'
Expand Down
38 changes: 25 additions & 13 deletions commons/src/main/java/fr/geonature/commons/input/InputManager.kt
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
package fr.geonature.commons.input

import android.app.Application
import android.preference.PreferenceManager
import androidx.preference.PreferenceManager
import fr.geonature.commons.input.io.InputJsonReader
import fr.geonature.commons.input.io.InputJsonWriter
import fr.geonature.commons.util.FileUtils
import fr.geonature.commons.util.StringUtils
import fr.geonature.commons.util.StringUtils.isEmpty
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Dispatchers.IO
import kotlinx.coroutines.coroutineScope
Expand All @@ -24,13 +24,24 @@ import java.io.Writer
*
* @author [S. Grimault](mailto:[email protected])
*/
class InputManager(private val application: Application,
inputJsonReaderListener: InputJsonReader.OnInputJsonReaderListener,
inputJsonWriterListener: InputJsonWriter.OnInputJsonWriterListener) {
class InputManager<T : AbstractInput>(private val application: Application,
inputJsonReaderListener: InputJsonReader.OnInputJsonReaderListener<T>,
inputJsonWriterListener: InputJsonWriter.OnInputJsonWriterListener<T>) {

private val preferenceManager = PreferenceManager.getDefaultSharedPreferences(application)
private val inputJsonReader: InputJsonReader = InputJsonReader(inputJsonReaderListener)
private val inputJsonWriter: InputJsonWriter = InputJsonWriter(inputJsonWriterListener)
private val inputJsonReader: InputJsonReader<T> = InputJsonReader(inputJsonReaderListener)
private val inputJsonWriter: InputJsonWriter<T> = InputJsonWriter(inputJsonWriterListener)

/**
* Reads all [AbstractInput]s.
*
* @return A list of [AbstractInput]s
*/
suspend fun readInputs(): List<T> = withContext(IO) {
preferenceManager.all.filterKeys { it.startsWith("${KEY_PREFERENCE_INPUT}_") }
.values.mapNotNull { if (it is String && !isEmpty(it)) inputJsonReader.read(it) else null }
.sortedBy { it.id }
}

/**
* Reads [AbstractInput] from given ID.
Expand All @@ -39,14 +50,14 @@ class InputManager(private val application: Application,
*
* @return [AbstractInput] or `null` if not found
*/
suspend fun readInput(id: Long? = null): AbstractInput? = withContext(IO) {
suspend fun readInput(id: Long? = null): T? = withContext(IO) {
val inputPreferenceKey =
buildInputPreferenceKey(id ?: preferenceManager.getLong(KEY_PREFERENCE_CURRENT_INPUT,
0))
val inputAsJson = preferenceManager.getString(inputPreferenceKey,
null)

if (StringUtils.isEmpty(inputAsJson)) {
if (isEmpty(inputAsJson)) {
return@withContext null
}

Expand All @@ -58,7 +69,7 @@ class InputManager(private val application: Application,
*
* @return [AbstractInput] or `null` if not found
*/
suspend fun readCurrentInput(): AbstractInput? {
suspend fun readCurrentInput(): T? {
return readInput()
}

Expand All @@ -67,10 +78,10 @@ class InputManager(private val application: Application,
*
* @return `true` if the given [AbstractInput] has been successfully saved, `false` otherwise
*/
suspend fun saveInput(input: AbstractInput): Boolean = withContext(IO) {
suspend fun saveInput(input: T): Boolean = withContext(IO) {
val inputAsJson = inputJsonWriter.write(input)

if (StringUtils.isEmpty(inputAsJson)) return@withContext false
if (isEmpty(inputAsJson)) return@withContext false

preferenceManager.edit()
.putString(buildInputPreferenceKey(input.id),
Expand Down Expand Up @@ -111,7 +122,8 @@ class InputManager(private val application: Application,
* @return `true` if the given [AbstractInput] has been successfully exported, `false` otherwise
*/
suspend fun exportInput(id: Long): Boolean = coroutineScope {
val inputToExport = withContext(Dispatchers.Default) { readInput(id) } ?: return@coroutineScope false
val inputToExport =
withContext(Dispatchers.Default) { readInput(id) } ?: return@coroutineScope false

val exported = withContext(IO) {
inputJsonWriter.write(getInputExportWriter(inputToExport),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import java.io.StringReader
*
* @see InputJsonWriter
*/
class InputJsonReader(private val onInputJsonReaderListener: OnInputJsonReaderListener) {
class InputJsonReader<T : AbstractInput>(private val onInputJsonReaderListener: OnInputJsonReaderListener<T>) {

/**
* parse a `JSON` string to convert as [AbstractInput].
Expand All @@ -24,7 +24,7 @@ class InputJsonReader(private val onInputJsonReaderListener: OnInputJsonReaderLi
* @return a [AbstractInput] instance from the `JSON` string or `null` if something goes wrong
* @see .read
*/
fun read(json: String?): AbstractInput? {
fun read(json: String?): T? {
if (StringUtils.isEmpty(json)) {
return null
}
Expand All @@ -48,7 +48,7 @@ class InputJsonReader(private val onInputJsonReaderListener: OnInputJsonReaderLi
* @throws IOException if something goes wrong
*/
@Throws(IOException::class)
fun read(reader: Reader): AbstractInput {
fun read(reader: Reader): T {
val jsonReader = JsonReader(reader)
val input = readInput(jsonReader)
jsonReader.close()
Expand All @@ -57,7 +57,7 @@ class InputJsonReader(private val onInputJsonReaderListener: OnInputJsonReaderLi
}

@Throws(IOException::class)
private fun readInput(reader: JsonReader): AbstractInput {
private fun readInput(reader: JsonReader): T {
val input = onInputJsonReaderListener.createInput()

reader.beginObject()
Expand All @@ -77,20 +77,19 @@ class InputJsonReader(private val onInputJsonReaderListener: OnInputJsonReaderLi
return input
}


/**
* Callback used by [InputJsonReader].
*
* @author [S. Grimault](mailto:[email protected])
*/
interface OnInputJsonReaderListener {
interface OnInputJsonReaderListener<T : AbstractInput> {

/**
* Returns a new instance of [AbstractInput].
*
* @return new instance of [AbstractInput]
*/
fun createInput(): AbstractInput
fun createInput(): T

/**
* Reading some additional data to set to the given [AbstractInput].
Expand All @@ -103,7 +102,7 @@ class InputJsonReader(private val onInputJsonReaderListener: OnInputJsonReaderLi
@Throws(IOException::class)
fun readAdditionalInputData(reader: JsonReader,
keyName: String,
input: AbstractInput)
input: T)
}

companion object {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import java.io.Writer
* @author [S. Grimault](mailto:[email protected])
* @see InputJsonReader
*/
class InputJsonWriter(private val onInputJsonWriterListener: OnInputJsonWriterListener) {
class InputJsonWriter<T : AbstractInput>(private val onInputJsonWriterListener: OnInputJsonWriterListener<T>) {

private var indent: String = ""

Expand All @@ -26,7 +26,7 @@ class InputJsonWriter(private val onInputJsonWriterListener: OnInputJsonWriterLi
*
* @return InputJsonWriter fluent interface
*/
fun setIndent(indent: String): InputJsonWriter {
fun setIndent(indent: String): InputJsonWriter<T> {
this.indent = indent

return this
Expand All @@ -39,7 +39,7 @@ class InputJsonWriter(private val onInputJsonWriterListener: OnInputJsonWriterLi
* @return a `JSON` string representation of the given [AbstractInput] or `null` if something goes wrong
* @see .write
*/
fun write(input: AbstractInput?): String? {
fun write(input: T?): String? {
if (input == null) {
return null
}
Expand Down Expand Up @@ -69,7 +69,7 @@ class InputJsonWriter(private val onInputJsonWriterListener: OnInputJsonWriterLi
*/
@Throws(IOException::class)
fun write(out: Writer,
input: AbstractInput) {
input: T) {
val writer = JsonWriter(out)
writer.setIndent(this.indent)
writeInput(writer,
Expand All @@ -80,7 +80,7 @@ class InputJsonWriter(private val onInputJsonWriterListener: OnInputJsonWriterLi

@Throws(IOException::class)
private fun writeInput(writer: JsonWriter,
input: AbstractInput) {
input: T) {
writer.beginObject()

writer.name("id")
Expand All @@ -99,7 +99,7 @@ class InputJsonWriter(private val onInputJsonWriterListener: OnInputJsonWriterLi
*
* @author [S. Grimault](mailto:[email protected])
*/
interface OnInputJsonWriterListener {
interface OnInputJsonWriterListener<T : AbstractInput> {

/**
* Adding some additional data to write from the current [AbstractInput].
Expand All @@ -110,7 +110,7 @@ class InputJsonWriter(private val onInputJsonWriterListener: OnInputJsonWriterLi
*/
@Throws(IOException::class)
fun writeAdditionalInputData(writer: JsonWriter,
input: AbstractInput)
input: T)
}

companion object {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package fr.geonature.commons.settings

import android.app.Application
import android.util.Log
import fr.geonature.commons.model.MountPoint.StorageType.INTERNAL
import fr.geonature.commons.settings.io.AppSettingsJsonReader
import fr.geonature.commons.util.FileUtils.getFile
import fr.geonature.commons.util.FileUtils.getRootFolder
import kotlinx.coroutines.Dispatchers.IO
import kotlinx.coroutines.Dispatchers.Main
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.io.File
import java.io.FileReader
import java.io.IOException

/**
* Manage [IAppSettings].
* - Read [IAppSettings] from `JSON` file
*
* @author [S. Grimault](mailto:[email protected])
*/
class AppSettingsManager<T : IAppSettings>(private val application: Application,
onAppSettingsJsonJsonReaderListener: AppSettingsJsonReader.OnAppSettingsJsonReaderListener<T>) {

private val appSettingsJsonReader: AppSettingsJsonReader<T> =
AppSettingsJsonReader(onAppSettingsJsonJsonReaderListener)

init {
GlobalScope.launch(Main) {
withContext(IO) {
getRootFolder(application,
INTERNAL).mkdirs()
}
}
}

fun getAppSettingsFilename(): String {
val packageName = application.packageName

return "settings_${packageName.substring(packageName.lastIndexOf('.') + 1)}.json"
}

/**
* Loads [IAppSettings] from `JSON` file.
*
* @return [IAppSettings] or `null` if not found
*/
suspend fun loadAppSettings(): T? = withContext(IO) {
val settingsJsonFile = getAppSettingsAsFile()

if (!settingsJsonFile.exists()) {
Log.w(TAG,
"'${settingsJsonFile.absolutePath}' not found")
null
}
else {
try {
appSettingsJsonReader.read(FileReader(settingsJsonFile))
}
catch (e: IOException) {
Log.w(TAG,
"Failed to load '${settingsJsonFile.name}'")

null
}
}
}

internal fun getAppSettingsAsFile(): File {
return getFile(getRootFolder(application,
INTERNAL),
getAppSettingsFilename())
}

companion object {
private val TAG = AppSettingsManager::class.java.name
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package fr.geonature.commons.settings

import android.os.Parcelable

/**
* Global internal settings.
*
* @author [S. Grimault](mailto:[email protected])
*/
interface IAppSettings : Parcelable
Loading

0 comments on commit cd4d309

Please sign in to comment.