Merge branch 'chore/50-change-used-markdown-embed-technique' into 'main'

Replace SVG with PNG graphics in documentation

Closes #50

See merge request cs108-fs26/Gruppe-13!79
This commit was merged in pull request #235.
This commit is contained in:
Lars Simon Winzer
2026-04-05 12:48:42 +02:00
23 changed files with 10 additions and 21 deletions
+1 -1
View File
@@ -6,7 +6,7 @@ Each command consists of four classes: a **Parser**, a **Request**, a **Handler*
The infrastructure for routing and dispatching commands lives in the `network/` layer and is intentionally kept generic.
The concrete implementations for each command live in `app/commands/` and are wired together at startup in `ServerApp`.
![Overview of all components directly related to executing requests](/documents/images/docs/networking/commands/overview.svg)
![Overview of all components directly related to executing requests](../../../images/docs/networking/commands/overview.png)
## Contents
### Guides
@@ -10,11 +10,11 @@ An incoming request travels through two sequential pipelines: **parsing** and **
The parsing pipeline converts a stringly-typed `PrimitiveRequest` into a strongly-typed `Request` subclass.
The execution pipeline routes that typed request to the correct handler, which produces a `Response`.
![Sequence diagram of all involved components to process and respond to an incoming request](/documents/images/docs/networking/commands/sequence_diagram.svg)
<img src="../../../images/docs/networking/commands/sequence_diagram.png" alt="Sequence diagram of all involved components to process and respond to an incoming request" />
## Parsing Pipeline
### `CommandParser<T extends Request>`
![Class diagram of the CommandParser](/documents/images/docs/networking/commands/command_parser.svg)
<img src="../../../images/docs/networking/commands/command_parser.png" alt="Class diagram of the CommandParser" />
The `CommandParser` is a single-method interface responsible for converting a `PrimitiveRequest` into a concrete, typed `Request` subclass.
Implementations live in `app/commands/<name>/` and are registered by name in `CommandParserDispatcher`.
@@ -25,7 +25,7 @@ If a required parameter is absent, `RequestParameterAccessor.require(...)` throw
Parsers **do not** perform any domain logic. Their only job is extraction and type conversion.
### `CommandParserDispatcher`
![Class diagram of CommandParserDispatcher](/documents/images/docs/networking/commands/command_parser_dispatcher.svg)
<img src="../../../images/docs/networking/commands/command_parser_dispatcher.png" alt="Class diagram of CommandParserDispatcher" />
The `CommandParserDispatcher` holds a map from command name strings (e.g. `"PING"`) to their corresponding `CommandParser`.
When the `SessionReader` receives a `PrimitiveRequest`, it calls `dispatcher.parse(...)`, which looks up the parser by the request's command string and delegates parsing.
@@ -33,7 +33,7 @@ When the `SessionReader` receives a `PrimitiveRequest`, it calls `dispatcher.par
If no parser is registered for the command name, `parse(...)` throws an `UnknownCommandException`, which `SessionReader` catches and converts into an `UNKNOWN_COMMAND` error response for the client.
### `RequestParameterAccessor`
![Class diagram of RequestParameterAccessor](/documents/images/docs/networking/commands/request_parameter_accessor.svg)
<img src="../../../images/docs/networking/commands/request_parameter_accessor.png" alt="Class diagram of RequestParameterAccessor" />
The `RequestParameterAccessor` is a helper provided to parsers for reading typed parameter values from a `PrimitiveRequest`.
It indexes the parameter list by key on construction for O(1) lookups.
@@ -54,7 +54,7 @@ The `RequestParameterAccessor` wraps it in a `ParameterParseException`.
## Execution Pipeline
### `Request`
![Class diagram of Request](/documents/images/docs/networking/commands/request.svg)
<img src="../../../images/docs/networking/commands/request.png" alt="Class diagram of the Request" />
The `Request` is the abstract base class for all typed command requests. It carries a `RequestContext`, an immutable record containing the originating `SessionId` and the numeric `requestId`.
Both of which are later used by the handler to direct the response to the correct session.
@@ -62,7 +62,7 @@ Both of which are later used by the handler to direct the response to the correc
Concrete subclasses add command-specific fields, all set via constructor. Requests are immutable value objects. They carry data, not behaviour.
### `CommandHandler<T extends Request>`
![Class diagram of CommandHandler](/documents/images/docs/networking/commands/command_handler.svg)
<img src="../../../images/docs/networking/commands/command_handler.png" alt="Class diagram of the CommandHandler" />
The `CommandHandler` is a single-method interface responsible for executing a typed request.
The handler contains the domain logic: reading from registries and managers, modifying state, and dispatching a response via the `ResponseDispatcher`.
@@ -71,7 +71,7 @@ Handlers receive their dependencies (the `ResponseDispatcher`, registries and ma
This keeps them fully testable without the network layer.
### `CommandRouter`
![Class diagram of CommandRouter](/documents/images/docs/networking/commands/command_router.svg)
<img src="../../../images/docs/networking/commands/command_router.png" alt="Class diagram of the CommandRouter" />
The `CommandRouter` maps `Request` subclasses to their handlers using the request's runtime class as the key.
The type safety of `register(...)` ensures that a handler can only be registered for the exact type it is parameterised on.
@@ -81,7 +81,7 @@ If no handler is registered for the given request type, `execute(...)` throws `U
Unlike `UnknownCommandException` (which covers unknown command strings), this exception indicates a programming error i.e. a parser was registered without a corresponding handler.
## Response Types
![Class diagram of the response interface and built-in implementations](/documents/images/docs/networking/commands/response_types.svg)
<img src="../../../images/docs/networking/commands/response_types.png" alt="Class diagram of the response interface and built-in implementations" />
The `Response` is the abstract base for all server responses. Its two concrete branches are `SuccessResponse` (prefix `+OK`) and `ErrorResponse` (prefix `-ERR`).
Command-specific responses extend `SuccessResponse` and populate the body using the `ResponseBodyBuilder`.
@@ -26,8 +26,7 @@ Responses start with `+OK` on success or `-ERR` when something goes wrong. Comma
We don't use HTTP, there's no JSON body, no headers. Just a raw socket, a text stream, and a clearly defined set of commands.
## Core Components & Their Roles
![PlantUML diagramm of all components outlined in this document](/documents/images/docs/networking/server-architecure/networking_components.svg)
<img src="../../images/docs/networking/server-architecure/networking_components.png" alt="PlantUML diagram of all components outlined in this document" />
Here's a quick rundown of the main building blocks:
Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

@@ -1 +0,0 @@
<?plantuml 1.2026.2?><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" contentStyleType="text/css" data-diagram-type="CLASS" height="85px" preserveAspectRatio="none" style="width:287px;height:85px;" version="1.1" viewBox="0 0 287 85" width="287px" zoomAndPan="magnify"><defs/><g><!--class CommandHandler--><g class="entity" data-qualified-name="CommandHandler" data-source-line="3" id="ent0002"><rect fill="#F1F1F1" height="64.4883" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:0.5;" width="266.835" x="7" y="7"/><ellipse cx="22" cy="23" fill="#B4A7E5" rx="11" ry="11" style="stroke:#181818;stroke-width:1;"/><path d="M18.4277,19.2651 L18.4277,17.1069 L25.8071,17.1069 L25.8071,19.2651 L23.3418,19.2651 L23.3418,27.3418 L25.8071,27.3418 L25.8071,29.5 L18.4277,29.5 L18.4277,27.3418 L20.8931,27.3418 L20.8931,19.2651 Z " fill="#000000"/><text fill="#000000" font-family="sans-serif" font-size="14" font-style="italic" lengthAdjust="spacing" textLength="122.7529" x="36" y="28.291">CommandHandler</text><rect fill="#FFFFFF" height="16.1328" style="stroke:#181818;stroke-width:1;stroke-dasharray:2,2;" width="110.082" x="166.7529" y="4"/><text fill="#000000" font-family="sans-serif" font-size="12" font-style="italic" lengthAdjust="spacing" textLength="108.082" x="167.7529" y="16.6016">T extends Request</text><line style="stroke:#181818;stroke-width:0.5;" x1="8" x2="272.835" y1="39" y2="39"/><line style="stroke:#181818;stroke-width:0.5;" x1="8" x2="272.835" y1="47" y2="47"/><g data-visibility-modifier="PUBLIC_METHOD"><ellipse cx="18" cy="60.7441" fill="#84BE84" rx="3" ry="3" style="stroke:#038048;stroke-width:1;"/></g><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="168.6631" x="27" y="64.5352">execute(request: T): void</text></g><?plantuml-src 9Sb12W8n34RXVKwHfU8D1d4p6zSo5uZjhvIP9fgc8eXtj-23j_hQMlGXBfMlajQxMzSyssREuQ9j43I8YWRy9WayMwsY-JpUuCU5yGveRdp1iwF5YJ_4eyC0f1xO-HycNlOJlwna-j8F?></g></svg>
Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

@@ -1 +0,0 @@
<?plantuml 1.2026.2?><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" contentStyleType="text/css" data-diagram-type="CLASS" height="85px" preserveAspectRatio="none" style="width:347px;height:85px;" version="1.1" viewBox="0 0 347 85" width="347px" zoomAndPan="magnify"><defs/><g><!--class CommandParser--><g class="entity" data-qualified-name="CommandParser" data-source-line="3" id="ent0002"><rect fill="#F1F1F1" height="64.4883" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:0.5;" width="326.5283" x="7" y="7"/><ellipse cx="54.2124" cy="23" fill="#B4A7E5" rx="11" ry="11" style="stroke:#181818;stroke-width:1;"/><path d="M50.6401,19.2651 L50.6401,17.1069 L58.0195,17.1069 L58.0195,19.2651 L55.5542,19.2651 L55.5542,27.3418 L58.0195,27.3418 L58.0195,29.5 L50.6401,29.5 L50.6401,27.3418 L53.1055,27.3418 L53.1055,19.2651 Z " fill="#000000"/><text fill="#000000" font-family="sans-serif" font-size="14" font-style="italic" lengthAdjust="spacing" textLength="111.5215" x="74.7124" y="28.291">CommandParser</text><rect fill="#FFFFFF" height="16.1328" style="stroke:#181818;stroke-width:1;stroke-dasharray:2,2;" width="110.082" x="226.4463" y="4"/><text fill="#000000" font-family="sans-serif" font-size="12" font-style="italic" lengthAdjust="spacing" textLength="108.082" x="227.4463" y="16.6016">T extends Request</text><line style="stroke:#181818;stroke-width:0.5;" x1="8" x2="332.5283" y1="39" y2="39"/><line style="stroke:#181818;stroke-width:0.5;" x1="8" x2="332.5283" y1="47" y2="47"/><g data-visibility-modifier="PUBLIC_METHOD"><ellipse cx="18" cy="60.7441" fill="#84BE84" rx="3" ry="3" style="stroke:#038048;stroke-width:1;"/></g><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="300.5283" x="27" y="64.5352">parse(primitiveRequest: PrimitiveRequest): T</text></g><?plantuml-src NOf12i9034NtESLVAjwWY9jUe4Wl43jHXZgPCKcB8DxT2gvyo_UUpraR6nTSU9flLXTDVRrNGnYhRqaqYBA6s9KdGLzBOKq3cuiTHyWpH9FZB8z5F4vu4JOEQDzZrooN77cLN-ym_9bzXv7Uz040?></g></svg>
Binary file not shown.

After

Width:  |  Height:  |  Size: 8.9 KiB

@@ -1 +0,0 @@
<?plantuml 1.2026.2?><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" contentStyleType="text/css" data-diagram-type="CLASS" height="118px" preserveAspectRatio="none" style="width:434px;height:118px;" version="1.1" viewBox="0 0 434 118" width="434px" zoomAndPan="magnify"><defs/><g><!--class CommandParserDispatcher--><g class="entity" data-qualified-name="CommandParserDispatcher" data-source-line="3" id="ent0002"><rect fill="#F1F1F1" height="97.4648" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:0.5;" width="413.0234" x="7" y="7"/><ellipse cx="117.0825" cy="23" fill="#ADD1B2" rx="11" ry="11" style="stroke:#181818;stroke-width:1;"/><path d="M119.5557,29.1431 Q118.9746,29.4419 118.3354,29.5913 Q117.6963,29.7407 116.9907,29.7407 Q114.4839,29.7407 113.1641,28.0889 Q111.8442,26.437 111.8442,23.3159 Q111.8442,20.1865 113.1641,18.5347 Q114.4839,16.8828 116.9907,16.8828 Q117.6963,16.8828 118.3438,17.0322 Q118.9912,17.1816 119.5557,17.4805 L119.5557,20.2031 Q118.9248,19.6221 118.3313,19.3523 Q117.7378,19.0825 117.1069,19.0825 Q115.7622,19.0825 115.0774,20.1492 Q114.3926,21.2158 114.3926,23.3159 Q114.3926,25.4077 115.0774,26.4744 Q115.7622,27.541 117.1069,27.541 Q117.7378,27.541 118.3313,27.2712 Q118.9248,27.0015 119.5557,26.4204 Z " fill="#000000"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="184.3584" x="137.5825" y="28.291">CommandParserDispatcher</text><line style="stroke:#181818;stroke-width:0.5;" x1="8" x2="419.0234" y1="39" y2="39"/><g data-visibility-modifier="PRIVATE_FIELD"><rect fill="none" height="6" style="stroke:#C82930;stroke-width:1;" width="6" x="15" y="49.7441"/></g><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="270.1426" x="27" y="56.5352">parsers: Map&lt;String, CommandParser&gt;</text><line style="stroke:#181818;stroke-width:0.5;" x1="8" x2="419.0234" y1="63.4883" y2="63.4883"/><g data-visibility-modifier="PUBLIC_METHOD"><ellipse cx="18" cy="77.2324" fill="#84BE84" rx="3" ry="3" style="stroke:#038048;stroke-width:1;"/></g><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="387.0234" x="27" y="81.0234">register(command: String, parser: CommandParser): void</text><g data-visibility-modifier="PUBLIC_METHOD"><ellipse cx="18" cy="93.7207" fill="#84BE84" rx="3" ry="3" style="stroke:#038048;stroke-width:1;"/></g><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="346.001" x="27" y="97.5117">parse(primitiveRequest: PrimitiveRequest): Request</text></g><?plantuml-src NOmx3i8m343tdC9Z4N212B6K5Qc24vZKAbQR3tRQ1N5tehOCnPFbzvwrvv1GqCC3NTz974DRno4APC6W1L78nhW1LQ6EtcDe6nGbkN2XsJr9u6sWp17I3DJ25TFfdeL3TzX6PpEhUn3gM3D9vHPiuUSlJ-ossrcO8hThF2jL4lQSUQ8RlKRIRA7vkvHgtSp7V040?></g></svg>
Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

@@ -1 +0,0 @@
<?plantuml 1.2026.2?><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" contentStyleType="text/css" data-diagram-type="CLASS" height="118px" preserveAspectRatio="none" style="width:531px;height:118px;" version="1.1" viewBox="0 0 531 118" width="531px" zoomAndPan="magnify"><defs/><g><!--class CommandRouter--><g class="entity" data-qualified-name="CommandRouter" data-source-line="3" id="ent0002"><rect fill="#F1F1F1" height="97.4648" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:0.5;" width="510.5996" x="7" y="7"/><ellipse cx="200.7681" cy="23" fill="#ADD1B2" rx="11" ry="11" style="stroke:#181818;stroke-width:1;"/><path d="M203.2412,29.1431 Q202.6602,29.4419 202.021,29.5913 Q201.3818,29.7407 200.6763,29.7407 Q198.1694,29.7407 196.8496,28.0889 Q195.5298,26.437 195.5298,23.3159 Q195.5298,20.1865 196.8496,18.5347 Q198.1694,16.8828 200.6763,16.8828 Q201.3818,16.8828 202.0293,17.0322 Q202.6768,17.1816 203.2412,17.4805 L203.2412,20.2031 Q202.6104,19.6221 202.0168,19.3523 Q201.4233,19.0825 200.7925,19.0825 Q199.4478,19.0825 198.7629,20.1492 Q198.0781,21.2158 198.0781,23.3159 Q198.0781,25.4077 198.7629,26.4744 Q199.4478,27.541 200.7925,27.541 Q201.4233,27.541 202.0168,27.2712 Q202.6104,27.0015 203.2412,26.4204 Z " fill="#000000"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="114.5635" x="221.2681" y="28.291">CommandRouter</text><line style="stroke:#181818;stroke-width:0.5;" x1="8" x2="516.5996" y1="39" y2="39"/><g data-visibility-modifier="PRIVATE_FIELD"><rect fill="none" height="6" style="stroke:#C82930;stroke-width:1;" width="6" x="15" y="49.7441"/></g><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="459.2725" x="27" y="56.5352">handlers: Map&lt;Class&lt;? extends Request&gt;, CommandHandler&lt;?&gt;&gt;</text><line style="stroke:#181818;stroke-width:0.5;" x1="8" x2="516.5996" y1="63.4883" y2="63.4883"/><g data-visibility-modifier="PUBLIC_METHOD"><ellipse cx="18" cy="77.2324" fill="#84BE84" rx="3" ry="3" style="stroke:#038048;stroke-width:1;"/></g><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="484.5996" x="27" y="81.0234">register(requestClass: Class&lt;T&gt;, handler: CommandHandler&lt;T&gt;): void</text><g data-visibility-modifier="PUBLIC_METHOD"><ellipse cx="18" cy="93.7207" fill="#84BE84" rx="3" ry="3" style="stroke:#038048;stroke-width:1;"/></g><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="214.1357" x="27" y="97.5117">execute(request: Request): void</text></g><?plantuml-src NOun3i8m34NtdC8Z2BX0LAL35nQMgXSmZLMgjacn4rG9SNT2sonujDz_tpBqRaR62UxO3Xtxw6pbHyyG69sa4xcWL3kY25H-cj3PsiT036y5QIxmIAkHM3JSS2wg7rcKG4iWPmLgUaQIOCuvVTtmeZHc5Po0gUib6G-yiQj2msPgKd9lqF-AnXmrl7nlTn4jrARNiaVdyanzr1S0?></g></svg>
Binary file not shown.

After

Width:  |  Height:  |  Size: 61 KiB

File diff suppressed because one or more lines are too long
Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

@@ -1 +0,0 @@
<?plantuml 1.2026.2?><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" contentStyleType="text/css" data-diagram-type="CLASS" height="134px" preserveAspectRatio="none" style="width:248px;height:134px;" version="1.1" viewBox="0 0 248 134" width="248px" zoomAndPan="magnify"><defs/><g><!--class Request--><g class="entity" data-qualified-name="Request" data-source-line="3" id="ent0002"><rect fill="#F1F1F1" height="113.9531" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:0.5;" width="227.7217" x="7" y="7"/><ellipse cx="89.4482" cy="23" fill="#A9DCDF" rx="11" ry="11" style="stroke:#181818;stroke-width:1;"/><path d="M89.3115,18.3481 L88.1577,23.4199 L90.4736,23.4199 Z M87.8174,16.1069 L90.814,16.1069 L94.1592,28.5 L91.7104,28.5 L90.9468,25.437 L87.668,25.437 L86.9209,28.5 L84.4722,28.5 Z " fill="#000000"/><text fill="#000000" font-family="sans-serif" font-size="14" font-style="italic" lengthAdjust="spacing" textLength="54.3252" x="109.9482" y="28.291">Request</text><line style="stroke:#181818;stroke-width:0.5;" x1="8" x2="233.7217" y1="39" y2="39"/><g data-visibility-modifier="PROTECTED_FIELD"><polygon fill="none" points="18,47.7441,22,51.7441,18,55.7441,14,51.7441" style="stroke:#B38D22;stroke-width:1;"/></g><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="168.335" x="27" y="56.5352">context: RequestContext</text><line style="stroke:#181818;stroke-width:0.5;" x1="8" x2="233.7217" y1="63.4883" y2="63.4883"/><g data-visibility-modifier="PUBLIC_METHOD"><ellipse cx="18" cy="77.2324" fill="#84BE84" rx="3" ry="3" style="stroke:#038048;stroke-width:1;"/></g><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="201.7217" x="27" y="81.0234">getContext(): RequestContext</text><g data-visibility-modifier="PUBLIC_METHOD"><ellipse cx="18" cy="93.7207" fill="#84BE84" rx="3" ry="3" style="stroke:#038048;stroke-width:1;"/></g><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="167.3164" x="27" y="97.5117">getSessionId(): SessionId</text><g data-visibility-modifier="PUBLIC_METHOD"><ellipse cx="18" cy="110.209" fill="#84BE84" rx="3" ry="3" style="stroke:#038048;stroke-width:1;"/></g><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="124.8721" x="27" y="114">getRequestId(): int</text></g><?plantuml-src AyxEp2j8B4hCLKXAJCvEByelpKjnpi_9Br8eAKhCAmPAfUQLS74b9XK3-Sab2iavYSN52a6fXQMfnIKArLmAGA2ia9oVLv9QKM85at26yC6osWhfgJ013KtSIe9JYuipy_CyKq2Au1o4F5GVH3uJwAXQBW00?></g></svg>
Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

@@ -1 +0,0 @@
<?plantuml 1.2026.2?><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" contentStyleType="text/css" data-diagram-type="CLASS" height="167px" preserveAspectRatio="none" style="width:510px;height:167px;" version="1.1" viewBox="0 0 510 167" width="510px" zoomAndPan="magnify"><defs/><g><!--class RequestParameterAccessor--><g class="entity" data-qualified-name="RequestParameterAccessor" data-source-line="3" id="ent0002"><rect fill="#F1F1F1" height="146.9297" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:0.5;" width="489.9072" x="7" y="7"/><ellipse cx="156.0576" cy="23" fill="#ADD1B2" rx="11" ry="11" style="stroke:#181818;stroke-width:1;"/><path d="M158.5308,29.1431 Q157.9497,29.4419 157.3105,29.5913 Q156.6714,29.7407 155.9658,29.7407 Q153.459,29.7407 152.1392,28.0889 Q150.8193,26.437 150.8193,23.3159 Q150.8193,20.1865 152.1392,18.5347 Q153.459,16.8828 155.9658,16.8828 Q156.6714,16.8828 157.3188,17.0322 Q157.9663,17.1816 158.5308,17.4805 L158.5308,20.2031 Q157.8999,19.6221 157.3064,19.3523 Q156.7129,19.0825 156.082,19.0825 Q154.7373,19.0825 154.0525,20.1492 Q153.3677,21.2158 153.3677,23.3159 Q153.3677,25.4077 154.0525,26.4744 Q154.7373,27.541 156.082,27.541 Q156.7129,27.541 157.3064,27.2712 Q157.8999,27.0015 158.5308,26.4204 Z " fill="#000000"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="183.292" x="176.5576" y="28.291">RequestParameterAccessor</text><line style="stroke:#181818;stroke-width:0.5;" x1="8" x2="495.9072" y1="39" y2="39"/><g data-visibility-modifier="PRIVATE_FIELD"><rect fill="none" height="6" style="stroke:#C82930;stroke-width:1;" width="6" x="15" y="49.7441"/></g><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="186.4502" x="27" y="56.5352">index: Map&lt;String, String&gt;</text><line style="stroke:#181818;stroke-width:0.5;" x1="8" x2="495.9072" y1="63.4883" y2="63.4883"/><g data-visibility-modifier="PUBLIC_METHOD"><ellipse cx="18" cy="77.2324" fill="#84BE84" rx="3" ry="3" style="stroke:#038048;stroke-width:1;"/></g><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="454.2002" x="27" y="81.0234">RequestParameterAccessor(parameters: List&lt;RequestParameters&gt;)</text><g data-visibility-modifier="PUBLIC_METHOD"><ellipse cx="18" cy="93.7207" fill="#84BE84" rx="3" ry="3" style="stroke:#038048;stroke-width:1;"/></g><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="178.6641" x="27" y="97.5117">require(key: String): String</text><g data-visibility-modifier="PUBLIC_METHOD"><ellipse cx="18" cy="110.209" fill="#84BE84" rx="3" ry="3" style="stroke:#038048;stroke-width:1;"/></g><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="345.2969" x="27" y="114">require(key: String, parser: ThrowingParser&lt;T&gt;): T</text><g data-visibility-modifier="PUBLIC_METHOD"><ellipse cx="18" cy="126.6973" fill="#84BE84" rx="3" ry="3" style="stroke:#038048;stroke-width:1;"/></g><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="328.3916" x="27" y="130.4883">optional(key: String, defaultValue: String): String</text><g data-visibility-modifier="PUBLIC_METHOD"><ellipse cx="18" cy="143.1855" fill="#84BE84" rx="3" ry="3" style="stroke:#038048;stroke-width:1;"/></g><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="463.9072" x="27" y="146.9766">optional(key: String, defaultValue: T, parser: ThrowingParser&lt;T&gt;): T</text></g><?plantuml-src ZOvD2i9038NtSueiMzGBb58Gjmf5Y_lOHXqwpjHaYefuTyVQBXIAPfE_xxr4QcqRP3p13ilwmAwrrS8Pn-0PhOGLMQzKQL04rdHkINp-uiaJpykIH09xLn1Y1jfMT4rWXKswyQpjOGhldAcEc8nQHCqmaGIMMdpwJKeMznuSDfefgkcMzFxnK8mZKmWdX3Y1uiZk4YPvrwT55jH5BtIDrywY-LHMjCVM-2sQbiPE_gCiVZtnK4y0?></g></svg>
Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

File diff suppressed because one or more lines are too long
Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

File diff suppressed because one or more lines are too long
Binary file not shown.

After

Width:  |  Height:  |  Size: 80 KiB

File diff suppressed because one or more lines are too long