Minor: move the groupBy method to TransactionForVerification where it belongs.

This commit is contained in:
Mike Hearn 2015-11-20 19:36:20 +01:00
parent a8e34a2bb2
commit b0b8c74c25
5 changed files with 49 additions and 56 deletions

View File

@ -66,7 +66,7 @@ object Cash : Contract {
override fun verify(tx: TransactionForVerification) {
// Each group is a set of input/output states with distinct (deposit, currency) attributes. These types
// of cash are not fungible and must be kept separated for bookkeeping purposes.
val groups = groupStates<Cash.State>(tx.inStates, tx.outStates) { Pair(it.deposit, it.amount.currency) }
val groups = tx.groupStates<Cash.State>() { Pair(it.deposit, it.amount.currency) }
for ((inputs, outputs) in groups) {
requireThat {

View File

@ -43,7 +43,7 @@ object CommercialPaper : Contract {
override fun verify(tx: TransactionForVerification) {
// Group by everything except owner: any modification to the CP at all is considered changing it fundamentally.
val groups = groupStates<State>(tx.inStates, tx.outStates) { it.withoutOwner() }
val groups = tx.groupStates<State>() { it.withoutOwner() }
// There are two possible things that can be done with this CP. The first is trading it. The second is redeeming
// it for cash on or after the maturity date.

View File

@ -1,6 +1,7 @@
package contracts;
import core.*;
import core.TransactionForVerification.*;
import core.serialization.*;
import kotlin.*;
import org.jetbrains.annotations.*;
@ -77,8 +78,8 @@ public class JavaCommercialPaper implements Contract {
public void verify(@NotNull TransactionForVerification tx) {
// There are two possible things that can be done with CP. The first is trading it. The second is redeeming it
// for cash on or after the maturity date.
List<InOutGroup<State>> groups = ContractTools.groupStates(State.class, tx.getInStates(), tx.getOutStates(),
state -> new Pair<>(state.getIssuance(), state.faceValue.getCurrency()));
List<InOutGroup<State>> groups =
tx.groupStates(State.class, state -> new Pair<>(state.getIssuance(), state.faceValue.getCurrency()));
// Find the command that instructs us what to do and check there's exactly one.
AuthenticatedObject<Command> cmd = requireSingleCommand(tx.getCommands(), Commands.class);

View File

@ -1,52 +0,0 @@
@file:JvmName("ContractTools")
package core
import java.util.*
/**
* Utilities for contract writers to incorporate into their logic.
*/
data class InOutGroup<T : ContractState>(val inputs: List<T>, val outputs: List<T>)
// For Java users.
fun <T : ContractState> groupStates(ofType: Class<T>, allInputs: List<ContractState>,
allOutputs: List<ContractState>, selector: (T) -> Any): List<InOutGroup<T>> {
val inputs = allInputs.filterIsInstance(ofType)
val outputs = allOutputs.filterIsInstance(ofType)
val inGroups = inputs.groupBy(selector)
val outGroups = outputs.groupBy(selector)
@Suppress("DEPRECATION")
return groupStatesInternal(inGroups, outGroups)
}
// For Kotlin users: this version has nicer syntax and avoids reflection/object creation for the lambda.
inline fun <reified T : ContractState> groupStates(allInputs: List<ContractState>,
allOutputs: List<ContractState>,
selector: (T) -> Any): List<InOutGroup<T>> {
val inputs = allInputs.filterIsInstance<T>()
val outputs = allOutputs.filterIsInstance<T>()
val inGroups = inputs.groupBy(selector)
val outGroups = outputs.groupBy(selector)
@Suppress("DEPRECATION")
return groupStatesInternal(inGroups, outGroups)
}
@Deprecated("Do not use this directly: exposed as public only due to function inlining")
fun <T : ContractState> groupStatesInternal(inGroups: Map<Any, List<T>>, outGroups: Map<Any, List<T>>): List<InOutGroup<T>> {
val result = ArrayList<InOutGroup<T>>()
for ((k, v) in inGroups.entries)
result.add(InOutGroup(v, outGroups[k] ?: emptyList()))
for ((k, v) in outGroups.entries) {
if (inGroups[k] == null)
result.add(InOutGroup(emptyList(), v))
}
return result
}

View File

@ -207,6 +207,50 @@ data class TransactionForVerification(val inStates: List<ContractState>,
}
}
}
/**
* Utilities for contract writers to incorporate into their logic.
*/
data class InOutGroup<T : ContractState>(val inputs: List<T>, val outputs: List<T>)
// For Java users.
fun <T : ContractState> groupStates(ofType: Class<T>, selector: (T) -> Any): List<InOutGroup<T>> {
val inputs = inStates.filterIsInstance(ofType)
val outputs = outStates.filterIsInstance(ofType)
val inGroups = inputs.groupBy(selector)
val outGroups = outputs.groupBy(selector)
@Suppress("DEPRECATION")
return groupStatesInternal(inGroups, outGroups)
}
// For Kotlin users: this version has nicer syntax and avoids reflection/object creation for the lambda.
inline fun <reified T : ContractState> groupStates(selector: (T) -> Any): List<InOutGroup<T>> {
val inputs = inStates.filterIsInstance<T>()
val outputs = outStates.filterIsInstance<T>()
val inGroups = inputs.groupBy(selector)
val outGroups = outputs.groupBy(selector)
@Suppress("DEPRECATION")
return groupStatesInternal(inGroups, outGroups)
}
@Deprecated("Do not use this directly: exposed as public only due to function inlining")
fun <T : ContractState> groupStatesInternal(inGroups: Map<Any, List<T>>, outGroups: Map<Any, List<T>>): List<InOutGroup<T>> {
val result = ArrayList<InOutGroup<T>>()
for ((k, v) in inGroups.entries)
result.add(InOutGroup(v, outGroups[k] ?: emptyList()))
for ((k, v) in outGroups.entries) {
if (inGroups[k] == null)
result.add(InOutGroup(emptyList(), v))
}
return result
}
}
/** Thrown if a verification fails due to a contract rejection. */