com.lightningkite.lightningdb.ConditionSimplify.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of server-core Show documentation
Show all versions of server-core Show documentation
A set of tools to fill in/replace what Ktor is lacking in.
The newest version!
package com.lightningkite.lightningdb
import kotlin.reflect.KProperty1
// Sink properties, reduce within properties, reduce all
fun Condition.simplify(): Condition {
return when(this) {
is Condition.And -> {
// println("AND simplifying $this")
conditions.asSequence().flatMap { it.andByField() }
.groupBy { it.first }
.mapNotNull {
// println("AND key ${it.key.map { it.name }}: merging parts ${it.value.map { it.second }}")
val keyCond = it.value.map { it.second as Condition }.reduce(::reduceAnd).finalSimplify()
// println("AND reduced to $keyCond")
when (keyCond) {
is Condition.Always -> return@mapNotNull null
is Condition.Never -> return Condition.Never()
else -> make(it.key, keyCond) as Condition
}
}
.let {
// println("AND total simplification list: $it")
if (it.isEmpty()) Condition.Always()
else if (it.size == 1) it.first()
else Condition.And(it)
}
// .also { println("AND final is $it") }
}
is Condition.Or -> {
// println("OR simplifying $this")
conditions.asSequence().flatMap { it.orByField() }
.groupBy { it.first }
.mapNotNull {
// println("OR key ${it.key.map { it.name }}: merging parts ${it.value.map { it.second }}")
val keyCond = it.value.map { it.second as Condition }.reduce(::reduceOr).finalSimplify()
// println("OR reduced to $keyCond")
when (keyCond) {
is Condition.Always -> return Condition.Always()
is Condition.Never -> return@mapNotNull null
else -> make(it.key, keyCond) as Condition
}
}
.let {
// println("OR total simplification list: $it")
if (it.isEmpty()) Condition.Never()
else if (it.size == 1) it.first()
else Condition.Or(it)
}
// .also { println("OR final is $it") }
}
else -> finalSimplify()
}
}
private fun Condition.finalSimplify(): Condition = when(this) {
is Condition.Inside -> if(values.isEmpty()) Condition.Never() else this
is Condition.NotInside -> if(values.isEmpty()) Condition.Always() else this
else -> this
}
private fun Condition<*>.andByField(): Sequence>, Condition<*>>> {
return when (this) {
is Condition.And -> conditions.asSequence().flatMap { it.andByField() }
is Condition.OnField<*, *> -> condition.andByField().map {
(listOf(key) + it.first) to it.second
}
else -> {
val s = this.simplify()
if(s is Condition.OnField<*, *>) s.condition.andByField().map {
(listOf(s.key) + it.first) to it.second
} else sequenceOf(listOf>() to s)
}
}
}
private fun Condition<*>.orByField(): Sequence>, Condition<*>>> {
return when (this) {
is Condition.Or -> conditions.asSequence().flatMap { it.orByField() }
is Condition.OnField<*, *> -> condition.orByField().map {
(listOf(key) + it.first) to it.second
}
else -> {
val s = this.simplify()
if(s is Condition.OnField<*, *>) s.condition.orByField().map {
(listOf(s.key) + it.first) to it.second
} else sequenceOf(listOf>() to s)
}
}
}
private fun make(prop: List>, cond: Condition<*>): Condition<*> {
@Suppress("UNCHECKED_CAST")
(return if (prop.isEmpty()) cond
else Condition.OnField(
prop.first() as KProperty1,
make(prop.subList(1, prop.size), cond) as Condition
))
}
private fun reduceAnd(a: Condition, b: Condition): Condition {
return when (a) {
is Condition.Always -> b
is Condition.Never -> a
is Condition.And -> when (b) {
is Condition.And -> Condition.And(a.conditions + b.conditions)
else -> Condition.And(a.conditions + b)
}
is Condition.Equal -> when (b) {
is Condition.Equal -> if (a.value == b.value) a else Condition.Never()
is Condition.GreaterThan -> if (a.value.let { it as Comparable } > b.value.let { it as Comparable }) a else Condition.Never()
is Condition.LessThan -> if (a.value.let { it as Comparable } < b.value.let { it as Comparable }) a else Condition.Never()
is Condition.GreaterThanOrEqual -> if (a.value.let { it as Comparable } >= b.value.let { it as Comparable }) a else Condition.Never()
is Condition.LessThanOrEqual -> if (a.value.let { it as Comparable } <= b.value.let { it as Comparable }) a else Condition.Never()
is Condition.NotEqual -> if (a.value != b.value) a else Condition.Never()
is Condition.Inside -> if (a.value in b.values) a else Condition.Never()
is Condition.NotInside -> if (a.value !in b.values) a else Condition.Never()
is Condition.And -> Condition.And(b.conditions + a)
else -> Condition.And(listOf(a, b))
}
is Condition.GreaterThan -> when (b) {
is Condition.GreaterThan -> if (a.value.let { it as Comparable } > b.value.let { it as Comparable }) a else b
is Condition.GreaterThanOrEqual -> if (a.value.let { it as Comparable } >= b.value.let { it as Comparable }) a else b
is Condition.LessThan -> if (a.value.let { it as Comparable } >= b.value.let { it as Comparable }) Condition.Never() else Condition.And(listOf(a, b))
is Condition.LessThanOrEqual -> if (a.value.let { it as Comparable } >= b.value.let { it as Comparable }) Condition.Never() else Condition.And(listOf(a, b))
is Condition.Always,
is Condition.Never,
is Condition.And,
is Condition.Equal -> reduceAnd(b, a)
else -> Condition.And(listOf(a, b))
}
is Condition.LessThan -> when (b) {
is Condition.LessThan -> if (a.value.let { it as Comparable } < b.value.let { it as Comparable }) a else b
is Condition.LessThanOrEqual -> if (a.value.let { it as Comparable } <= b.value.let { it as Comparable }) a else b
is Condition.GreaterThan,
is Condition.GreaterThanOrEqual,
is Condition.Always,
is Condition.Never,
is Condition.And,
is Condition.Equal -> reduceAnd(b, a)
else -> Condition.And(listOf(a, b))
}
is Condition.GreaterThanOrEqual -> when (b) {
is Condition.GreaterThanOrEqual -> if (a.value.let { it as Comparable } >= b.value.let { it as Comparable }) a else b
is Condition.LessThan -> if (a.value.let { it as Comparable } >= b.value.let { it as Comparable }) Condition.Never() else Condition.And(listOf(a, b))
is Condition.LessThanOrEqual -> if (a.value.let { it as Comparable } > b.value.let { it as Comparable }) Condition.Never() else Condition.And(listOf(a, b))
is Condition.GreaterThan,
is Condition.Always,
is Condition.Never,
is Condition.And,
is Condition.Equal -> reduceAnd(b, a)
else -> Condition.And(listOf(a, b))
}
is Condition.LessThanOrEqual -> when (b) {
is Condition.LessThanOrEqual -> if (a.value.let { it as Comparable } <= b.value.let { it as Comparable }) a else b
is Condition.LessThan,
is Condition.Always,
is Condition.Never,
is Condition.And,
is Condition.Equal -> reduceAnd(b, a)
else -> Condition.And(listOf(a, b))
}
is Condition.Inside -> when (b) {
is Condition.Inside -> Condition.Inside(a.values.toSet().intersect(b.values.toSet()).toList())
is Condition.NotInside -> Condition.Inside(a.values.toSet().minus(b.values.toSet()).toList())
is Condition.GreaterThan,
is Condition.LessThan,
is Condition.Always,
is Condition.Never,
is Condition.And,
is Condition.Equal -> reduceAnd(b, a)
else -> Condition.And(listOf(a, b))
}
is Condition.NotInside -> when (b) {
is Condition.NotInside -> Condition.NotInside(a.values.toSet().union(b.values.toSet()).toList())
is Condition.Inside,
is Condition.GreaterThan,
is Condition.LessThan,
is Condition.Always,
is Condition.Never,
is Condition.And,
is Condition.Equal -> reduceAnd(b, a)
else -> Condition.And(listOf(a, b))
}
else -> Condition.And(listOf(a, b))
}
}
private fun reduceOr(a: Condition, b: Condition): Condition {
return when (a) {
is Condition.Always -> a
is Condition.Never -> b
is Condition.Or -> when (b) {
is Condition.Or -> Condition.Or(a.conditions + b.conditions)
else -> Condition.Or(a.conditions + b)
}
is Condition.Equal -> when (b) {
is Condition.Equal -> if (a.value == b.value) a else Condition.Inside(listOf(a.value, b.value))
is Condition.GreaterThan -> if (a.value.let { it as Comparable } > b.value.let { it as Comparable }) b else Condition.Or(listOf(a, b))
is Condition.LessThan -> if (a.value.let { it as Comparable } < b.value.let { it as Comparable }) b else Condition.Or(listOf(a, b))
is Condition.GreaterThanOrEqual -> if (a.value.let { it as Comparable } >= b.value.let { it as Comparable }) b else Condition.Or(listOf(a, b))
is Condition.LessThanOrEqual -> if (a.value.let { it as Comparable } <= b.value.let { it as Comparable }) b else Condition.Or(listOf(a, b))
is Condition.NotEqual -> if (a.value != b.value) b else Condition.Always()
is Condition.Inside -> if (a.value in b.values) b else Condition.Inside(b.values + a.value)
is Condition.NotInside -> if (a.value !in b.values) b else Condition.NotInside(b.values - a.value)
is Condition.Or -> Condition.Or(b.conditions + a)
else -> Condition.Or(listOf(a, b))
}
is Condition.GreaterThan -> when (b) {
is Condition.GreaterThan -> if (a.value.let { it as Comparable } > b.value.let { it as Comparable }) b else a
is Condition.GreaterThanOrEqual -> if (a.value.let { it as Comparable } >= b.value.let { it as Comparable }) b else a
is Condition.Always,
is Condition.Never,
is Condition.Or,
is Condition.Equal -> reduceOr(b, a)
else -> Condition.Or(listOf(a, b))
}
is Condition.LessThan -> when (b) {
is Condition.LessThan -> if (a.value.let { it as Comparable } < b.value.let { it as Comparable }) b else a
is Condition.LessThanOrEqual -> if (a.value.let { it as Comparable } <= b.value.let { it as Comparable }) b else a
is Condition.Always,
is Condition.Never,
is Condition.Or,
is Condition.Equal -> reduceOr(b, a)
else -> Condition.Or(listOf(a, b))
}
is Condition.GreaterThanOrEqual -> when (b) {
is Condition.GreaterThanOrEqual -> if (a.value.let { it as Comparable } >= b.value.let { it as Comparable }) b else a
is Condition.GreaterThan,
is Condition.Always,
is Condition.Never,
is Condition.Or,
is Condition.Equal -> reduceOr(b, a)
else -> Condition.Or(listOf(a, b))
}
is Condition.LessThanOrEqual -> when (b) {
is Condition.LessThanOrEqual -> if (a.value.let { it as Comparable } <= b.value.let { it as Comparable }) b else a
is Condition.LessThan,
is Condition.Always,
is Condition.Never,
is Condition.Or,
is Condition.Equal -> reduceOr(b, a)
else -> Condition.Or(listOf(a, b))
}
is Condition.Inside -> when (b) {
is Condition.Inside -> Condition.Inside(a.values.toSet().union(b.values.toSet()).toList())
is Condition.NotInside -> Condition.NotInside(b.values.toSet().minus(a.values.toSet()).toList())
is Condition.GreaterThan,
is Condition.LessThan,
is Condition.Always,
is Condition.Never,
is Condition.Or,
is Condition.Equal -> reduceOr(b, a)
else -> Condition.Or(listOf(a, b))
}
is Condition.NotInside -> when (b) {
is Condition.NotInside -> Condition.NotInside(a.values.toSet().intersect(b.values.toSet()).toList())
is Condition.Inside,
is Condition.GreaterThan,
is Condition.LessThan,
is Condition.Always,
is Condition.Never,
is Condition.Or,
is Condition.Equal -> reduceOr(b, a)
else -> Condition.Or(listOf(a, b))
}
else -> Condition.Or(listOf(a, b))
}
}