Initiated CSV auto custom field mapping

csv
Laurent 6 years ago
parent fa9b6317fd
commit 36f52b6681
  1. 41
      app/src/main/java/net/pokeranalytics/android/util/csv/CSVDescriptor.kt
  2. 14
      app/src/main/java/net/pokeranalytics/android/util/csv/CSVField.kt
  3. 9
      app/src/main/java/net/pokeranalytics/android/util/csv/CSVImporter.kt
  4. 11
      app/src/main/java/net/pokeranalytics/android/util/csv/ProductCSVDescriptors.kt
  5. 22
      app/src/main/java/net/pokeranalytics/android/util/csv/SessionField.kt

@ -4,6 +4,7 @@ import io.realm.Realm
import io.realm.kotlin.deleteFromRealm
import net.pokeranalytics.android.model.interfaces.Identifiable
import net.pokeranalytics.android.model.interfaces.ObjectIdentifier
import net.pokeranalytics.android.model.realm.CustomField
import net.pokeranalytics.android.model.realm.Session
import net.pokeranalytics.android.util.extensions.findById
import org.apache.commons.csv.CSVRecord
@ -26,7 +27,7 @@ abstract class DataCSVDescriptor<T : Identifiable>(source: DataSource, vararg el
/**
* List of Realm object identificators
*/
val realmModelIds = mutableListOf<ObjectIdentifier>()
private val realmModelIds = mutableListOf<ObjectIdentifier>()
abstract fun parseData(realm: Realm, record: CSVRecord): T?
@ -83,29 +84,19 @@ abstract class CSVDescriptor(var source: DataSource, vararg elements: CSVField)
/**
* The CSVField list describing the CSV header format
*/
protected var fields: List<CSVField> = listOf()
protected var fields: MutableList<CSVField> = mutableListOf()
/**
* The mapping of CSVField with their index in the CSV file
*/
protected var fieldMapping: MutableMap<CSVField, Int> = mutableMapOf()
init {
if (elements.size > 0) {
this.fields = elements.toList()
if (elements.isNotEmpty()) {
this.fields = elements.toMutableList()
}
}
companion object {
/**
* The list of all managed CSVDescriptors
*/
val all: List<CSVDescriptor> =
listOf(ProductCSVDescriptors.pokerIncomeCash,
ProductCSVDescriptors.pokerBankrollTracker,
ProductCSVDescriptors.runGoodCashGames,
ProductCSVDescriptors.runGoodTournaments)
}
/**
* Method called when iterating on a CSVRecord
*/
@ -140,4 +131,24 @@ abstract class CSVDescriptor(var source: DataSource, vararg elements: CSVField)
return count >= mandatoryfields.size
}
fun mapCustomField(record: CSVRecord, realm: Realm) {
val customFields = realm.where(CustomField::class.java).findAll()
val headers = record.toSet()
headers.forEach { header ->
val customField = customFields.firstOrNull { it.name == header }
customField?.let {
if (it.isListType) {
} else {
val f = MappedCustomCVSField.Number(header, null, "", it)
fields.add(f)
}
}
}
}
}

@ -1,5 +1,7 @@
package net.pokeranalytics.android.util.csv
import net.pokeranalytics.android.model.realm.CustomField
import net.pokeranalytics.android.model.realm.CustomFieldEntry
import timber.log.Timber
import java.text.DateFormat
import java.text.NumberFormat
@ -82,6 +84,18 @@ interface BlindCSVField : TypedCSVField<Pair<Double, Double>> {
}
interface CustomEntryCSVField : TypedCSVField<CustomFieldEntry>, CustomCSVField {
}
interface CustomNumberCSVField : NumberCSVField, CustomCSVField {
}
interface CustomCSVField {
var customField: CustomField
}
interface TypedCSVField<T> : CSVField {
fun parse(value: String) : T?
var callback: ((String) -> T?)?

@ -36,10 +36,12 @@ open class CSVImporter(istream: InputStream) {
* Number of commits required to commit a Realm transaction
*/
private val COMMIT_FREQUENCY = 100
/**
* The number of column indicating a valid record
*/
private val VALID_RECORD_COLUMNS = 4
/**
* The number of valid record to test for descriptor before throwing a File Format Exception
*/
@ -111,7 +113,7 @@ open class CSVImporter(istream: InputStream) {
this.notifyDelegate()
if (this.currentDescriptor == null) { // find descriptor
this.currentDescriptor = this.findDescriptor(record)
this.currentDescriptor = this.findDescriptor(record, realm)
if (this.currentDescriptor == null) {
@ -174,10 +176,11 @@ open class CSVImporter(istream: InputStream) {
/**
* Search for a descriptor in the list of managed formats
*/
private fun findDescriptor(record: CSVRecord): CSVDescriptor? {
private fun findDescriptor(record: CSVRecord, realm: Realm): CSVDescriptor? {
CSVDescriptor.all.forEach { descriptor ->
ProductCSVDescriptors.all.forEach { descriptor ->
if (descriptor.matches(record)) {
descriptor.mapCustomField(record, realm)
this.currentDescriptor = descriptor
Timber.d("Identified source: ${descriptor.source}")
return descriptor

@ -4,6 +4,17 @@ class ProductCSVDescriptors {
companion object {
/**
* The list of all managed CSVDescriptors
*/
val all: List<CSVDescriptor> =
listOf(
ProductCSVDescriptors.pokerIncomeCash,
ProductCSVDescriptors.pokerBankrollTracker,
ProductCSVDescriptors.runGoodCashGames,
ProductCSVDescriptors.runGoodTournaments
)
val pokerIncomeCash: CSVDescriptor = SessionCSVDescriptor(
DataSource.POKER_INCOME,
false,

@ -1,7 +1,29 @@
package net.pokeranalytics.android.util.csv
import net.pokeranalytics.android.model.realm.CustomField
import net.pokeranalytics.android.model.realm.CustomFieldEntry
import java.util.*
sealed class MappedCustomCVSField {
data class Number(
override var header: String,
override var callback: ((String) -> Double?)? = null,
override val numberFormat: String?,
override var customField: CustomField) : CustomNumberCSVField
data class List(
override var header: String,
override var callback: ((String) -> CustomFieldEntry?)? = null,
override var customField: CustomField) : CustomEntryCSVField {
override fun parse(value: String): CustomFieldEntry? {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
}
}
sealed class TransactionField {
data class TransactionType(

Loading…
Cancel
Save