PlantUML¶
Introduction¶
PlantUML makes it easy to create and maintain software diagrams.
real-world-plantuml.com shows many examples of PlantUML diagrams.
A template/theme is provided as part of DocDac that fits with the overall ReadTheDocs template i.e. blue, white and grey skins for PlantUML objects.
Note
PlantUML is great for software diagrams (class diagrams, sequence diagrams, etc…). But for non-UML diagrams, or for where you want to control the exact layout, auto-generation via PlantUML may not be the way to go.
Using PlantUML¶
PlantUML source files referenced in rst files are automatically converted to diagrams e.g.
.. uml:: plantuml/examples/state.puml
:align: center
:caption: *State Diagram - without theme*
Tip
To manually convert a PlantUML file:
docker run -u `id -u $USER`:`id -g $USER` -i --rm -v $(pwd):/home/documentation -t  docdac:ubuntu-1.0 java -jar /usr/share/plantuml/plantuml.jar docs/plantuml/examples/state.puml  -o "nostyle"
To manually convert several PlantUML files:
docker run -u `id -u $USER`:`id -g $USER` -i --rm -v $(pwd):/home/documentation -t  docdac:ubuntu-1.0 java -jar /usr/share/plantuml/plantuml.jar -Idocs/plantuml/plantuml_cfg.puml docs/plantuml/examples/*.puml
PlantUML Theme¶
The default (yellow) PlantUML theme is overridden with a Blue (#BDE3FF and white) theme as specified in plantuml_cfg.puml:
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 | ' https://plantuml-documentation.readthedocs.io/en/latest/formatting/all-skin-params.html
' colour  decoder: https://www.google.com/search?q=hex+color+picker&oq=hex+col&aqs=chrome.0.0l2j69i57j0l3.1975j0j7&sourceid=chrome&ie=UTF-8
' http://plantuml.com/skinparam
skinparam backgroundColor white
skinparam note {
    BackgroundColor #F1FFFF
    BorderColor #2980B9
}
skinparam activity {
    BackgroundColor #BDE3FF
    ArrowColor #2980B9
    BorderColor #2980B9
    StartColor #227BC6
    EndColor #227BC6
    BarColor #227BC6
}
skinparam sequence {
    ArrowColor  #2980B9
    DividerBackgroundColor  #BDE3FF
    GroupBackgroundColor    #BDE3FF
    LifeLineBackgroundColor white
    LifeLineBorderColor #2980B9
    ParticipantBackgroundColor  #BDE3FF
    ParticipantBorderColor  #2980B9
    BoxLineColor    #2980B9
    BoxBackgroundColor  #DDDDDD
}
skinparam componentBackgroundColor    #BDE3FF
skinparam component {
    skinparam componentArrowColor #A80036
    skinparam BorderColor    #A80036
    skinparam InterfaceBackgroundColor   #BDE3FF
    skinparam InterfaceBorderColor   #A80036
}
'for some reason if we put BackgroundColor inside {} it does not work?
skinparam stateBackgroundColor #BDE3FF
skinparam state {
    skinparam BorderColor #2980B9
    skinparam ArrowColor #2980B9
    skinparam StartColor black
    skinparam EndColor   black
}
skinparam stereotype {                  
    skinparam CBackgroundColor  #ADD1B2
    skinparam ABackgroundColor  #A9DCDF
    skinparam IBackgroundColor  #B4A7E5
    skinparam EBackgroundColor  #EB937F
}
'for some reason if we put BackgroundColor inside {} it does not work?
skinparam actorBackgroundColor #BDE3FF
skinparam actor {
    skinparam BorderColor    #A80036
}
skinparam usecase {
    skinparam ArrowColor   #A80036
    skinparam BorderColor  #A80036
}
skinparam class {
    skinparam ArrowColor #A80036
    skinparam BackgroundColor    #BDE3FF
    skinparam BorderColor    #A80036
}
skinparam object {
    skinparam ArrowColor    #A80036
    skinparam BackgroundColor   #BDE3FF
    skinparam BorderColor   #A80036
}
skinparam packageBackgroundColor  #white
skinparam agentBackgroundColor  #BDE3FF
skinparam artifactBackgroundColor  #BDE3FF
skinparam boundaryBackgroundColor  #BDE3FF
skinparam cardBackgroundColor  #BDE3FF
skinparam cloudBackgroundColor  #BDE3FF
skinparam controlBackgroundColor  #BDE3FF
skinparam databaseBackgroundColor  #BDE3FF
skinparam entityBackgroundColor  #BDE3FF
skinparam fileBackgroundColor  #BDE3FF
skinparam folderBackgroundColor  #BDE3FF
skinparam frameBackgroundColor  #BDE3FF
skinparam interfaceBackgroundColor  #BDE3FF
skinparam nodeBackgroundColor  #BDE3FF
skinparam queueBackgroundColor  #BDE3FF
skinparam stackBackgroundColor  #BDE3FF
skinparam rectangleBackgroundColor  #BDE3FF
skinparam storageBackgroundColor  #BDE3FF
skinparam usecaseBackgroundColor #BDE3FF
 | 
This theme is specified in Sphinx configuration file conf.py.
Example diagrams¶
Activity¶
![' https://real-world-plantuml.com/umls/4886556628221952
@startuml
title Servlet Container
(*) --> "ClickServlet.handleRequest()"
--> "new Page"
if "Page.onSecurityCheck" then
  ->[true] "Page.onInit()"
  if "isForward?" then
   ->[no] "Process controls"
   if "continue processing?" then
     -->[yes] ===RENDERING===
   else
     -->[no] ===REDIRECT_CHECK===
   endif
  else
   -->[yes] ===RENDERING===
  endif
  if "is Post?" then
    -->[yes] "Page.onPost()"
    --> "Page.onRender()" as render
    --> ===REDIRECT_CHECK===
  else
    -->[no] "Page.onGet()"
    --> render
  endif
else
  -->[false] ===REDIRECT_CHECK===
endif
if "Do redirect?" then
 ->[yes] "redirect request"
 --> ==BEFORE_DESTROY===
else
 if "Do Forward?" then
  -left->[yes] "Forward request"
  --> ==BEFORE_DESTROY===
 else
  -right->[no] "Render page template"
  --> ==BEFORE_DESTROY===
 endif
endif
--> "Page.onDestroy()"
-->(*)
@enduml](_images/plantuml-2305ea052199c42b67e967dfc8880cd43f3ac960.png) 
Activity Diagram¶
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 | ' https://real-world-plantuml.com/umls/4886556628221952
@startuml
title Servlet Container
(*) --> "ClickServlet.handleRequest()"
--> "new Page"
if "Page.onSecurityCheck" then
  ->[true] "Page.onInit()"
  if "isForward?" then
   ->[no] "Process controls"
   if "continue processing?" then
     -->[yes] ===RENDERING===
   else
     -->[no] ===REDIRECT_CHECK===
   endif
  else
   -->[yes] ===RENDERING===
  endif
  if "is Post?" then
    -->[yes] "Page.onPost()"
    --> "Page.onRender()" as render
    --> ===REDIRECT_CHECK===
  else
    -->[no] "Page.onGet()"
    --> render
  endif
else
  -->[false] ===REDIRECT_CHECK===
endif
if "Do redirect?" then
 ->[yes] "redirect request"
 --> ==BEFORE_DESTROY===
else
 if "Do Forward?" then
  -left->[yes] "Forward request"
  --> ==BEFORE_DESTROY===
 else
  -right->[no] "Render page template"
  --> ==BEFORE_DESTROY===
 endif
endif
--> "Page.onDestroy()"
-->(*)
@enduml
 | 
Sequence¶
 
Sequence Diagram¶
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | ' https://real-world-plantuml.com/umls/4606798564687872
@startuml
autonumber
    participant "app: Application" as app
    participant "cm: ContentManager" as cm
    participant "item: DownloadItem" as item
    
    activate app
    activate cm
    
    note over app: User enters media info page
    
    note over app: Check if item exists
    app->cm: findItem(itemId)
    cm->cm: lookup(itemId)
    
    alt item found
        cm-->app: item
    else not found
        cm-->app: null
        app->cm: createItem(itemId, contentURL)
        cm->item: new(itemId, contentURL)
        activate item
        cm-->app: item
    
        app->cm: loadMetadata()
        note over cm
            Download and parse manifest, save in db
        end note
        cm-->app: onTracksAvailable
        cm-->app: onDownloadMetadata
        note over app: * See //track-selection// flow
    end group
    
    note over app: app is ready to start downloading
    app->item: startDownload()
    
    
    @enduml
 | 
State¶
![' https://real-world-plantuml.com/umls/4724780511002624
@startuml
title performing I/O
[*] --> Client
Client: Process uri in Client
Client -> Server : uri-data
state Server {
  [*] -> monitor
  monitor: Server starts monitoring
  monitor: Stops at end of Server life
}
Client -> Database: Client
Database: database operations
state runcommand {
  Database -> command: Database
  command -> find: query
  command: send command to server
  monitor -> select: server-data
  find --> select
  select: select process to find proper server
  select --> find: Server
  find --> query: server
  query: encodes query and send to server
  query: decodes result
  query --> find: result
}
find -> Cursor: cursor-data
Cursor: stores docs
Cursor: retrieves new docs
Cursor -> fetch: document
fetch --> getmore
getmore: encodes query and send to server
getmore: decodes result
getmore --> fetch: new-documents
fetch -> [*]
@enduml](_images/plantuml-c533e767910b1cc1adaa6885672becff778692db.png) 
State Diagram¶
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | ' https://real-world-plantuml.com/umls/4724780511002624
@startuml
title performing I/O
[*] --> Client
Client: Process uri in Client
Client -> Server : uri-data
state Server {
  [*] -> monitor
  monitor: Server starts monitoring
  monitor: Stops at end of Server life
}
Client -> Database: Client
Database: database operations
state runcommand {
  Database -> command: Database
  command -> find: query
  command: send command to server
  monitor -> select: server-data
  find --> select
  select: select process to find proper server
  select --> find: Server
  find --> query: server
  query: encodes query and send to server
  query: decodes result
  query --> find: result
}
find -> Cursor: cursor-data
Cursor: stores docs
Cursor: retrieves new docs
Cursor -> fetch: document
fetch --> getmore
getmore: encodes query and send to server
getmore: decodes result
getmore --> fetch: new-documents
fetch -> [*]
@enduml
 | 
Component¶
![' https://real-world-plantuml.com/umls/4619683198140416
@startuml
package "ArduCopter - Simple Version" {
  [EnginesControl] -down-> Engines
  [EnginesControl] - [MainCopterProcess]
  [MainCopterProcess] - [Rangefinder]
  [Rangefinder] -down-> BottomSonicSensor
  [MainCopterProcess] -down- [GPSSignalListener]
}
package "CarDuino Nano" {
  [GPSSignalMaker] -down- [MainCarDuinoProcess]
  [MainCarDuinoProcess] -down- [CommandListener]
  [GPSSignalMaker] -up- [GPSSignalSender]
  [MainCarDuinoProcess] - [5x Rangefinders]
  [5x Rangefinders] -down-> 5xSonicSensors
  [TelemetricsSender] - [MainCarDuinoProcess]
  [TelemetricsSender] -down- MiniUSB
  [CommandListener] -left- MiniUSB
}
package "Intell 2800 - Simple Version" {
  [ComputerCommunications] -up- USB
  [ComputerCommunications] - [MainComputerProcess]
  [KinectProcessing] -down-> KINECT
  [KinectProcessing] - [MainComputerProcess]
  [VideoProcessing] -down-> Camera
  [VideoProcessing] - [MainComputerProcess] 
  [ComputerCommunications2] -up- [MainComputerProcess]
  [ComputerCommunications2] -down- WiFi
  [ComputerCommunications2] -down- Bluetooth
}
[GPSSignalListener] -down- [GPSSignalSender]
USB -up- MiniUSB
@enduml](_images/plantuml-ca7c3d614705eebbc93ccd38f7e105b56eed1ee6.png) 
Component Diagram¶
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | ' https://real-world-plantuml.com/umls/4619683198140416
@startuml
package "ArduCopter - Simple Version" {
  [EnginesControl] -down-> Engines
  [EnginesControl] - [MainCopterProcess]
  [MainCopterProcess] - [Rangefinder]
  [Rangefinder] -down-> BottomSonicSensor
  [MainCopterProcess] -down- [GPSSignalListener]
}
package "CarDuino Nano" {
  [GPSSignalMaker] -down- [MainCarDuinoProcess]
  [MainCarDuinoProcess] -down- [CommandListener]
  [GPSSignalMaker] -up- [GPSSignalSender]
  [MainCarDuinoProcess] - [5x Rangefinders]
  [5x Rangefinders] -down-> 5xSonicSensors
  [TelemetricsSender] - [MainCarDuinoProcess]
  [TelemetricsSender] -down- MiniUSB
  [CommandListener] -left- MiniUSB
}
package "Intell 2800 - Simple Version" {
  [ComputerCommunications] -up- USB
  [ComputerCommunications] - [MainComputerProcess]
  [KinectProcessing] -down-> KINECT
  [KinectProcessing] - [MainComputerProcess]
  [VideoProcessing] -down-> Camera
  [VideoProcessing] - [MainComputerProcess] 
  [ComputerCommunications2] -up- [MainComputerProcess]
  [ComputerCommunications2] -down- WiFi
  [ComputerCommunications2] -down- Bluetooth
}
[GPSSignalListener] -down- [GPSSignalSender]
USB -up- MiniUSB
@enduml
 | 
Deployment¶
 
Deployment Diagram¶
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | ' http://plantuml.com/deployment-diagram
@startuml
actor actor
agent agent
artifact artifact
boundary boundary
card card
cloud cloud
component component
control control
database database
entity entity
file file
folder folder
frame frame
interface  interface
node node
package package
queue queue
stack stack
rectangle rectangle
storage storage
usecase usecase
@enduml
 | 
Timing¶
 
Timing Diagram¶
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | ' http://plantuml.com/timing-diagram
@startuml
robust "Web Browser" as WB
concise "Web User" as WU
WB is Initializing
WU is Absent
@WB
0 is idle
+200 is Processing
+100 is Waiting
WB@0 <-> @50 : {50 ms lag}
@WU
0 is Waiting
+500 is ok
@200 <-> @+150 : {150 ms}
@enduml
 | 
Handwritten Draft Diagram¶
Per handwritten “To emphasize the fact that your diagrams are still under work, you can generate handwritten diagrams”.
The plantuml_handwritten.puml is included to give the handwritten effect.
| 1 | skinparam handwritten true
 | 
docker run -u `id -u $USER`:`id -g $USER` -i --rm -v $(pwd):/home/documentation -t  docdac:ubuntu-1.0 java -jar /usr/share/plantuml/plantuml.jar -Idocs/plantuml/plantuml_cfg.puml -Idocs/plantuml/plantuml_handwritten.puml  docs/plantuml/examples/*.puml -o handwritten/
This givens a handwritten wavy effect to diagrams e.g.
Draft Sequence¶
 
Sequence Diagram Draft¶
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | ' https://real-world-plantuml.com/umls/4606798564687872
@startuml
skinparam handwritten true
autonumber
    participant "app: Application" as app
    participant "cm: ContentManager" as cm
    participant "item: DownloadItem" as item
    
    activate app
    activate cm
    
    note over app: User enters media info page
    
    note over app: Check if item exists
    app->cm: findItem(itemId)
    cm->cm: lookup(itemId)
    
    alt item found
        cm-->app: item
    else not found
        cm-->app: null
        app->cm: createItem(itemId, contentURL)
        cm->item: new(itemId, contentURL)
        activate item
        cm-->app: item
    
        app->cm: loadMetadata()
        note over cm
            Download and parse manifest, save in db
        end note
        cm-->app: onTracksAvailable
        cm-->app: onDownloadMetadata
        note over app: * See //track-selection// flow
    end group
    
    note over app: app is ready to start downloading
    app->item: startDownload()
    
    
    @enduml
 | 
Draft State¶
![' https://real-world-plantuml.com/umls/4724780511002624
@startuml
skinparam handwritten true
title performing I/O
[*] --> Client
Client: Process uri in Client
Client -> Server : uri-data
state Server {
  [*] -> monitor
  monitor: Server starts monitoring
  monitor: Stops at end of Server life
}
Client -> Database: Client
Database: database operations
state runcommand {
  Database -> command: Database
  command -> find: query
  command: send command to server
  monitor -> select: server-data
  find --> select
  select: select process to find proper server
  select --> find: Server
  find --> query: server
  query: encodes query and send to server
  query: decodes result
  query --> find: result
}
find -> Cursor: cursor-data
Cursor: stores docs
Cursor: retrieves new docs
Cursor -> fetch: document
fetch --> getmore
getmore: encodes query and send to server
getmore: decodes result
getmore --> fetch: new-documents
fetch -> [*]
@enduml](_images/plantuml-abc42eda9030a76e9e8f28f9dee1b7197a9523af.png) 
State Diagram Draft¶
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | ' https://real-world-plantuml.com/umls/4724780511002624
@startuml
skinparam handwritten true
title performing I/O
[*] --> Client
Client: Process uri in Client
Client -> Server : uri-data
state Server {
  [*] -> monitor
  monitor: Server starts monitoring
  monitor: Stops at end of Server life
}
Client -> Database: Client
Database: database operations
state runcommand {
  Database -> command: Database
  command -> find: query
  command: send command to server
  monitor -> select: server-data
  find --> select
  select: select process to find proper server
  select --> find: Server
  find --> query: server
  query: encodes query and send to server
  query: decodes result
  query --> find: result
}
find -> Cursor: cursor-data
Cursor: stores docs
Cursor: retrieves new docs
Cursor -> fetch: document
fetch --> getmore
getmore: encodes query and send to server
getmore: decodes result
getmore --> fetch: new-documents
fetch -> [*]
@enduml
 | 
VSCode PlantUML Extension¶
VSCode Plantuml Extension makes it easy to create and edit plantuml diagrams. It includes a real-time preview within VSCode.
References¶
- http://plantuml.com/ homepage 
- real-world-plantuml.com shows many examples of PlantUML diagrams. 
- https://www.planttext.com/ free online site where you can copyNpaste the text description to auto-generate a diagram 
- https://www.websequencediagrams.com/ free online site where you can copyNpaste the text description to auto-generate a diagram 
Todo
DFD diagram template
Attack tree templates