make filtering functions generic

feature/top10
Laurent 7 years ago
parent 755b821f42
commit e549ab0798
  1. 27
      app/src/main/java/net/pokeranalytics/android/model/filter/Filterable.kt
  2. 34
      app/src/main/java/net/pokeranalytics/android/model/filter/QueryType.kt
  3. 18
      app/src/main/java/net/pokeranalytics/android/model/realm/Filter.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 <reified T : Filterable> fieldNameForQueryType(queryType: QueryType) : String? {
when (T::class) {
is Session -> {
Session.fieldNameForQueryType(queryType)
}
}
throw UnmanagedFilterField("Filterable type fields are not defined")
}
}
}
//

@ -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<out RealmObject>, filterable: Filterable): RealmQuery<out RealmObject> {
inline fun <reified T : Filterable> filter(realmQuery: RealmQuery<T>): RealmQuery<T> {
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<T>(queryType = SMALL_BLIND)
val bigBlindFieldName = FilterHelper.fieldNameForQueryType<T>(queryType = BIG_BLIND)
val currencyCodeFieldName = FilterHelper.fieldNameForQueryType<T>(CURRENCY_CODE)
smallBlindFieldName ?: throw FilterValueMapException("fieldName is missing")
bigBlindFieldName ?: throw FilterValueMapException("fieldName is missing")
currencyCodeFieldName ?: throw FilterValueMapException("fieldName is missing")
val blinds: RealmList<FilterElementBlind> 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<T>(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<String> 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")

@ -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<QueryType>): RealmResults<*> {
val realmEntity : Class < out RealmObject > = FilterableClass.filterableClass(entity).relatedEntity
var realmQuery : RealmQuery<out RealmObject> = realm.where(realmEntity)
inline fun <reified T : Filterable> queryOn(realm: Realm, queries: List<QueryType>): RealmResults<T> {
var realmQuery = realm.where<T>()
queries.forEach {
realmQuery = (it.filter(realmQuery, entity))
realmQuery = (it.filter<T>(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<out RealmObject> = realm.where(realmEntity)
inline fun <reified T : Filterable> results(): RealmResults<T> {
var realmQuery : RealmQuery<T> = realm.where<T>()
this.filterElements.map {
it.queryType
}.forEach {
realmQuery = (it.filter(realmQuery, filterableClass.filterable))
realmQuery = it.filter(realmQuery)
}
return realmQuery.findAll()
}
}

Loading…
Cancel
Save