universal: prettyPrint

This commit is contained in:
Sofus Mortensen 2017-01-05 23:13:04 +01:00
parent 4fdeee5bf8
commit 306a3cdff7
5 changed files with 193 additions and 121 deletions

View File

@ -40,6 +40,14 @@ class ActionsBuilder {
infix fun Party.or(party: Party) = setOf(this, party)
infix fun Set<Party>.or(party: Party) = this.plus(party)
fun String.givenThat(condition: Perceivable<Boolean>, init: ContractBuilder.() -> Arrangement): Action {
val b = ContractBuilder()
b.init()
val a = Action(this, condition, b.final())
actions.add(a)
return a
}
}
@Suppress("UNUSED")
@ -145,7 +153,7 @@ interface GivenThatResolve {
}
class ActionBuilder(val actors: Set<Party>) {
val actions = mutableListOf<Action>()
internal val actions = mutableListOf<Action>()
fun String.givenThat(condition: Perceivable<Boolean>, init: ContractBuilder.() -> Arrangement): Action {
val b = ContractBuilder()

View File

@ -82,9 +82,6 @@ fun signedByOneOf(actors: Collection<Party>): Perceivable<Boolean> =
else
actors.drop(1).fold(signedBy(actors.first())) { total, next -> total or signedBy(next) }
/**
* Perceivable based on time
*/

View File

@ -1,126 +1,187 @@
package net.corda.contracts.universal
import net.corda.core.crypto.CompositeKey
import net.corda.core.crypto.Party
import java.math.BigDecimal
import java.time.Instant
/**
* Created by sofusmortensen on 30/12/2016.
*/
private class PrettyPrint(arr : Arrangement) {
val parties = involvedParties(arr)
private val sb = StringBuilder()
private var indentLevel = 0
class PrettyPrint
{
val sb = StringBuilder()
// fun print
}
fun prettyPrintPerInstant(per: Perceivable<Instant>, indentArg : Int) {
val sb = StringBuilder()
var indent = indentArg
when (per) {
is Const -> {
print("\"${per.value}\"")
}
is StartDate -> {
print("startDate")
}
is EndDate -> {
print("endDate")
}
else -> print(per)
private var atStart = true
private fun print(msg: String) {
if (atStart)
repeat(indentLevel, { sb.append(' ') })
sb.append(msg)
atStart = false
}
}
fun prettyPrintPerBD(per: Perceivable<BigDecimal>, indentArg : Int) {
var indent = indentArg
private fun println(message: Any?) {
if (atStart)
repeat(indentLevel, { sb.append(' ') })
sb.appendln(message)
atStart = true
}
fun println(message: Any?)
private fun print(msg: Any?) {
if (atStart)
repeat(indentLevel, { sb.append(' ') })
sb.append(msg)
atStart = false
}
fun <T> indent(body: () -> T): T {
indentLevel += 2
val rv = body()
indentLevel -= 2
return rv
}
val partyMap = mutableMapOf<CompositeKey, String>()
val usedPartyNames = mutableSetOf<String>()
fun createPartyName(party : Party) : String
{
repeat(indent, { print(' ')})
System.out.println(message)
val parts = party.name.toLowerCase().split(' ')
var camelName = parts.drop(1).fold(parts.first()) {
s, i -> s + i.first().toUpperCase() + i.drop(1)
}
if (usedPartyNames.contains(camelName)) {
camelName += "_" + partyMap.size.toString()
}
partyMap.put(party.owningKey, camelName)
usedPartyNames.add(camelName)
return camelName
}
init {
parties.forEach {
println( "val ${createPartyName(it)} = Party(\"${it.name}\", \"${it.owningKey}\")" )
}
}
when (per) {
is PerceivableOperation<BigDecimal> -> {
prettyPrintPerBD(per.left, indent + 2)
when (per.op)
{
Operation.PLUS -> print(" + ")
Operation.MINUS -> print(" - ")
Operation.DIV -> print(" / ")
Operation.TIMES -> print(" * ")
else -> print(per.op)
fun prettyPrintPerBoolean(per: Perceivable<Boolean>) {
when (per) {
is Const -> {
print("\"${per.value}\"")
}
prettyPrintPerBD(per.right, indent + 2)
is PerceivableOr -> {
prettyPrintPerBoolean(per.left)
print(" or ")
prettyPrintPerBoolean(per.right)
}
is ActorPerceivable -> {
print("signedBy(${partyMap[per.actor.owningKey]})")
}
else -> print(per)
}
is Const -> {
print(per.value)
}
fun prettyPrintPerInstant(per: Perceivable<Instant>) {
when (per) {
is Const -> {
print("\"${per.value}\"")
}
is StartDate -> {
print("startDate")
}
is EndDate -> {
print("endDate")
}
else -> print(per)
}
is Interest -> {
println("Interest(")
prettyPrintPerBD(per.amount, indent + 2)
print(", \"${per.dayCountConvention}\", ")
prettyPrintPerBD(per.amount, indent)
print(", ")
prettyPrintPerInstant(per.start, indent)
print(", ")
prettyPrintPerInstant(per.end, indent)
print(")")
}
fun prettyPrintPerBD(per: Perceivable<BigDecimal>) {
when (per) {
is PerceivableOperation<BigDecimal> -> {
prettyPrintPerBD(per.left)
when (per.op) {
Operation.PLUS -> print(" + ")
Operation.MINUS -> print(" - ")
Operation.DIV -> print(" / ")
Operation.TIMES -> print(" * ")
else -> print(per.op)
}
prettyPrintPerBD(per.right)
}
is Const -> {
print(per.value)
}
is Interest -> {
print("Interest(")
prettyPrintPerBD(per.amount)
print(", \"${per.dayCountConvention}\", ")
prettyPrintPerBD(per.amount)
print(", ")
prettyPrintPerInstant(per.start)
print(", ")
prettyPrintPerInstant(per.end)
print(")")
}
else -> println(per)
}
else -> println(per)
}
fun prettyPrint(arr: Arrangement) {
when (arr) {
is Zero -> print("zero")
is RollOut -> {
println("rollOut(\"${arr.startDate}\".ld, \"${arr.endDate}\".ld, Frequency.${arr.frequency}) { ")
indent {
prettyPrint(arr.template)
}
println("}")
}
is And -> {
for (it in arr.arrangements) {
prettyPrint(it)
}
}
is Continuation -> {
println("next()")
}
is Obligation -> {
print("${partyMap[arr.from.owningKey]}.gives( ${partyMap[arr.to.owningKey]}, ")
prettyPrintPerBD(arr.amount)
println(", ${arr.currency})")
}
is Actions -> {
println("actions {")
indent {
for ((name, condition, arrangement) in arr.actions) {
print("\"$name\".givenThat(")
prettyPrintPerBoolean(condition)
println(") {")
indent {
prettyPrint(arrangement)
}
println("}")
}
}
println("}")
}
else -> println(arr)
}
}
override fun toString(): String {
return sb.toString()
}
}
fun prettyPrint(arr: Arrangement, indentArg: Int = 0) {
fun prettyPrint(arr: Arrangement): String {
val pb = PrettyPrint(arr)
pb.prettyPrint(arr)
return pb.toString()
}
var indent = indentArg
fun println(message: Any?)
{
repeat(indent, { print(' ')})
System.out.println(message)
}
when (arr) {
is Zero -> print("zero")
is RollOut -> {
println("rollout(\"${arr.startDate}\", \"${arr.endDate}\", Frequency.${arr.frequency}) { ")
prettyPrint(arr.template, indent + 2)
println("}")
}
is And -> {
for (it in arr.arrangements) {
prettyPrint(it, indent + 2)
}
}
is Continuation -> {
println("next()")
}
is Obligation -> {
println( "\"${arr.from.name}\".gives( \"${arr.to.name}\", ")
prettyPrintPerBD(arr.amount, indent)
println( ", ${arr.currency})" )
}
is Actions -> {
println("actions {")
indent += 2
for (it in arr.actions) {
println( "\"" + it.name + "\" anytime {")
prettyPrint(it.arrangement, indent + 2)
println( "}" )
}
indent -= 2
println("}")
}
else -> println(arr)
}
}

View File

@ -12,12 +12,12 @@ fun Instant.toLocalDate(): LocalDate = LocalDate.ofEpochDay(this.epochSecond / 6
fun LocalDate.toInstant(): Instant = Instant.ofEpochSecond(this.toEpochDay() * 60 * 60 * 24)
private fun signingParties(perceivable: Perceivable<Boolean>) : ImmutableSet<CompositeKey> =
private fun signingParties(perceivable: Perceivable<Boolean>) : ImmutableSet<Party> =
when (perceivable) {
is ActorPerceivable -> ImmutableSet.of( perceivable.actor.owningKey )
is ActorPerceivable -> ImmutableSet.of( perceivable.actor )
is PerceivableAnd -> Sets.union( signingParties( perceivable.left ), signingParties(perceivable.right) ).immutableCopy()
is PerceivableOr -> Sets.union( signingParties( perceivable.left ), signingParties(perceivable.right) ).immutableCopy()
is TimePerceivable -> ImmutableSet.of<CompositeKey>()
is TimePerceivable -> ImmutableSet.of<Party>()
else -> throw IllegalArgumentException("signingParties " + perceivable)
}
@ -45,22 +45,24 @@ private fun liablePartiesVisitor(action: Action): ImmutableSet<CompositeKey> {
/** Returns list of potentially liable parties for a given contract */
fun liableParties(contract: Arrangement): Set<CompositeKey> = liablePartiesVisitor(contract)
private fun involvedPartiesVisitor(action: Action): Set<CompositeKey> =
private fun involvedPartiesVisitor(action: Action): Set<Party> =
Sets.union(involvedPartiesVisitor(action.arrangement), signingParties(action.condition)).immutableCopy()
private fun involvedPartiesVisitor(arrangement: Arrangement): ImmutableSet<CompositeKey> =
private fun involvedPartiesVisitor(arrangement: Arrangement): ImmutableSet<Party> =
when (arrangement) {
is Zero -> ImmutableSet.of<CompositeKey>()
is Obligation -> ImmutableSet.of(arrangement.from.owningKey)
is Zero -> ImmutableSet.of<Party>()
is Obligation -> ImmutableSet.of(arrangement.from)
is RollOut -> involvedPartiesVisitor(arrangement.template)
is Continuation -> ImmutableSet.of<Party>()
is And ->
arrangement.arrangements.fold(ImmutableSet.builder<CompositeKey>(), { builder, k -> builder.addAll(involvedPartiesVisitor(k)) }).build()
arrangement.arrangements.fold(ImmutableSet.builder<Party>(), { builder, k -> builder.addAll(involvedPartiesVisitor(k)) }).build()
is Actions ->
arrangement.actions.fold(ImmutableSet.builder<CompositeKey>(), { builder, k -> builder.addAll(involvedPartiesVisitor(k)) }).build()
else -> throw IllegalArgumentException()
arrangement.actions.fold(ImmutableSet.builder<Party>(), { builder, k -> builder.addAll(involvedPartiesVisitor(k)) }).build()
else -> throw IllegalArgumentException(arrangement.toString())
}
/** returns list of involved parties for a given contract */
fun involvedParties(arrangement: Arrangement): Set<CompositeKey> = involvedPartiesVisitor(arrangement)
fun involvedParties(arrangement: Arrangement): Set<Party> = involvedPartiesVisitor(arrangement)
fun replaceParty(perceivable: Perceivable<Boolean>, from: Party, to: Party): Perceivable<Boolean> =
when (perceivable) {

View File

@ -6,6 +6,7 @@ import net.corda.core.contracts.Frequency
import net.corda.core.contracts.Tenor
import net.corda.core.utilities.DUMMY_NOTARY
import net.corda.testing.transaction
import org.junit.Ignore
import org.junit.Test
import java.time.Instant
import java.time.LocalDate
@ -164,8 +165,6 @@ class Cap {
@Test
fun issue() {
prettyPrint(contractInitial)
transaction {
output { stateInitial }
timestamp(TEST_TX_TIME_1)
@ -311,4 +310,9 @@ class Cap {
this.verifies()
}
}
@Test @Ignore
fun `pretty print`() {
println ( prettyPrint(contractInitial) )
}
}