mirror of
https://github.com/corda/corda.git
synced 2025-02-20 17:33:15 +00:00
Simplified the implementation of the tx query APIs with the introduction of Class.castIfPossible
This commit is contained in:
parent
a485bbada8
commit
3e199e51fc
@ -54,6 +54,8 @@ fun Path.writeLines(lines: Iterable<CharSequence>, charset: Charset = UTF_8, var
|
||||
|
||||
fun InputStream.copyTo(target: Path, vararg options: CopyOption): Long = Files.copy(this, target, *options)
|
||||
|
||||
fun <T> Class<T>.castIfPossible(obj: Any): T? = if (isInstance(obj)) cast(obj) else null
|
||||
|
||||
/** Returns a [DeclaredField] wrapper around the declared (possibly non-public) static field of the receiver [Class]. */
|
||||
fun <T> Class<*>.staticField(name: String): DeclaredField<T> = DeclaredField(this, name, null)
|
||||
/** Returns a [DeclaredField] wrapper around the declared (possibly non-public) static field of the receiver [KClass]. */
|
||||
|
@ -5,6 +5,7 @@ import com.esotericsoftware.kryo.KryoException
|
||||
import com.esotericsoftware.kryo.Serializer
|
||||
import com.esotericsoftware.kryo.io.Input
|
||||
import com.esotericsoftware.kryo.io.Output
|
||||
import net.corda.core.internal.castIfPossible
|
||||
import net.corda.core.node.ServiceHub
|
||||
import net.corda.core.serialization.SingletonSerializationToken.Companion.singletonSerializationToken
|
||||
|
||||
@ -46,11 +47,7 @@ class SerializeAsTokenSerializer<T : SerializeAsToken> : Serializer<T>() {
|
||||
override fun read(kryo: Kryo, input: Input, type: Class<T>): T {
|
||||
val token = (kryo.readClassAndObject(input) as? SerializationToken) ?: throw KryoException("Non-token read for tokenized type: ${type.name}")
|
||||
val fromToken = token.fromToken(kryo.serializationContext() ?: throw KryoException("Attempt to read a token for a ${SerializeAsToken::class.simpleName} instance of ${type.name} without initialising a context"))
|
||||
if (type.isAssignableFrom(fromToken.javaClass)) {
|
||||
return type.cast(fromToken)
|
||||
} else {
|
||||
throw KryoException("Token read ($token) did not return expected tokenized type: ${type.name}")
|
||||
}
|
||||
return type.castIfPossible(fromToken) ?: throw KryoException("Token read ($token) did not return expected tokenized type: ${type.name}")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3,6 +3,7 @@ package net.corda.core.transactions
|
||||
import net.corda.core.contracts.*
|
||||
import net.corda.core.identity.Party
|
||||
import net.corda.core.indexOfOrThrow
|
||||
import net.corda.core.internal.castIfPossible
|
||||
import java.security.PublicKey
|
||||
import java.util.*
|
||||
import java.util.function.Predicate
|
||||
@ -65,7 +66,6 @@ abstract class BaseTransaction(
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
fun <T : ContractState> outRef(index: Int): StateAndRef<T> = StateAndRef(outputs[index] as TransactionState<T>, StateRef(id, index))
|
||||
|
||||
|
||||
/**
|
||||
* Returns a [StateAndRef] for the requested output state, or throws [IllegalArgumentException] if not found.
|
||||
*/
|
||||
@ -89,34 +89,41 @@ abstract class BaseTransaction(
|
||||
* Clazz must be an extension of [ContractState].
|
||||
* @return the possibly empty list of output states matching the clazz restriction.
|
||||
*/
|
||||
fun <T : ContractState> outputsOfType(clazz: Class<T>): List<T> {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
return outputs.filter { clazz.isInstance(it.data) }.map { it.data as T }
|
||||
}
|
||||
fun <T : ContractState> outputsOfType(clazz: Class<T>): List<T> = outputs.mapNotNull { clazz.castIfPossible(it.data) }
|
||||
|
||||
inline fun <reified T : ContractState> outputsOfType(): List<T> = outputsOfType(T::class.java)
|
||||
|
||||
/**
|
||||
* Helper to simplify filtering outputs according to a [Predicate].
|
||||
* @param predicate A filtering function taking a state of type T and returning true if it should be included in the list.
|
||||
* The class filtering is applied before the predicate.
|
||||
* @param clazz The class type used for filtering via an [Class.isInstance] check.
|
||||
* Clazz must be an extension of [ContractState].
|
||||
* @param predicate A filtering function taking a state of type T and returning true if it should be included in the list.
|
||||
* The class filtering is applied before the predicate.
|
||||
* @return the possibly empty list of output states matching the predicate and clazz restrictions.
|
||||
*/
|
||||
fun <T : ContractState> filterOutputs(predicate: Predicate<T>, clazz: Class<T>): List<T> {
|
||||
fun <T : ContractState> filterOutputs(clazz: Class<T>, predicate: Predicate<T>): List<T> {
|
||||
return outputsOfType(clazz).filter { predicate.test(it) }
|
||||
}
|
||||
|
||||
inline fun <reified T : ContractState> filterOutputs(crossinline predicate: (T) -> Boolean): List<T> {
|
||||
return filterOutputs(T::class.java, Predicate { predicate(it) })
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper to simplify finding a single output matching a [Predicate].
|
||||
* @param predicate A filtering function taking a state of type T and returning true if this is the desired item.
|
||||
* The class filtering is applied before the predicate.
|
||||
* @param clazz The class type used for filtering via an [Class.isInstance] check.
|
||||
* Clazz must be an extension of [ContractState].
|
||||
* @param predicate A filtering function taking a state of type T and returning true if this is the desired item.
|
||||
* The class filtering is applied before the predicate.
|
||||
* @return the single item matching the predicate.
|
||||
* @throws IllegalArgumentException if no item, or multiple items are found matching the requirements.
|
||||
*/
|
||||
fun <T : ContractState> findOutput(predicate: Predicate<T>, clazz: Class<T>): T {
|
||||
return filterOutputs(predicate, clazz).single()
|
||||
fun <T : ContractState> findOutput(clazz: Class<T>, predicate: Predicate<T>): T {
|
||||
return outputsOfType(clazz).single { predicate.test(it) }
|
||||
}
|
||||
|
||||
inline fun <reified T : ContractState> findOutput(crossinline predicate: (T) -> Boolean): T {
|
||||
return findOutput(T::class.java, Predicate { predicate(it) })
|
||||
}
|
||||
|
||||
/**
|
||||
@ -126,55 +133,44 @@ abstract class BaseTransaction(
|
||||
* @return the possibly empty list of output [StateAndRef<T>] states matching the clazz restriction.
|
||||
*/
|
||||
fun <T : ContractState> outRefsOfType(clazz: Class<T>): List<StateAndRef<T>> {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
return outputs.mapIndexed { index, state -> StateAndRef(state, StateRef(id, index)) }
|
||||
.filter { clazz.isInstance(it.state.data) }
|
||||
.map { it as StateAndRef<T> }
|
||||
return outputs.mapIndexedNotNull { index, state ->
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
clazz.castIfPossible(state.data)?.let { StateAndRef(state as TransactionState<T>, StateRef(id, index)) }
|
||||
}
|
||||
}
|
||||
|
||||
inline fun <reified T : ContractState> outRefsOfType(): List<StateAndRef<T>> = outRefsOfType(T::class.java)
|
||||
|
||||
/**
|
||||
* Helper to simplify filtering output [StateAndRef] items according to a [Predicate].
|
||||
* @param predicate A filtering function taking a state of type T and returning true if it should be included in the list.
|
||||
* The class filtering is applied before the predicate.
|
||||
* @param clazz The class type used for filtering via an [Class.isInstance] check.
|
||||
* Clazz must be an extension of [ContractState].
|
||||
* @param predicate A filtering function taking a state of type T and returning true if it should be included in the list.
|
||||
* The class filtering is applied before the predicate.
|
||||
* @return the possibly empty list of output [StateAndRef] states matching the predicate and clazz restrictions.
|
||||
*/
|
||||
fun <T : ContractState> filterOutRefs(predicate: Predicate<T>, clazz: Class<T>): List<StateAndRef<T>> {
|
||||
fun <T : ContractState> filterOutRefs(clazz: Class<T>, predicate: Predicate<T>): List<StateAndRef<T>> {
|
||||
return outRefsOfType(clazz).filter { predicate.test(it.state.data) }
|
||||
}
|
||||
|
||||
inline fun <reified T : ContractState> filterOutRefs(crossinline predicate: (T) -> Boolean): List<StateAndRef<T>> {
|
||||
return filterOutRefs(T::class.java, Predicate { predicate(it) })
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper to simplify finding a single output [StateAndRef] matching a [Predicate].
|
||||
* @param predicate A filtering function taking a state of type T and returning true if this is the desired item.
|
||||
* The class filtering is applied before the predicate.
|
||||
* @param clazz The class type used for filtering via an [Class.isInstance] check.
|
||||
* Clazz must be an extension of [ContractState].
|
||||
* @param predicate A filtering function taking a state of type T and returning true if this is the desired item.
|
||||
* The class filtering is applied before the predicate.
|
||||
* @return the single [StateAndRef] item matching the predicate.
|
||||
* @throws IllegalArgumentException if no item, or multiple items are found matching the requirements.
|
||||
*/
|
||||
fun <T : ContractState> findOutRef(predicate: Predicate<T>, clazz: Class<T>): StateAndRef<T> {
|
||||
return filterOutRefs(predicate, clazz).single()
|
||||
}
|
||||
|
||||
//Kotlin extension methods to take advantage of Kotlin's smart type inference when querying the LedgerTransaction
|
||||
inline fun <reified T : ContractState> outputsOfType(): List<T> = this.outputsOfType(T::class.java)
|
||||
|
||||
inline fun <reified T : ContractState> filterOutputs(crossinline predicate: (T) -> Boolean): List<T> {
|
||||
return filterOutputs(Predicate { predicate(it) }, T::class.java)
|
||||
}
|
||||
|
||||
inline fun <reified T : ContractState> findOutput(crossinline predicate: (T) -> Boolean): T {
|
||||
return findOutput(Predicate { predicate(it) }, T::class.java)
|
||||
}
|
||||
|
||||
inline fun <reified T : ContractState> outRefsOfType(): List<StateAndRef<T>> = this.outRefsOfType(T::class.java)
|
||||
|
||||
inline fun <reified T : ContractState> filterOutRefs(crossinline predicate: (T) -> Boolean): List<StateAndRef<T>> {
|
||||
return filterOutRefs(Predicate { predicate(it) }, T::class.java)
|
||||
fun <T : ContractState> findOutRef(clazz: Class<T>, predicate: Predicate<T>): StateAndRef<T> {
|
||||
return outRefsOfType(clazz).single { predicate.test(it.state.data) }
|
||||
}
|
||||
|
||||
inline fun <reified T : ContractState> findOutRef(crossinline predicate: (T) -> Boolean): StateAndRef<T> {
|
||||
return findOutRef(Predicate { predicate(it) }, T::class.java)
|
||||
return findOutRef(T::class.java, Predicate { predicate(it) })
|
||||
}
|
||||
}
|
@ -3,6 +3,7 @@ package net.corda.core.transactions
|
||||
import net.corda.core.contracts.*
|
||||
import net.corda.core.crypto.SecureHash
|
||||
import net.corda.core.identity.Party
|
||||
import net.corda.core.internal.castIfPossible
|
||||
import net.corda.core.serialization.CordaSerializable
|
||||
import java.security.PublicKey
|
||||
import java.util.*
|
||||
@ -51,7 +52,7 @@ class LedgerTransaction(
|
||||
* @return The [StateAndRef]
|
||||
*/
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
fun <T : ContractState> inRef(index: Int) = inputs[index] as StateAndRef<T>
|
||||
fun <T : ContractState> inRef(index: Int): StateAndRef<T> = inputs[index] as StateAndRef<T>
|
||||
|
||||
/**
|
||||
* Verifies this transaction and throws an exception if not valid, depending on the type. For general transactions:
|
||||
@ -158,10 +159,9 @@ class LedgerTransaction(
|
||||
* [clazz] must be an extension of [ContractState].
|
||||
* @return the possibly empty list of inputs matching the clazz restriction.
|
||||
*/
|
||||
fun <T : ContractState> inputsOfType(clazz: Class<T>): List<T> {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
return inputs.map { it.state.data }.filterIsInstance(clazz)
|
||||
}
|
||||
fun <T : ContractState> inputsOfType(clazz: Class<T>): List<T> = inputs.mapNotNull { clazz.castIfPossible(it.state.data) }
|
||||
|
||||
inline fun <reified T : ContractState> inputsOfType(): List<T> = inputsOfType(T::class.java)
|
||||
|
||||
/**
|
||||
* Helper to simplify getting all inputs states of a particular class, interface, or base class.
|
||||
@ -171,18 +171,26 @@ class LedgerTransaction(
|
||||
*/
|
||||
fun <T : ContractState> inRefsOfType(clazz: Class<T>): List<StateAndRef<T>> {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
return inputs.filter { clazz.isInstance(it.state.data) }.map { it as StateAndRef<T> }
|
||||
return inputs.mapNotNull { if (clazz.isInstance(it.state.data)) it as StateAndRef<T> else null }
|
||||
}
|
||||
|
||||
inline fun <reified T : ContractState> inRefsOfType(): List<StateAndRef<T>> = inRefsOfType(T::class.java)
|
||||
|
||||
/**
|
||||
* Helper to simplify filtering inputs according to a [Predicate].
|
||||
* @param predicate A filtering function taking a state of type T and returning true if it should be included in the list.
|
||||
* The class filtering is applied before the predicate.
|
||||
* @param clazz The class type used for filtering via an [Class.isInstance] check.
|
||||
* [clazz] must be an extension of [ContractState].
|
||||
* @param predicate A filtering function taking a state of type T and returning true if it should be included in the list.
|
||||
* The class filtering is applied before the predicate.
|
||||
* @return the possibly empty list of input states matching the predicate and clazz restrictions.
|
||||
*/
|
||||
fun <T : ContractState> filterInputs(predicate: Predicate<T>, clazz: Class<T>): List<T> = inputsOfType(clazz).filter { predicate.test(it) }
|
||||
fun <T : ContractState> filterInputs(clazz: Class<T>, predicate: Predicate<T>): List<T> {
|
||||
return inputsOfType(clazz).filter { predicate.test(it) }
|
||||
}
|
||||
|
||||
inline fun <reified T : ContractState> filterInputs(crossinline predicate: (T) -> Boolean): List<T> {
|
||||
return filterInputs(T::class.java, Predicate { predicate(it) })
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper to simplify filtering inputs according to a [Predicate].
|
||||
@ -192,29 +200,47 @@ class LedgerTransaction(
|
||||
* [clazz] must be an extension of [ContractState].
|
||||
* @return the possibly empty list of inputs [StateAndRef] matching the predicate and clazz restrictions.
|
||||
*/
|
||||
fun <T : ContractState> filterInRefs(predicate: Predicate<T>, clazz: Class<T>): List<StateAndRef<T>> = inRefsOfType(clazz).filter { predicate.test(it.state.data) }
|
||||
fun <T : ContractState> filterInRefs(clazz: Class<T>, predicate: Predicate<T>): List<StateAndRef<T>> {
|
||||
return inRefsOfType(clazz).filter { predicate.test(it.state.data) }
|
||||
}
|
||||
|
||||
inline fun <reified T : ContractState> filterInRefs(crossinline predicate: (T) -> Boolean): List<StateAndRef<T>> {
|
||||
return filterInRefs(T::class.java, Predicate { predicate(it) })
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper to simplify finding a single input [ContractState] matching a [Predicate].
|
||||
* @param predicate A filtering function taking a state of type T and returning true if this is the desired item.
|
||||
* The class filtering is applied before the predicate.
|
||||
* @param clazz The class type used for filtering via an [Class.isInstance] check.
|
||||
* [clazz] must be an extension of ContractState.
|
||||
* @param predicate A filtering function taking a state of type T and returning true if this is the desired item.
|
||||
* The class filtering is applied before the predicate.
|
||||
* @return the single item matching the predicate.
|
||||
* @throws IllegalArgumentException if no item, or multiple items are found matching the requirements.
|
||||
*/
|
||||
fun <T : ContractState> findInput(predicate: Predicate<T>, clazz: Class<T>): T = filterInputs(predicate, clazz).single()
|
||||
fun <T : ContractState> findInput(clazz: Class<T>, predicate: Predicate<T>): T {
|
||||
return inputsOfType(clazz).single { predicate.test(it) }
|
||||
}
|
||||
|
||||
inline fun <reified T : ContractState> findInput(crossinline predicate: (T) -> Boolean): T {
|
||||
return findInput(T::class.java, Predicate { predicate(it) })
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper to simplify finding a single input matching a [Predicate].
|
||||
* @param predicate A filtering function taking a state of type T and returning true if this is the desired item.
|
||||
* The class filtering is applied before the predicate.
|
||||
* @param clazz The class type used for filtering via an [Class.isInstance] check.
|
||||
* [clazz] must be an extension of ContractState.
|
||||
* @param predicate A filtering function taking a state of type T and returning true if this is the desired item.
|
||||
* The class filtering is applied before the predicate.
|
||||
* @return the single item matching the predicate.
|
||||
* @throws IllegalArgumentException if no item, or multiple items are found matching the requirements.
|
||||
*/
|
||||
fun <T : ContractState> findInRef(predicate: Predicate<T>, clazz: Class<T>): StateAndRef<T> = filterInRefs(predicate, clazz).single()
|
||||
fun <T : ContractState> findInRef(clazz: Class<T>, predicate: Predicate<T>): StateAndRef<T> {
|
||||
return inRefsOfType(clazz).single { predicate.test(it.state.data) }
|
||||
}
|
||||
|
||||
inline fun <reified T : ContractState> findInRef(crossinline predicate: (T) -> Boolean): StateAndRef<T> {
|
||||
return findInRef(T::class.java, Predicate { predicate(it) })
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper to simplify getting an indexed command.
|
||||
@ -230,34 +256,44 @@ class LedgerTransaction(
|
||||
* @return the possibly empty list of commands with [CommandData] values matching the clazz restriction.
|
||||
*/
|
||||
fun <T : CommandData> commandsOfType(clazz: Class<T>): List<Command> {
|
||||
return commands.filter { clazz.isInstance(it.value) }.map { Command(it.value, it.signers) }
|
||||
return commands.mapNotNull { (signers, _, value) -> clazz.castIfPossible(value)?.let { Command(it, signers) } }
|
||||
}
|
||||
|
||||
inline fun <reified T : CommandData> commandsOfType(): List<Command> = commandsOfType(T::class.java)
|
||||
|
||||
/**
|
||||
* Helper to simplify filtering [Command] items according to a [Predicate].
|
||||
* @param predicate A filtering function taking a [CommandData] item of type T and returning true if it should be included in the list.
|
||||
* The class filtering is applied before the predicate.
|
||||
* @param clazz The class type used for filtering via an [Class.isInstance] check.
|
||||
* [clazz] must be an extension of [CommandData].
|
||||
* @param predicate A filtering function taking a [CommandData] item of type T and returning true if it should be included in the list.
|
||||
* The class filtering is applied before the predicate.
|
||||
* @return the possibly empty list of [Command] items with [CommandData] values matching the predicate and clazz restrictions.
|
||||
*/
|
||||
fun <T : CommandData> filterCommands(predicate: Predicate<T>, clazz: Class<T>): List<Command> {
|
||||
fun <T : CommandData> filterCommands(clazz: Class<T>, predicate: Predicate<T>): List<Command> {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
return commandsOfType(clazz).filter { predicate.test(it.value as T) }
|
||||
}
|
||||
|
||||
inline fun <reified T : CommandData> filterCommands(crossinline predicate: (T) -> Boolean): List<Command> {
|
||||
return filterCommands(T::class.java, Predicate { predicate(it) })
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper to simplify finding a single [Command] items according to a [Predicate].
|
||||
* @param predicate A filtering function taking a [CommandData] item of type T and returning true if it should be included in the list.
|
||||
* The class filtering is applied before the predicate.
|
||||
* @param clazz The class type used for filtering via an [Class.isInstance] check.
|
||||
* [clazz] must be an extension of [CommandData].
|
||||
* @param predicate A filtering function taking a [CommandData] item of type T and returning true if it should be included in the list.
|
||||
* The class filtering is applied before the predicate.
|
||||
* @return the [Command] item with [CommandData] values matching the predicate and clazz restrictions.
|
||||
* @throws IllegalArgumentException if no items, or multiple items matched the requirements.
|
||||
*/
|
||||
fun <T : CommandData> findCommand(predicate: Predicate<T>, clazz: Class<T>): Command {
|
||||
return filterCommands(predicate, clazz).single()
|
||||
fun <T : CommandData> findCommand(clazz: Class<T>, predicate: Predicate<T>): Command {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
return commandsOfType(clazz).single { predicate.test(it.value as T) }
|
||||
}
|
||||
|
||||
inline fun <reified T : CommandData> findCommand(crossinline predicate: (T) -> Boolean): Command {
|
||||
return findCommand(T::class.java, Predicate { predicate(it) })
|
||||
}
|
||||
|
||||
/**
|
||||
@ -273,37 +309,6 @@ class LedgerTransaction(
|
||||
* @return The Attachment with the matching id.
|
||||
* @throws IllegalArgumentException if no item matches the id.
|
||||
*/
|
||||
fun getAttachment(id: SecureHash): Attachment = attachments.single { it.id == id }
|
||||
|
||||
//Kotlin extension methods to take advantage of Kotlin's smart type inference when querying the LedgerTransaction
|
||||
inline fun <reified T : ContractState> inputsOfType(): List<T> = this.inputsOfType(T::class.java)
|
||||
|
||||
inline fun <reified T : ContractState> inRefsOfType(): List<StateAndRef<T>> = this.inRefsOfType(T::class.java)
|
||||
|
||||
inline fun <reified T : ContractState> filterInputs(crossinline predicate: (T) -> Boolean): List<T> {
|
||||
return filterInputs(Predicate { predicate(it) }, T::class.java)
|
||||
}
|
||||
|
||||
inline fun <reified T : ContractState> filterInRefs(crossinline predicate: (T) -> Boolean): List<StateAndRef<T>> {
|
||||
return filterInRefs(Predicate { predicate(it) }, T::class.java)
|
||||
}
|
||||
|
||||
inline fun <reified T : ContractState> findInRef(crossinline predicate: (T) -> Boolean): StateAndRef<T> {
|
||||
return findInRef(Predicate { predicate(it) }, T::class.java)
|
||||
}
|
||||
|
||||
inline fun <reified T : ContractState> findInput(crossinline predicate: (T) -> Boolean): T {
|
||||
return findInput(Predicate { predicate(it) }, T::class.java)
|
||||
}
|
||||
|
||||
inline fun <reified T : CommandData> commandsOfType(): List<Command> = this.commandsOfType(T::class.java)
|
||||
|
||||
inline fun <reified T : CommandData> filterCommands(crossinline predicate: (T) -> Boolean): List<Command> {
|
||||
return filterCommands(Predicate { predicate(it) }, T::class.java)
|
||||
}
|
||||
|
||||
inline fun <reified T : CommandData> findCommand(crossinline predicate: (T) -> Boolean): Command {
|
||||
return findCommand(Predicate { predicate(it) }, T::class.java)
|
||||
}
|
||||
fun getAttachment(id: SecureHash): Attachment = attachments.first { it.id == id }
|
||||
}
|
||||
|
||||
|
@ -189,7 +189,7 @@ class LedgerTransactionQueryTests : TestDependencyInjectionBase() {
|
||||
@Test
|
||||
fun `Filtered Input Tests`() {
|
||||
val ltx = makeDummyTransaction()
|
||||
val intStates = ltx.filterInputs(Predicate { it.data.rem(2) == 0 }, IntTypeDummyState::class.java)
|
||||
val intStates = ltx.filterInputs(IntTypeDummyState::class.java, Predicate { it.data.rem(2) == 0 })
|
||||
assertEquals(3, intStates.size)
|
||||
assertEquals(listOf(0, 2, 4), intStates.map { it.data })
|
||||
val stringStates: List<StringTypeDummyState> = ltx.filterInputs { it.data == "3" }
|
||||
@ -199,7 +199,7 @@ class LedgerTransactionQueryTests : TestDependencyInjectionBase() {
|
||||
@Test
|
||||
fun `Filtered InRef Tests`() {
|
||||
val ltx = makeDummyTransaction()
|
||||
val intStates = ltx.filterInRefs(Predicate { it.data.rem(2) == 0 }, IntTypeDummyState::class.java)
|
||||
val intStates = ltx.filterInRefs(IntTypeDummyState::class.java, Predicate { it.data.rem(2) == 0 })
|
||||
assertEquals(3, intStates.size)
|
||||
assertEquals(listOf(0, 2, 4), intStates.map { it.state.data.data })
|
||||
assertEquals(listOf(ltx.inputs[0], ltx.inputs[4], ltx.inputs[8]), intStates)
|
||||
@ -211,7 +211,7 @@ class LedgerTransactionQueryTests : TestDependencyInjectionBase() {
|
||||
@Test
|
||||
fun `Filtered Output Tests`() {
|
||||
val ltx = makeDummyTransaction()
|
||||
val intStates = ltx.filterOutputs(Predicate { it.data.rem(2) == 0 }, IntTypeDummyState::class.java)
|
||||
val intStates = ltx.filterOutputs(IntTypeDummyState::class.java, Predicate { it.data.rem(2) == 0 })
|
||||
assertEquals(3, intStates.size)
|
||||
assertEquals(listOf(0, 2, 4), intStates.map { it.data })
|
||||
val stringStates: List<StringTypeDummyState> = ltx.filterOutputs { it.data == "3" }
|
||||
@ -221,7 +221,7 @@ class LedgerTransactionQueryTests : TestDependencyInjectionBase() {
|
||||
@Test
|
||||
fun `Filtered OutRef Tests`() {
|
||||
val ltx = makeDummyTransaction()
|
||||
val intStates = ltx.filterOutRefs(Predicate { it.data.rem(2) == 0 }, IntTypeDummyState::class.java)
|
||||
val intStates = ltx.filterOutRefs(IntTypeDummyState::class.java, Predicate { it.data.rem(2) == 0 })
|
||||
assertEquals(3, intStates.size)
|
||||
assertEquals(listOf(0, 2, 4), intStates.map { it.state.data.data })
|
||||
assertEquals(listOf(0, 4, 8), intStates.map { it.ref.index })
|
||||
@ -235,7 +235,7 @@ class LedgerTransactionQueryTests : TestDependencyInjectionBase() {
|
||||
@Test
|
||||
fun `Filtered Commands Tests`() {
|
||||
val ltx = makeDummyTransaction()
|
||||
val intCmds1 = ltx.filterCommands(Predicate { it.id.rem(2) == 0 }, Commands.Cmd1::class.java)
|
||||
val intCmds1 = ltx.filterCommands(Commands.Cmd1::class.java, Predicate { it.id.rem(2) == 0 })
|
||||
assertEquals(3, intCmds1.size)
|
||||
assertEquals(listOf(0, 2, 4), intCmds1.map { (it.value as Commands.Cmd1).id })
|
||||
val intCmds2 = ltx.filterCommands<Commands.Cmd2> { it.id == 3 }
|
||||
@ -245,7 +245,7 @@ class LedgerTransactionQueryTests : TestDependencyInjectionBase() {
|
||||
@Test
|
||||
fun `Find Input Tests`() {
|
||||
val ltx = makeDummyTransaction()
|
||||
val intState = ltx.findInput(Predicate { it.data == 4 }, IntTypeDummyState::class.java)
|
||||
val intState = ltx.findInput(IntTypeDummyState::class.java, Predicate { it.data == 4 })
|
||||
assertEquals(ltx.getInput(8), intState)
|
||||
val stringState: StringTypeDummyState = ltx.findInput { it.data == "3" }
|
||||
assertEquals(ltx.getInput(7), stringState)
|
||||
@ -254,7 +254,7 @@ class LedgerTransactionQueryTests : TestDependencyInjectionBase() {
|
||||
@Test
|
||||
fun `Find InRef Tests`() {
|
||||
val ltx = makeDummyTransaction()
|
||||
val intState = ltx.findInRef(Predicate { it.data == 4 }, IntTypeDummyState::class.java)
|
||||
val intState = ltx.findInRef(IntTypeDummyState::class.java, Predicate { it.data == 4 })
|
||||
assertEquals(ltx.inRef(8), intState)
|
||||
val stringState: StateAndRef<StringTypeDummyState> = ltx.findInRef { it.data == "3" }
|
||||
assertEquals(ltx.inRef(7), stringState)
|
||||
@ -263,7 +263,7 @@ class LedgerTransactionQueryTests : TestDependencyInjectionBase() {
|
||||
@Test
|
||||
fun `Find Output Tests`() {
|
||||
val ltx = makeDummyTransaction()
|
||||
val intState = ltx.findOutput(Predicate { it.data == 4 }, IntTypeDummyState::class.java)
|
||||
val intState = ltx.findOutput(IntTypeDummyState::class.java, Predicate { it.data == 4 })
|
||||
assertEquals(ltx.getOutput(8), intState)
|
||||
val stringState: StringTypeDummyState = ltx.findOutput { it.data == "3" }
|
||||
assertEquals(ltx.getOutput(7), stringState)
|
||||
@ -272,7 +272,7 @@ class LedgerTransactionQueryTests : TestDependencyInjectionBase() {
|
||||
@Test
|
||||
fun `Find OutRef Tests`() {
|
||||
val ltx = makeDummyTransaction()
|
||||
val intState = ltx.findOutRef(Predicate { it.data == 4 }, IntTypeDummyState::class.java)
|
||||
val intState = ltx.findOutRef(IntTypeDummyState::class.java, Predicate { it.data == 4 })
|
||||
assertEquals(ltx.outRef(8), intState)
|
||||
val stringState: StateAndRef<StringTypeDummyState> = ltx.findOutRef { it.data == "3" }
|
||||
assertEquals(ltx.outRef(7), stringState)
|
||||
@ -281,7 +281,7 @@ class LedgerTransactionQueryTests : TestDependencyInjectionBase() {
|
||||
@Test
|
||||
fun `Find Commands Tests`() {
|
||||
val ltx = makeDummyTransaction()
|
||||
val intCmd1 = ltx.findCommand(Predicate { it.id == 2 }, Commands.Cmd1::class.java)
|
||||
val intCmd1 = ltx.findCommand(Commands.Cmd1::class.java, Predicate { it.id == 2 })
|
||||
assertEquals(ltx.getCommand(4), intCmd1)
|
||||
val intCmd2 = ltx.findCommand<Commands.Cmd2> { it.id == 3 }
|
||||
assertEquals(ltx.getCommand(7), intCmd2)
|
||||
|
@ -1,5 +1,6 @@
|
||||
package net.corda.node.services.database
|
||||
|
||||
import net.corda.core.internal.castIfPossible
|
||||
import net.corda.core.schemas.MappedSchema
|
||||
import net.corda.core.utilities.loggerFor
|
||||
import net.corda.node.services.api.SchemaService
|
||||
@ -100,17 +101,14 @@ class HibernateConfiguration(val schemaService: SchemaService, val useDefaultLog
|
||||
|
||||
override fun supportsAggressiveRelease(): Boolean = true
|
||||
|
||||
override fun getConnection(): Connection =
|
||||
DatabaseTransactionManager.newTransaction(Connection.TRANSACTION_REPEATABLE_READ).connection
|
||||
|
||||
override fun <T : Any?> unwrap(unwrapType: Class<T>): T {
|
||||
try {
|
||||
return unwrapType.cast(this)
|
||||
} catch(e: ClassCastException) {
|
||||
throw UnknownUnwrapTypeException(unwrapType)
|
||||
}
|
||||
override fun getConnection(): Connection {
|
||||
return DatabaseTransactionManager.newTransaction(Connection.TRANSACTION_REPEATABLE_READ).connection
|
||||
}
|
||||
|
||||
override fun isUnwrappableAs(unwrapType: Class<*>?): Boolean = (unwrapType == NodeDatabaseConnectionProvider::class.java)
|
||||
override fun <T : Any?> unwrap(unwrapType: Class<T>): T {
|
||||
return unwrapType.castIfPossible(this) ?: throw UnknownUnwrapTypeException(unwrapType)
|
||||
}
|
||||
|
||||
override fun isUnwrappableAs(unwrapType: Class<*>?): Boolean = unwrapType == NodeDatabaseConnectionProvider::class.java
|
||||
}
|
||||
}
|
@ -4,6 +4,7 @@ import net.corda.core.flows.FlowException
|
||||
import net.corda.core.flows.FlowLogic
|
||||
import net.corda.core.flows.UnexpectedFlowEndException
|
||||
import net.corda.core.identity.Party
|
||||
import net.corda.core.internal.castIfPossible
|
||||
import net.corda.core.serialization.CordaSerializable
|
||||
import net.corda.core.utilities.UntrustworthyData
|
||||
|
||||
@ -42,10 +43,7 @@ data class ErrorSessionEnd(override val recipientSessionId: Long, val errorRespo
|
||||
data class ReceivedSessionMessage<out M : ExistingSessionMessage>(val sender: Party, val message: M)
|
||||
|
||||
fun <T> ReceivedSessionMessage<SessionData>.checkPayloadIs(type: Class<T>): UntrustworthyData<T> {
|
||||
if (type.isInstance(message.payload)) {
|
||||
return UntrustworthyData(type.cast(message.payload))
|
||||
} else {
|
||||
throw UnexpectedFlowEndException("We were expecting a ${type.name} from $sender but we instead got a " +
|
||||
"${message.payload.javaClass.name} (${message.payload})")
|
||||
}
|
||||
return type.castIfPossible(message.payload)?.let { UntrustworthyData(it) } ?:
|
||||
throw UnexpectedFlowEndException("We were expecting a ${type.name} from $sender but we instead got a " +
|
||||
"${message.payload.javaClass.name} (${message.payload})")
|
||||
}
|
||||
|
@ -17,6 +17,7 @@ import net.corda.core.flows.FlowInitiator
|
||||
import net.corda.core.flows.FlowLogic
|
||||
import net.corda.core.flows.StateMachineRunId
|
||||
import net.corda.core.identity.Party
|
||||
import net.corda.core.internal.castIfPossible
|
||||
import net.corda.core.messaging.DataFeed
|
||||
import net.corda.core.serialization.*
|
||||
import net.corda.core.serialization.SerializationDefaults.CHECKPOINT_CONTEXT
|
||||
@ -145,10 +146,9 @@ class StateMachineManager(val serviceHub: ServiceHubInternal,
|
||||
fun <P : FlowLogic<T>, T> findStateMachines(flowClass: Class<P>): List<Pair<P, ListenableFuture<T>>> {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
return mutex.locked {
|
||||
stateMachines.keys
|
||||
.map { it.logic }
|
||||
.filterIsInstance(flowClass)
|
||||
.map { it to (it.stateMachine as FlowStateMachineImpl<T>).resultFuture }
|
||||
stateMachines.keys.mapNotNull {
|
||||
flowClass.castIfPossible(it.logic)?.let { it to (it.stateMachine as FlowStateMachineImpl<T>).resultFuture }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -380,7 +380,7 @@ class StateMachineManager(val serviceHub: ServiceHubInternal,
|
||||
|
||||
private fun deserializeFiber(checkpoint: Checkpoint, logger: Logger): FlowStateMachineImpl<*>? {
|
||||
return try {
|
||||
checkpoint.serializedFiber.deserialize<FlowStateMachineImpl<*>>(context = CHECKPOINT_CONTEXT.withTokenContext(serializationContext)).apply { fromCheckpoint = true }
|
||||
checkpoint.serializedFiber.deserialize(context = CHECKPOINT_CONTEXT.withTokenContext(serializationContext)).apply { fromCheckpoint = true }
|
||||
} catch (t: Throwable) {
|
||||
logger.error("Encountered unrestorable checkpoint!", t)
|
||||
null
|
||||
|
Loading…
x
Reference in New Issue
Block a user