I'm trying a program build with Jetbrain/Exposed as ORM library and TornadoFX which is a kotlin version wrapper of JavaFX as UI Framework. There is a problem that an entity's class property is delegated by Exposed.
object Paintings: UUIDTable() {
...
val description = text("description").default("")
...
}
class Painting(id: EntityID<UUID>) : UUIDEntity(id) {
...
var description by Paintings.description
...
}
And I'm also want to create an property delegated to JavaFX's property like this
class Painting(id: EntityID<UUID>) : UUIDEntity(id) {
...
var description by property<String>()
fun descriptionProperty() = getProperty(Painting::description)
...
}
There is a conflict here,so I'm trying to build a own delegate class to wrapper two framework's delegated.Maybe build something which can wrap two frameworks's delegate though a infix function extension.
class Painting(id: EntityID<UUID>) : UUIDEntity(id) {
...
var description by Paintings.description notify property<String>()
fun descriptionProperty() = getProperty(Painting::description)
...
}
And here is the problem that the operator setValue
and getValue
for delegate from Exposed is declare in Entity
class
open class Entity<ID:Comparable<ID>>(val id: EntityID<ID>) {
...
operator fun <T> Column<T>.getValue(o: Entity<ID>, desc: KProperty<*>): T =
lookup()
operator fun <T> Column<T>.setValue(o: Entity<ID>, desc: KProperty<*>, value: T) {...}
If I declare a wrapper class it just cannot access the delegate operator for Column
which is scoped in Entity
class
//Global Extension instead of scoped to `Entity`
infix fun <T> Column<T>.notify(fxProperty: PropertyDelegate<T>) {
return DelegateWrapper(this,fxProperty)
}
class DelegateWrapper<T>(val column: Column<T>, val fxProperty: PropertyDelegate<T>) {
operator fun getValue(thisRef: Any?, property: KProperty<*>): String {
return column.getValue(...) <-cannot resolve getValue
}
operator fun setValue(thisRef: Any?, property: KProperty<*>, value: String)
{
...
}
}
As a work arround I guess I had to build a subclass of UUIDEntity and add those extension as member extension and nest class to make it work.
You can do that by limiting the type that the delegate can be used with to Entity
.
This can be done by replacing thisRef: Any?
with thisRef: Entity<ID>
and calling the getValue
extension in a thisRef.run { ... }
block that provides an Entitiy<ID>
receiver as follows:
class DelegateWrapper<T>(val column: Column<T>, val fxProperty: PropertyDelegate<T>) {
operator fun <ID : Comparable<ID>> getValue(
thisRef: Entity<ID>, // <-- here
property: KProperty<*>
): String =
thisRef.run { column.getValue(thisRef, property) }
operator fun setValue(thisRef: Any?, property: KProperty<*>, value: String) = TODO()
}