Skip to content

Commit cfe2bd8

Browse files
committed
update of examples and the pumla user guide.
1 parent 044113c commit cfe2bd8

File tree

8 files changed

+254
-33
lines changed

8 files changed

+254
-33
lines changed

pumla_UsersGuide.md

Lines changed: 120 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -88,22 +88,26 @@ you can name these in a `pumla_blacklist.txt` file. You can also have comments i
8888
blacklist file using `#` as first character of the line. But comments must be
8989
standalone lines, you cannot put a comment behind a path or filename.
9090
The .puml files found will be parsed
91-
and if they are pumla files, their relevant content will be extracted and stored in the
91+
and if they are pumla architecture files, their relevant content will be extracted and stored in the
9292
`modelrepo_json.puml` file or the given
93-
filename. Each call will overwrite the existing `modelrepo_json.puml`
93+
filename. For docs-as-code requirements files, the relevant content will be extracted and stored in the
94+
`reqsrepo_json.puml` file.
95+
Each call will overwrite the existing `modelrepo_json.puml` and `reqsrepo_json.puml`
9496
file, therefore they should not be modified by hand,
9597
because changes will get lost. These repository files are the basis for the
9698
PlantUML extension macros. The macros help to get data out of these repositories
9799
and thereby re-use the once defined model elements and diagrams in a structured
98100
way.
99101

100-
The generated `modelrepo_json.puml` should also not be checked-in into a version
102+
The generated `modelrepo_json.puml` as well as the `reqsrepo_json.puml`
103+
should also not be checked-in into a version
101104
control system, as it contains absolute paths that are different on every computer
102105
where the source code is checked out. Therefore, after a fresh checkout/clone of
103106
a source code repository, first thing to do is call `pumla init` to create a link
104107
to the pumla macros to access the model repository JSON database, the second
105108
thing to do is call `pumla update` to scan the source code repository for pumla
106-
files and create the `modelrepo_json.puml` file. After that you can use the
109+
files and create the `modelrepo_json.puml` and `reqsrepo_json.puml` file.
110+
After that you can use the
107111
model repository to create diagrams and are able to use all the macro commands
108112
explained in the following chapters.
109113

@@ -127,11 +131,19 @@ is put to the command line output.
127131
Called without any other argument, pumla writes out to the console a
128132
list of all `.puml` files that are `pumla` files (marked with either `'PUMLAMR`
129133
(PUMLA-ModelRepo) or `'PUMLADR` (PUMLA-DiagramRepo) in the first line of the file).
134+
Requirements are described in YAML files (`.yaml`) and will therefore not
135+
be shown by this command, as they are not standalone PlantUML-compliant files.
130136

131137
### `pumla elements`
132138
Writes out to the console all `pumla` model elements and diagrams of
133139
the model repository and diagram repository, with all their relevant
134-
attributes.
140+
attributes. This does not include requirements, for that we have the
141+
call described next.
142+
143+
### `pumla reqs` - not yet implemented
144+
Writes out to the console all `pumla` requirements elements and diagrams of
145+
the model repository and diagram repository, with all their relevant
146+
attributes.
135147

136148
### `pumla getjson <subcommand>`
137149
Prints out a JSON data structure containing the request elements (by subcommand).
@@ -183,14 +195,19 @@ This comment marks the file as a re-usable asset of a dynamic behaviour
183195
element description. In a file marked like that, only the dynamic aspect
184196
should be modelled, by e.g. a sequence, state or activity diagram.
185197

198+
### `'PUMLARR`
199+
This comment put into the first line of a `.yaml` file marks the file
200+
as `pumla` requirement element description that shall be part of the re-usable
201+
requirements repository.
202+
186203
---
187204

188205
## Extension Macros
189206
The following macros (that are PlantUML unquoted functions and procedures) can be
190207
used within each PlantUML file by including `pumla_macros.puml`. They are the
191208
user "API" of `pumla`.
192209

193-
## Creating Re-usable Elements
210+
## Creating Re-usable Model Elements
194211

195212
### `PUMLAReUsableAsset($name : string, $alias : string, $type : string, $stereotypes : string (optinal)) {...}`
196213
Creates a re-usable asset (RUA). The asset can be of any PlantUML type, like class, component, node, rectangle, ...
@@ -313,7 +330,7 @@ you manage your architecture relations and artefacts.
313330
Similar to previous, but instead of information about file path and file name you
314331
get the list of tagged values that are attached to each of the connections.
315332

316-
## Putting Re-usable Elements onto Diagrams
333+
## Putting Re-usable Model Elements onto Diagrams
317334

318335
### `PUMLAPutElement( elem_alias )`
319336
This macro puts the model element with the given alias `elem_alias` onto the diagram.
@@ -577,6 +594,102 @@ global variable `$PUMVarShowBodyInternals` is true. With this macro, the given a
577594
of which not to show the internals. In order to show internals for that element within the scope of the same diagram
578595
again, the "filter list" has to be resetted with the next macro.
579596

597+
## Creating Re-usable Requirements Elements
598+
599+
### Creating a single re-usable docs-as-code requirement
600+
Requirements are stored in YAML files (`.yaml`) with a file marking `#PUMLARR`in the first line.
601+
Then, within the file, one or more requirements can be described. The requirements are elements
602+
of a YAML list with at least the following attributes:
603+
- alias: the unique short-ID
604+
- type: describing the kind of requirement. Can be set according to needs. Could be "Requirement", "Constraint", ...
605+
- status: also here, the status model is not defined by PUMLA; put status values as you need and like.
606+
- derived_from: the alias of the (parent) requirement where this requirement is derived from.
607+
- content: The text content of the requirement itself.
608+
609+
The following attributes are optional:
610+
- taggedvalues: a list of tag/values pairs, where values is list by itself.
611+
612+
Requirement files can be distributed across the folders in a git repository and therefore be
613+
stored close to the code if wanted. The `pumla update`
614+
command will find each of them, considering the blacklist.
615+
616+
Example:
617+
```
618+
File: req.yaml
619+
620+
#PUMLARR
621+
- type: Requirement
622+
alias: REQ_WS1
623+
status: decided
624+
derived_from:
625+
taggedvalues:
626+
- tag: "Vendor"
627+
values:
628+
- A Inc.
629+
- C Ltd.
630+
- tag: "Variant"
631+
values: [SysA, SysB]
632+
content:
633+
This is a requirement towards my Weather Station. The Weather Station shall
634+
be able to measure the temperature.
635+
636+
- type: Requirement
637+
alias: REQ_WS2
638+
status: new
639+
derived_from:
640+
content:
641+
This is another requirement. The Weather Station housing shall be blue.
642+
```
643+
644+
## Overview on the Requirements Repository of Re-usable Elements
645+
### `PUMLAPutAllReqsTable()`
646+
This macro puts all requirements of the `reqsrepo_json.puml` into a table on the diagram,
647+
with a count of the requirements as well as the files where the requirements are stored in. It
648+
is similar to the `CheatSheets` of the architecture model elements.
649+
650+
### `PUMLAPutReqByCount($count)`
651+
This macro is solely meant for overview purposes, allowing you to quickly step through each
652+
single requirement in the requirements repository by addressing it by its number (`$count`).
653+
654+
Hint: The `$count` shall not be used to address a requirement a certain requirement or put
655+
it onto a real diagram with a real purpose. The numbering in the requirements repository can
656+
change by calling `pumla update`, so that the `$count` may point to another requirement.
657+
In real diagram, requirements shall always be addressed by their unique short-ID, the `alias`.
658+
659+
## Putting Re-usable Requirements Elements onto Diagrams
660+
### `PUMLAPutReq($alias)`
661+
Puts the requirement with the given alias in form of a PlantUML JSON table with all its
662+
attributes onto the diagram.
663+
664+
### `PUMLAPutAllReqs()`
665+
Puts all the requirements of the requirements repository (`reqsrepo_json.puml`) onto the
666+
diagram.
667+
668+
### `PUMLAPutAllReqsWithStatusTable($value)`
669+
Puts all requirements of the requirements repository, where the status has the given `$value`,
670+
onto the diagram.
671+
672+
### `PUMLAPutAllReqsWithTypeTable($value)`
673+
Puts all requirements of the requirements repository, where the type has the given `$value`,
674+
onto the diagram.
675+
676+
### `PUMLAPutReqBrief($alias)`
677+
Puts the requirement with the given alias onto the diagram, focussing on a limited amount of
678+
attributes:
679+
- type
680+
- content
681+
- status
682+
683+
### `PUMLAPutReqAsNote($alias)`
684+
Puts the brief requirement with the given alias wrapped into a PlantUML note onto the diagram.
685+
686+
Hint: This macro can be useful to put the requirement onto diagrams along with classes, components or
687+
dynamic behaviour descriptions.
688+
689+
### `PUMLAPutAllReqsBrief()`
690+
Puts all the requirements of the requirements repository (`reqsrepo_json.puml`) onto the
691+
diagram, but only with the brief set of attributes (see `PUMLAPutReqBrief($alias)`).
692+
580693
## Working around some PlantUML limitations
581694

582695
### `PUMLASetAsComponentDiagram()`

pumla_macros_reqs.puml

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,12 @@ _PUMLARecursivePutReqsBreakdownTraceFor($dtra,$cnt, $alias)
6262
' requirement with the given alias in a
6363
' recursive way.
6464
!unquoted procedure PUMLAPutReqsBreakdownTraceFor($alias)
65+
!foreach $r in $allreqs.reqs
66+
!if $r.alias == $alias
67+
!$int_suc = %true()
68+
!endif
69+
!endfor
70+
PUMLAPutElementErrorCheck($int_suc, $alias)
6571
_PUMLARecursivePutReqsBreakdownTraceFor($alias,0, $alias)
6672
!endprocedure
6773

@@ -74,9 +80,98 @@ _PUMLARecursivePutReqsBreakdownTraceFor($alias,0, $alias)
7480
!unquoted procedure PUMLAPutReq($alias)
7581
!foreach $r in $allreqs.reqs
7682
!if $r.alias == $alias
83+
!$int_suc = %true()
7784
json $r.alias $r
7885
!endif
7986
!endfor
87+
PUMLAPutElementErrorCheck($int_suc, $alias)
88+
!endprocedure
89+
90+
' ############################################
91+
' ---------------------------------------------
92+
' put a requirement with a count number onto
93+
' the diagram; count refers to the number
94+
' from the PUMLAPutAllReqsTable(). count
95+
' shall not be used as a reference, as it does
96+
' not qualify as a stable element ID.
97+
!unquoted procedure PUMLAPutReqByCount($count)
98+
!$cntall=0
99+
!foreach $r in $allreqs.reqs
100+
!$cntall=$cntall+1
101+
!if $count == $cntall
102+
!$int_suc = %true()
103+
json $r.alias $r
104+
!endif
105+
!endfor
106+
PUMLAPutElementErrorCheck($int_suc, $alias)
107+
!endprocedure
108+
109+
' ############################################
110+
' ---------------------------------------------
111+
' put a list of all requirements out
112+
!unquoted procedure PUMLAPutAllReqs()
113+
!foreach $r in $allreqs.reqs
114+
json $r.alias $r
115+
!endfor
116+
!endprocedure
117+
118+
' ############################################
119+
' ---------------------------------------------
120+
' put a list of all requirements out
121+
!unquoted procedure PUMLAPutAllReqsTable()
122+
!$cntall=0
123+
note as allreqstable
124+
|= count |= alias |= type |= content |= status |= derived_from |= derived_to |= file |
125+
!foreach $r in $allreqs.reqs
126+
!$cntall=$cntall+1
127+
| | | | | | | |
128+
| $cntall | $r.alias | $r.type | $r.content | $r.status | $r.derived_from | $r.derived_to | $r.in_file |
129+
!endfor
130+
131+
A total of $cntall requirements.
132+
end note
133+
!endprocedure
134+
135+
' ############################################
136+
' ---------------------------------------------
137+
' put a list of all where status=$value requirements out
138+
!unquoted procedure PUMLAPutAllReqsWithStatusTable($value)
139+
!$cntall=0
140+
!$cntstat=0
141+
note as allreqstable
142+
|= alias |= type |= content |= status |= derived_from |= derived_to |= file |
143+
!foreach $r in $allreqs.reqs
144+
!$cntall=$cntall+1
145+
!if $r.status==$value
146+
!$cntstat=$cntstat+1
147+
| | | | | | |
148+
| $r.alias | $r.type | $r.content | $r.status | $r.derived_from | $r.derived_to | $r.in_file |
149+
!endif
150+
!endfor
151+
152+
$cntstat out of $cntall requirements matched the request (status=$value).
153+
end note
154+
!endprocedure
155+
156+
' ############################################
157+
' ---------------------------------------------
158+
' put a list of all where type=$value requirements out
159+
!unquoted procedure PUMLAPutAllReqsWithTypeTable($value)
160+
!$cntall=0
161+
!$cnttype=0
162+
note as allreqstable
163+
|= alias |= type |= content |= status |= derived_from |= derived_to |= file |
164+
!foreach $r in $allreqs.reqs
165+
!$cntall=$cntall+1
166+
!if $r.type==$value
167+
!$cnttype=$cnttype+1
168+
| | | | | | |
169+
| $r.alias | $r.type | $r.content | $r.status | $r.derived_from | $r.derived_to | $r.in_file |
170+
!endif
171+
!endfor
172+
173+
$cnttype out of $cntall requirements matched the request (type=$value).
174+
end note
80175
!endprocedure
81176

82177
' ############################################
@@ -87,9 +182,11 @@ json $r.alias $r
87182
!unquoted procedure PUMLAPutReqBrief($alias)
88183
!foreach $r in $allreqs.reqs
89184
!if $r.alias == $alias
185+
!$int_suc = %true()
90186
_PUMLACreateReqObject($r.alias)
91187
!endif
92188
!endfor
189+
PUMLAPutElementErrorCheck($int_suc, $alias)
93190
!endprocedure
94191

95192
' ############################################
@@ -99,13 +196,15 @@ _PUMLACreateReqObject($r.alias)
99196
!unquoted procedure PUMLAPutReqAsNote($alias)
100197
!foreach $r in $allreqs.reqs
101198
!if $r.alias == $alias
199+
!$int_suc = %true()
102200
note as $r.alias #white
103201
{{
104202
PUMLAPutReqBrief($alias)
105203
}}
106204
end note
107205
!endif
108206
!endfor
207+
PUMLAPutElementErrorCheck($int_suc, $alias)
109208
!endprocedure
110209

111210
' ############################################

src/pumla/control/reqparse.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,9 @@ def updatePUMLAReqRepo(path, mrefilename):
7474
der_to.append(e.get("to"))
7575
r.update({"derived_to": der_to})
7676

77+
for r in pumlareqslist:
78+
if r.get("derived_from")==None:
79+
r["derived_from"] = []
7780

7881
# make it accessible from within PlantUML.
7982
# $allreqs is the preprocessor variable that

test/examples/WeatherStation/exampleAllReqs.puml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,7 @@ left to right direction
99
' and show the trace among them.
1010
PUMLAPutAllReqsBrief()
1111

12+
' table of all requirements
13+
PUMLAPutAllReqsTable()
14+
1215
@enduml

test/examples/WeatherStation/exampleReqTrace.puml

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,7 @@
55
' show how the given requirement is broken down
66
' into further requirements with a
77
' "realizing" trace.
8-
PUMLAPutReqsBreakdownTraceFor(REQ_WS1)
8+
PUMLAPutReqsBreakdownTraceFor(REQ_WS4)
99

10-
'PUMLAPutReq(REQ_WS2)
11-
'
12-
'PUMLAPutReqBrief(REQ_WS3)
13-
'
14-
'' these arrows don't make sense, just to test
15-
'REQ_WS2 --> REQ_WS3
16-
'REQ_WS1 --> REQ_WS2
1710

1811
@enduml
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
@startuml
2+
!include reqsrepo_json.puml
3+
!include pumla_macros.puml
4+
5+
' show how the given requirement is broken down
6+
' into further requirements with a
7+
' "realizing" trace.
8+
PUMLAPutReqBrief(REQ_WS1)
9+
10+
@enduml
Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
@startjson
2-
{"reqsrepopath": ".", "reqsrepofile": "./reqsrepo_json.puml", "reqs": [{"type": "Requirement", "alias": "REQ_WS1", "status": "decided", "derived_from": null, "taggedvalues": [{"tag": "Vendor", "values": ["A Inc.", "C Ltd."]},
3-
{"tag": "Variant", "values": ["SysA", "SysB"]}], "content": "This is a requirement towards my Weather Station. The Weather Station shall be able to measure the temperature.", "derived_to": ["REQ_SW_CWeather1", "REQ_SW_CWeather2", "REQ_SensorA1"], "in_file": "./req.yaml"},
4-
{"type": "Requirement", "alias": "REQ_WS2", "status": "new", "derived_from": null, "content": "This is another requirement. The Weather Station housing shall be blue.", "derived_to": [], "in_file": "./req.yaml"},
5-
{"type": "Requirement", "alias": "REQ_WS3", "status": "aligned", "derived_from": null, "content": "The Weather Station shall display the measured temperature so that it is conveniently readable by a human looking at it in a distance of up to 3m.", "derived_to": [], "in_file": "./req.yaml"},
6-
{"type": "Requirement", "alias": "REQ_WS4", "status": "aligned", "derived_from": null, "content": "It shall be possible to switch the unit of the displayed temperature between degree Celsius and Fahrenheit.", "derived_to": ["REQ_SW_CWeather1", "REQ_SW_CWeather2"], "in_file": "./req.yaml"},
7-
{"type": "Requirement", "alias": "REQ_WS5", "status": "aligned", "derived_from": null, "content": "The unit in which the temperature is displayed shall stay as it is even after the batteries and/or the power supply has been removed.", "derived_to": [], "in_file": "./req.yaml"},
2+
{"reqsrepopath": "../../../test/examples/WeatherStation/", "reqsrepofile": "reqsrepo_json.puml", "reqs": [{"type": "Requirement", "alias": "REQ_WS1", "status": "decided", "derived_from": [], "taggedvalues": [{"tag": "Vendor", "values": ["A Inc.", "C Ltd."]},
3+
{"tag": "Variant", "values": ["SysA", "SysB"]}], "content": "This is a requirement towards my Weather Station. The Weather Station shall be able to measure the temperature.", "derived_to": ["REQ_SW_CWeather1", "REQ_SW_CWeather2", "REQ_SensorA1"], "in_file": "../../../test/examples/WeatherStation/req.yaml"},
4+
{"type": "Requirement", "alias": "REQ_WS2", "status": "new", "derived_from": [], "content": "This is another requirement. The Weather Station housing shall be blue.", "derived_to": [], "in_file": "../../../test/examples/WeatherStation/req.yaml"},
5+
{"type": "Requirement", "alias": "REQ_WS3", "status": "aligned", "derived_from": [], "content": "The Weather Station shall display the measured temperature so that it is conveniently readable by a human looking at it in a distance of up to 3m.", "derived_to": [], "in_file": "../../../test/examples/WeatherStation/req.yaml"},
6+
{"type": "Requirement", "alias": "REQ_WS4", "status": "aligned", "derived_from": [], "content": "It shall be possible to switch the unit of the displayed temperature between degree Celsius and Fahrenheit.", "derived_to": ["REQ_SW_CWeather1", "REQ_SW_CWeather2"], "in_file": "../../../test/examples/WeatherStation/req.yaml"},
7+
{"type": "Requirement", "alias": "REQ_WS5", "status": "aligned", "derived_from": [], "content": "The unit in which the temperature is displayed shall stay as it is even after the batteries and/or the power supply has been removed.", "derived_to": [], "in_file": "../../../test/examples/WeatherStation/req.yaml"},
88
{"type": "Requirement", "alias": "REQ_SW_CWeather1", "status": "decided", "derived_from": ["REQ_WS1", "REQ_WS4"], "taggedvalues": [{"tag": "Level", "values": "Software"},
9-
{"tag": "Variant", "values": ["SysA", "SysB"]}], "content": "There shall be one central class to manage all data regarding weather.", "derived_to": ["REQ_SW_CWeather2"], "in_file": "./CWeather/req.yaml"},
10-
{"type": "Requirement", "alias": "REQ_SW_CWeather2", "status": "decided", "derived_from": ["REQ_WS4", "REQ_WS1", "REQ_SW_CWeather1"], "taggedvalues": null, "content": "The Weather class shall be able to converse the data between different units.", "derived_to": [], "in_file": "./CWeather/req.yaml"},
11-
{"type": "Requirement", "alias": "REQ_SensorA1", "status": "aligned", "derived_from": ["REQ_WS1"], "content": "The sensor shall be able to measure the temperature of the surrounding air in the room.", "derived_to": [], "in_file": "./tempSensorA/req.yaml"}]}
9+
{"tag": "Variant", "values": ["SysA", "SysB"]}], "content": "There shall be one central class to manage all data regarding weather.", "derived_to": ["REQ_SW_CWeather2"], "in_file": "../../../test/examples/WeatherStation/CWeather/req.yaml"},
10+
{"type": "Requirement", "alias": "REQ_SW_CWeather2", "status": "decided", "derived_from": ["REQ_WS4", "REQ_WS1", "REQ_SW_CWeather1"], "taggedvalues": null, "content": "The Weather class shall be able to converse the data between different units.", "derived_to": [], "in_file": "../../../test/examples/WeatherStation/CWeather/req.yaml"},
11+
{"type": "Requirement", "alias": "REQ_SensorA1", "status": "aligned", "derived_from": ["REQ_WS1"], "content": "The sensor shall be able to measure the temperature of the surrounding air in the room.", "derived_to": [], "in_file": "../../../test/examples/WeatherStation/tempSensorA/req.yaml"}]}
1212
@endjson
1313

1414

0 commit comments

Comments
 (0)