mirror of
https://github.com/corda/corda.git
synced 2025-01-19 03:06:36 +00:00
client: Document models
This commit is contained in:
parent
cb956e0979
commit
0c8f58b2ac
@ -10,13 +10,20 @@ import javafx.collections.ObservableList
|
||||
import kotlinx.support.jdk8.collections.removeIf
|
||||
import org.reactfx.EventStream
|
||||
|
||||
class StatesDiff<out T : ContractState>(val added: Collection<StateAndRef<T>>, val removed: Collection<StateRef>)
|
||||
class StatesDiff<out T : ContractState>(
|
||||
val added: Collection<StateAndRef<T>>,
|
||||
val removed: Collection<StateRef>
|
||||
)
|
||||
|
||||
/**
|
||||
* This model exposes the list of owned contract states.
|
||||
*/
|
||||
class ContractStateModel {
|
||||
private val serviceToClient: EventStream<ServiceToClientEvent> by stream(WalletMonitorModel::serviceToClient)
|
||||
private val outputStates = serviceToClient.filter(ServiceToClientEvent.OutputState::class.java)
|
||||
|
||||
val contractStatesDiff = outputStates.map { StatesDiff(it.produced, it.consumed) }
|
||||
// We filter the diff first rather than the complete contract state list.
|
||||
val cashStatesDiff = contractStatesDiff.map {
|
||||
StatesDiff(it.added.filterIsInstance<StateAndRef<Cash.State>>(), it.removed)
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ package com.r3corda.client.model
|
||||
|
||||
import com.r3corda.core.contracts.Amount
|
||||
import javafx.beans.property.SimpleObjectProperty
|
||||
import javafx.beans.value.ObservableValue
|
||||
import java.util.*
|
||||
|
||||
|
||||
@ -13,9 +14,12 @@ fun ExchangeRate.exchangeAmount(amount: Amount<Currency>, to: Currency) =
|
||||
fun ExchangeRate.exchangeDouble(amount: Amount<Currency>, to: Currency) =
|
||||
rate(amount.token, to) * amount.quantity
|
||||
|
||||
/**
|
||||
* This model provides an exchange rate from arbitrary currency to arbitrary currency.
|
||||
* TODO hook up an actual oracle
|
||||
*/
|
||||
class ExchangeRateModel {
|
||||
// TODO hook up an actual oracle
|
||||
val exchangeRate = SimpleObjectProperty<ExchangeRate>(object : ExchangeRate {
|
||||
val exchangeRate: ObservableValue<ExchangeRate> = SimpleObjectProperty<ExchangeRate>(object : ExchangeRate {
|
||||
override fun rate(from: Currency, to: Currency) = 1.0
|
||||
})
|
||||
}
|
||||
|
@ -12,13 +12,17 @@ import kotlin.reflect.KProperty
|
||||
|
||||
/**
|
||||
* This file defines a global [Models] store and delegates to inject event streams/sinks. Note that all streams here
|
||||
* are global to the app.
|
||||
* are global.
|
||||
*
|
||||
* This allows us to decouple UI logic from stream initialisation and provides us with a central place to inspect data flows.
|
||||
* It also allows detecting of looping logic by constructing a stream dependency graph TODO do this
|
||||
* This allows decoupling of UI logic from stream initialisation and provides us with a central place to inspect data
|
||||
* flows. It also allows detecting of looping logic by constructing a stream dependency graph TODO do this.
|
||||
*
|
||||
* General rule of thumb: A stream/observable should be a model if it may be reused several times.
|
||||
*
|
||||
* Usage:
|
||||
* // Inject service -> client stream
|
||||
* private val serviceToClient: EventStream<ServiceToClientEvent> by stream(WalletMonitorModel::serviceToClient)
|
||||
*
|
||||
* Usage: In your piece of UI use the [stream] and [sink] delegates to access external streams. If you have a reusable
|
||||
* stream put it in a Model. See [NetworkModel] for an example
|
||||
*/
|
||||
|
||||
inline fun <reified M : Any, T> stream(noinline streamProperty: (M) -> EventStream<T>) =
|
||||
@ -40,7 +44,7 @@ inline fun <reified M : Any, T> observableList(noinline observableListProperty:
|
||||
TrackedDelegate.ObservableListDelegate(M::class, observableListProperty)
|
||||
|
||||
inline fun <reified M : Any, T> observableListReadOnly(noinline observableListProperty: (M) -> ObservableList<out T>) =
|
||||
TrackedDelegate.ObservableListDelegateReadOnly(M::class, observableListProperty)
|
||||
TrackedDelegate.ObservableListReadOnlyDelegate(M::class, observableListProperty)
|
||||
|
||||
object Models {
|
||||
private val modelStore = HashMap<KClass<*>, Any>()
|
||||
@ -68,35 +72,34 @@ sealed class TrackedDelegate<M : Any>(val klass: KClass<M>) {
|
||||
return streamProperty(Models.get(klass, thisRef.javaClass.kotlin))
|
||||
}
|
||||
}
|
||||
|
||||
class Sink<M : Any, T> (klass: KClass<M>, val sinkProperty: (M) -> EventSink<T>) : TrackedDelegate<M>(klass) {
|
||||
operator fun getValue(thisRef: Any, property: KProperty<*>): EventSink<T> {
|
||||
return sinkProperty(Models.get(klass, thisRef.javaClass.kotlin))
|
||||
}
|
||||
}
|
||||
class ObservableValueDelegate<M : Any, T>(klass: KClass<M>, val sinkProperty: (M) -> ObservableValue<T>) : TrackedDelegate<M>(klass) {
|
||||
class ObservableValueDelegate<M : Any, T>(klass: KClass<M>, val observableValueProperty: (M) -> ObservableValue<T>) : TrackedDelegate<M>(klass) {
|
||||
operator fun getValue(thisRef: Any, property: KProperty<*>): ObservableValue<T> {
|
||||
return sinkProperty(Models.get(klass, thisRef.javaClass.kotlin))
|
||||
return observableValueProperty(Models.get(klass, thisRef.javaClass.kotlin))
|
||||
}
|
||||
}
|
||||
class WritableValueDelegate<M : Any, T>(klass: KClass<M>, val sinkProperty: (M) -> WritableValue<T>) : TrackedDelegate<M>(klass) {
|
||||
class WritableValueDelegate<M : Any, T>(klass: KClass<M>, val writableValueProperty: (M) -> WritableValue<T>) : TrackedDelegate<M>(klass) {
|
||||
operator fun getValue(thisRef: Any, property: KProperty<*>): WritableValue<T> {
|
||||
return sinkProperty(Models.get(klass, thisRef.javaClass.kotlin))
|
||||
return writableValueProperty(Models.get(klass, thisRef.javaClass.kotlin))
|
||||
}
|
||||
}
|
||||
class ObservableListDelegate<M : Any, T>(klass: KClass<M>, val sinkProperty: (M) -> ObservableList<T>) : TrackedDelegate<M>(klass) {
|
||||
class ObservableListDelegate<M : Any, T>(klass: KClass<M>, val observableListProperty: (M) -> ObservableList<T>) : TrackedDelegate<M>(klass) {
|
||||
operator fun getValue(thisRef: Any, property: KProperty<*>): ObservableList<T> {
|
||||
return sinkProperty(Models.get(klass, thisRef.javaClass.kotlin))
|
||||
return observableListProperty(Models.get(klass, thisRef.javaClass.kotlin))
|
||||
}
|
||||
}
|
||||
class ObservableListDelegateReadOnly<M : Any, T>(klass: KClass<M>, val sinkProperty: (M) -> ObservableList<out T>) : TrackedDelegate<M>(klass) {
|
||||
class ObservableListReadOnlyDelegate<M : Any, T>(klass: KClass<M>, val observableListReadOnlyProperty: (M) -> ObservableList<out T>) : TrackedDelegate<M>(klass) {
|
||||
operator fun getValue(thisRef: Any, property: KProperty<*>): ObservableList<out T> {
|
||||
return sinkProperty(Models.get(klass, thisRef.javaClass.kotlin))
|
||||
return observableListReadOnlyProperty(Models.get(klass, thisRef.javaClass.kotlin))
|
||||
}
|
||||
}
|
||||
class ObjectPropertyDelegate<M : Any, T>(klass: KClass<M>, val sinkProperty: (M) -> ObjectProperty<T>) : TrackedDelegate<M>(klass) {
|
||||
class ObjectPropertyDelegate<M : Any, T>(klass: KClass<M>, val objectPropertyProperty: (M) -> ObjectProperty<T>) : TrackedDelegate<M>(klass) {
|
||||
operator fun getValue(thisRef: Any, property: KProperty<*>): ObjectProperty<T> {
|
||||
return sinkProperty(Models.get(klass, thisRef.javaClass.kotlin))
|
||||
return objectPropertyProperty(Models.get(klass, thisRef.javaClass.kotlin))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -58,6 +58,9 @@ data class TransactionCreateStateWritable(
|
||||
override val lastUpdate: SimpleObjectProperty<Instant>
|
||||
) : TransactionCreateState
|
||||
|
||||
/**
|
||||
* This model provides an observable list of states relating to the creation of a transaction not yet on ledger.
|
||||
*/
|
||||
class TransactionCreateStateModel {
|
||||
|
||||
private val serviceToClient: EventStream<ServiceToClientEvent> by stream(WalletMonitorModel::serviceToClient)
|
||||
|
@ -1,17 +1,17 @@
|
||||
package com.r3corda.client.model
|
||||
|
||||
import com.r3corda.client.WalletMonitorClient
|
||||
import com.r3corda.core.contracts.Amount
|
||||
import com.r3corda.core.contracts.ClientToServiceCommand
|
||||
import com.r3corda.core.messaging.MessagingService
|
||||
import com.r3corda.core.node.NodeInfo
|
||||
import com.r3corda.node.services.monitor.ServiceToClientEvent
|
||||
import javafx.beans.property.SimpleObjectProperty
|
||||
import org.reactfx.EventSink
|
||||
import org.reactfx.EventSource
|
||||
import org.reactfx.EventStream
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
* This model exposes raw event streams to and from the [WalletMonitorService] through a [WalletMonitorClient]
|
||||
*/
|
||||
class WalletMonitorModel {
|
||||
private val clientToServiceSource = EventSource<ClientToServiceCommand>()
|
||||
val clientToService: EventSink<ClientToServiceCommand> = clientToServiceSource
|
||||
@ -19,7 +19,12 @@ class WalletMonitorModel {
|
||||
private val serviceToClientSource = EventSource<ServiceToClientEvent>()
|
||||
val serviceToClient: EventStream<ServiceToClientEvent> = serviceToClientSource
|
||||
|
||||
// TODO provide an unsubscribe mechanism
|
||||
/**
|
||||
* Register for updates to/from a given wallet.
|
||||
* @param messagingService The messaging to use for communication.
|
||||
* @param walletMonitorNodeInfo the [Node] to connect to.
|
||||
* TODO provide an unsubscribe mechanism
|
||||
*/
|
||||
fun register(messagingService: MessagingService, walletMonitorNodeInfo: NodeInfo) {
|
||||
val monitorClient = WalletMonitorClient(
|
||||
messagingService,
|
||||
|
Loading…
Reference in New Issue
Block a user