UmlSequence/Syntax
Contents
Parser usage
{ { {#!umlsequence [OPTIONS] STATEMENTS... } } }
(as usual, without spaces between the successive curly braces on the first and last lines above)
Options:
debug=0 : no debug output
debug=1 : outputs source text, before the image
debug=2 : outputs source text with Spinellis equivalent notation, before the image
help=0 : no help
help=1 : outputs help
percent=NUMBER : image scaling factor
UML Notation
All elements of an UML sequence diagram :
The time flows from top to bottom.
Synchronous message have filled arrow heads.
Asynchronous message have lined arrow heads.
Return messages have dashed arrow lines.
Constraints are marked between {}'s.
White spaces and source comments
- Source text lines can contain zero or more leading white spaces, which are ignored.
- Terms can be separated by one or more leading white spaces.
Lines beginning by zero or more white spaces, followed by "#" and any text, are considered as comments and ignored.
Defining Objects
Regular objects are declared in this form "OBJECT : LABEL" :
O : Inst:Class
The OBJECT is used further in the diagram, so it should be rather short to be handy.
The LABEL can be an arbitrary name, but is usually in the form: "Instance:Class" or ":Class".
Actors are declared in this form "OBJECT * LABEL" :
A * MyActor
The LABEL is opional and may be empty.
Placeholder objects are declared in this form "OBJECT : #COMMENT" :
O : Object1 P : #Placeholder O ::> P Object2
"#COMMENT" can be ommitted
The reserved line becomes visible only as an object is instanciated using its OBJECT (see below).
Layout control:
- Objects appear in the diagram from left to right, in their order of declaration.
- Placeholders can be declared (but never used) in order to add some horizontal space.
O1 : Obj1 O2 : Obj2 SP : # Spacer O3 : O1 --> O2 O2 ::> O3 Obj3
Creating and Destroying Objects
Object can create objects using this form "OBJECT :> OBJECT LABEL" arrow :
O1 : Object1 O2 : O1 ::> O2 Object2
Object can destroy objects using a "OBJECT #> OBJECT" arrow :
O1 : Object1 O2 : Object2 O1 ##> O2
Object can destroy themeselves using this form "`OBJECT~" :
O : Object O~
Objects can complete (i.e. stop their time line) by means of "OBJECT#" :
O1 : Object1 O2 : Object2 : O1# : O2#
Messages / Calls
Messages are created in this form "OBJECT -> OBJECT MESSAGE" :
O1 : Object1 O2 : Object2 O1 -> O2 a message
By default, the message text is centered on the arrow, but it can be justified by prepending "<(>" or "<)>" to the message text :
O1 : Object1 SPACER : O2 : Object2 O1 -> O2 message 1 O1 -> O2 <(> message 2 O1 -> O2 <)> message 3
Results
Result messages are created in this form "OBJECT => OBJECT RESULT" :
O1 : Object1 O2 : Object2 O2 => O1 the result
A request-result combination of messages is created in the form "OBJECT => OBJECT RESULT=REQUEST" :
O1 : Object1 SPACER : O2 : Object2 O1 => O2 the result = the request (with params)
- This automatically creates the request message, a short activation, and the result message.
Asynchronous messages, Arrows Direction
By default, messages are synchronous.
Asynchronous messages can be specified by adding "?" to the arrow tail. Once rendered, asynchronous messages have lined heads, whereas synchronous messages have filled heads.
Arrows can be directed from left to right and vice-versa.
O1 : Object1 O2 : O1 ?:> O2 Object2 O1 <-- O2 sync Ack : O1 ?-> O2 async message : O1 <=? O2 async result
Request-result combinations can be asynchronous for the request, the result, or for both, by adding "?" to the arrow tail, head, or both, respectively. Examples:
O1 : Object1 O2 : O1 ?=> O2 sync result = async call() : O1 ==>? O2 async result = sync call() : O1 ?=>? O2 async result = async call()
Activations
The time line can be activated or deactivated at any time, using the form "OBJECT+" and "OBJECT-".
A flash activation (activation, step, deactivation) can be done using the form "OBJECT!".
Activation or deactivation can be done in combination with messages.
Activations can be nested.
- Example:
O1 : Object1 O2 : Object2 T : :Timer T! : O1+ O1 --> O2+ call+activate O2 T+ T ?=> O2 result = async call to O2 T- O2- ==> O1 result O1- : T!
Self-Activation
A self-activation is an action performed by the object itself, and has the form "OBJECT > ACTION" :
O : Object O > Do something by myself
Vertical Spacing (Step)
Vertical spacing (or step) can be inserted in the form ":" :
O1 : Object1 O2 : Object2 O1 -> O2 a message O1 -> O2 another message : O1 -> O2 final message
Constraints
Constraints can be attached to an object's creation in the form "{{TEXT}}", right after the object is created :
O1 : Object 1 {{constr 1}} O2 : O1 ::> O2 Object 2 {{constr 2}}
Constraints can be attached to an object's time line, above the current position, in the form "OBJECT {{TEXT}}", or below the current position, in the form "OBJECT _{{TEXT}}" :
O1 : Object 1 O2 : Object 2 O1 --> O2 message a O2 {{constr a}} : O1 --> O2 message b O1 _{{constr b}} : O1+ : O1 {{constr c}} O1-
Boxes
It is possible to enclose portions of the diagram into named boxes. Boxes start in the form "BOXNAME [ OBJECT1 BOXLABEL", and end in the form " OBJECT2 ] BOXNAME" :
O1: Object1 O2: Object2 Box [ O1 Label : O2 ] Box
OBJECT1 and OBJECT2 define respectively the top-left and bottom-right corners of the box. They can be the same object :
O1: Object # Box encloses only one object Box [ O1 Label : O1 ] Box
- There can be multiple boxes, and they may even overlap :
O1 : Object1 O2 : Object2 O3 : Object3 # Boxes 1 and 2 are overlapping Box1 [ O1 Label 1 : Box2 [ O2 Label 2 : O2 ] Box1 : O3 ] Box2 :
Comment Notes
Lines starting with zero or more white spaces followed by "#" are ignored. This allows to comment the source.
Comment Notes can be inserted into the diagram by means of "//" :
O : Object O // A simple comment
The comment text can be preceeded by optional parameters in the form "[LABEL,OFFSET,SIZE]" :
O : Object O //[C1, down 0.3 right 0.3, wid 6] A named comment with specified size and position
Any one of the LABEL, OFFSET and SIZE parameters can be left empty. If SIZE is ommitted, it is guessed ( /wiki/classic/img/alert.png currently, sometimes incorrectly --sorry).
The comment text can contain newlines, and span over multiple source lines, using "\n" and "\n\" :
O : Object O // A comment \n with a new line : : O // Another comment \n\ written on multiple lines, \ one of which is pretty long
- Comments can have multiple anchors. It must be named, then later referred using its name and no text :
O : Object O //[C1] A comment : O //[C1] : O //[C1]
Use OFFSET to place it nicely :
O : Object O //[C1, down 0.25 right 0.5] A better-placed comment : O //[C1] : O //[C1]
Text layout in the source
Thanks to the fact that:
- arrow "stem" character can be repeated as wanted,
- leading or separating white spaces can be repeated as wanted,
it is possible to arrange the source text in a layout that can be visually appealing. This variant :
S : s:Caller W : :Switch C : #c:Convers R : r:Caller W+ S+ ?-----> W liftReceiver S <------ W setDialTone() S ?-----> W *dialDigit(d) W {{dialing.executionTime < 30s}} W >routeCalls(s,n) W ::::::> C+ c:Convers C ------> R+ ring() C <-----? R liftReceiver W <------ C connect(r,s) S <------ W connect(r) W -----------------> R <(> connect(s)
is equivalent to this one :
S : s:Caller W : :Switch C : #c:Convers R : r:Caller W+ S+ ?-> W liftReceiver S <- W setDialTone() S ?-> W *dialDigit(d) W {{dialing.executionTime < 30s}} W >routeCalls(s,n) W :> C+ c:Convers C -> R+ ring() C <-? R liftReceiver W <- C connect(r,s) S <- W connect(r) W -> R <(> connect(s)
Although the first variant is looking nicer at the source level, the second one is easier to both write and maintain, because the alignments are fixed.
Diomidis Spinellis and the Author encourage the usage of the second variant.
The Author is using the second variant like this (three-characters arrow for better alignment) :
S : s:Caller W : :Switch C : #c:Convers R : r:Caller W+ S+ ?-> W liftReceiver S <-- W setDialTone() S ?-> W *dialDigit(d) W {{dialing.executionTime < 30s}} W >routeCalls(s,n) W ::> C+ c:Convers C --> R+ ring() C <-? R liftReceiver W <-- C connect(r,s) S <-- W connect(r) W --> R <(> connect(s)