Skip to content

The Bank Example (Advanced Role features)

Max Leuthäuser edited this page Feb 15, 2018 · 3 revisions

The Bank Example (Advanced Role-features)

This page shows some more advanced role-features within the bank example.

Role-Groups

┏━━━━━━━━━━━━━━━━━━┓
┃    Transaction   ┃
┣━━━━━━━━━━━━━━━━━━┫
┃      (2..2)      ┃
┃╭┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄╮┃
┃┆     (1..1)     ┆┃
┃┆╭──────────────╮┆┃
┃┆│    Source    │┆┃
┃┆╰──────────────╯┆┃ Role-Group Participants
┃┆╭──────────────╮┆┃ (an account cannot play both
┃┆│    Target    │┆┃  roles at the same time
┃┆╰──────────────╯┆┃  in the same transaction!)
┃╰┄┄┄┄┄┄┄▲┄┄┄┄┄┄┄┄╯┃
┗━━━━━━━━┿━━━━━━━━━┛
    ┏━━━━┷━━━━┓
    ┃ Account ┃
    ┗━━━━━━━━━┛

You may check your role-binding statements like this:

val aAccount = new Account(10)

new Transaction(10) {
  RoleGroup("Participants").containing[Source, Target](1, 1)(2, 2)
  
  RoleGroupsChecked { 
    aAccount play new Source
    aAccount play new Target
  }
}

Executing this code results in:

java.lang.RuntimeException: Constraint set for inner cardinality of role group 'Participants' violated!
  at scroll.internal.support.RoleGroups.scroll$internal$support$RoleGroups$$eval(RoleGroups.scala:131)
  at scroll.internal.support.RoleGroups.$anonfun$validateInnerCardinality$2(RoleGroups.scala:136)
  at scala.collection.immutable.List.foreach(List.scala:389)
  at scroll.internal.support.RoleGroups.validateInnerCardinality(RoleGroups.scala:136)
  at scroll.internal.support.RoleGroups.validate(RoleGroups.scala:148)
  at scroll.internal.support.RoleGroups.RoleGroupsChecked(RoleGroups.scala:35)
  at scroll.internal.support.RoleGroups.RoleGroupsChecked$(RoleGroups.scala:33)
  at Transaction.RoleGroupsChecked(<console>:17)
  ... 52 elided

The following modification fixes the constraint violation like expected:

val aAccount = new Account(10)
val anotherAccount = new Account(0)

new Transaction(10) {
  RoleGroup("Participants").containing[Source, Target](1, 1)(2, 2)
  
  RoleGroupsChecked { 
    aAccount play new Source
    anotherAccount play new Target
  }
}

Role-Constraints (Riehle)

┏━━━━━━━━━━━━━━━━┓
┃   Transaction  ┃
┣━━━━━━━━━━━━━━━━┫
┃╭──────────────╮┃
┃│    Source    │┃
┃╰──▲───────────╯┃
┃   │    ┯       ┃
┃   │    │       ┃ Role-Prohibition
┃   │    ┷       ┃ (semantically equivalent to
┃╭──┼───────────╮┃  the Role-Group shown already)
┃│  │ Target    │┃
┃╰──┼────────▲──╯┃
┗━━━┿━━━━━━━━┿━━━┛
   ┏┷━━━━━━━━┷┓
   ┃  Account ┃
   ┗━━━━━━━━━━┛

You may check your role-binding statements like this:

val aAccount = new Account(10)

new Transaction(10) {
  RoleProhibition[Source, Target]
  
  RoleConstraintsChecked { 
    aAccount play new Source
    aAccount play new Target
  }
}

Executing this code results in:

java.lang.RuntimeException: Role prohibition constraint violation: 'Account@53a7646' plays role 'Transaction$Target', but it is not allowed to do so!
  at scroll.internal.support.RoleConstraints.$anonfun$checkProhibitions$5(RoleConstraints.scala:57)
  at scroll.internal.support.RoleConstraints.$anonfun$checkProhibitions$5$adapted(RoleConstraints.scala:56)
  at scala.collection.immutable.Set$Set1.foreach(Set.scala:95)
  at scroll.internal.support.RoleConstraints.checkProhibitions(RoleConstraints.scala:56)
  at scroll.internal.support.RoleConstraints.validateConstraints(RoleConstraints.scala:126)
  at scroll.internal.support.RoleConstraints.$anonfun$RoleConstraintsChecked$2(RoleConstraints.scala:113)
  at scroll.internal.support.RoleConstraints.$anonfun$RoleConstraintsChecked$2$adapted(RoleConstraints.scala:113)
  at scala.collection.immutable.List.foreach(List.scala:389)
  at scala.collection.generic.TraversableForwarder.foreach(TraversableForwarder.scala:35)
  at scala.collection.generic.TraversableForwarder.foreach$(TraversableForwarder.scala:35)
  at scala.collection.mutable.ListBuffer.foreach(ListBuffer.scala:44)
  at scroll.internal.support.RoleConstraints.$anonfun$RoleConstraintsChecked$1(RoleConstraints.scala:113)
  at scroll.internal.support.RoleConstraints.$anonfun$RoleConstraintsChecked$1$adapted(RoleConstraints.scala:113)
  at scala.collection.mutable.ResizableArray.foreach(ResizableArray.scala:59)
  at scala.collection.mutable.ResizableArray.foreach$(ResizableArray.scala:52)
  at scala.collection.mutable.ArrayBuffer.foreach(ArrayBuffer.scala:48)
  at scroll.internal.support.RoleConstraints.RoleConstraintsChecked(RoleConstraints.scala:113)
  at scroll.internal.support.RoleConstraints.RoleConstraintsChecked$(RoleConstraints.scala:111)
  at Transaction.RoleConstraintsChecked(<console>:17)
  ... 52 elided

The following modification fixes the constraint violation like expected:

val aAccount = new Account(10)
val anotherAccount = new Account(0)

new Transaction(10) {
  RoleProhibition[Source, Target]
  
  RoleConstraintsChecked { 
    aAccount play new Source
    anotherAccount play new Target
  }
}

Role-Relationships

┏━━━━━━━━━━━━━━━━━━┓
┃    Transaction   ┃
┣━━━━━━━━━━━━━━━━━━┫
┃      (2..2)      ┃
┃╭┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄╮┃
┃┆     (1..1)     ┆┃
┃┆╭──────────────╮┆┃
┃┆│    Source    │┆┃
┃┆╰────┬─────────╯┆┃
┃┆    1│          ┆┃
┃┆     │ transfer ┆┃ Role-Relationship
┃┆    1│          ┆┃
┃┆╭────┴─────────╮┆┃
┃┆│    Target    │┆┃
┃┆╰──────────────╯┆┃
┃╰┄┄┄┄┄┄┄▲┄┄┄┄┄┄┄┄╯┃
┗━━━━━━━━┿━━━━━━━━━┛
    ┏━━━━┷━━━━┓
    ┃ Account ┃
    ┗━━━━━━━━━┛

You can define relationships like this:

val aAccount = new Account(10)
val anotherAccount = new Account(0)

new Transaction(10) {
  aAccount play new Source
  anotherAccount play new Target

  val r = Relationship("transfer").from[Source](1).to[Target](1)

  println("Left side: " + r.left())
  println("Right side: " + r.right())
}

Execution this code would print:

Left side: ArrayBuffer(Transaction$Source@30612fa6)
Right side: ArrayBuffer(Transaction$Target@16cef1cf)

The following code violates the relationship cardinalities specified:

val aAccount = new Account(10)
val anotherAccount = new Account(0)
val aThirdAccount = new Account(0)

new Transaction(10) {
  aAccount play new Source
  anotherAccount play new Target
  aThirdAccount play new Target

  val r = Relationship("transfer").from[Source](1).to[Target](1)

  println("Left side: " + r.left())
  println("Right side: " + r.right())
}

Executing this would print:

Left side: ArrayBuffer(Transaction$Source@54970d40)
java.lang.AssertionError: assertion failed: With a concrete multiplicity for 'transfer' of '1' the resulting role set should have the same size!
  at scala.Predef$.assert(Predef.scala:219)
  at scroll.internal.support.Relationships$Relationship.checkMul(Relationships.scala:66)
  at scroll.internal.support.Relationships$Relationship.right(Relationships.scala:91)
  ... 52 elided
Clone this wiki locally