commonMain.jetbrains.datalore.base.observable.property.Properties.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of lets-plot-common Show documentation
Show all versions of lets-plot-common Show documentation
Lets-Plot JVM package without rendering part
/*
* Copyright (c) 2019. JetBrains s.r.o.
* Use of this source code is governed by the MIT license that can be found in the LICENSE file.
*/
package jetbrains.datalore.base.observable.property
import jetbrains.datalore.base.function.Predicate
import jetbrains.datalore.base.function.Runnable
import jetbrains.datalore.base.function.Supplier
import jetbrains.datalore.base.function.Value
import jetbrains.datalore.base.observable.collections.CollectionAdapter
import jetbrains.datalore.base.observable.collections.CollectionItemEvent
import jetbrains.datalore.base.observable.collections.ObservableCollection
import jetbrains.datalore.base.observable.event.EventHandler
import jetbrains.datalore.base.observable.event.EventSource
import jetbrains.datalore.base.registration.Registration
import kotlin.jvm.JvmOverloads
object Properties {
val TRUE = constant(true)
val FALSE = constant(false)
fun not(prop: ReadableProperty): ReadableProperty {
return map(prop) { value -> if (value == null) null else !value }
}
fun notNull(prop: ReadableProperty): ReadableProperty {
return map(prop) { value -> value != null }
}
fun isNull(prop: ReadableProperty): ReadableProperty {
return map(prop) { value -> value == null }
}
fun startsWith(string: ReadableProperty, prefix: ReadableProperty): ReadableProperty {
return object : DerivedProperty(false, string, prefix) {
override val propExpr: String
get() = "startsWith(" + string.propExpr + ", " + prefix.propExpr + ")"
override fun doGet(): Boolean {
if (string.get() == null) return false
return if (prefix.get() == null) false else string.get()!!.startsWith(prefix.get()!!)
}
}
}
fun isNullOrEmpty(prop: ReadableProperty): ReadableProperty {
return object : DerivedProperty(false, prop) {
override val propExpr: String
get() = "isEmptyString(" + prop.propExpr + ")"
override fun doGet(): Boolean {
val `val` = prop.get()
return `val` == null || `val`.isEmpty()
}
}
}
fun and(op1: ReadableProperty, op2: ReadableProperty): ReadableProperty {
return object : DerivedProperty(null, op1, op2) {
override val propExpr: String
get() = "(" + op1.propExpr + " && " + op2.propExpr + ")"
override fun doGet(): Boolean? {
return and(op1.get(), op2.get())
}
}
}
private fun and(b1: Boolean?, b2: Boolean?): Boolean? {
if (b1 == null) {
return andWithNull(b2)
}
return if (b2 == null) {
andWithNull(b1)
} else b1 && b2
}
private fun andWithNull(b: Boolean?): Boolean? {
return if (b == null || b) {
null
} else false
}
fun or(op1: ReadableProperty, op2: ReadableProperty): ReadableProperty {
return object : DerivedProperty(null, op1, op2) {
override val propExpr: String
get() = "(" + op1.propExpr + " || " + op2.propExpr + ")"
override fun doGet(): Boolean? {
return or(op1.get(), op2.get())
}
}
}
private fun or(b1: Boolean?, b2: Boolean?): Boolean? {
if (b1 == null) {
return orWithNull(b2)
}
return if (b2 == null) {
orWithNull(b1)
} else b1 || b2
}
private fun orWithNull(b: Boolean?): Boolean? {
return if (b == null || !b) {
null
} else true
// return !(b == null || !b)
}
fun add(p1: ReadableProperty, p2: ReadableProperty): ReadableProperty {
return object : DerivedProperty(null, p1, p2) {
override val propExpr: String
get() = "(" + p1.propExpr + " + " + p2.propExpr + ")"
override fun doGet(): Int? {
return if (p1.get() == null || p2.get() == null) null else p1.get()!! + p2.get()!!
}
}
}
fun select(
source: ReadableProperty, `fun`: (SourceT?) -> ReadableProperty): ReadableProperty {
return select(source, `fun`, null)
}
fun select(
source: ReadableProperty, `fun`: (SourceT?) -> ReadableProperty,
nullValue: TargetT?
): ReadableProperty {
val calc = object : Supplier {
override fun get(): TargetT? {
val value = source.get() ?: return nullValue
val prop = `fun`(value)
return prop.get()
}
}
return object : BaseDerivedProperty(null) {
// return object : BaseDerivedProperty() {
private var myTargetProperty: ReadableProperty? = null
private var mySourceRegistration: Registration? = null
private var myTargetRegistration: Registration? = null
override val propExpr: String
get() = "select(" + source.propExpr + ", " + `fun` + ")"
override fun doAddListeners() {
myTargetProperty = if (source.get() == null) null else `fun`(source.get())
val targetHandler = object : EventHandler> {
override fun onEvent(event: PropertyChangeEvent) {
somethingChanged()
}
}
val sourceHandler = object : EventHandler> {
override fun onEvent(event: PropertyChangeEvent) {
if (myTargetProperty != null) {
myTargetRegistration!!.remove()
}
val sourceValue = source.get()
if (sourceValue != null) {
myTargetProperty = `fun`(sourceValue)
} else {
myTargetProperty = null
}
if (myTargetProperty != null) {
myTargetRegistration = myTargetProperty!!.addHandler(targetHandler)
}
somethingChanged()
}
}
mySourceRegistration = source.addHandler(sourceHandler)
if (myTargetProperty != null) {
myTargetRegistration = myTargetProperty!!.addHandler(targetHandler)
}
}
override fun doRemoveListeners() {
if (myTargetProperty != null) {
myTargetRegistration!!.remove()
}
mySourceRegistration!!.remove()
}
override fun doGet(): TargetT? {
return calc.get()
}
}
}
fun selectRw(
source: ReadableProperty, `fun`: (SourceT) -> Property): Property {
val calc = object : Supplier {
override fun get(): TargetT? {
val value = source.get() ?: return null
val prop = `fun`(value)
return prop.get()
}
}
class MyProperty : BaseDerivedProperty(calc.get()), Property {
// class MyProperty : BaseDerivedProperty(), Property {
private var myTargetProperty: Property? = null
private var mySourceRegistration: Registration? = null
private var myTargetRegistration: Registration? = null
override val propExpr: String
get() = "select(" + source.propExpr + ", " + `fun` + ")"
override fun doAddListeners() {
myTargetProperty = if (source.get() == null) null else `fun`(source.get())
val targetHandler = object : EventHandler> {
override fun onEvent(event: PropertyChangeEvent) {
somethingChanged()
}
}
val sourceHandler = object : EventHandler> {
override fun onEvent(event: PropertyChangeEvent) {
if (myTargetProperty != null) {
myTargetRegistration!!.remove()
}
val sourceValue = source.get()
if (sourceValue != null) {
myTargetProperty = `fun`(sourceValue)
} else {
myTargetProperty = null
}
if (myTargetProperty != null) {
myTargetRegistration = myTargetProperty!!.addHandler(targetHandler)
}
somethingChanged()
}
}
mySourceRegistration = source.addHandler(sourceHandler)
if (myTargetProperty != null) {
myTargetRegistration = myTargetProperty!!.addHandler(targetHandler)
}
}
override fun doRemoveListeners() {
if (myTargetProperty != null) {
myTargetRegistration!!.remove()
}
mySourceRegistration!!.remove()
}
override fun doGet(): TargetT? {
return calc.get()
}
override fun set(value: TargetT?) {
if (myTargetProperty == null) return
myTargetProperty!!.set(value)
}
}
return MyProperty()
}
fun selectEvent(
prop: ReadableProperty, selector: (ValueT) -> EventSource): EventSource {
return object : EventSource {
override fun addHandler(handler: EventHandler): Registration {
val esReg = Value(Registration.EMPTY)
val update = object : Runnable {
override fun run() {
esReg.get().remove()
if (prop.get() != null) {
esReg.set(selector(prop.get()).addHandler(handler))
} else {
esReg.set(Registration.EMPTY)
}
}
}
update.run()
val propReg = prop.addHandler(object : EventHandler> {
override fun onEvent(event: PropertyChangeEvent) {
update.run()
}
})
return object : Registration() {
override fun doRemove() {
propReg.remove()
esReg.get().remove()
}
}
}
}
}
fun same(prop: ReadableProperty, v: ValueT?): ReadableProperty {
return map(prop) { value -> value === v }
}
fun equals(prop: ReadableProperty, v: ValueT?): ReadableProperty {
return map(prop) { value -> value == v }
}
fun equals(p1: ReadableProperty, p2: ReadableProperty): ReadableProperty {
return object : DerivedProperty(false, p1, p2) {
override val propExpr: String
get() = "equals(" + p1.propExpr + ", " + p2.propExpr + ")"
override fun doGet(): Boolean {
return p1.get() == p2.get()
}
}
}
fun notEquals(prop: ReadableProperty, value: ValueT?): ReadableProperty {
return not(equals(prop, value))
}
fun notEquals(p1: ReadableProperty, p2: ReadableProperty): ReadableProperty {
return not(equals(p1, p2))
}
fun map(
prop: ReadableProperty, f: (SourceT) -> TargetT): ReadableProperty {
return object : DerivedProperty(f(prop.get()), prop) {
override val propExpr: String
get() = "transform(" + prop.propExpr + ", " + f + ")"
override fun doGet(): TargetT {
return f(prop.get())
}
}
}
fun map(
prop: Property, sToT: (SourceT?) -> TargetT,
tToS: (TargetT) -> SourceT
): Property {
class TransformedProperty : Property {
override val propExpr: String
get() = "transform(" + prop.propExpr + ", " + sToT + ", " + tToS + ")"
override fun get(): TargetT {
return sToT(prop.get())
}
override fun addHandler(handler: EventHandler>): Registration {
return prop.addHandler(object : EventHandler> {
override fun onEvent(event: PropertyChangeEvent) {
val oldValue = sToT(event.oldValue)
val newValue = sToT(event.newValue)
if (oldValue == newValue) return
handler.onEvent(PropertyChangeEvent(oldValue, newValue))
}
})
}
override fun set(value: TargetT) {
prop.set(tToS(value))
}
}
return TransformedProperty()
}
fun constant(value: ValueT): ReadableProperty {
return object : BaseReadableProperty() {
override val propExpr: String
get() = "constant($value)"
override fun get(): ValueT {
return value
}
override fun addHandler(handler: EventHandler>): Registration {
return Registration.EMPTY
}
}
}
fun isEmpty(collection: ObservableCollection): ReadableProperty {
return object : SimpleCollectionProperty(collection, collection.isEmpty()) {
// return object : SimpleCollectionProperty(collection) {
override val propExpr: String
get() = "isEmpty($collection)"
override fun doGet(): Boolean {
return collection.isEmpty()
}
}
}
fun size(collection: ObservableCollection): ReadableProperty {
return object : SimpleCollectionProperty(collection, collection.size) {
override val propExpr: String
get() = "size($collection)"
override fun doGet(): Int {
return collection.size
}
}
}
/*
fun indexOf(
collection: ObservableList,
item: ReadableProperty): ReadableProperty {
return simplePropertyWithCollection(collection, item, object : Supplier {
override fun get(): Int {
return collection.indexOf(item.get())
}
})
}
fun contains(
collection: ObservableCollection,
item: ReadableProperty): ReadableProperty {
return simplePropertyWithCollection(collection, item, object : Supplier {
override fun get(): Boolean {
return collection.contains(item.get())
}
})
}
*/
/*
fun simplePropertyWithCollection(
collection: ObservableCollection<*>,
item: ReadableProperty<*>,
supplier: Supplier): ReadableProperty {
// return object : BaseDerivedProperty(supplier.get()) {
return object : BaseDerivedProperty() {
private var myRegistration: Registration? = null
private var myCollectionRegistration: Registration? = null
override val propExpr: String
get() = "fromCollection($collection, $item, $supplier)"
override fun doGet(): T {
return supplier.get()
}
override fun doAddListeners() {
myRegistration = item.addHandler(object : EventHandler> {
override fun onEvent(event: PropertyChangeEvent<*>) {
somethingChanged()
}
})
myCollectionRegistration = collection.addListener(Properties.simpleAdapter(object : Runnable {
override fun run() {
somethingChanged()
}
}))
}
protected override fun doRemoveListeners() {
myRegistration!!.remove()
myCollectionRegistration!!.remove()
}
}
}
*/
fun notEmpty(collection: ObservableCollection): ReadableProperty {
return not(empty(collection) as ReadableProperty)
}
fun empty(collection: ObservableCollection): ReadableProperty {
return object : BaseDerivedProperty(collection.isEmpty()) {
// return object : BaseDerivedProperty() {
private var myCollectionRegistration: Registration? = null
override val propExpr: String
get() = "empty($collection)"
override fun doAddListeners() {
myCollectionRegistration = collection.addListener(simpleAdapter(object : Runnable {
override fun run() {
somethingChanged()
}
}))
}
override fun doRemoveListeners() {
myCollectionRegistration!!.remove()
}
override fun doGet(): Boolean {
return collection.isEmpty()
}
}
}
private fun simpleAdapter(r: Runnable): CollectionAdapter {
return object : CollectionAdapter() {
override fun onItemAdded(event: CollectionItemEvent) {
r.run()
}
override fun onItemRemoved(event: CollectionItemEvent) {
r.run()
}
}
}
fun ifProp(
cond: ReadableProperty, ifTrue: ReadableProperty, ifFalse: ReadableProperty): ReadableProperty {
return object : DerivedProperty(null, cond, ifTrue, ifFalse) {
override val propExpr: String
get() = "if(" + cond.propExpr + ", " + ifTrue.propExpr + ", " + ifFalse.propExpr + ")"
override fun doGet(): ValueT {
return if (cond.get()) ifTrue.get() else ifFalse.get()
}
}
}
fun ifProp(cond: ReadableProperty, ifTrue: ValueT, ifFalse: ValueT): ReadableProperty {
return ifProp(cond, constant(ifTrue), constant(ifFalse))
}
fun ifProp(cond: WritableProperty, ifTrue: ValueT, ifFalse: ValueT): WritableProperty {
return object : WritableProperty {
override fun set(value: Boolean) {
if (value) {
cond.set(ifTrue)
} else {
cond.set(ifFalse)
}
}
}
}
fun withDefaultValue(prop: ReadableProperty, ifNull: ValueT): ReadableProperty {
return object : DerivedProperty(ifNull, prop) {
override fun doGet(): ValueT {
return if (prop.get() == null) {
ifNull
} else {
prop.get()
}
}
}
}
fun firstNotNull(vararg values: ReadableProperty): ReadableProperty {
return object : DerivedProperty(null, *values) {
override val propExpr: String
get() {
val result = StringBuilder()
result.append("firstNotNull(")
var first = true
for (v in values) {
if (first) {
first = false
} else {
result.append(", ")
}
result.append(v.propExpr)
}
result.append(")")
return result.toString()
}
override fun doGet(): ValueT? {
for (v in values) {
if (v.get() != null) {
return v.get()
}
}
return null
}
}
}
fun isPropertyValid(source: ReadableProperty, validator: Predicate): ReadableProperty {
return object : DerivedProperty(false, source) {
override val propExpr: String
get() = "isValid(" + source.propExpr + ", " + validator + ")"
override fun doGet(): Boolean {
return validator(source.get())
}
}
}
fun validatedProperty(source: Property, validator: Predicate): Property {
class ValidatedProperty : DerivedProperty(null, source), Property {
private var myLastValid: ValueT? = null
override val propExpr: String
get() = "validated(" + source.propExpr + ", " + validator + ")"
override fun doGet(): ValueT? {
val sourceValue = source.get()
if (validator(sourceValue)) {
myLastValid = sourceValue
}
return myLastValid
}
override fun set(value: ValueT?) {
if (!validator(value)) {
return
}
source.set(value)
}
}
return ValidatedProperty()
}
@JvmOverloads
fun toStringOf(p: ReadableProperty<*>, nullValue: String = "null"): ReadableProperty {
return object : DerivedProperty(nullValue, p) {
override fun doGet(): String {
val value = p.get()
return if (value != null) "" + value else nullValue
}
}
}
fun property(read: ReadableProperty, write: WritableProperty): Property {
return object : Property {
override val propExpr: String
get() = read.propExpr
override fun get(): ValueT {
return read.get()
}
override fun addHandler(handler: EventHandler>): Registration {
return read.addHandler(handler)
}
override fun set(value: ValueT) {
write.set(value)
}
}
}
fun compose(vararg props: WritableProperty): WritableProperty {
return object : WritableProperty {
override fun set(value: ValueT) {
for (wp in props) {
wp.set(value)
}
}
}
}
fun forSingleItemCollection(coll: ObservableCollection): Property {
if (coll.size > 1) {
throw IllegalStateException("Collection $coll has more than one item")
}
return object : Property {
override val propExpr: String
get() = "singleItemCollection($coll)"
override fun get(): ItemT? {
return if (coll.isEmpty()) {
null
} else coll.iterator().next()
}
override fun set(value: ItemT?) {
val current = get()
if (current == value) return
coll.clear()
if (value != null) {
coll.add(value)
}
}
override fun addHandler(handler: EventHandler>): Registration {
return coll.addListener(object : CollectionAdapter() {
override fun onItemAdded(event: CollectionItemEvent) {
if (coll.size != 1) {
throw IllegalStateException()
}
handler.onEvent(PropertyChangeEvent(null, event.newItem))
}
override fun onItemSet(event: CollectionItemEvent) {
if (event.index != 0) {
throw IllegalStateException()
}
handler.onEvent(PropertyChangeEvent(event.oldItem, event.newItem))
}
override fun onItemRemoved(event: CollectionItemEvent) {
if (!coll.isEmpty()) {
throw IllegalStateException()
}
handler.onEvent(PropertyChangeEvent(event.oldItem, null))
}
})
}
}
}
fun and(vararg props: ReadableProperty): ReadableProperty {
if (props.isEmpty()) {
throw IllegalArgumentException("No arguments")
}
return object : DerivedProperty(null, *props) {
override val propExpr: String
get() {
val propExpr = StringBuilder("(")
propExpr.append(props[0].propExpr)
for (i in 1 until props.size) {
propExpr.append(" && ").append(props[i].propExpr)
}
return propExpr.append(")").toString()
}
override fun doGet(): Boolean? {
var res: Boolean? = true
for (prop in props) {
res = and(res, prop.get())
}
return res
}
}
}
fun or(vararg props: ReadableProperty): ReadableProperty {
if (props.isEmpty()) {
throw IllegalArgumentException("No arguments")
}
return object : DerivedProperty(null, *props) {
override val propExpr: String
get() {
val propExpr = StringBuilder("(")
propExpr.append(props[0].propExpr)
for (i in 1 until props.size) {
propExpr.append(" || ").append(props[i].propExpr)
}
return propExpr.append(")").toString()
}
override fun doGet(): Boolean? {
var res: Boolean? = false
for (prop in props) {
res = or(res, prop.get())
}
return res
}
}
}
/*
fun > enumAsInteger(source: Property, enumClass: KClass): Property {
return property(map(source) { value -> value.ordinal },
object : WritableProperty {
override fun set(value: Int?) {
if (value == null) {
source.set(null)
return
}
source.set(enumClass.getEnumConstants()[value])
}
})
}
*/
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy