State diagrams: support a `<<junction>>` pseudostate distinct from `<<choice>>`

0 votes
asked 10 hours ago in Wanted features by dmf19 (400 points)

PlantUML state diagrams currently only expose <<choice>> (e.g. state c <<choice>>) for conditional branching. UML also defines a separate junction pseudostate, which PlantUML has no way to express - modeling a junction today means reusing <<choice>>, which doesn't capture the intended semantics.

Per the UML spec, the two are not interchangeable:

  • Choice is a dynamic conditional branch: guards are evaluated at run time and may depend on effects executed on the transition leading into the choice.
  • Junction is a static conditional branch: it merges multiple incoming transitions into a single compound transition, and its outgoing guards must be evaluated against state that existed before the compound transition began - no side effects from reaching the junction can influence the branch. This makes the whole path atomic: if no outgoing guard matches, the machine stays in its original state with nothing executed.

Junction also natively supports multiple incoming transitions merging into shared outgoing branches (fan-in + fan-out in one compound transition), which is a common pattern in things like retry/attempt-counter logic (e.g. an ATM PIN check where both "first attempt" and "retry" paths merge into one junction that then branches on attemptsRemaining).

Potential Solution

Add a new stereotype, e.g. <<junction>>, alongside the existing <<choice>>, <<fork>>, and <<join>>:

@startuml
state EnterPIN
state RetryPIN
state PromptRetry
state CardLocked
state j <<junction>>

EnterPIN --> j
RetryPIN --> j
j --> PromptRetry : [attemptsRemaining > 0]
j --> CardLocked : [attemptsRemaining == 0]
@enduml

Ideally rendered distinctly enough from <<choice>> (UML tools often draw junction as a filled circle/dot rather than a diamond) so the semantic difference is visible in the diagram, not just in the source.

Alternatives

Continuing to reuse <<choice>> for junction-style merges - works visually but is semantically incorrect and doesn't communicate the atomic/static-guard intent to readers of the diagram or to any tooling that might validate transition semantics.

Additional context

Relates to existing pseudostate support for <<choice>>, <<fork>>, and <<join>> in state diagrams.

1 Answer

0 votes
answered 2 hours ago by The-Lum

Hello D.,

Perhaps, as a first step, we could make "junction" a synonym for "start"...

@startuml
state EnterPIN
state RetryPIN
state PromptRetry
state CardLocked
state j <<start>>

EnterPIN --> j
RetryPIN --> j
j --> PromptRetry : [attemptsRemaining > 0]
j --> CardLocked : [attemptsRemaining == 0]
@enduml

Regards,
Th.

...