Skip to content

The Bank Example (Advanced Role features)

Max Leuthaeuser edited this page May 10, 2026 · 4 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:

scroll.internal.errors.SCROLLErrors$RoleGroupInnerCardinalityViolation:
Constraint set for inner cardinality of role group 'Participants' violated!

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:

scroll.internal.errors.SCROLLErrors$RoleProhibitionConstraintViolation:
Role prohibition constraint violation: 'Account@53a7646' plays role 'Transaction$Target', but it is not allowed to do so!

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)
scroll.internal.errors.SCROLLErrors$ConcreteRelationshipMultiplicityViolation:
With a concrete multiplicity for 'transfer' of '1' the resulting role set should have the same size!

Clone this wiki locally