diff --git a/app/src/main/java/net/pokeranalytics/android/model/filter/Filterable.kt b/app/src/main/java/net/pokeranalytics/android/model/filter/Filterable.kt index 3625acca..afa66436 100644 --- a/app/src/main/java/net/pokeranalytics/android/model/filter/Filterable.kt +++ b/app/src/main/java/net/pokeranalytics/android/model/filter/Filterable.kt @@ -1,6 +1,7 @@ package net.pokeranalytics.android.model.filter -import io.realm.RealmObject +import io.realm.RealmModel +import net.pokeranalytics.android.model.realm.Session /** * We want to be able to store filters in the database: @@ -28,15 +29,37 @@ import io.realm.RealmObject * */ +class UnmanagedFilterField(message: String) : Exception(message) { + +} /** * Companion-level Interface to indicate an RealmObject class can be filtered and to provide all the fieldNames (eg: parameter's path) needed to be query on. */ -interface Filterable { +interface Filterable : RealmModel { /** * return the path of the parameter used in the [QueryType] related to this entity */ fun fieldNameForQueryType(queryType: QueryType) : String? + + +} + +class FilterHelper { + + companion object { + + inline fun fieldNameForQueryType(queryType: QueryType) : String? { + when (T::class) { + is Session -> { + Session.fieldNameForQueryType(queryType) + } + } + throw UnmanagedFilterField("Filterable type fields are not defined") + } + + } + } // diff --git a/app/src/main/java/net/pokeranalytics/android/model/filter/QueryType.kt b/app/src/main/java/net/pokeranalytics/android/model/filter/QueryType.kt index 2ba40ed6..403f2b57 100644 --- a/app/src/main/java/net/pokeranalytics/android/model/filter/QueryType.kt +++ b/app/src/main/java/net/pokeranalytics/android/model/filter/QueryType.kt @@ -1,12 +1,10 @@ package net.pokeranalytics.android.model.filter import io.realm.RealmList -import io.realm.RealmObject import io.realm.RealmQuery import net.pokeranalytics.android.exceptions.FilterValueMapException -import net.pokeranalytics.android.model.realm.FilterElementBlind import net.pokeranalytics.android.model.realm.FilterElement -import net.pokeranalytics.android.model.realm.Session +import net.pokeranalytics.android.model.realm.FilterElementBlind import java.util.* @@ -16,7 +14,7 @@ import java.util.* * To handle that, the enum has a public [valueMap] variable * A new type should also set the expected numericValues required in the [filterValuesExpectedKeys] */ -enum class QueryType(private var subType:SubType? = null) { +enum class QueryType(var subType:SubType? = null) { LIVE, CASH, ONLINE, @@ -68,7 +66,7 @@ enum class QueryType(private var subType:SubType? = null) { ; - private enum class SubType { + enum class SubType { BETWEEN, MORE, LESS; @@ -98,18 +96,19 @@ enum class QueryType(private var subType:SubType? = null) { * main method of the enum * providing a base RealmQuery [realmQuery], the method is able to attached the corresponding query and returns the newly formed [RealmQuery] */ - fun filter(realmQuery: RealmQuery, filterable: Filterable): RealmQuery { + inline fun filter(realmQuery: RealmQuery): RealmQuery { when { this == BLINDS -> { - val smallBlindFieldName = filterable.fieldNameForQueryType(SMALL_BLIND) - val bigBlindFieldName = filterable.fieldNameForQueryType(BIG_BLIND) - val currencyCodeFieldName = filterable.fieldNameForQueryType(CURRENCY_CODE) + + val smallBlindFieldName = FilterHelper.fieldNameForQueryType(queryType = SMALL_BLIND) + val bigBlindFieldName = FilterHelper.fieldNameForQueryType(queryType = BIG_BLIND) + val currencyCodeFieldName = FilterHelper.fieldNameForQueryType(CURRENCY_CODE) smallBlindFieldName ?: throw FilterValueMapException("fieldName is missing") bigBlindFieldName ?: throw FilterValueMapException("fieldName is missing") currencyCodeFieldName ?: throw FilterValueMapException("fieldName is missing") val blinds: RealmList by valueMap - blinds.forEachIndexed {index, blind -> + blinds.forEachIndexed { index, blind -> realmQuery .beginGroup() @@ -137,11 +136,8 @@ enum class QueryType(private var subType:SubType? = null) { } return realmQuery } - this == ONLINE -> return LIVE.filter(realmQuery.not(), filterable) - this == TOURNAMENT -> return CASH.filter(realmQuery.not(), filterable) - this == WEEK_DAY -> return WEEK_END.filter(realmQuery.not(), filterable) else -> { - val fieldName = filterable.fieldNameForQueryType(this) + val fieldName = FilterHelper.fieldNameForQueryType(this) fieldName ?: throw FilterValueMapException("fieldName is missing") this.subType?.let { subType -> @@ -163,8 +159,8 @@ enum class QueryType(private var subType:SubType? = null) { } return when (this) { - LIVE -> realmQuery.equalTo(fieldName, true) - CASH -> realmQuery.equalTo(fieldName, Session.Type.CASH_GAME.ordinal) + LIVE, ONLINE -> realmQuery.equalTo(fieldName, this == LIVE) + CASH, TOURNAMENT -> realmQuery.equalTo(fieldName, this.ordinal) ALL_TOURNAMENT_FEATURES -> { val ids: Array by valueMap ids.forEach { @@ -212,8 +208,10 @@ enum class QueryType(private var subType:SubType? = null) { val year: Int by valueMap realmQuery.equalTo(fieldName, year) } - WEEK_END -> { - realmQuery.`in`(fieldName, arrayOf(Calendar.SATURDAY, Calendar.SUNDAY)) + WEEK_END, WEEK_DAY -> { + var query = realmQuery.`in`(fieldName, arrayOf(Calendar.SATURDAY, Calendar.SUNDAY)) + if (this == WEEK_DAY) { query.not() } + query } else -> { throw FilterValueMapException("filter type not handled") diff --git a/app/src/main/java/net/pokeranalytics/android/model/realm/Filter.kt b/app/src/main/java/net/pokeranalytics/android/model/realm/Filter.kt index 8fb6ad60..a41ca77b 100644 --- a/app/src/main/java/net/pokeranalytics/android/model/realm/Filter.kt +++ b/app/src/main/java/net/pokeranalytics/android/model/realm/Filter.kt @@ -2,7 +2,7 @@ package net.pokeranalytics.android.model.realm import io.realm.* import io.realm.annotations.PrimaryKey -import net.pokeranalytics.android.exceptions.FilterMissingEntityException +import io.realm.kotlin.where import net.pokeranalytics.android.exceptions.FilterUnhandledEntityException import net.pokeranalytics.android.model.filter.Filterable import net.pokeranalytics.android.model.filter.QueryType @@ -64,11 +64,10 @@ open class Filter(entity:Filterable) : RealmObject() { companion object { @TestOnly - fun queryOn(realm: Realm, entity: Filterable, queries:List): RealmResults<*> { - val realmEntity : Class < out RealmObject > = FilterableClass.filterableClass(entity).relatedEntity - var realmQuery : RealmQuery = realm.where(realmEntity) + inline fun queryOn(realm: Realm, queries: List): RealmResults { + var realmQuery = realm.where() queries.forEach { - realmQuery = (it.filter(realmQuery, entity)) + realmQuery = (it.filter(realmQuery)) } return realmQuery.findAll() } @@ -130,16 +129,15 @@ open class Filter(entity:Filterable) : RealmObject() { return filterElementRow.contains(filtered) } - fun results(): RealmResults<*> { - val filterableClass : FilterableClass = this.filterableClass ?: throw FilterMissingEntityException("this filter has no entity initialized") - val realmEntity : Class < out RealmObject > = filterableClass.relatedEntity - var realmQuery : RealmQuery = realm.where(realmEntity) + inline fun results(): RealmResults { + var realmQuery : RealmQuery = realm.where() this.filterElements.map { it.queryType }.forEach { - realmQuery = (it.filter(realmQuery, filterableClass.filterable)) + realmQuery = it.filter(realmQuery) } return realmQuery.findAll() } + }