summaryrefslogtreecommitdiff
path: root/31-qualitaetsheft-kolloquium
diff options
context:
space:
mode:
authorOrangerot <purple@orangerot.dev>2024-05-24 17:42:08 +0200
committerOrangerot <purple@orangerot.dev>2024-05-24 17:47:22 +0200
commit7fcdc1c788725f866de71fc9dfd8c4d1cb132b57 (patch)
tree89931c85ae3f149884ba02c69862558e93f01531 /31-qualitaetsheft-kolloquium
Initial commitHEADmain
Diffstat (limited to '31-qualitaetsheft-kolloquium')
-rw-r--r--31-qualitaetsheft-kolloquium/.gitignore303
-rw-r--r--31-qualitaetsheft-kolloquium/.gitlab-ci.yml37
-rw-r--r--31-qualitaetsheft-kolloquium/CHANGELOG.md34
-rw-r--r--31-qualitaetsheft-kolloquium/Makefile19
-rw-r--r--31-qualitaetsheft-kolloquium/README.md118
-rw-r--r--31-qualitaetsheft-kolloquium/assets/.gitignore3
-rw-r--r--31-qualitaetsheft-kolloquium/assets/.gitingnore3
-rw-r--r--31-qualitaetsheft-kolloquium/assets/commits-dashboard.pngbin0 -> 44171 bytes
-rw-r--r--31-qualitaetsheft-kolloquium/assets/commits-server.pngbin0 -> 36705 bytes
-rw-r--r--31-qualitaetsheft-kolloquium/assets/contributors-dashboard.pngbin0 -> 193750 bytes
-rw-r--r--31-qualitaetsheft-kolloquium/assets/contributors-server.pngbin0 -> 222521 bytes
-rw-r--r--31-qualitaetsheft-kolloquium/assets/coverage/authenticationService.pngbin0 -> 26274 bytes
-rw-r--r--31-qualitaetsheft-kolloquium/assets/coverage/episodeActionService.pngbin0 -> 14649 bytes
-rw-r--r--31-qualitaetsheft-kolloquium/assets/coverage/server.pngbin0 -> 42666 bytes
-rw-r--r--31-qualitaetsheft-kolloquium/assets/coverage/subscriptionsService.pngbin0 -> 14334 bytes
-rw-r--r--31-qualitaetsheft-kolloquium/assets/coverage/util.pngbin0 -> 17510 bytes
-rw-r--r--31-qualitaetsheft-kolloquium/assets/diagrams/backendComponentDiagram.puml61
-rw-r--r--31-qualitaetsheft-kolloquium/assets/diagrams/classdiagram-authentication.puml112
-rw-r--r--31-qualitaetsheft-kolloquium/assets/diagrams/classdiagram-episode-actions.puml84
-rw-r--r--31-qualitaetsheft-kolloquium/assets/diagrams/classdiagram-model.puml109
-rw-r--r--31-qualitaetsheft-kolloquium/assets/diagrams/classdiagram-subscriptions.puml75
-rw-r--r--31-qualitaetsheft-kolloquium/assets/diagrams/classdiagram-util.puml43
-rw-r--r--31-qualitaetsheft-kolloquium/assets/diagrams/classdiagram.puml68
-rw-r--r--31-qualitaetsheft-kolloquium/assets/diagrams/componentdiagram.puml53
-rw-r--r--31-qualitaetsheft-kolloquium/assets/diagrams/db.puml78
-rw-r--r--31-qualitaetsheft-kolloquium/assets/diagrams/deployment.puml59
-rw-r--r--31-qualitaetsheft-kolloquium/assets/diagrams/sequencediagram-forgotAndResetPW.puml41
-rw-r--r--31-qualitaetsheft-kolloquium/assets/diagrams/sequencediagram-getEpisodeActions.puml38
-rw-r--r--31-qualitaetsheft-kolloquium/assets/diagrams/sequencediagram-getEpisodeActionsOfPodcastSince.puml32
-rw-r--r--31-qualitaetsheft-kolloquium/assets/diagrams/sequencediagram-getSubscriptions.puml38
-rw-r--r--31-qualitaetsheft-kolloquium/assets/diagrams/sequencediagram-register.puml26
-rw-r--r--31-qualitaetsheft-kolloquium/assets/diagrams/sequencediagram-uploadEpisodeActions.puml38
-rw-r--r--31-qualitaetsheft-kolloquium/assets/diagrams/sequencediagram-uploadSubscriptions.puml32
-rw-r--r--31-qualitaetsheft-kolloquium/assets/episode.pngbin0 -> 10778 bytes
-rw-r--r--31-qualitaetsheft-kolloquium/assets/gantt-plan.puml31
-rw-r--r--31-qualitaetsheft-kolloquium/assets/gantt-reality.puml39
-rw-r--r--31-qualitaetsheft-kolloquium/assets/help.pngbin0 -> 14423 bytes
-rw-r--r--31-qualitaetsheft-kolloquium/assets/lasttest/goodSpecsApdex.pngbin0 -> 20917 bytes
-rw-r--r--31-qualitaetsheft-kolloquium/assets/lasttest/goodSpecsResponse.pngbin0 -> 22682 bytes
-rw-r--r--31-qualitaetsheft-kolloquium/assets/lasttest/goodSpecsTable.pngbin0 -> 46496 bytes
-rw-r--r--31-qualitaetsheft-kolloquium/assets/lasttest/minimumSpecsApdex.pngbin0 -> 22565 bytes
-rw-r--r--31-qualitaetsheft-kolloquium/assets/lasttest/minimumSpecsResponse.pngbin0 -> 21284 bytes
-rw-r--r--31-qualitaetsheft-kolloquium/assets/lasttest/minimumSpecsTable.pngbin0 -> 46556 bytes
-rw-r--r--31-qualitaetsheft-kolloquium/assets/lastupdate.pngbin0 -> 9363 bytes
-rw-r--r--31-qualitaetsheft-kolloquium/assets/logo.svg211
-rw-r--r--31-qualitaetsheft-kolloquium/assets/navbar.pngbin0 -> 8940 bytes
-rw-r--r--31-qualitaetsheft-kolloquium/assets/password-margin.pngbin0 -> 8701 bytes
-rw-r--r--31-qualitaetsheft-kolloquium/assets/password.pngbin0 -> 8781 bytes
-rw-r--r--31-qualitaetsheft-kolloquium/assets/sources/checkstyle-after-processed.txt1
-rw-r--r--31-qualitaetsheft-kolloquium/assets/sources/checkstyle-after.txt22
-rw-r--r--31-qualitaetsheft-kolloquium/assets/sources/checkstyle-before-processed.txt23
-rw-r--r--31-qualitaetsheft-kolloquium/assets/sources/checkstyle-before.txt820
-rw-r--r--31-qualitaetsheft-kolloquium/assets/sources/linter-dashboard-after-processed.txt1
-rw-r--r--31-qualitaetsheft-kolloquium/assets/sources/linter-dashboard-after.txt10
-rw-r--r--31-qualitaetsheft-kolloquium/assets/sources/linter-dashboard-before-processed.txt22
-rw-r--r--31-qualitaetsheft-kolloquium/assets/sources/linter-dashboard-before.txt358
-rw-r--r--31-qualitaetsheft-kolloquium/assets/subscription.pngbin0 -> 79929 bytes
-rw-r--r--31-qualitaetsheft-kolloquium/logos/banner_2020_kit.jpgbin0 -> 96829 bytes
-rw-r--r--31-qualitaetsheft-kolloquium/logos/kitlogo_de_rgb.pdfbin0 -> 11304 bytes
-rw-r--r--31-qualitaetsheft-kolloquium/logos/kitlogo_en_rgb.pdfbin0 -> 6459 bytes
-rw-r--r--31-qualitaetsheft-kolloquium/logos/pse_logo.pdfbin0 -> 11797 bytes
-rw-r--r--31-qualitaetsheft-kolloquium/notizen40
-rw-r--r--31-qualitaetsheft-kolloquium/presentation.tex62
-rw-r--r--31-qualitaetsheft-kolloquium/sdqbeamer.cls975
-rw-r--r--31-qualitaetsheft-kolloquium/slides/changes.tex146
-rw-r--r--31-qualitaetsheft-kolloquium/slides/classdiagram.tex36
-rw-r--r--31-qualitaetsheft-kolloquium/slides/codestyle.tex179
-rw-r--r--31-qualitaetsheft-kolloquium/slides/components.tex7
-rw-r--r--31-qualitaetsheft-kolloquium/slides/coverage.tex23
-rw-r--r--31-qualitaetsheft-kolloquium/slides/difficulties.tex34
-rw-r--r--31-qualitaetsheft-kolloquium/slides/einführung.tex40
-rw-r--r--31-qualitaetsheft-kolloquium/slides/features.tex37
-rw-r--r--31-qualitaetsheft-kolloquium/slides/gantt.tex11
-rw-r--r--31-qualitaetsheft-kolloquium/slides/integrationstrategie.tex82
-rw-r--r--31-qualitaetsheft-kolloquium/slides/pattern.tex12
-rw-r--r--31-qualitaetsheft-kolloquium/slides/performance.tex56
-rw-r--r--31-qualitaetsheft-kolloquium/slides/problems.tex59
-rw-r--r--31-qualitaetsheft-kolloquium/slides/requirements.tex58
-rw-r--r--31-qualitaetsheft-kolloquium/slides/statistics.tex85
-rw-r--r--31-qualitaetsheft-kolloquium/slides/synchronisation.tex36
-rw-r--r--31-qualitaetsheft-kolloquium/slides/testing.tex59
-rw-r--r--31-qualitaetsheft-kolloquium/slides/zielsetzung.tex39
-rw-r--r--31-qualitaetsheft-kolloquium/tikz-uml.sty5377
83 files changed, 10495 insertions, 0 deletions
diff --git a/31-qualitaetsheft-kolloquium/.gitignore b/31-qualitaetsheft-kolloquium/.gitignore
new file mode 100644
index 0000000..595d70a
--- /dev/null
+++ b/31-qualitaetsheft-kolloquium/.gitignore
@@ -0,0 +1,303 @@
+## Core latex/pdflatex auxiliary files:
+*.aux
+*.lof
+*.log
+*.lot
+*.fls
+*.out
+*.toc
+*.fmt
+*.fot
+*.cb
+*.cb2
+.*.lb
+
+## Intermediate documents:
+*.dvi
+*.xdv
+*-converted-to.*
+# these rules might exclude image files for figures etc.
+# *.ps
+*.eps
+*.pdf
+# !assets/*.pdf
+!logos/*.pdf
+
+## Generated if empty string is given at "Please type another file name for output:"
+.pdf
+
+## Bibliography auxiliary files (bibtex/biblatex/biber):
+*.bbl
+*.bcf
+*.blg
+*-blx.aux
+*-blx.bib
+*.run.xml
+
+## Build tool auxiliary files:
+*.fdb_latexmk
+*.synctex
+*.synctex(busy)
+*.synctex.gz
+*.synctex.gz(busy)
+*.pdfsync
+
+## Build tool directories for auxiliary files
+# latexrun
+latex.out/
+
+## Auxiliary and intermediate files from other packages:
+# algorithms
+*.alg
+*.loa
+
+# achemso
+acs-*.bib
+
+# amsthm
+*.thm
+
+# beamer
+*.nav
+*.pre
+*.snm
+*.vrb
+
+# changes
+*.soc
+
+# comment
+*.cut
+
+# cprotect
+*.cpt
+
+# elsarticle (documentclass of Elsevier journals)
+*.spl
+
+# endnotes
+*.ent
+
+# fixme
+*.lox
+
+# feynmf/feynmp
+*.mf
+*.mp
+*.t[1-9]
+*.t[1-9][0-9]
+*.tfm
+
+#(r)(e)ledmac/(r)(e)ledpar
+*.end
+*.?end
+*.[1-9]
+*.[1-9][0-9]
+*.[1-9][0-9][0-9]
+*.[1-9]R
+*.[1-9][0-9]R
+*.[1-9][0-9][0-9]R
+*.eledsec[1-9]
+*.eledsec[1-9]R
+*.eledsec[1-9][0-9]
+*.eledsec[1-9][0-9]R
+*.eledsec[1-9][0-9][0-9]
+*.eledsec[1-9][0-9][0-9]R
+
+# glossaries
+*.acn
+*.acr
+*.glg
+*.glo
+*.gls
+*.glsdefs
+*.lzo
+*.lzs
+*.slg
+*.slo
+*.sls
+
+# uncomment this for glossaries-extra (will ignore makeindex's style files!)
+*.ist
+
+# gnuplot
+*.gnuplot
+*.table
+
+# gnuplottex
+*-gnuplottex-*
+
+# gregoriotex
+*.gaux
+*.glog
+*.gtex
+
+# htlatex
+*.4ct
+*.4tc
+*.idv
+*.lg
+*.trc
+*.xref
+
+# hyperref
+*.brf
+
+# knitr
+*-concordance.tex
+# TODO Uncomment the next line if you use knitr and want to ignore its generated tikz files
+# *.tikz
+*-tikzDictionary
+
+# listings
+*.lol
+
+# luatexja-ruby
+*.ltjruby
+
+# makeidx
+*.idx
+*.ilg
+*.ind
+
+# minitoc
+*.maf
+*.mlf
+*.mlt
+*.mtc[0-9]*
+*.slf[0-9]*
+*.slt[0-9]*
+*.stc[0-9]*
+
+# minted
+_minted*
+*.pyg
+
+# morewrites
+*.mw
+
+# newpax
+*.newpax
+
+# nomencl
+*.nlg
+*.nlo
+*.nls
+
+# pax
+*.pax
+
+# pdfpcnotes
+*.pdfpc
+
+# sagetex
+*.sagetex.sage
+*.sagetex.py
+*.sagetex.scmd
+
+# scrwfile
+*.wrt
+
+# svg
+svg-inkscape/
+
+# sympy
+*.sout
+*.sympy
+sympy-plots-for-*.tex/
+
+# pdfcomment
+*.upa
+*.upb
+
+# pythontex
+*.pytxcode
+pythontex-files-*/
+
+# tcolorbox
+*.listing
+
+# thmtools
+*.loe
+
+# TikZ & PGF
+*.dpth
+*.md5
+*.auxlock
+
+# titletoc
+*.ptc
+
+# todonotes
+*.tdo
+
+# vhistory
+*.hst
+*.ver
+
+# easy-todo
+*.lod
+
+# xcolor
+*.xcp
+
+# xmpincl
+*.xmpi
+
+# xindy
+*.xdy
+
+# xypic precompiled matrices and outlines
+*.xyc
+*.xyd
+
+# endfloat
+*.ttt
+*.fff
+
+# Latexian
+TSWLatexianTemp*
+
+## Editors:
+# WinEdt
+*.bak
+*.sav
+
+# Texpad
+.texpadtmp
+
+# LyX
+*.lyx~
+
+# Kile
+*.backup
+
+# gummi
+.*.swp
+
+# KBibTeX
+*~[0-9]*
+
+# TeXnicCenter
+*.tps
+
+# auto folder when using emacs and auctex
+./auto/*
+*.el
+
+# expex forward references with \gathertags
+*-tags.tex
+
+# standalone packages
+*.sta
+
+# Makeindex log files
+*.lpz
+
+# xwatermark package
+*.xwm
+
+# REVTeX puts footnotes in the bibliography by default, unless the nofootinbib
+# option is specified. Footnotes are the stored in a file with suffix Notes.bib.
+# Uncomment the next line to have this generated file ignored.
+#*Notes.bib
diff --git a/31-qualitaetsheft-kolloquium/.gitlab-ci.yml b/31-qualitaetsheft-kolloquium/.gitlab-ci.yml
new file mode 100644
index 0000000..c4ad5e0
--- /dev/null
+++ b/31-qualitaetsheft-kolloquium/.gitlab-ci.yml
@@ -0,0 +1,37 @@
+plantuml:
+ stage: .pre
+ image:
+ name: eclipse-temurin:17-alpine
+ entrypoint: [""]
+ script:
+ - java -jar plantuml.jar -tpdf assets/diagrams/*.puml
+ - java -jar plantuml.jar -teps assets/*.puml
+ artifacts:
+ paths:
+ - assets
+
+tex:
+ stage: build
+ image: texlive/texlive
+ script:
+ - mkdir public
+ - make tex
+ - mv *.pdf public
+ artifacts:
+ paths:
+ - public
+ dependencies:
+ - plantuml
+
+pages:
+ stage: deploy
+ script:
+ - echo Hello, World!
+ artifacts:
+ paths:
+ - public
+ rules:
+ - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
+ dependencies:
+ - tex
+
diff --git a/31-qualitaetsheft-kolloquium/CHANGELOG.md b/31-qualitaetsheft-kolloquium/CHANGELOG.md
new file mode 100644
index 0000000..7671a41
--- /dev/null
+++ b/31-qualitaetsheft-kolloquium/CHANGELOG.md
@@ -0,0 +1,34 @@
+# Changelog
+Alle Änderungen an diesem Projekt werden in dieser Datei dokumentiert.
+Die Versionsnummern folgt der Syntax in `sdqbeamer.cls`.
+
+## [2022-05-03 v3.1.3]
+- Die Breite des Gruppennamens in der Fußzeile kann nun über `\groupnamewidth{}` gesteuert werden
+- FIX: zweizeilige Fußzeilen haben nun gleichmäßigen vertikalen Abstand (Issue #16 in Gitlab)
+
+## [2021-08-10 v3.1.2]
+- FIX: framesubtitle wird nun angezeigt (Issue #6 in Gitlab)
+
+## [2020-12-08 v3.1.1]
+- FIX: Titelbild (Issue #4 in Gitlab)
+
+## [2020-12-07 v3.1]
+- Umgebung ``contentblock`` (farbloser Block mit fetter Überschrift) hinzugefügt
+- Farbboxen (``greenblock``, ``blueblock``, …) hinzugefügt
+- Abstufungen der KIT-Farben in 10er-Schritten entsprechend der Gestaltungsrichtlinien eingeführt
+- FIX: Navigationspunkte für Subsections in eine Zeile gesetzt, um vertikal Platz zu sparen
+- FIX: ``inputenc`` an den Anfang von ``sdqbeamer.cls`` verschoben
+
+## [2020-11-16 v3.0]
+- Seitenformat 16:10 hinzugefügt
+- Umstellung auf KIT-Design vom 1. August 2020
+ - Anpassung auf neues Farbschema und Maße
+ - neues Titelbild aus der KIT-Bildwelt
+- Neue Optionen:
+ - durch `smallfoot` und `bigfoot` kann die Schriftgröße der Fußzeile gesteuert werden
+ - durch `navbarkit` kann eine Fußzeile nach KIT-Vorgaben erzwungen werden
+- Deutsch (`de`) ist nun die Standard-Option
+- Ordner `templates` wurde gelöscht und die Inhalte in `sdqbeamer.cls` integriert
+- Globale Größe auf 10 pt verringert (vorher: 11 pt), da der beschreibbare Bereich im Vergleich zur 2009er Version kleiner geworden ist
+- SDQ-spezifische Logos und Titelbilder entfernt. Diese sind ab sofort im Branch »sdq« verfügbar.
+- Fix: Zeilenumbruch bei Titel in der Fußzeile repariert \ No newline at end of file
diff --git a/31-qualitaetsheft-kolloquium/Makefile b/31-qualitaetsheft-kolloquium/Makefile
new file mode 100644
index 0000000..3e1e58a
--- /dev/null
+++ b/31-qualitaetsheft-kolloquium/Makefile
@@ -0,0 +1,19 @@
+MAIN = presentation
+FLAGS = -pdf
+
+all: clean compile
+compile: diagram tex
+clean: clean-diagram clean-tex
+
+dev:
+ latexmk $(FLAGS) -pvc $(MAIN)
+tex:
+ latexmk $(FLAGS) $(MAIN)
+diagram:
+ java -jar plantuml.jar -tpdf assets/diagrams/*.puml
+ java -jar plantuml.jar -teps assets/*.puml
+clean-tex:
+ latexmk -C
+clean-diagram:
+ find assets/diagrams -type f -not -name '*.puml' -delete
+
diff --git a/31-qualitaetsheft-kolloquium/README.md b/31-qualitaetsheft-kolloquium/README.md
new file mode 100644
index 0000000..6a5e9ea
--- /dev/null
+++ b/31-qualitaetsheft-kolloquium/README.md
@@ -0,0 +1,118 @@
+LaTeX-Vorlage für Präsentationen
+================================
+
+Das vorliegende Paket dient als Vorlage für Präsentationen im [Corporate Design des KIT](https://intranet.kit.edu/gestaltungsrichtlinien.php) (Fassung vom 1. August 2020).
+
+Es wird an der Forschungsgruppe [DSiS](https://dsis.kastel.kit.edu) an der KIT-Fakultät für Informatik entwickelt und basiert auf [LaTeX Beamer](https://ctan.org/pkg/beamer).
+
+Autor: [Dr.-Ing. Erik Burger](https://dsis.kastel.kit.edu/staff_erik_burger.php)
+mit Beiträgen von Christian Hammer, Klaus Krogmann und Maximilian Schambach
+
+Siehe https://sdqweb.ipd.kit.edu/wiki/Dokumentvorlagen
+
+Hinweise, Verbesserungsvorschläge
+=================================
+
+Bitte verwenden Sie das [Issue-Tracking-System von Gitlab](https://git.scc.kit.edu/i43/dokumentvorlagen/praesentationen/beamer/-/issues), um auf Probleme mit der Vorlage hinzuweisen oder Erweiterungswünsche zu äußern. Sie können gerne auch eine Änderung per Merge-Request vorschlagen.
+
+Verwendung
+==========
+
+Optionen der Dokumentklasse `sdqbeamer`
+-----------------------------------------
+Durch die folgenden Optionen kann das Seitenverhältnis der Folien bestimmt werden:
+
+| Seitenverhältnis | Option |
+| ---------------- | ------------------- |
+| 16:9 | `16:9` (Standard) |
+| 16:10 | `16:10` |
+| 4:3 | `4:3` |
+
+Die Schriftgröße in der Fußzeile ist standardmäßig größer gewählt, als in den Gestaltungsrichtlinien vorgegeben. Diese Vorgabe kann durch die Option `smallfoot` erzwungen werden.
+
+| Schriftgröße Fußzeile | Option |
+| ----------------------| -------------------- |
+| etwas größer (12pt) | `bigfoot` (Standard) |
+| KIT-Vorgabe (9pt) | `smallfoot` |
+
+Die Plazierung der Navigationsleiste kann durch folgende Optionen beeinflußt werden:
+
+| Position | Option | Bemerkung |
+| ------------------------ | ---------------- | ------------------------------------------ |
+| oberhalb der Trennlinie | `navbarinline` | Standard |
+| unterhalb der Trennlinie | `navbarinfooter` | keine Subsection-Punkte, Größe `smallfoot` |
+| Seitenleiste links | `navbarside` | keine Subsection-Punkte |
+| keine Navigationsleiste | `navbaroff` | |
+| KIT-Vorgabe | `navbarkit` | entspricht `navbaroff` und `smallfoot` |
+
+Als Sprache sind Deutsch und Englisch verfügbar. Durch die Sprachwahl werden automatisch die passenden Logos und Formate (z.B. Datum) gewählt.
+
+| Sprache | |
+| -------- |---------------- |
+| Deutsch | `de` (Standard) |
+| Englisch | `en` |
+
+Beispiel: `\documentclass[de,16:9,navbarinline]{sdqbeamer}`
+
+Titelbild
+---------
+
+Das Bild auf der Titelfolie kann mit dem Befehl
+
+`\titleimage{myimage}` (ohne Dateiendung)
+
+gesetzt werden. Um ein eigenes Bild zu verwenden, bitte die Datei (z.B. `myimage.jpg`) ins `logos/`-Verzeichnis legen und den Befehl anpassen. Mitgeliefert wird ein generisches Bild aus der KIT-Bildwelt (https://intranet.kit.edu/gestaltungsrichtlinien.php) in der Datei `logos/banner_2020_kit.jpg`. Falls kein Titelbild eingefügt werden soll, bitte `\titleimage{}` setzen.
+
+Für 16:9-Folien sollte das Verhältnis des Bildes 160:37 betragen, für 4:3-Folien 63:20. Es können auch breitere Bilder verwendet werden, da das Titelbild auf die Höhe des Rahmens skaliert und zentriert wird.
+
+Logo und Name Abteilung/KIT-Fakultät/Institut
+---------------------------------------------
+
+Das Logo rechts oben auf der Titelfolie kann mit dem folgenden Befehl gesetzt werden:
+
+`\grouplogo{mylogo}` (ohne Dateiendung)
+
+Um ein eigenes Logo zu verwenden, bitte die Datei (z.B. `mylogo.pdf`) in das Verzeichnis `logos/` legen und den Befehl anpassen. Falls kein Logo eingefügt werden soll, bitte `\grouplogo{}` setzen.
+
+Der Gruppenname kann mit folgendem Befehl gesetzt werden:
+
+`\groupname{Software Design and Quality}`
+
+Der Gruppenname erscheint in der Fußzeile rechts unten. Lange Namen werden in zwei Zeilen umgebrochen. Falls der Gruppenname leer gelassen wird (`\groupname{}`), wird die volle Breite der Fußzeile für Autornamen und Titel verwendet.
+
+Die Standardbreite des Gruppennamens sind 50 mm. Sie kann mit
+
+`\groupnamewidth{80mm}`
+
+verändert werden, wodurch sich auch die Breite des Textfeldes mit Autor und Titel entsprechend ändert. Umbrüche sind mit `\\` möglich. Statt zweizeiliger Fußzeilen empfiehlt sich eventuell die Option `smallfoot`.
+
+LaTeX allgemein
+---------------
+Siehe https://sdqweb.ipd.kit.edu/wiki/LaTeX
+
+Dateistruktur
+============
+`presentation.tex`
+------------------
+Hauptdatei des LaTeX-Dokuments.
+
+`presentation.bib`
+-------------
+Beispieldatei für BibTeX-Referenzen
+https://sdqweb.ipd.kit.edu/wiki/BibTeX-Literaturlisten
+
+`sdqbeamer.cls`
+-----------------
+Dokumentklasse für Präsentationen im KIT-Design.
+
+`logos/`
+--------
+In diesem Verzeichnis befinden das KIT-Logo als PDF sowie das Hintergrundbild der Titelfolie als JPG.
+
+`CHANGELOG.md`
+--------------
+Dokumentation der Änderungen in den jeweiligen Versionen.
+
+`README.md`
+-----------
+Dieser Text.
diff --git a/31-qualitaetsheft-kolloquium/assets/.gitignore b/31-qualitaetsheft-kolloquium/assets/.gitignore
new file mode 100644
index 0000000..16252a4
--- /dev/null
+++ b/31-qualitaetsheft-kolloquium/assets/.gitignore
@@ -0,0 +1,3 @@
+diagrams/*
+!diagrams/*.puml
+
diff --git a/31-qualitaetsheft-kolloquium/assets/.gitingnore b/31-qualitaetsheft-kolloquium/assets/.gitingnore
new file mode 100644
index 0000000..16252a4
--- /dev/null
+++ b/31-qualitaetsheft-kolloquium/assets/.gitingnore
@@ -0,0 +1,3 @@
+diagrams/*
+!diagrams/*.puml
+
diff --git a/31-qualitaetsheft-kolloquium/assets/commits-dashboard.png b/31-qualitaetsheft-kolloquium/assets/commits-dashboard.png
new file mode 100644
index 0000000..89672d6
--- /dev/null
+++ b/31-qualitaetsheft-kolloquium/assets/commits-dashboard.png
Binary files differ
diff --git a/31-qualitaetsheft-kolloquium/assets/commits-server.png b/31-qualitaetsheft-kolloquium/assets/commits-server.png
new file mode 100644
index 0000000..a9d1a5c
--- /dev/null
+++ b/31-qualitaetsheft-kolloquium/assets/commits-server.png
Binary files differ
diff --git a/31-qualitaetsheft-kolloquium/assets/contributors-dashboard.png b/31-qualitaetsheft-kolloquium/assets/contributors-dashboard.png
new file mode 100644
index 0000000..3621c31
--- /dev/null
+++ b/31-qualitaetsheft-kolloquium/assets/contributors-dashboard.png
Binary files differ
diff --git a/31-qualitaetsheft-kolloquium/assets/contributors-server.png b/31-qualitaetsheft-kolloquium/assets/contributors-server.png
new file mode 100644
index 0000000..500bb43
--- /dev/null
+++ b/31-qualitaetsheft-kolloquium/assets/contributors-server.png
Binary files differ
diff --git a/31-qualitaetsheft-kolloquium/assets/coverage/authenticationService.png b/31-qualitaetsheft-kolloquium/assets/coverage/authenticationService.png
new file mode 100644
index 0000000..4ad91e1
--- /dev/null
+++ b/31-qualitaetsheft-kolloquium/assets/coverage/authenticationService.png
Binary files differ
diff --git a/31-qualitaetsheft-kolloquium/assets/coverage/episodeActionService.png b/31-qualitaetsheft-kolloquium/assets/coverage/episodeActionService.png
new file mode 100644
index 0000000..c81f26f
--- /dev/null
+++ b/31-qualitaetsheft-kolloquium/assets/coverage/episodeActionService.png
Binary files differ
diff --git a/31-qualitaetsheft-kolloquium/assets/coverage/server.png b/31-qualitaetsheft-kolloquium/assets/coverage/server.png
new file mode 100644
index 0000000..d28917a
--- /dev/null
+++ b/31-qualitaetsheft-kolloquium/assets/coverage/server.png
Binary files differ
diff --git a/31-qualitaetsheft-kolloquium/assets/coverage/subscriptionsService.png b/31-qualitaetsheft-kolloquium/assets/coverage/subscriptionsService.png
new file mode 100644
index 0000000..fdb7c9b
--- /dev/null
+++ b/31-qualitaetsheft-kolloquium/assets/coverage/subscriptionsService.png
Binary files differ
diff --git a/31-qualitaetsheft-kolloquium/assets/coverage/util.png b/31-qualitaetsheft-kolloquium/assets/coverage/util.png
new file mode 100644
index 0000000..823cd9e
--- /dev/null
+++ b/31-qualitaetsheft-kolloquium/assets/coverage/util.png
Binary files differ
diff --git a/31-qualitaetsheft-kolloquium/assets/diagrams/backendComponentDiagram.puml b/31-qualitaetsheft-kolloquium/assets/diagrams/backendComponentDiagram.puml
new file mode 100644
index 0000000..e382351
--- /dev/null
+++ b/31-qualitaetsheft-kolloquium/assets/diagrams/backendComponentDiagram.puml
@@ -0,0 +1,61 @@
+@startuml
+' skinparam linetype ortho
+
+'#########################################################################
+'SubscriptionsAPI
+component SubscriptionsAPI {
+
+ component SubscriptionService
+ component SubscriptionController
+ component SubscriptionDataAccessLayer
+
+ portout "Webserver" as wSub
+ portin "Database" as dSub
+ }
+
+dSub --0)- SubscriptionDataAccessLayer
+SubscriptionDataAccessLayer --0)- SubscriptionService
+SubscriptionService --0)- SubscriptionController
+SubscriptionController --0)- wSub
+
+'#########################################################################
+
+
+'#########################################################################
+'EpisodeActionsAPI
+
+component EpisodeActionsAPI {
+ component EpisodeActionService
+ component EpisodeActionController
+ component EpisodeActionDataAccessLayer
+
+ portout "Webserver" as wEpisode
+ portin "Database" as dEpisode
+}
+
+dEpisode --0)- EpisodeActionDataAccessLayer
+EpisodeActionController --0)- wEpisode
+EpisodeActionDataAccessLayer --0)- EpisodeActionService
+EpisodeActionService --0)- EpisodeActionController
+
+'#########################################################################
+
+
+'#########################################################################
+'AuthenticationAPI
+
+component AuthenticationAPI {
+ component AuthenticationService
+ component AuthenticationController
+ component AuthenticationDataAccessLayer
+
+ portout "Webserver" as wAuth
+ portin "Database" as dAuth
+}
+
+dAuth --0)- AuthenticationDataAccessLayer
+AuthenticationController --0)- wAuth
+AuthenticationDataAccessLayer --0)- AuthenticationService
+AuthenticationService --0)- AuthenticationController
+
+@enduml
diff --git a/31-qualitaetsheft-kolloquium/assets/diagrams/classdiagram-authentication.puml b/31-qualitaetsheft-kolloquium/assets/diagrams/classdiagram-authentication.puml
new file mode 100644
index 0000000..a2b3518
--- /dev/null
+++ b/31-qualitaetsheft-kolloquium/assets/diagrams/classdiagram-authentication.puml
@@ -0,0 +1,112 @@
+@startuml
+
+package authenticationAPI <<Frame>> {
+ package authenticationDataAccessLayer <<Frame>> {
+ ' interface AuthenticationDao {
+ ' String login(String username)
+ ' int logout(String username)
+ ' }
+
+ ' class AuthenticationDataAccessService <<@Respository>> {
+ ' <<create>> AuthenticationDataAccessService(JpaTemplate jpaTemplate)
+ ' String login(String username)
+ ' int logout(String username)
+ ' }
+
+ interface UserDetailsManager {
+ void createUser(UserDetails userDetails)
+ void changePassword(String oldPassword, String newPassword)
+ void deleteUser(String username)
+ void updateUser(UserDetails user)
+ boolean userExists(String username)
+ }
+ note left
+ Aus org.springframework.security.provisioning
+ - liefert Methoden zum Erstellen neuer User
+ und zum Aktualisieren bestehender.
+ end note
+
+ class JdbcUserDetailsManager <<@Repository>> {
+ <<create>> JdbcUserDetailsManager(DataSource dataSource)
+ void createUser(UserDetails user)
+ void changePassword(String oldPassword, String newPassword)
+ void deleteUser(String username)
+ void updateUser(UserDetails user)
+ boolean userExists(String username)
+ }
+ note right
+ User Management Service aus dem Paket
+ org.springframework.security.provisioning
+ der CRUD Operationen für User bereitstellt.
+ Hier sind nur die relevanten Methoden modelliert.
+ end note
+ }
+
+ package authenticationService <<Frame>> {
+ class AuthenticationService <<@Service>> {
+ --
+ <<create>> AuthenticationService(UserDetailsManager userDetailsManager)
+ List<String> verifyLogin(String username)
+ int logout(String username)
+ int forgotPassword(ForgotPasswordRequest forgotPasswordRequest)
+ .. via JdbcUserDetailsManager ..
+ int resetPassword(String username, RequestWithPassword requestWithPassword)
+ int registerUser(UserDetails user)
+ int changePassword(String username, ChangePasswordRequest changePasswordRequest)
+ int deleteUser(String username, RequestWithPassword requestWithPassword)
+ }
+
+ class JavaMailSenderImpl {}
+ note left
+ Aus org.springframework.mail.javamail.
+ Implementierung des JavaMailSender Interfaces,
+ welches das MailSender Interface durch Unterstützung
+ von MIME Nachrichten erweitert.
+ Das MailSender Interface definiert dabei eine
+ Strategie zum Versenden einfacher Mails.
+ Unterstützt sowohl JavaMail MimeMessages und
+ Spring SimpleMailMessages.
+ end note
+ }
+
+ package authenticationController <<Frame>> {
+ class AuthenticationController <<@Controller>> {
+ <<create>> AuthenticationController(AuthenticationService authenticationService)
+ ResponseEntity<List<String>> verifyLogin(String username)
+ ResponseEntity<Integer> logout(String username)
+ ResponseEntity<Integer> forgotPassword(ForgotPasswordRequest forgotPasswordRequest)
+ ResponseEntity<Integer> resetPassword(String username, RequestWithPassword requestWithPassword)
+ ResponseEntity<Integer> registerUser(UserDetails user)
+ ResponseEntity<Integer> changePassword(String username, ChangePasswordRequest changePasswordRequest)
+ ResponseEntity<Integer> deleteUser(String username, RequestWithPassword requestWithPassword)
+ }
+
+ class ChangePasswordRequest {
+ <<create>> ChangePasswordRequest(String oldPassword, String newPassword)
+ String getOldPassword()
+ String getNewPassword()
+ }
+
+ class ForgotPasswordRequest {
+ <<create>> ForgotPasswordRequest(String email)
+ String getEmail()
+ }
+
+ class RequestWithPassword {
+ <<create>> ResetPasswordRequest(String password)
+ String getPassword()
+ }
+ }
+}
+
+' User <.. AuthenticationDataAccessService: DB
+' User <.. JdbcUserDetailsManager: DB
+UserDetailsManager <.. AuthenticationService: <<use>>
+' AuthenticationDao <.. AuthenticationService: <<use>>
+AuthenticationService --o AuthenticationController
+' AuthenticationDao <|. AuthenticationDataAccessService: <<realize>>
+UserDetailsManager <|. JdbcUserDetailsManager: <<realize>>
+JavaMailSenderImpl <. AuthenticationService: <<use>>
+
+@enduml
+
diff --git a/31-qualitaetsheft-kolloquium/assets/diagrams/classdiagram-episode-actions.puml b/31-qualitaetsheft-kolloquium/assets/diagrams/classdiagram-episode-actions.puml
new file mode 100644
index 0000000..7a4530e
--- /dev/null
+++ b/31-qualitaetsheft-kolloquium/assets/diagrams/classdiagram-episode-actions.puml
@@ -0,0 +1,84 @@
+@startuml
+
+package episodeActionsAPI <<Frame>> {
+ package episodeActionDataAccessLayer <<Frame>> {
+ class EpisodeActionDataAccessService <<@Repository>> {
+ <<create>> EpisodeActionDataAccessService (JpaTemplate jpaTemplate)
+ long addEpisodeActions(String username, List<EpisodeActionPost> episodeActionPosts)
+ List<EpisodeActionPost> getEpisodeActions(String username)
+ List<EpisodeActionPost> getEpisodeActionsOfPodcast(String username, String podcastURL)
+ List<EpisodeActionPost> getEpisodeActionsSince(String username, LocalDateTime since)
+ List<EpisodeActionPost> getEpisodeActionsOfPodcastSince(String username, String podcastURL, LocalDateTime since)
+ }
+
+ interface EpisodeActionDao {
+ long addEpisodeActions(String username, List<EpisodeActionPost> episodeActionPosts)
+ List<EpisodeActionPost> getEpisodeActions(String username)
+ List<EpisodeActionPost> getEpisodeActionsOfPodcast(String username, String podcastURL)
+ List<EpisodeActionPost> getEpisodeActionsSince(String username, LocalDateTime since)
+ List<EpisodeActionPost> getEpisodeActionsOfPodcastSince(String username, String podcastURL, LocalDateTime since)
+ }
+ }
+
+ package episodeActionService <<Frame>> {
+ class EpisodeActionService <<@Service>> {
+ <<create>> EpisodeActionService (EpisodeActionDao episodeActionDao)
+ LocalDateTime addEpisodeActions(String username, List<EpisodeActionPosts> episodeActionPosts)
+ List<EpisodeActionPost> getEpisodeActions(String username)
+ List<EpisodeActionPost> getEpisodeActionsOfPodcast(String username, String podcastURL)
+ List<EpisodeActionPost> getEpisodeActionsSince(String username, LocalDateTime since)
+ List<EpisodeActionPost> getEpisodeActionsOfPodcastSince(String username, String podcastURL, LocalDateTime since)
+ }
+ }
+
+ package episodeActionController <<Frame>> {
+ class EpisodeActionController <<@Controller>>{
+ <<create>> EpisodeActionController (EpisodeActionService episodeActionService)
+ ResponseEntity<EpisodeActionPostResponse> addEpisodeActions(String username, EpisodeActionPostRequest episodeActionPostRequest)
+ ResponseEntity<EpisodeActionGetResponse> getEpisodeActions(String username, String deviceID, boolean aggregated)
+ ResponseEntity<EpisodeActionGetResponse> getEpisodeActionsOfPodcast(String username, String podcastURL, String deviceID, boolean aggregated)
+ ResponseEntity<EpisodeActionGetResponse> getEpisodeActionsSince(String username, String deviceID, long since, boolean aggregated)
+ ResponseEntity<EpisodeActionGetResponse> getEpisodeActionsOfPodcastSince(String username, String podcastURL, String deviceID, long since, boolean aggregated)
+ }
+
+ class EpisodeActionPostResponse {
+ <<create>> EpisodeActionPostResponse(List<Pair<String, String>> updateURLs)
+ long getTimestamp()
+ List<Pair<String, String>> getUpdatedURLs()
+ }
+
+ class EpisodeActionPost {
+ <<create>> EpisodeActionPost(String podcastURL, String episodeURL, Action action, LocalDateTime timestamp, int started, int position)
+ String getPodcastURL()
+ String getEpisodeURL()
+ int getGUID()
+ Action getAction()
+ LocalDateTime getTimestamp()
+ int getStarted()
+ int getPosition()
+ EpisodeAction getEpisodeAction()
+ }
+
+ class EpisodeActionPostRequest {
+ <<create>> EpisodeActionPostRequest(List<EpisodeActionPost> episodeActionPosts)
+ List<EpisodeActionPost> getEpisodeActionPosts()
+ }
+
+ class EpisodeActionGetResponse {
+ <<create>> EpisodeActionGetResponse(List<EpisodeActionPost> episodeActionPosts)
+ List<EpisodeActionPost> getEpisodeActionPosts()
+ long getTimestamp()
+ }
+ }
+}
+
+EpisodeActionPost -o EpisodeActionGetResponse
+EpisodeActionPost -o EpisodeActionPostRequest
+' EpisodeAction <.. EpisodeActionDataAccessService: DB
+' Episode <.. EpisodeActionDataAccessService: DB
+EpisodeActionDao <.. EpisodeActionService: <<use>>
+EpisodeActionService --o EpisodeActionController
+EpisodeActionDao <|. EpisodeActionDataAccessService: <<realize>>
+
+@enduml
+
diff --git a/31-qualitaetsheft-kolloquium/assets/diagrams/classdiagram-model.puml b/31-qualitaetsheft-kolloquium/assets/diagrams/classdiagram-model.puml
new file mode 100644
index 0000000..72ad49f
--- /dev/null
+++ b/31-qualitaetsheft-kolloquium/assets/diagrams/classdiagram-model.puml
@@ -0,0 +1,109 @@
+@startuml
+
+package model <<Frame>> {
+ class Subscription {
+ <<create>> Subscription(String url, String title)
+ int getID()
+ String getURL()
+ long getLastActionTimestamp()
+ String getTitle()
+ }
+
+ class SubscriptionAction {
+ <<create>> SubscriptionAction(int userID, int subscriptionID)
+ int getID()
+ int getUserID()
+ int getSubscriptionID()
+ long getTimestamp()
+ boolean getAdded()
+ }
+
+ class Episode {
+ <<create>> Episode(int subscriptionID, int id, String url, String title, String thumbnailURL, int total)
+ int getSubscriptionID()
+ int getID()
+ int getGUID()
+ String getURL()
+ String getTitle()
+ int getTotal()
+ }
+
+ enum Action {
+ Download
+ Play
+ Delete
+ New
+ Flattr
+ String getJsonProperty()
+ }
+
+ class EpisodeAction {
+ <<create>> EpisodeAction(Action action, LocalDateTime timestamp, int started, int position)
+ int getEpisodeID()
+ Action getAction()
+ long getTimestamp()
+ int getStarted()
+ int getPosition()
+ void setEpisodeID()
+ EpisodeActionPost getEpisodeActionPost(String podcastURL, String episodeURL)
+ }
+
+ interface UserDetails {
+ String getUsername()
+ String getPassword()
+ Collection<Authority> getAuthorities()
+ boolean isAccountExpired()
+ boolean isAccountLocked()
+ boolean isCredentialsNonExpired()
+ boolean isEnabled()
+ }
+ note left
+ Aus org.springframework.security.core.userdetails.
+ Wird für die Schnittstelle UserDetailsManager benötigt.
+ Stellt wichtige Informationen eines Users bereit.
+ Diese werden nur indirekt von Spring Security
+ benutzt, indem sie vorher in Authentication Objekten
+ gekapselt werden.
+ end note
+
+ class User {
+ --
+ <<create>> User(String username, String password)
+ int getID()
+ String getSessionToken()
+ boolean getEmailIsValidated()
+ .. interface methods ..
+ String getUsername()
+ String getPassword()
+ Collection<Authority> getAuthorities()
+ boolean isAccountExpired()
+ boolean isAccountLocked()
+ boolean isCredentialsNonExpired()
+ boolean isEnabled()
+ }
+
+ interface GrantedAuthority {
+ String getAuthority()
+ }
+ note right
+ Aus org.springframework.security.core.
+ Wird für die Schnittstelle UserDetails benötigt.
+ Repräsentiert eine Autorisierung, die einem
+ Authentication Objekt gewährt wird.
+ end note
+
+ class Authority {
+ <<create>> Authority()
+ String getAuthority()
+ }
+}
+
+Subscription <. SubscriptionAction: ID
+Action <-- EpisodeAction
+EpisodeAction .> Episode: ID
+UserDetails <|.. User: <<realize>>
+User -> Authority
+GrantedAuthority <|.. Authority: <<realize>>
+
+@enduml
+
diff --git a/31-qualitaetsheft-kolloquium/assets/diagrams/classdiagram-subscriptions.puml b/31-qualitaetsheft-kolloquium/assets/diagrams/classdiagram-subscriptions.puml
new file mode 100644
index 0000000..432f185
--- /dev/null
+++ b/31-qualitaetsheft-kolloquium/assets/diagrams/classdiagram-subscriptions.puml
@@ -0,0 +1,75 @@
+@startuml
+
+package subscriptionsAPI <<Frame>> {
+ package subscriptionDataAccessLayer <<Frame>> {
+ class SubscriptionDataAccessService <<@Repository>> {
+ <<create>> SubscriptionDataAccessService(JpaTemplate jpaTemplate)
+ int uploadSubscriptions(String username, List<SubscriptionAction> subscriptions)
+ List<String> getSubscriptions(String username)
+ List<String> getSubscriptionsSince(String username, LocalDateTime time)
+ int addSubscriptions(String username, List<SubscriptionAction> addedSubscriptions)
+ int removeSubscriptions(String username, List<SubscriptionAction> removedSubscriptions)
+ List<SubscriptionTitles> getTitles(String username)
+ }
+
+ interface SubscriptionDao {
+ int uploadSubscriptions(String username, List<SubscriptionAction> subscriptions)
+ List<String> getSubscriptions(String username)
+ List<String> getSubscriptionsSince(String username, LocalDateTime time)
+ int addSubscriptions(String username, List<SubscriptionAction> addedSubscriptions)
+ int removeSubscriptions(String username, List<SubscriptionAction> removedSubscriptions)
+ List<SubscriptionTitles> getTitles(String username)
+ }
+ }
+
+ package subscriptionService <<Frame>> {
+ class SubscriptionService <<@Service>> {
+ <<create>> SubscriptionService(SubscriptionDao subscriptionDao)
+ int uploadSubscriptions(String username, List<SubscriptionAction> subscriptions)
+ List<String> getSubscriptions(String username)
+ List<String> getSubscriptionsSince(String username, LocalDateTime time)
+ int addSubscriptions(String username, List<SubscriptionAction> addedSubscriptions)
+ int removeSubscriptions(String username, List<SubscriptionAction> removedSubscriptions)
+ List<SubscriptionTitles> getTitles(String username)
+ }
+ }
+
+ package subscriptionController <<Frame>> {
+ class SubscriptionController <<@Controller>>{
+ ' @Autowired
+ <<create>> SubscriptionController(SubscriptionService subscriptionService)
+ ' @GetMapping
+ ResponseEntity<List<String>> getSubscriptions(String username, String deviceID, String functionJSONP)
+ ' @PutMapping
+ ResponseEntity<String> uploadSubscriptions(String username, String deviceID, List<String> subscriptions)
+ ' @PostMapping
+ ResponseEntity<SubscriptionDelta> applySubscriptionDelta(String username, String deviceID, SubscriptionDelta delta)
+ ' @GetMapping
+ ResponseEntity<SubscriptionDelta> getSubscriptionDelta(String username, String deviceID, long since)
+ ResponseEntity<List<SubscriptionTitles>> getTitles(String username, String deviceID)
+ }
+
+ class SubscriptionTitles {
+ <<create>> SubscriptionTitles(Subscription subscription, List<EpisodeActionPost> episodeTitles)
+ Subscription getSubscription()
+ List<EpisodeActionPost> getEpisodesTitles()
+ }
+
+ class SubscriptionDelta {
+ <<create>> SubscriptionDelta(List<String> add, List<String> remove)
+ List<String> getRemove()
+ LocalDate getTimestamp()
+ List<List<String>> getUpdate_urls()
+ }
+ }
+
+}
+
+' Subscription <.. SubscriptionDataAccessService: DB
+' SubscriptionAction <.. SubscriptionDataAccessService: DB
+SubscriptionService --o SubscriptionController
+SubscriptionDao <.. SubscriptionService: <<use>>
+SubscriptionDao <|. SubscriptionDataAccessService: <<realize>>
+
+@enduml
+
diff --git a/31-qualitaetsheft-kolloquium/assets/diagrams/classdiagram-util.puml b/31-qualitaetsheft-kolloquium/assets/diagrams/classdiagram-util.puml
new file mode 100644
index 0000000..03dfc9a
--- /dev/null
+++ b/31-qualitaetsheft-kolloquium/assets/diagrams/classdiagram-util.puml
@@ -0,0 +1,43 @@
+@startuml
+
+package util <<Frame>> {
+ class RSSParser {
+ <<create>> RSSParser(String subscriptionURL)
+ String getSubscriptionTitle()
+ List<Episode> getEpisodes()
+ Episode getEpisodeForURL(String episodeURL)
+ }
+ note bottom
+ Verwendet intern Spring um
+ HTTP-Anfragen zu erstellen.
+ end note
+
+ class CleanCronJob {
+ <<create>> CleanCronJob(JdbcUserDetailsManager jdbcUserDetailsManager)
+ void cleanInvalidUsers()
+ }
+ note bottom
+ Hintergrundservice, der in periodischen Abständen
+ Nutzer, die ihre E-Mail-Adresse nicht nach 24 Stunden
+ bestätigt haben, wieder aus der Datenbank löscht.
+ (Auf die Assoziation zu JdbcUserDetailsManager wird
+ im Sinne der Übersichtlichkeit verzichtet.)
+ end note
+
+ class ResponseEntity<T> {
+ <<create>> ResponseEntity(T body, HttpStatusCode status)
+ T getBody()
+ HttpStatusCode getStatusCode()
+ }
+ note bottom
+ Aus org.springframework.http.
+ Erweitert die Klasse HttpEntity, welche
+ ein HTTP Anfrage- oder Antwort-Objekt
+ repräsentiert, durch einen HttpStatusCode.
+ Wird von den Controller-Methoden als
+ Rückgabewert verwendet.
+ end note
+}
+
+@enduml
+
diff --git a/31-qualitaetsheft-kolloquium/assets/diagrams/classdiagram.puml b/31-qualitaetsheft-kolloquium/assets/diagrams/classdiagram.puml
new file mode 100644
index 0000000..f833aa2
--- /dev/null
+++ b/31-qualitaetsheft-kolloquium/assets/diagrams/classdiagram.puml
@@ -0,0 +1,68 @@
+@startuml
+' skinparam linetype ortho
+' skinparam groupInheritance 2
+allowmixing
+
+!include classdiagram-authentication.puml
+!include classdiagram-episode-actions.puml
+!include classdiagram-model.puml
+!include classdiagram-subscriptions.puml
+!include classdiagram-util.puml
+
+class SecurityConfigurationBasicAuth {
+ <<create>> SecurityConfigurationBasicAuth()
+ PasswordEncoder encoder()
+ UserDetailsManager userDetailsService()
+ SecuryFilterChain fiterChain(HTTPSecurity http) throws Excpetion
+}
+note top
+ Erstellt einen Servlet Filter (springSecurityFilterChain)
+ der für die gesamte Sicherheit zuständig ist (Schutz der URLs,
+ Validierung von Anmeldedaten, Weiterleitung zur Anmeldung, etc.).
+end note
+
+class PSEApplication {
+ <<create>> PSEApplication()
+ void main(String[] args)
+}
+
+database Datenbank
+Datenbank <-[hidden]d- subscriptionsAPI
+Datenbank <-[hidden]d- episodeActionsAPI
+Datenbank <-[hidden]d- authenticationAPI
+() SQL as SQLSub
+() SQL as SQLAuth
+() SQL as SQLEpisode
+
+Datenbank -- SQLSub
+Datenbank -- SQLAuth
+Datenbank -- SQLEpisode
+
+Subscription --o SubscriptionTitles
+EpisodeActionPost -o SubscriptionTitles
+UserDetailsManager <.. SecurityConfigurationBasicAuth: <<use>>
+
+SubscriptionController ..o PSEApplication
+AuthenticationController ..o PSEApplication
+EpisodeActionController ..o PSEApplication
+SecurityConfigurationBasicAuth ..o PSEApplication
+
+PSEApplication --() HTTP
+
+SQLSub )-- SubscriptionDataAccessService: JPA
+' SQLAuth )-- AuthenticationDataAccessService: JPA
+SQLAuth )-- JdbcUserDetailsManager: JDBC
+SQLEpisode )-- EpisodeActionDataAccessService: JPA
+
+RSSParser <. SubscriptionDataAccessService: <<use>>
+RSSParser <. EpisodeActionDataAccessService: <<use>>
+' JdbcUserDetailsManager <-- CleanCronJob
+
+model .o Datenbank: ORM (User, SubscriptionAction, Subscription, EpisodeAction, Episode)
+' Datenbank o.. Subscription: ORM
+' Datenbank o.. SubscriptionAction: ORM
+' Datenbank o.. Episode: ORM
+' Datenbank o.. EpisodeAction: ORM
+' Datenbank o.. User: ORM
+
+@enduml
diff --git a/31-qualitaetsheft-kolloquium/assets/diagrams/componentdiagram.puml b/31-qualitaetsheft-kolloquium/assets/diagrams/componentdiagram.puml
new file mode 100644
index 0000000..dea4a1d
--- /dev/null
+++ b/31-qualitaetsheft-kolloquium/assets/diagrams/componentdiagram.puml
@@ -0,0 +1,53 @@
+@startuml
+
+[App] as app
+[VueRouter] as router
+[NavbarComponent] as navbar
+[LoginPage] as login_page
+[SubscriptionsPage] as abo_page
+[EpisodesPage] as episodes_page
+[SettingsPage] as settings_page
+[ForgotPasswordPage] as forgot_page
+[ResetPasswordPage] as reset_page
+note top
+ Wird in der E-Mail zum Zurücksetzen des Passworts mit dem JWT-Token verlinkt.
+ Sendet das alte und neue Passwort und den JWT an die API.
+end note
+[RegistrationPage] as registration_page
+
+[SubscriptionComponent] as sub
+[EpisodeComponent] as episode
+[LastUpdateComponent] as last_update
+[PasswordValidatorComponent] as password
+
+app --> router
+
+app --> navbar
+router --> login_page
+router --> forgot_page
+router --> reset_page
+router --> registration_page
+router --> abo_page
+router --> episodes_page
+router --> settings_page
+
+navbar -[hidden] router
+
+episodes_page -[hidden] abo_page
+login_page -[hidden] forgot_page
+registration_page -[hidden] reset_page
+abo_page -[hidden] settings_page
+forgot_page -[hidden] episodes_page
+' forgot_page -[hidden] settings_page
+
+abo_page --> sub
+episodes_page --> episode
+
+sub --> last_update
+episode --> last_update
+
+settings_page --> password
+reset_page --> password
+registration_page --> password
+
+@enduml
diff --git a/31-qualitaetsheft-kolloquium/assets/diagrams/db.puml b/31-qualitaetsheft-kolloquium/assets/diagrams/db.puml
new file mode 100644
index 0000000..bdefaea
--- /dev/null
+++ b/31-qualitaetsheft-kolloquium/assets/diagrams/db.puml
@@ -0,0 +1,78 @@
+@startuml
+' Type Symbol
+' Zero or One |o--
+' Exactly One ||--
+' Zero or Many }o--
+' One or Many }|--
+
+skinparam linetype ortho
+
+entity User {
+ * int id <<unique>>
+ * <u>String email</u>
+ * String password
+ * boolean verified
+ * long created_at
+}
+
+entity SubscriptionAction {
+ * int id <<unique>>
+ * <u>int user_id</u>
+ * long timestamp
+ * int subscription_id
+ * boolean added
+}
+
+entity Subscription {
+ * int id <<unique>>
+ * <u>String url</u>
+ * long timestamp
+ * String title
+}
+
+entity Episode {
+ * int id <<unique>>
+ * <u>int guid <<unique>></u>
+ * <u>String url</u>
+ * String title
+ * int total
+ * int subscription_id
+}
+note right
+ Wenn der Client eine GUID aus dem Feed mitsendet, wird
+ diese statt der URL verwendet um die Episode zu finden.
+ So wird die Episode auch noch gefunden, nachdem sich
+ die URL geändert hat.
+end note
+note bottom of Episode
+ Wenn für die Episoden-URL einer EpisodeAction noch keine Episode in der Datenbank steht,
+ dann schreibe dafür ein Dummy-Objekt in Datenbank und lade asynchron die Episoden der Subscription.
+ Ersetze dann die Dummy-Objekte durch die Episoden und setze den Timestamp der Subscription auf
+ die aktuelle Zeit.
+ Um DoS-Angriffe auf den Backend-Server abzuwenden, können die Episoden einer Subscription erst
+ nach einer Stunde erneut gefetched werden. Bis dahin werden für EpisodeActions, die sich auf noch
+ nicht geladene Episoden beziehen, nur Dummy-Objekte für die Episoden in die Datenbank geschrieben.
+ Es sei noch darauf hingewiesen, dass diese Dummy-Episoden bei Anfragen nicht mit ausgegeben werden.
+end note
+
+entity EpisodeAction {
+ * int id <<unique>>
+ * <u>int user_id</u>
+ * int episode_id
+ * long timestamp
+ * int action
+ * int started
+ * int position
+}
+note right
+ Speichere für jede Episode
+ nur letzte Play-Action.
+endnote
+
+User ||--o{ EpisodeAction
+User ||--o{ SubscriptionAction
+SubscriptionAction }|--|| Subscription
+EpisodeAction }|--|| Episode
+Subscription ||-right-|{ Episode
+
+@enduml
diff --git a/31-qualitaetsheft-kolloquium/assets/diagrams/deployment.puml b/31-qualitaetsheft-kolloquium/assets/diagrams/deployment.puml
new file mode 100644
index 0000000..b8d0491
--- /dev/null
+++ b/31-qualitaetsheft-kolloquium/assets/diagrams/deployment.puml
@@ -0,0 +1,59 @@
+@startuml
+
+node "<<device>> \nBackend Server" as backendServer{
+ database " <<database system>> \n MariaDB Server 10.6" as database {
+ rectangle rectangle1 [
+ <<schema>>
+ User
+ ]
+ rectangle rectangle2 [
+ <<schema>>
+ SubscriptionAction
+ ]
+ rectangle rectangle3 [
+ <<schema>>
+ EpisodeAction
+ ]
+ rectangle rectangle4 [
+ <<schema>>
+ Subscription
+ ]
+ rectangle rectangle5 [
+ <<schema>>
+ Episode
+ ]
+ }
+
+ node "<<framework>> \nJava Spring" as javaSpring{
+ node " <<device>> \n Tomcat Webserver"
+ }
+}
+
+node "<<device>> \nFrontend" as frontendServer {
+
+}
+
+node "<<device>> \nEndgerät" as terminal {
+ node "<<application>> \nBrowser" as browser
+ node "<<application>> \nPodcatcher" as podcatcher
+}
+
+backendServer "1" - "*" podcatcher
+
+node "<<device>> \nFrontend Server" as frontendServer{
+ node "<<framework>> \nVue.js" as vuejs {
+
+ }
+}
+
+podcatcher -[hidden] browser
+
+backendServer - "1" frontendServer
+
+database "1" -- "1" javaSpring
+
+browser "*" -- frontendServer
+
+
+
+@enduml
diff --git a/31-qualitaetsheft-kolloquium/assets/diagrams/sequencediagram-forgotAndResetPW.puml b/31-qualitaetsheft-kolloquium/assets/diagrams/sequencediagram-forgotAndResetPW.puml
new file mode 100644
index 0000000..603130c
--- /dev/null
+++ b/31-qualitaetsheft-kolloquium/assets/diagrams/sequencediagram-forgotAndResetPW.puml
@@ -0,0 +1,41 @@
+@startuml
+
+skinparam ParticipantPadding 30
+
+participant AuthenticationController << (C, #ADD1B2) @Controller >>
+-> AuthenticationController: ""POST /api/2/auth/forgot.json"" \n//@RequestBody ForgotPasswordRequest forgotPasswordRequest// \n\n-> forgotPassword(//forgotPasswordRequest//)
+activate AuthenticationController
+participant AuthenticationService << (C, #ADD1B2) @Service >>
+AuthenticationController -> AuthenticationService: forgotPassword(//forgotPasswordRequest//)
+activate AuthenticationService
+participant JavaMailSenderImpl << (C, #ADD1B2) >>
+AuthenticationService -> JavaMailSenderImpl: create link to reset password with JWT as URL parameter \n-> send(SimpleMailMessage simpleMessage) with link
+activate JavaMailSenderImpl
+<<- JavaMailSenderImpl: sends email with link containing a JWT to reset password
+JavaMailSenderImpl --> AuthenticationService
+deactivate JavaMailSenderImpl
+AuthenticationService --> AuthenticationController: int indicating status
+deactivate AuthenticationService
+<-- AuthenticationController: ResponseEntity<Integer> indicating status \n\n-> ""HTTP status code""
+deactivate AuthenticationController
+||60||
+-> AuthenticationController: ""PUT /api/2/auth/{username}/resetpassword.json"" \n//@RequestParam String jwt// \n//@RequestBody ResetPasswordRequest resetPasswordRequest// \n\n-> login user (""username"") via JWT (//jwt//) \n-> resetPassword(""username"", //resetPasswordRequest//)
+activate AuthenticationController
+AuthenticationController -> AuthenticationService: resetPassword(""username"", //resetPasswordRequest//)
+activate AuthenticationService
+participant JdbcUserDetailsManager << (C, #ADD1B2) @Repository >>
+AuthenticationService -> JdbcUserDetailsManager: String oldPassword = //resetPasswordRequest//.getOldPassword() \nString newPassword = //resetPasswordRequest//.getNewPassword() \n-> changePassword(newPassword, oldPassword)
+activate JdbcUserDetailsManager
+database Database
+JdbcUserDetailsManager -> Database: change password of logged in user
+activate Database
+Database --> JdbcUserDetailsManager
+deactivate Database
+JdbcUserDetailsManager --> AuthenticationService: int indicating status
+deactivate JdbcUserDetailsManager
+AuthenticationService --> AuthenticationController: int indicating status
+deactivate AuthenticationService
+<-- AuthenticationController: ResponseEntity<Integer> indicating status \n\n-> ""HTTP status code""
+deactivate AuthenticationController
+
+@enduml \ No newline at end of file
diff --git a/31-qualitaetsheft-kolloquium/assets/diagrams/sequencediagram-getEpisodeActions.puml b/31-qualitaetsheft-kolloquium/assets/diagrams/sequencediagram-getEpisodeActions.puml
new file mode 100644
index 0000000..47497d5
--- /dev/null
+++ b/31-qualitaetsheft-kolloquium/assets/diagrams/sequencediagram-getEpisodeActions.puml
@@ -0,0 +1,38 @@
+@startuml
+
+' title =**Get All Episode Actions**
+
+participant EpisodeActionController << (C, #ADD1B2) @Controller >>
+-> EpisodeActionController: ""GET /api/2/episodes/{username}.json"" \n//@RequestParam("device") String deviceID// \n//@RequestParam("aggregated") boolean aggregated// \n\n-> getEpisodeActions(""username"", //deviceID//, //aggregated//)
+note right
+ Die Parameter //deviceID// und //aggregated// werden ignoriert,
+ da nicht zwischen Geräten unterschieden und für jede
+ Episode sowieso nur die letzte Play-Action gespeichert
+ wird. Dies gilt für alle GET-Anfragen der Episode Actions API.
+end note
+activate EpisodeActionController
+participant EpisodeActionService << (C, #ADD1B2) @Service >>
+EpisodeActionController -> EpisodeActionService: getEpisodeActions(""username"")
+activate EpisodeActionService
+participant EpisodeActionDataAccessService << (C, #ADD1B2) @Repository >>
+EpisodeActionService -> EpisodeActionDataAccessService: getEpisodeActions(""username"")
+activate EpisodeActionDataAccessService
+EpisodeActionDataAccessService -> EpisodeActionDataAccessService: getEpisodeActionsSince(""username"", \nLocalDateTime.MIN.toEpochSecond(ZoneOffset.UTC))
+database Database
+activate EpisodeActionDataAccessService
+EpisodeActionDataAccessService -> Database: get all EpisodeActions for all subscribed podcasts
+activate Database
+Database --> EpisodeActionDataAccessService: List<EpisodeAction> selectedEpisodeActions \n-> then remove all older than LocalDateTime.MIN (none)
+EpisodeActionDataAccessService -> Database: join EpisodeActions in selectedEpisodeActions with episodeURL of Episode
+Database --> EpisodeActionDataAccessService
+deactivate Database
+EpisodeActionDataAccessService --> EpisodeActionDataAccessService: List<EpisodeActionPost> episodeActionPosts
+deactivate EpisodeActionDataAccessService
+EpisodeActionDataAccessService --> EpisodeActionService: List<EpisodeActionPost> episodeActionPosts
+deactivate EpisodeActionDataAccessService
+EpisodeActionService --> EpisodeActionController: List<EpisodeActionPost> episodeActionPosts
+deactivate EpisodeActionService
+<-- EpisodeActionController: ResponseEntity<EpisodeActionGetResponse> response \n\n-> ""HTTP status code"" \n-> ""JSON""
+deactivate EpisodeActionController
+
+@enduml \ No newline at end of file
diff --git a/31-qualitaetsheft-kolloquium/assets/diagrams/sequencediagram-getEpisodeActionsOfPodcastSince.puml b/31-qualitaetsheft-kolloquium/assets/diagrams/sequencediagram-getEpisodeActionsOfPodcastSince.puml
new file mode 100644
index 0000000..d8797d1
--- /dev/null
+++ b/31-qualitaetsheft-kolloquium/assets/diagrams/sequencediagram-getEpisodeActionsOfPodcastSince.puml
@@ -0,0 +1,32 @@
+@startuml
+
+' title =**Get Episode Actions of Podcast Since**
+
+participant EpisodeActionController << (C, #ADD1B2) @Controller >>
+-> EpisodeActionController: ""GET /api/2/episodes/{username}.json"" \n//@RequestParam("podcast") String podcastURL// \n//@RequestParam("device") String deviceID// \n//@RequestParam("since") long since// \n//@RequestParam("aggregated") boolean aggregated// \n\n-> getEpisodeActionsOfPodcastSince(""username"", //podcastURL//, //deviceID//, //since//, //aggregated//)
+note right
+ Die Parameter //deviceID// und //aggregated// werden ignoriert.
+ Siehe Notiz in Sequenzdiagramm **Get All Episode Actions**.
+end note
+activate EpisodeActionController
+participant EpisodeActionService << (C, #ADD1B2) @Service >>
+EpisodeActionController -> EpisodeActionService: getEpisodeActionsOfPodcastSince(""username"", //podcastURL//, //since//)
+activate EpisodeActionService
+participant EpisodeActionDataAccessService << (C, #ADD1B2) @Repository >>
+EpisodeActionService -> EpisodeActionDataAccessService: getEpisodeActionsOfPodcastSince(""username"", //podcastURL//, //since//)
+activate EpisodeActionDataAccessService
+database Database
+EpisodeActionDataAccessService -> Database: get all EpisodeActions the given podcast (//podcastURL//)
+activate Database
+Database --> EpisodeActionDataAccessService: List<EpisodeAction> selectedEpisodeActions \n-> then remove all older than //since//
+EpisodeActionDataAccessService -> Database: join EpisodeActions in selectedEpisodeActions with episodeURL of Episode
+Database --> EpisodeActionDataAccessService
+deactivate Database
+EpisodeActionDataAccessService --> EpisodeActionService: List<EpisodeActionPost> episodeActionPosts
+deactivate EpisodeActionDataAccessService
+EpisodeActionService --> EpisodeActionController: List<EpisodeActionPost> episodeActionPosts
+deactivate EpisodeActionService
+<-- EpisodeActionController: ResponseEntity<EpisodeActionGetResponse> response \n\n-> ""HTTP status code"" \n-> ""JSON""
+deactivate EpisodeActionController
+
+@enduml \ No newline at end of file
diff --git a/31-qualitaetsheft-kolloquium/assets/diagrams/sequencediagram-getSubscriptions.puml b/31-qualitaetsheft-kolloquium/assets/diagrams/sequencediagram-getSubscriptions.puml
new file mode 100644
index 0000000..4d8ab90
--- /dev/null
+++ b/31-qualitaetsheft-kolloquium/assets/diagrams/sequencediagram-getSubscriptions.puml
@@ -0,0 +1,38 @@
+@startuml
+
+' title =**Get All Subscriptions**
+
+participant SubscriptionController << (C, #ADD1B2) @Controller >>
+-> SubscriptionController: ""GET /subscriptions/{username}.json"" \n"" /subscriptions/{username}/{deviceid}.json"" \n//@RequestParam("jsonp") String functionJSONP// \n\n-> getSubscriptions(""username"", ""deviceid"", //functionJSONP//)
+activate SubscriptionController
+note right
+ Die Parameter ""deviceid"" und
+ //functionJSONP// werden ignoriert,
+ da nicht zwischen Geräten unterschieden
+ und JSONP nicht unterstützt wird.
+end note
+participant SubscriptionService << (C, #ADD1B2) @Service >>
+SubscriptionController -> SubscriptionService: getSubscriptions(""username"")
+activate SubscriptionService
+participant SubscriptionDataAccessService << (C, #ADD1B2) @Repository >>
+SubscriptionService -> SubscriptionDataAccessService: getSubscriptions(""username"")
+activate SubscriptionDataAccessService
+SubscriptionDataAccessService -> SubscriptionDataAccessService: getSubscriptionsSince(""username"", LocalDateTime.MIN)
+database Database
+activate SubscriptionDataAccessService
+SubscriptionDataAccessService -> Database: get all Subscriptions for ""username""
+activate Database
+Database --> SubscriptionDataAccessService: List<Subscription> subscriptions
+SubscriptionDataAccessService -> Database: get Podcasts from Subscriptions
+Database --> SubscriptionDataAccessService: List<Podcast> subscribedPodcasts
+deactivate Database
+SubscriptionDataAccessService --> SubscriptionDataAccessService: List<String> podcastURLs
+deactivate SubscriptionDataAccessService
+SubscriptionDataAccessService --> SubscriptionService: List<String> podcastURLs
+deactivate SubscriptionDataAccessService
+SubscriptionService --> SubscriptionController: List<String> podcastURLs
+deactivate SubscriptionService
+<-- SubscriptionController: ResponseEntity<List<String>> podcastURLs \n \n-> ""HTTP status code"" \n-> ""JSON""
+deactivate SubscriptionController
+
+@enduml \ No newline at end of file
diff --git a/31-qualitaetsheft-kolloquium/assets/diagrams/sequencediagram-register.puml b/31-qualitaetsheft-kolloquium/assets/diagrams/sequencediagram-register.puml
new file mode 100644
index 0000000..b7b7aa1
--- /dev/null
+++ b/31-qualitaetsheft-kolloquium/assets/diagrams/sequencediagram-register.puml
@@ -0,0 +1,26 @@
+@startuml
+
+' title =**Register**
+
+participant AuthenticationController << (C, #ADD1B2) @Controller >>
+-> AuthenticationController: ""POST /api/2/auth/register.json"" \n//@RequestBody UserDetails user// \n\n-> registerUser(//user//)
+activate AuthenticationController
+participant AuthenticationService << (C, #ADD1B2) @Service >>
+AuthenticationController -> AuthenticationService: registerUser(//user//)
+activate AuthenticationService
+participant JdbcUserDetailsManager << (C, #ADD1B2) @Repository >>
+AuthenticationService -> JdbcUserDetailsManager: createUser(//user//)
+activate JdbcUserDetailsManager
+database Database
+JdbcUserDetailsManager -> Database: create new User with given UserDetails (//user//)
+activate Database
+Database --> JdbcUserDetailsManager
+deactivate Database
+JdbcUserDetailsManager --> AuthenticationService: int indicating status
+deactivate JdbcUserDetailsManager
+AuthenticationService --> AuthenticationController: int indicating status
+deactivate AuthenticationService
+<-- AuthenticationController: ResponseEntity<Integer> indicating status \n\n-> ""HTTP status code""
+deactivate AuthenticationController
+
+@enduml \ No newline at end of file
diff --git a/31-qualitaetsheft-kolloquium/assets/diagrams/sequencediagram-uploadEpisodeActions.puml b/31-qualitaetsheft-kolloquium/assets/diagrams/sequencediagram-uploadEpisodeActions.puml
new file mode 100644
index 0000000..d3dac57
--- /dev/null
+++ b/31-qualitaetsheft-kolloquium/assets/diagrams/sequencediagram-uploadEpisodeActions.puml
@@ -0,0 +1,38 @@
+@startuml
+
+' title =**Upload Episode Actions**
+
+participant EpisodeActionController << (C, #ADD1B2) @Controller >>
+-> EpisodeActionController: ""POST /api/2/episodes/{username}.json"" \n//@RequestBody EpisodeActionPostRequest episodeActionPostRequest// \n\n-> addEpisodeActions(""username"", //episodeActionPostRequest//)
+activate EpisodeActionController
+participant EpisodeActionService << (C, #ADD1B2) @Service >>
+EpisodeActionController -> EpisodeActionService: addEpisodeActions(""username"", \nepisodeActionPosts = //episodeActionPostRequest//.getEpisodeActionPosts())
+activate EpisodeActionService
+participant EpisodeActionDataAccessService << (C, #ADD1B2) @Repository >>
+EpisodeActionService -> EpisodeActionDataAccessService: addEpisodeActions(""username"", episodeActionPosts)
+database Database
+activate EpisodeActionDataAccessService
+loop for each EpisodeActionPost in episodeActionPosts -> episodeAction = episodeActionPost.getEpisodeAction()
+opt episodeAction.getAction().equals(Action.PLAY)
+EpisodeActionDataAccessService -> Database: set episodeID field of episodeAction for this ""username"" via podcastURL and episodeURL
+activate Database
+Database --> EpisodeActionDataAccessService
+EpisodeActionDataAccessService -> Database: get last EpisodeAction with this episodeID if present
+Database --> EpisodeActionDataAccessService: Optional<EpisodeAction> lastEpisodeAction
+opt lastEpisodeAction.isPresent()
+EpisodeActionDataAccessService -> Database: replace lastEpisodeAction with episodeAction
+else else
+EpisodeActionDataAccessService -> Database: add episodeAction to DB as new entry
+end
+Database --> EpisodeActionDataAccessService
+deactivate Database
+end
+end
+EpisodeActionDataAccessService --> EpisodeActionService: long latestTimestamp
+deactivate EpisodeActionDataAccessService
+EpisodeActionService --> EpisodeActionController: LocalDateTime timestamp = LocalDateTime.ofEpochSecond(latestTimestamp, 0, ZoneOffset.UTC)
+deactivate EpisodeActionService
+<-- EpisodeActionController: ResponseEntity<EpisodeActionPostResponse> \n(with empty list for updateURLs) \n\n-> ""HTTP status code"" \n-> ""JSON""
+deactivate EpisodeActionController
+
+@enduml \ No newline at end of file
diff --git a/31-qualitaetsheft-kolloquium/assets/diagrams/sequencediagram-uploadSubscriptions.puml b/31-qualitaetsheft-kolloquium/assets/diagrams/sequencediagram-uploadSubscriptions.puml
new file mode 100644
index 0000000..1edc8cf
--- /dev/null
+++ b/31-qualitaetsheft-kolloquium/assets/diagrams/sequencediagram-uploadSubscriptions.puml
@@ -0,0 +1,32 @@
+@startuml
+
+' title =**Upload Subscriptions**
+
+participant SubscriptionController << (C, #ADD1B2) @Controller >>
+-> SubscriptionController: ""PUT /subscriptions/{username}/{deviceid}.json"" \n//@RequestBody List<String> subscriptions// \n\n-> uploadSubscriptions(""username"", ""deviceid"", //subscriptions//)
+activate SubscriptionController
+participant SubscriptionService << (C, #ADD1B2) @Service >>
+SubscriptionController -> SubscriptionService: uploadSubscriptions(""username"", //subscriptions//)
+activate SubscriptionService
+participant SubscriptionDataAccessService << (C, #ADD1B2) @Repository >>
+SubscriptionService -> SubscriptionDataAccessService: uploadSubscriptions(""username"", //subscriptions//)
+activate SubscriptionDataAccessService
+database Database
+SubscriptionDataAccessService -> Database: delete all subsciptions of ""username""
+activate Database
+Database --> SubscriptionDataAccessService
+SubscriptionDataAccessService -> SubscriptionDataAccessService: addSubscriptions(""username"", //subscriptions//)
+activate SubscriptionDataAccessService
+SubscriptionDataAccessService -> Database: upload all subscriptions (//subscriptions//) for ""username""
+Database --> SubscriptionDataAccessService
+deactivate Database
+SubscriptionDataAccessService --> SubscriptionDataAccessService: int indicating status
+deactivate SubscriptionDataAccessService
+SubscriptionDataAccessService --> SubscriptionService: int indicating status
+deactivate SubscriptionDataAccessService
+SubscriptionService --> SubscriptionController: int indicating status
+deactivate SubscriptionService
+<-- SubscriptionController: ResponseEntity<String> with empty String for success \n\n-> ""HTTP status code"" \n-> ""JSON""
+deactivate SubscriptionController
+
+@enduml \ No newline at end of file
diff --git a/31-qualitaetsheft-kolloquium/assets/episode.png b/31-qualitaetsheft-kolloquium/assets/episode.png
new file mode 100644
index 0000000..c0db4a2
--- /dev/null
+++ b/31-qualitaetsheft-kolloquium/assets/episode.png
Binary files differ
diff --git a/31-qualitaetsheft-kolloquium/assets/gantt-plan.puml b/31-qualitaetsheft-kolloquium/assets/gantt-plan.puml
new file mode 100644
index 0000000..0e90aa2
--- /dev/null
+++ b/31-qualitaetsheft-kolloquium/assets/gantt-plan.puml
@@ -0,0 +1,31 @@
+@startgantt
+
+printscale daily zoom 5
+project starts on 2023-01-30
+
+-- Backend --
+[Controller-Schicht] on {Immanuel} lasts 2 days
+[Service-Schicht (Daten durchreichen)] on {Daniel} lasts 2 days
+[Authentifizierung] on {Gero} lasts 4 days
+[Model-Paket] on {Daniel} lasts 1 days
+[Datenbank aufsetzen] on {Immanuel} lasts 4 days
+[Util-Paket (RSSParser)] on {Daniel} {Lukas} lasts 6 days
+[DataAccess-Schicht] on {Immanuel} {Julius} lasts 8 days
+[Service-Schicht (Geschäftslogik)] on {Daniel} {Immanuel} lasts 8 days
+[Util-Paket (CleanCronJob)] on {Julius} lasts 2 days
+-- Frontend --
+[Komponenten] on {Gero} {Julius} {Lukas} lasts 15 days
+[API-Anbindung] on {Gero} {Lukas} lasts 4 days
+
+'Backend
+[Service-Schicht (Daten durchreichen)] starts at [Controller-Schicht]'s end
+[Datenbank aufsetzen] starts at [Model-Paket]'s end
+[Authentifizierung] starts at [Controller-Schicht]'s end
+[DataAccess-Schicht] starts at [Datenbank aufsetzen]'s end
+[Util-Paket (RSSParser)] starts at [Datenbank aufsetzen]'s end
+[Service-Schicht (Geschäftslogik)] starts at [DataAccess-Schicht]'s end
+[Util-Paket (CleanCronJob)] starts at [DataAccess-Schicht]'s end
+'Frontend
+[API-Anbindung] starts at [DataAccess-Schicht]'s end
+
+@endgantt \ No newline at end of file
diff --git a/31-qualitaetsheft-kolloquium/assets/gantt-reality.puml b/31-qualitaetsheft-kolloquium/assets/gantt-reality.puml
new file mode 100644
index 0000000..f726c56
--- /dev/null
+++ b/31-qualitaetsheft-kolloquium/assets/gantt-reality.puml
@@ -0,0 +1,39 @@
+@startgantt
+
+printscale daily zoom 5
+project starts on 2023-01-30
+
+-- Backend --
+[Controller-Schicht] on {Immanuel} lasts 3 days
+[Model-Paket] on {Daniel} lasts 3 days
+[Datenbank aufsetzen] on {Immanuel} lasts 6 days
+[Util-Paket (RSSParser)] on {Daniel} {Lukas} lasts 32 days
+[DAO-Interfaces] on {Julius} {Immanuel} lasts 6 days
+[Authentifizierung] on {Immanuel} lasts 13 days
+[Service-Schicht mit Datenzugriff] on {Julius} lasts 14 days
+[Util-Paket (CleanCronJob)] on {Daniel} lasts 2 days
+[Docker] on {Daniel} lasts 12 days
+[EMailService] on {Gero} lasts 1 days
+-- Frontend --
+[Komponenten] on {Gero} {Julius} lasts 15 days
+[Mehrsprachigkeit] on {Lukas} lasts 5 days
+[Router] on {Gero} lasts 1 days
+[API-Anbindung] on {Gero} {Lukas} lasts 28 days
+[Error-Handling] on {Gero} lasts 5 days
+
+'Backend
+[Datenbank aufsetzen] starts at [Model-Paket]'s end
+[Util-Paket (RSSParser)] starts at [Datenbank aufsetzen]'s end
+[DAO-Interfaces] starts at [Datenbank aufsetzen]'s end
+[Authentifizierung] starts at [DAO-Interfaces]'s end
+[Service-Schicht mit Datenzugriff] starts at [DAO-Interfaces]'s end
+[Util-Paket (CleanCronJob)] starts at [DAO-Interfaces]'s end
+[Docker] starts at [Util-Paket (CleanCronJob)]'s end
+[EMailService] starts 2023-02-14
+'Frontend
+[Mehrsprachigkeit] starts 2023-02-01
+[Router] starts at [Mehrsprachigkeit]'s end
+[API-Anbindung] starts at [Router]'s end
+[Error-Handling] starts 2023-02-05
+
+@endgantt \ No newline at end of file
diff --git a/31-qualitaetsheft-kolloquium/assets/help.png b/31-qualitaetsheft-kolloquium/assets/help.png
new file mode 100644
index 0000000..39a1b84
--- /dev/null
+++ b/31-qualitaetsheft-kolloquium/assets/help.png
Binary files differ
diff --git a/31-qualitaetsheft-kolloquium/assets/lasttest/goodSpecsApdex.png b/31-qualitaetsheft-kolloquium/assets/lasttest/goodSpecsApdex.png
new file mode 100644
index 0000000..17a7031
--- /dev/null
+++ b/31-qualitaetsheft-kolloquium/assets/lasttest/goodSpecsApdex.png
Binary files differ
diff --git a/31-qualitaetsheft-kolloquium/assets/lasttest/goodSpecsResponse.png b/31-qualitaetsheft-kolloquium/assets/lasttest/goodSpecsResponse.png
new file mode 100644
index 0000000..ca737f4
--- /dev/null
+++ b/31-qualitaetsheft-kolloquium/assets/lasttest/goodSpecsResponse.png
Binary files differ
diff --git a/31-qualitaetsheft-kolloquium/assets/lasttest/goodSpecsTable.png b/31-qualitaetsheft-kolloquium/assets/lasttest/goodSpecsTable.png
new file mode 100644
index 0000000..c247933
--- /dev/null
+++ b/31-qualitaetsheft-kolloquium/assets/lasttest/goodSpecsTable.png
Binary files differ
diff --git a/31-qualitaetsheft-kolloquium/assets/lasttest/minimumSpecsApdex.png b/31-qualitaetsheft-kolloquium/assets/lasttest/minimumSpecsApdex.png
new file mode 100644
index 0000000..f326e01
--- /dev/null
+++ b/31-qualitaetsheft-kolloquium/assets/lasttest/minimumSpecsApdex.png
Binary files differ
diff --git a/31-qualitaetsheft-kolloquium/assets/lasttest/minimumSpecsResponse.png b/31-qualitaetsheft-kolloquium/assets/lasttest/minimumSpecsResponse.png
new file mode 100644
index 0000000..c6d27ff
--- /dev/null
+++ b/31-qualitaetsheft-kolloquium/assets/lasttest/minimumSpecsResponse.png
Binary files differ
diff --git a/31-qualitaetsheft-kolloquium/assets/lasttest/minimumSpecsTable.png b/31-qualitaetsheft-kolloquium/assets/lasttest/minimumSpecsTable.png
new file mode 100644
index 0000000..db077cd
--- /dev/null
+++ b/31-qualitaetsheft-kolloquium/assets/lasttest/minimumSpecsTable.png
Binary files differ
diff --git a/31-qualitaetsheft-kolloquium/assets/lastupdate.png b/31-qualitaetsheft-kolloquium/assets/lastupdate.png
new file mode 100644
index 0000000..e9b7f5c
--- /dev/null
+++ b/31-qualitaetsheft-kolloquium/assets/lastupdate.png
Binary files differ
diff --git a/31-qualitaetsheft-kolloquium/assets/logo.svg b/31-qualitaetsheft-kolloquium/assets/logo.svg
new file mode 100644
index 0000000..1609066
--- /dev/null
+++ b/31-qualitaetsheft-kolloquium/assets/logo.svg
@@ -0,0 +1,211 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ version="1.2"
+ width="87.589989mm"
+ height="52.16547mm"
+ viewBox="0 0 8758.9989 5216.547"
+ preserveAspectRatio="xMidYMid"
+ fill-rule="evenodd"
+ stroke-width="28.222"
+ stroke-linejoin="round"
+ xml:space="preserve"
+ id="svg206"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:svg="http://www.w3.org/2000/svg">
+ <defs
+ class="ClipPathGroup"
+ id="defs8" />
+ <defs
+ id="defs51"><font
+ id="EmbeddedFont_1"
+ horiz-adv-x="2048"
+ horiz-origin-x="0"
+ horiz-origin-y="0"
+ vert-origin-x="512"
+ vert-origin-y="768"
+ vert-adv-y="1024">
+ <font-face
+ font-family="Noto Sans Display Light embedded"
+ units-per-em="2048"
+ font-weight="normal"
+ font-style="normal"
+ ascent="2170"
+ descent="609"
+ id="font-face10" />
+ <missing-glyph
+ horiz-adv-x="2048"
+ d="M 0,0 L 2047,0 2047,2047 0,2047 0,0 Z"
+ id="missing-glyph12" />
+ <glyph
+ unicode="y"
+ horiz-adv-x="927"
+ d="M 2,1089 L 127,1089 367,413 C 388,352 407,298 422,250 437,203 449,161 457,124 L 463,124 C 471,156 483,196 498,246 513,296 530,350 551,409 L 786,1089 913,1089 453,-193 C 418,-290 377,-364 328,-416 279,-468 213,-494 131,-494 107,-494 84,-493 63,-490 43,-487 25,-482 8,-476 L 8,-377 C 23,-383 40,-387 57,-391 75,-394 95,-396 117,-396 170,-396 214,-378 249,-342 284,-307 314,-252 340,-179 L 403,4 2,1089 Z"
+ id="glyph14" />
+ <glyph
+ unicode="t"
+ horiz-adv-x="610"
+ d="M 465,80 C 494,80 521,82 547,87 573,91 595,97 614,105 L 614,11 C 594,3 569,-5 541,-11 512,-17 481,-20 449,-20 363,-20 296,5 249,56 202,106 178,189 178,304 L 178,996 27,996 27,1061 178,1100 219,1350 295,1350 295,1090 608,1090 608,996 295,996 295,310 C 295,157 352,80 465,80 Z"
+ id="glyph16" />
+ <glyph
+ unicode="s"
+ horiz-adv-x="742"
+ d="M 817,289 C 817,191 782,115 713,61 643,7 545,-20 418,-20 347,-20 284,-14 228,-1 173,12 126,29 88,50 L 88,162 C 134,138 186,118 244,102 301,86 360,78 420,78 520,78 592,96 636,133 680,169 702,218 702,281 702,341 679,387 632,419 585,451 515,484 422,519 359,542 303,565 255,589 207,613 169,643 142,680 116,717 102,768 102,832 102,919 136,987 204,1037 271,1086 361,1110 473,1110 535,1110 592,1104 646,1092 700,1080 750,1063 795,1043 L 754,946 C 713,964 667,980 617,993 568,1006 518,1012 469,1012 388,1012 326,997 283,967 239,937 217,893 217,836 217,792 228,758 249,733 270,707 301,686 342,668 383,650 433,630 492,609 553,585 608,562 657,537 707,512 745,481 774,443 803,405 817,353 817,289 Z"
+ id="glyph18" />
+ <glyph
+ unicode="r"
+ horiz-adv-x="583"
+ d="M 596,1108 C 646,1108 692,1102 733,1091 L 717,983 C 674,995 632,1001 590,1001 497,1001 423,964 368,890 312,817 285,719 285,598 L 285,-1 168,-1 168,1089 266,1089 279,886 285,886 C 311,948 350,1000 402,1043 455,1086 520,1108 596,1108 Z"
+ id="glyph20" />
+ <glyph
+ unicode="o"
+ horiz-adv-x="927"
+ d="M 1030,547 C 1030,433 1012,333 976,248 940,164 887,98 818,51 749,4 665,-20 565,-20 471,-20 390,3 322,50 253,96 201,162 164,247 127,333 109,433 109,547 109,723 150,861 232,961 315,1061 429,1110 575,1110 672,1110 755,1087 822,1040 890,993 941,927 977,842 1012,757 1030,659 1030,547 Z M 229,547 C 229,407 257,294 312,208 368,123 453,80 567,80 685,80 771,123 826,209 882,295 909,408 909,547 909,637 898,717 875,787 851,856 815,911 766,951 717,990 653,1010 573,1010 459,1010 373,969 315,887 258,805 229,692 229,547 Z"
+ id="glyph22" />
+ <glyph
+ unicode="n"
+ horiz-adv-x="847"
+ d="M 633,1110 C 749,1110 838,1078 900,1014 962,950 993,850 993,713 L 993,1 877,1 877,705 C 877,809 854,885 810,935 766,985 701,1010 616,1010 395,1010 285,871 285,594 L 285,1 168,1 168,1090 262,1090 279,901 287,901 C 314,962 357,1011 416,1051 474,1091 547,1110 633,1110 Z"
+ id="glyph24" />
+ <glyph
+ unicode="m"
+ horiz-adv-x="1430"
+ d="M 1245,1110 C 1348,1110 1427,1080 1485,1018 1542,957 1571,860 1571,727 L 1571,1 1454,1 1454,723 C 1454,820 1434,892 1393,939 1352,986 1296,1010 1227,1010 1130,1010 1056,980 1005,919 953,858 928,764 928,637 L 928,1 811,1 811,723 C 811,820 791,892 750,939 709,986 653,1010 584,1010 487,1010 413,978 361,914 310,850 285,751 285,619 L 285,1 168,1 168,1090 262,1090 279,918 287,918 C 313,971 352,1016 403,1054 455,1092 521,1110 600,1110 675,1110 739,1093 791,1059 842,1025 879,975 899,908 L 907,908 C 936,972 980,1022 1038,1057 1097,1093 1166,1110 1245,1110 Z"
+ id="glyph26" />
+ <glyph
+ unicode="i"
+ horiz-adv-x="187"
+ d="M 227,1493 C 279,1493 305,1464 305,1405 305,1345 279,1315 227,1315 175,1315 150,1345 150,1405 150,1464 175,1493 227,1493 Z M 285,1090 L 285,0 168,0 168,1090 285,1090 Z"
+ id="glyph28" />
+ <glyph
+ unicode="h"
+ horiz-adv-x="847"
+ d="M 285,1059 C 285,1031 284,1003 283,977 281,951 279,926 276,901 L 285,901 C 312,962 355,1011 413,1051 471,1091 543,1110 629,1110 746,1110 836,1078 899,1014 962,950 993,850 993,713 L 993,1 877,1 877,705 C 877,809 854,885 810,935 766,985 701,1010 616,1010 395,1010 285,871 285,594 L 285,1 168,1 168,1557 285,1557 285,1059 Z"
+ id="glyph30" />
+ <glyph
+ unicode="f"
+ horiz-adv-x="689"
+ d="M 575,995 L 332,995 332,-1 213,-1 213,995 27,995 27,1058 213,1093 213,1202 C 213,1445 316,1566 522,1566 559,1566 593,1563 623,1557 653,1551 680,1544 705,1536 L 678,1439 C 655,1448 630,1454 603,1460 577,1465 550,1468 524,1468 456,1468 407,1447 377,1405 347,1362 332,1295 332,1202 L 332,1089 575,1089 575,995 Z"
+ id="glyph32" />
+ <glyph
+ unicode="e"
+ horiz-adv-x="874"
+ d="M 559,1110 C 646,1110 720,1089 779,1046 839,1003 883,944 913,869 943,794 958,708 958,611 L 958,531 229,531 C 231,386 262,275 325,198 387,121 476,82 592,82 656,82 712,88 759,100 806,111 858,130 915,156 L 915,50 C 865,25 814,7 764,-4 713,-15 655,-20 588,-20 434,-20 315,30 232,129 150,229 109,365 109,537 109,648 126,746 162,832 197,918 249,986 315,1036 382,1085 464,1110 559,1110 Z M 559,1012 C 465,1012 389,979 333,912 276,845 243,750 233,627 L 838,627 C 838,742 815,835 769,906 723,977 653,1012 559,1012 Z"
+ id="glyph34" />
+ <glyph
+ unicode="d"
+ horiz-adv-x="900"
+ d="M 535,-20 C 398,-20 293,27 219,120 145,214 109,352 109,535 109,722 147,865 224,963 301,1061 408,1110 545,1110 629,1110 698,1090 752,1050 805,1010 845,961 872,904 L 881,904 C 879,935 878,970 876,1009 873,1048 872,1084 872,1117 L 872,1557 989,1557 989,0 895,0 879,191 872,191 C 845,132 805,82 751,41 697,0 625,-20 535,-20 Z M 553,80 C 669,80 752,119 801,195 850,271 875,382 875,527 L 875,545 C 875,695 850,810 801,890 752,970 671,1010 559,1010 451,1010 369,969 313,886 257,804 229,686 229,533 229,385 256,273 309,196 363,119 444,80 553,80 Z"
+ id="glyph36" />
+ <glyph
+ unicode="c"
+ horiz-adv-x="768"
+ d="M 580,-20 C 429,-20 313,29 231,127 150,226 109,363 109,539 109,662 129,766 170,850 211,935 269,1000 343,1044 417,1088 504,1110 602,1110 651,1110 698,1106 742,1096 787,1087 825,1074 858,1057 L 825,957 C 791,972 754,984 714,993 673,1002 636,1006 600,1006 481,1006 390,964 326,881 261,798 229,685 229,541 229,405 258,294 314,210 371,126 459,84 580,84 630,84 678,90 723,101 768,112 809,125 846,142 L 846,37 C 812,20 773,6 729,-5 685,-15 636,-20 580,-20 Z"
+ id="glyph38" />
+ <glyph
+ unicode="a"
+ horiz-adv-x="822"
+ d="M 535,1108 C 651,1108 737,1078 795,1018 852,958 881,863 881,734 L 881,0 793,0 772,185 766,185 C 729,123 684,74 631,36 578,-1 503,-20 408,-20 311,-20 233,6 176,59 119,111 90,187 90,285 90,394 132,477 215,533 298,589 420,621 580,629 L 764,639 764,715 C 764,822 744,897 705,942 665,987 606,1010 528,1010 477,1010 426,1002 378,987 329,972 281,953 231,928 L 195,1022 C 242,1047 295,1067 352,1084 410,1100 470,1108 535,1108 Z M 594,543 C 466,536 370,512 307,470 244,429 213,367 213,285 213,217 232,165 271,131 310,96 363,78 430,78 535,78 617,111 676,176 735,240 764,330 764,445 L 764,551 594,543 Z"
+ id="glyph40" />
+ <glyph
+ unicode="S"
+ horiz-adv-x="875"
+ d="M 956,381 C 956,294 936,220 894,160 852,100 796,55 724,25 652,-5 571,-20 479,-20 396,-20 324,-14 262,-2 201,11 147,26 102,46 L 102,162 C 152,142 209,124 273,109 338,94 409,87 485,87 589,87 673,110 738,158 803,206 836,278 836,373 836,431 823,478 798,515 772,553 734,586 682,614 630,642 565,670 485,699 410,726 345,757 291,791 236,825 194,868 164,919 134,970 119,1035 119,1112 119,1192 138,1259 176,1314 214,1369 267,1411 333,1440 399,1469 474,1483 559,1483 626,1483 689,1476 750,1463 810,1449 868,1430 924,1405 L 883,1303 C 772,1352 663,1377 555,1377 462,1377 386,1354 328,1310 269,1266 240,1200 240,1114 240,1052 252,1001 278,964 303,926 340,895 389,869 438,843 498,817 567,791 648,762 717,731 775,698 833,664 878,623 909,573 941,523 956,459 956,381 Z"
+ id="glyph42" />
+ <glyph
+ unicode="P"
+ horiz-adv-x="848"
+ d="M 539,1462 C 869,1462 1034,1325 1034,1049 1034,908 992,798 907,718 823,638 690,598 510,598 L 311,598 311,0 193,0 193,1462 539,1462 Z M 528,1358 L 311,1358 311,702 498,702 C 629,702 730,727 803,776 875,825 911,914 911,1043 911,1152 880,1232 818,1282 756,1333 659,1358 528,1358 Z"
+ id="glyph44" />
+ <glyph
+ unicode="E"
+ horiz-adv-x="769"
+ d="M 950,0 L 193,0 193,1462 950,1462 950,1356 311,1356 311,821 913,821 913,715 311,715 311,107 950,107 950,0 Z"
+ id="glyph46" />
+ <glyph
+ unicode=" "
+ horiz-adv-x="503"
+ id="glyph48" />
+ </font></defs>
+ <defs
+ class="TextShapeIndex"
+ id="defs55" />
+ <defs
+ class="EmbeddedBulletChars"
+ id="defs87" />
+
+ <g
+ id="id10"
+ clip-path="none"
+ transform="translate(-700.00001,-2550)">
+
+ <text
+ class="SVGTextShape"
+ id="text151"
+ x="217.60002"
+ y="-56.506969"
+ style="letter-spacing:4.7625px;word-spacing:104.775px"><tspan
+ class="TextParagraph"
+ font-family="'Noto Sans Display Light', sans-serif"
+ font-size="494px"
+ font-weight="400"
+ id="tspan149"><tspan
+ class="TextPosition"
+ x="650.59998"
+ y="7647.4932"
+ id="tspan147"><tspan
+ fill="#808080"
+ stroke="none"
+ style="white-space:pre"
+ id="tspan145"
+ dx="2.1199999">Podcast Synchronisation made Efficient</tspan></tspan></tspan></text>
+ </g><g
+ id="g1277"
+ transform="translate(-700.00001,-2550)"><path
+ id="path131-3"
+ d="m 6694.0006,4763 c -559.5515,4.407 -980.3924,428.0893 -986.038,985.9863 18.2894,552.8957 454.3127,974.1166 989.0352,986.0379 v -235.0244 c -406.8751,-27.3888 -715.1078,-362.1649 -719.0259,-748.0163 12.7874,-421.0793 236.9242,-746.3999 750.0318,-749.98 895.0688,1.4728 1915.5158,0 2730.9957,0 V 4763 Z"
+ style="fill:#0084d1;fill-opacity:1"
+ clip-path="none" /><path
+ id="path131"
+ d="m 6685.0183,2562.996 c -559.5515,4.407 -980.3924,428.0893 -986.038,985.9863 18.2894,552.8957 454.3127,974.1167 989.0352,986.038 v -235.0244 c -406.8751,-27.3888 -715.1078,-362.165 -719.0259,-748.0164 12.7874,-421.0792 236.9242,-746.3998 750.0318,-749.98 895.0688,1.4728 1915.5158,0 2730.996,0 V 2562.996 Z"
+ style="fill:#0084d1;fill-opacity:1"
+ clip-path="none" /></g><g
+ id="g1263"
+ transform="translate(-700.00001,-2550)"><path
+ fill="none"
+ stroke="#069a2e"
+ stroke-width="265"
+ stroke-linejoin="round"
+ d="m 2793,5962 c 1283,0 429,-2762 1712,-2762"
+ id="path124" /><path
+ id="path110-6"
+ d="M 3198.0212,6550 V 6300.0411 H 2448.0411 V 6050.0305 5550.0094 H 2198.0305 V 6300.0411 6550 H 2448.0411 2698 Z"
+ style="fill:#069a2e;fill-opacity:1" /><path
+ id="path110"
+ d="m 4111.997,2550.0252 v 249.9589 h 749.9801 v 250.0106 500.0211 h 250.0106 v -750.0317 -249.9589 h -250.0106 -249.9589 z"
+ style="fill:#069a2e;fill-opacity:1" /></g>
+ <g
+ id="g1249"
+ transform="translate(-700.00001,-2550)"><path
+ fill="#ff8000"
+ stroke="none"
+ d="M 2215,4164 C 2412.6918,3832.6035 2379.3124,3383.7591 2135.4189,3084.8193 1956.8564,2857.4026 1671.3097,2718.8851 1382,2721 c 0,-52.6667 0,-105.3333 0,-158 -60.1303,-1.0792 190.6585,-1.2724 121.9814,2.7933 434.6311,30.3756 832.6257,336.7309 974.9655,748.2365 148.7336,402.6249 41.0263,883.7477 -266.0719,1183.8452 C 1996.6852,4716.1853 1689.0048,4838.6187 1382,4830 c 0,-61.6667 0,-123.3333 0,-185 338.199,2.9253 666.226,-186.816 833,-481 z"
+ id="path193" /><path
+ fill="#ff8000"
+ stroke="none"
+ d="m 1936,3979 c 175.8129,-283.3241 59.7943,-700.6319 -239.8255,-849.407 -94.2713,-50.9942 -201.887,-77.9344 -309.1745,-74.593 0,-57 0,-114 0,-171 396.3865,-24.0968 777.5367,297.6517 818.5878,693.1841 44.0348,337.5467 -149.4277,694.9971 -466.4953,826.9493 -110.1027,49.0687 -231.5272,73.543 -352.0925,67.8666 0,-61.6667 0,-123.3333 0,-185 220.6353,7.5804 440.8554,-115.3286 549,-308 z"
+ id="path186" /><path
+ fill="#ff8000"
+ stroke="none"
+ d="m 1659,3822 c 86.3933,-138.0398 18.2474,-344.669 -134.6962,-402.3205 C 1483.44,3402.2177 1438.3524,3394.2432 1394,3398 c 0,-56.6667 0,-113.3333 0,-170 223.1964,-19.6143 444.7886,153.3254 478.4886,375.1817 32.646,181.6951 -54.6854,381.4331 -217.3127,472.2205 -78.2316,46.131 -170.3991,69.3119 -261.1759,62.5978 0,-58.3333 0,-116.6667 0,-175 105.6736,9.5509 212.8962,-49.2218 265,-141 z"
+ id="path179" /><rect
+ class="BoundingBox"
+ stroke="none"
+ fill="none"
+ x="700"
+ y="2550"
+ width="501"
+ height="4001"
+ id="rect136"
+ style="fill:#ff8000;fill-opacity:1" /></g>
+
+</svg>
diff --git a/31-qualitaetsheft-kolloquium/assets/navbar.png b/31-qualitaetsheft-kolloquium/assets/navbar.png
new file mode 100644
index 0000000..dd9f8e8
--- /dev/null
+++ b/31-qualitaetsheft-kolloquium/assets/navbar.png
Binary files differ
diff --git a/31-qualitaetsheft-kolloquium/assets/password-margin.png b/31-qualitaetsheft-kolloquium/assets/password-margin.png
new file mode 100644
index 0000000..d9d4fa3
--- /dev/null
+++ b/31-qualitaetsheft-kolloquium/assets/password-margin.png
Binary files differ
diff --git a/31-qualitaetsheft-kolloquium/assets/password.png b/31-qualitaetsheft-kolloquium/assets/password.png
new file mode 100644
index 0000000..68248a0
--- /dev/null
+++ b/31-qualitaetsheft-kolloquium/assets/password.png
Binary files differ
diff --git a/31-qualitaetsheft-kolloquium/assets/sources/checkstyle-after-processed.txt b/31-qualitaetsheft-kolloquium/assets/sources/checkstyle-after-processed.txt
new file mode 100644
index 0000000..8bb59fa
--- /dev/null
+++ b/31-qualitaetsheft-kolloquium/assets/sources/checkstyle-after-processed.txt
@@ -0,0 +1 @@
+1 (design) HideUtilityClassConstructor
diff --git a/31-qualitaetsheft-kolloquium/assets/sources/checkstyle-after.txt b/31-qualitaetsheft-kolloquium/assets/sources/checkstyle-after.txt
new file mode 100644
index 0000000..cec00d5
--- /dev/null
+++ b/31-qualitaetsheft-kolloquium/assets/sources/checkstyle-after.txt
@@ -0,0 +1,22 @@
+[INFO] Scanning for projects...
+[INFO]
+[INFO] -----------------------< org.pse-squared:server >-----------------------
+[INFO] Building server 0.0.1-SNAPSHOT
+[INFO] --------------------------------[ jar ]---------------------------------
+[INFO]
+[INFO] --- maven-checkstyle-plugin:3.2.1:check (default-cli) @ server ---
+[INFO] There is 1 error reported by Checkstyle 9.3 with sun_checks.xml ruleset.
+[ERROR] src/main/java/org/psesquared/server/ServerApplication.java:[12,1] (design) HideUtilityClassConstructor: Hilfsklassen sollten keinen Standard-Konstruktur und keinen als public deklarierten Konstruktor haben.
+[INFO] ------------------------------------------------------------------------
+[INFO] BUILD FAILURE
+[INFO] ------------------------------------------------------------------------
+[INFO] Total time: 14.432 s
+[INFO] Finished at: 2023-03-18T08:30:11+01:00
+[INFO] ------------------------------------------------------------------------
+[ERROR] Failed to execute goal org.apache.maven.plugins:maven-checkstyle-plugin:3.2.1:check (default-cli) on project server: You have 1 Checkstyle violation. -> [Help 1]
+[ERROR]
+[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
+[ERROR] Re-run Maven using the -X switch to enable full debug logging.
+[ERROR]
+[ERROR] For more information about the errors and possible solutions, please read the following articles:
+[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoFailureException
diff --git a/31-qualitaetsheft-kolloquium/assets/sources/checkstyle-before-processed.txt b/31-qualitaetsheft-kolloquium/assets/sources/checkstyle-before-processed.txt
new file mode 100644
index 0000000..3a5af1a
--- /dev/null
+++ b/31-qualitaetsheft-kolloquium/assets/sources/checkstyle-before-processed.txt
@@ -0,0 +1,23 @@
+285 (sizes) LineLength
+143 (misc) FinalParameters
+101 (javadoc) JavadocVariable
+83 (javadoc) JavadocStyle
+43 (design) DesignForExtension
+39 (javadoc) MissingJavadocMethod
+26 (regexp) RegexpSingleline
+15 (whitespace) WhitespaceAround
+13 (javadoc) JavadocPackage
+10 (whitespace) OperatorWrap
+10 (javadoc) JavadocType
+7 (imports) AvoidStarImport
+6 (coding) MagicNumber
+4 (javadoc) JavadocMethod
+3 (coding) HiddenField
+2 (javadoc) InvalidJavadocPosition
+2 (design) HideUtilityClassConstructor
+2 (blocks) RightCurly
+1 (whitespace) WhitespaceAfter
+1 (whitespace) FileTabCharacter
+1 (misc) NewlineAtEndOfFile
+1 (misc) ArrayTypeStyle
+1 (imports) UnusedImports
diff --git a/31-qualitaetsheft-kolloquium/assets/sources/checkstyle-before.txt b/31-qualitaetsheft-kolloquium/assets/sources/checkstyle-before.txt
new file mode 100644
index 0000000..abc9f4f
--- /dev/null
+++ b/31-qualitaetsheft-kolloquium/assets/sources/checkstyle-before.txt
@@ -0,0 +1,820 @@
+[INFO] Scanning for projects...
+[INFO]
+[INFO] -----------------------< org.pse-squared:server >-----------------------
+[INFO] Building server 0.0.1-SNAPSHOT
+[INFO] --------------------------------[ jar ]---------------------------------
+[INFO]
+[INFO] --- maven-checkstyle-plugin:3.2.1:check (default-cli) @ server ---
+[INFO] There are 799 errors reported by Checkstyle 9.3 with sun_checks.xml ruleset.
+[ERROR] src/main/java/org/psesquared/server/config/AuthenticationValidatorInterceptor.java:[1] (javadoc) JavadocPackage: Es fehlt eine package-info.java.
+[ERROR] src/main/java/org/psesquared/server/config/AuthenticationValidatorInterceptor.java:[15,5] (javadoc) JavadocVariable: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/config/AuthenticationValidatorInterceptor.java:[16,5] (javadoc) JavadocVariable: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/config/AuthenticationValidatorInterceptor.java:[17,5] (javadoc) JavadocVariable: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/config/AuthenticationValidatorInterceptor.java:[18,5] (javadoc) JavadocVariable: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/config/AuthenticationValidatorInterceptor.java:[20,5] (design) DesignForExtension: Klasse 'AuthenticationValidatorInterceptor' sieht wie zur Erweiterung entworfen aus (kann subclassed werden), aber die Methode 'preHandle' besitzt keinen Javadoc-Kommentar, der erklärt, wie Sie das sicher tun. Wenn die Klasse nicht für Erweiterungen ausgelegt ist, sollten sie die Klasse 'AuthenticationValidatorInterceptor' final oder die Methode 'preHandle' static/final/abstract/empty machen oder die zugelassene Annotation für die Methode hinzufügen.
+[ERROR] src/main/java/org/psesquared/server/config/AuthenticationValidatorInterceptor.java:[21,30] (misc) FinalParameters: Der Parameter request sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/config/AuthenticationValidatorInterceptor.java:[22,13] (misc) FinalParameters: Der Parameter response sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/config/AuthenticationValidatorInterceptor.java:[23,13] (misc) FinalParameters: Der Parameter handler sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/config/AuthenticationValidatorInterceptor.java:[25] (sizes) LineLength: Zeile ist 81 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/config/AuthenticationValidatorInterceptor.java:[26] (sizes) LineLength: Zeile ist 113 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/config/AuthenticationValidatorInterceptor.java:[44,48] (misc) FinalParameters: Der Parameter request sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/config/AuthenticationValidatorInterceptor.java:[45] (sizes) LineLength: Zeile ist 117 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/config/AuthenticationValidatorInterceptor.java:[46] (sizes) LineLength: Zeile ist 101 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/config/AuthenticationValidatorInterceptor.java:[49] (sizes) LineLength: Zeile ist 90 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/config/SecurityConfigProperties.java:[6] (sizes) LineLength: Zeile ist 87 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/config/SecurityConfigProperties.java:[6,86] (whitespace) WhitespaceAround: Nach '{' fehlt ein Leerzeichen.
+[ERROR] src/main/java/org/psesquared/server/config/SecurityConfigProperties.java:[6,87] (whitespace) WhitespaceAround: Vor '}' fehlt ein Leerzeichen.
+[ERROR] src/main/java/org/psesquared/server/config/EMailConfigProperties.java:[6] (sizes) LineLength: Zeile ist 108 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/config/EMailConfigProperties.java:[6,107] (whitespace) WhitespaceAround: Nach '{' fehlt ein Leerzeichen.
+[ERROR] src/main/java/org/psesquared/server/config/EMailConfigProperties.java:[6,108] (whitespace) WhitespaceAround: Vor '}' fehlt ein Leerzeichen.
+[ERROR] src/main/java/org/psesquared/server/config/SecurityConfig.java:[22,5] (javadoc) JavadocVariable: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/config/SecurityConfig.java:[23,5] (javadoc) JavadocVariable: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/config/SecurityConfig.java:[24] (sizes) LineLength: Zeile ist 82 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/config/SecurityConfig.java:[24,5] (javadoc) JavadocVariable: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/config/SecurityConfig.java:[25] (sizes) LineLength: Zeile ist 97 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/config/SecurityConfig.java:[25,5] (javadoc) JavadocVariable: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/config/SecurityConfig.java:[27,5] (javadoc) JavadocVariable: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/config/SecurityConfig.java:[28,5] (javadoc) JavadocVariable: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/config/SecurityConfig.java:[30,5] (javadoc) MissingJavadocMethod: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/config/SecurityConfig.java:[30,5] (design) DesignForExtension: Klasse 'SecurityConfig' sieht wie zur Erweiterung entworfen aus (kann subclassed werden), aber die Methode 'securityFilterChain' besitzt keinen Javadoc-Kommentar, der erklärt, wie Sie das sicher tun. Wenn die Klasse nicht für Erweiterungen ausgelegt ist, sollten sie die Klasse 'SecurityConfig' final oder die Methode 'securityFilterChain' static/final/abstract/empty machen oder die zugelassene Annotation für die Methode hinzufügen.
+[ERROR] src/main/java/org/psesquared/server/config/SecurityConfig.java:[31] (sizes) LineLength: Zeile ist 88 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/config/SecurityConfig.java:[31,52] (misc) FinalParameters: Der Parameter http sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/config/SecurityConfig.java:[48] (sizes) LineLength: Zeile ist 91 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/config/SecurityConfig.java:[56,5] (design) DesignForExtension: Klasse 'SecurityConfig' sieht wie zur Erweiterung entworfen aus (kann subclassed werden), aber die Methode 'corsConfigurationSource' besitzt keinen Javadoc-Kommentar, der erklärt, wie Sie das sicher tun. Wenn die Klasse nicht für Erweiterungen ausgelegt ist, sollten sie die Klasse 'SecurityConfig' final oder die Methode 'corsConfigurationSource' static/final/abstract/empty machen oder die zugelassene Annotation für die Methode hinzufügen.
+[ERROR] src/main/java/org/psesquared/server/config/SecurityConfig.java:[63] (sizes) LineLength: Zeile ist 87 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/config/JwtService.java:[3,23] (imports) AvoidStarImport: Stern-Importe der Form '.*' sollten vermieden werden - io.jsonwebtoken.*.
+[ERROR] src/main/java/org/psesquared/server/config/JwtService.java:[21,5] (javadoc) JavadocVariable: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/config/JwtService.java:[22] (sizes) LineLength: Zeile ist 92 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/config/JwtService.java:[22,5] (javadoc) JavadocVariable: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/config/JwtService.java:[24,5] (javadoc) JavadocVariable: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/config/JwtService.java:[26,5] (javadoc) MissingJavadocMethod: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/config/JwtService.java:[26,5] (design) DesignForExtension: Klasse 'JwtService' sieht wie zur Erweiterung entworfen aus (kann subclassed werden), aber die Methode 'extractUsername' besitzt keinen Javadoc-Kommentar, der erklärt, wie Sie das sicher tun. Wenn die Klasse nicht für Erweiterungen ausgelegt ist, sollten sie die Klasse 'JwtService' final oder die Methode 'extractUsername' static/final/abstract/empty machen oder die zugelassene Annotation für die Methode hinzufügen.
+[ERROR] src/main/java/org/psesquared/server/config/JwtService.java:[26,35] (misc) FinalParameters: Der Parameter token sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/config/JwtService.java:[30,5] (javadoc) MissingJavadocMethod: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/config/JwtService.java:[30,5] (design) DesignForExtension: Klasse 'JwtService' sieht wie zur Erweiterung entworfen aus (kann subclassed werden), aber die Methode 'extractClaim' besitzt keinen Javadoc-Kommentar, der erklärt, wie Sie das sicher tun. Wenn die Klasse nicht für Erweiterungen ausgelegt ist, sollten sie die Klasse 'JwtService' final oder die Methode 'extractClaim' static/final/abstract/empty machen oder die zugelassene Annotation für die Methode hinzufügen.
+[ERROR] src/main/java/org/psesquared/server/config/JwtService.java:[30,31] (misc) FinalParameters: Der Parameter token sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/config/JwtService.java:[30,45] (misc) FinalParameters: Der Parameter claimsResolver sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/config/JwtService.java:[36] (regexp) RegexpSingleline: Line has trailing spaces.
+[ERROR] src/main/java/org/psesquared/server/config/JwtService.java:[41] (sizes) LineLength: Zeile ist 122 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/config/JwtService.java:[41,5] (javadoc) MissingJavadocMethod: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/config/JwtService.java:[41,5] (design) DesignForExtension: Klasse 'JwtService' sieht wie zur Erweiterung entworfen aus (kann subclassed werden), aber die Methode 'generateTokenString' besitzt keinen Javadoc-Kommentar, der erklärt, wie Sie das sicher tun. Wenn die Klasse nicht für Erweiterungen ausgelegt ist, sollten sie die Klasse 'JwtService' final oder die Methode 'generateTokenString' static/final/abstract/empty machen oder die zugelassene Annotation für die Methode hinzufügen.
+[ERROR] src/main/java/org/psesquared/server/config/JwtService.java:[41,39] (misc) FinalParameters: Der Parameter additionalClaims sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/config/JwtService.java:[41,77] (misc) FinalParameters: Der Parameter userDetails sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/config/JwtService.java:[41,102] (misc) FinalParameters: Der Parameter tokenLifespan sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/config/JwtService.java:[46] (sizes) LineLength: Zeile ist 84 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/config/JwtService.java:[51,5] (javadoc) MissingJavadocMethod: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/config/JwtService.java:[51,5] (design) DesignForExtension: Klasse 'JwtService' sieht wie zur Erweiterung entworfen aus (kann subclassed werden), aber die Methode 'generateAccessTokenString' besitzt keinen Javadoc-Kommentar, der erklärt, wie Sie das sicher tun. Wenn die Klasse nicht für Erweiterungen ausgelegt ist, sollten sie die Klasse 'JwtService' final oder die Methode 'generateAccessTokenString' static/final/abstract/empty machen oder die zugelassene Annotation für die Methode hinzufügen.
+[ERROR] src/main/java/org/psesquared/server/config/JwtService.java:[53] (sizes) LineLength: Zeile ist 95 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/config/JwtService.java:[56,5] (javadoc) MissingJavadocMethod: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/config/JwtService.java:[56,5] (design) DesignForExtension: Klasse 'JwtService' sieht wie zur Erweiterung entworfen aus (kann subclassed werden), aber die Methode 'generateUrlTokenString' besitzt keinen Javadoc-Kommentar, der erklärt, wie Sie das sicher tun. Wenn die Klasse nicht für Erweiterungen ausgelegt ist, sollten sie die Klasse 'JwtService' final oder die Methode 'generateUrlTokenString' static/final/abstract/empty machen oder die zugelassene Annotation für die Methode hinzufügen.
+[ERROR] src/main/java/org/psesquared/server/config/JwtService.java:[57] (sizes) LineLength: Zeile ist 92 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/config/JwtService.java:[60,5] (javadoc) MissingJavadocMethod: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/config/JwtService.java:[60,5] (design) DesignForExtension: Klasse 'JwtService' sieht wie zur Erweiterung entworfen aus (kann subclassed werden), aber die Methode 'isTokenValid' besitzt keinen Javadoc-Kommentar, der erklärt, wie Sie das sicher tun. Wenn die Klasse nicht für Erweiterungen ausgelegt ist, sollten sie die Klasse 'JwtService' final oder die Methode 'isTokenValid' static/final/abstract/empty machen oder die zugelassene Annotation für die Methode hinzufügen.
+[ERROR] src/main/java/org/psesquared/server/config/JwtService.java:[60,33] (misc) FinalParameters: Der Parameter token sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/config/JwtService.java:[60,47] (misc) FinalParameters: Der Parameter userDetails sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/config/JwtService.java:[62] (sizes) LineLength: Zeile ist 84 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/config/JwtService.java:[65,36] (misc) FinalParameters: Der Parameter token sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/config/JwtService.java:[69,36] (misc) FinalParameters: Der Parameter token sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/config/JwtService.java:[73,37] (misc) FinalParameters: Der Parameter token sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/config/JwtService.java:[88] (sizes) LineLength: Zeile ist 91 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/config/JwtAuthenticationFilter.java:[26,5] (javadoc) JavadocVariable: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/config/JwtAuthenticationFilter.java:[27,5] (javadoc) JavadocVariable: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/config/JwtAuthenticationFilter.java:[28] (sizes) LineLength: Zeile ist 82 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/config/JwtAuthenticationFilter.java:[28,5] (javadoc) JavadocVariable: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/config/JwtAuthenticationFilter.java:[29] (sizes) LineLength: Zeile ist 97 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/config/JwtAuthenticationFilter.java:[29,5] (javadoc) JavadocVariable: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/config/JwtAuthenticationFilter.java:[30,5] (javadoc) JavadocVariable: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/config/JwtAuthenticationFilter.java:[32,5] (javadoc) JavadocVariable: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/config/JwtAuthenticationFilter.java:[33,5] (javadoc) JavadocVariable: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/config/JwtAuthenticationFilter.java:[35,5] (design) DesignForExtension: Klasse 'JwtAuthenticationFilter' sieht wie zur Erweiterung entworfen aus (kann subclassed werden), aber die Methode 'doFilterInternal' besitzt keinen Javadoc-Kommentar, der erklärt, wie Sie das sicher tun. Wenn die Klasse nicht für Erweiterungen ausgelegt ist, sollten sie die Klasse 'JwtAuthenticationFilter' final oder die Methode 'doFilterInternal' static/final/abstract/empty machen oder die zugelassene Annotation für die Methode hinzufügen.
+[ERROR] src/main/java/org/psesquared/server/config/JwtAuthenticationFilter.java:[36,37] (misc) FinalParameters: Der Parameter request sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/config/JwtAuthenticationFilter.java:[37,37] (misc) FinalParameters: Der Parameter response sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/config/JwtAuthenticationFilter.java:[38,37] (misc) FinalParameters: Der Parameter filterChain sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/config/JwtAuthenticationFilter.java:[45] (sizes) LineLength: Zeile ist 96 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/config/JwtAuthenticationFilter.java:[54] (sizes) LineLength: Zeile ist 81 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/config/JwtAuthenticationFilter.java:[54,38] (misc) FinalParameters: Der Parameter cookie sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/config/JwtAuthenticationFilter.java:[54,53] (misc) FinalParameters: Der Parameter request sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/config/JwtAuthenticationFilter.java:[68] (sizes) LineLength: Zeile ist 95 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/config/JwtAuthenticationFilter.java:[69,13] (whitespace) WhitespaceAfter: Nach 'if' fehlt ein Leerzeichen.
+[ERROR] src/main/java/org/psesquared/server/config/JwtAuthenticationFilter.java:[70] (sizes) LineLength: Zeile ist 104 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/config/JwtAuthenticationFilter.java:[76] (sizes) LineLength: Zeile ist 82 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/config/ApplicationConfig.java:[32] (sizes) LineLength: Zeile ist 98 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/config/ApplicationConfig.java:[32,5] (javadoc) JavadocVariable: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/config/ApplicationConfig.java:[34,5] (javadoc) JavadocVariable: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/config/ApplicationConfig.java:[36,5] (javadoc) MissingJavadocMethod: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/config/ApplicationConfig.java:[36,5] (design) DesignForExtension: Klasse 'ApplicationConfig' sieht wie zur Erweiterung entworfen aus (kann subclassed werden), aber die Methode 'userDetailsService' besitzt keinen Javadoc-Kommentar, der erklärt, wie Sie das sicher tun. Wenn die Klasse nicht für Erweiterungen ausgelegt ist, sollten sie die Klasse 'ApplicationConfig' final oder die Methode 'userDetailsService' static/final/abstract/empty machen oder die zugelassene Annotation für die Methode hinzufügen.
+[ERROR] src/main/java/org/psesquared/server/config/ApplicationConfig.java:[39] (sizes) LineLength: Zeile ist 94 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/config/ApplicationConfig.java:[42,5] (javadoc) MissingJavadocMethod: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/config/ApplicationConfig.java:[42,5] (design) DesignForExtension: Klasse 'ApplicationConfig' sieht wie zur Erweiterung entworfen aus (kann subclassed werden), aber die Methode 'authenticationProvider' besitzt keinen Javadoc-Kommentar, der erklärt, wie Sie das sicher tun. Wenn die Klasse nicht für Erweiterungen ausgelegt ist, sollten sie die Klasse 'ApplicationConfig' final oder die Methode 'authenticationProvider' static/final/abstract/empty machen oder die zugelassene Annotation für die Methode hinzufügen.
+[ERROR] src/main/java/org/psesquared/server/config/ApplicationConfig.java:[44] (sizes) LineLength: Zeile ist 81 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/config/ApplicationConfig.java:[50,5] (javadoc) MissingJavadocMethod: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/config/ApplicationConfig.java:[50,5] (design) DesignForExtension: Klasse 'ApplicationConfig' sieht wie zur Erweiterung entworfen aus (kann subclassed werden), aber die Methode 'passwordEncoder' besitzt keinen Javadoc-Kommentar, der erklärt, wie Sie das sicher tun. Wenn die Klasse nicht für Erweiterungen ausgelegt ist, sollten sie die Klasse 'ApplicationConfig' final oder die Methode 'passwordEncoder' static/final/abstract/empty machen oder die zugelassene Annotation für die Methode hinzufügen.
+[ERROR] src/main/java/org/psesquared/server/config/ApplicationConfig.java:[55,5] (javadoc) MissingJavadocMethod: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/config/ApplicationConfig.java:[55,5] (design) DesignForExtension: Klasse 'ApplicationConfig' sieht wie zur Erweiterung entworfen aus (kann subclassed werden), aber die Methode 'authenticationManager' besitzt keinen Javadoc-Kommentar, der erklärt, wie Sie das sicher tun. Wenn die Klasse nicht für Erweiterungen ausgelegt ist, sollten sie die Klasse 'ApplicationConfig' final oder die Methode 'authenticationManager' static/final/abstract/empty machen oder die zugelassene Annotation für die Methode hinzufügen.
+[ERROR] src/main/java/org/psesquared/server/config/ApplicationConfig.java:[56] (sizes) LineLength: Zeile ist 109 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/config/ApplicationConfig.java:[56,56] (misc) FinalParameters: Der Parameter config sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/config/ApplicationConfig.java:[60,5] (javadoc) MissingJavadocMethod: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/config/ApplicationConfig.java:[60,5] (design) DesignForExtension: Klasse 'ApplicationConfig' sieht wie zur Erweiterung entworfen aus (kann subclassed werden), aber die Methode 'corsConfigurer' besitzt keinen Javadoc-Kommentar, der erklärt, wie Sie das sicher tun. Wenn die Klasse nicht für Erweiterungen ausgelegt ist, sollten sie die Klasse 'ApplicationConfig' final oder die Methode 'corsConfigurer' static/final/abstract/empty machen oder die zugelassene Annotation für die Methode hinzufügen.
+[ERROR] src/main/java/org/psesquared/server/config/ApplicationConfig.java:[64,41] (misc) FinalParameters: Der Parameter registry sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/config/ApplicationConfig.java:[73,5] (design) DesignForExtension: Klasse 'ApplicationConfig' sieht wie zur Erweiterung entworfen aus (kann subclassed werden), aber die Methode 'addInterceptors' besitzt keinen Javadoc-Kommentar, der erklärt, wie Sie das sicher tun. Wenn die Klasse nicht für Erweiterungen ausgelegt ist, sollten sie die Klasse 'ApplicationConfig' final oder die Methode 'addInterceptors' static/final/abstract/empty machen oder die zugelassene Annotation für die Methode hinzufügen.
+[ERROR] src/main/java/org/psesquared/server/config/ApplicationConfig.java:[74,33] (misc) FinalParameters: Der Parameter registry sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/model/Subscription.java:[1] (javadoc) JavadocPackage: Es fehlt eine package-info.java.
+[ERROR] src/main/java/org/psesquared/server/model/Subscription.java:[24] (javadoc) JavadocStyle: Der erste Satz sollte mit einem Punkt enden.
+[ERROR] src/main/java/org/psesquared/server/model/Subscription.java:[33] (sizes) LineLength: Zeile ist 105 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/model/Subscription.java:[36] (javadoc) JavadocStyle: Der erste Satz sollte mit einem Punkt enden.
+[ERROR] src/main/java/org/psesquared/server/model/Subscription.java:[45] (javadoc) JavadocStyle: Der erste Satz sollte mit einem Punkt enden.
+[ERROR] src/main/java/org/psesquared/server/model/Subscription.java:[51] (javadoc) JavadocStyle: Der erste Satz sollte mit einem Punkt enden.
+[ERROR] src/main/java/org/psesquared/server/model/Subscription.java:[57] (javadoc) JavadocStyle: Der erste Satz sollte mit einem Punkt enden.
+[ERROR] src/main/java/org/psesquared/server/model/Subscription.java:[63,5] (javadoc) JavadocVariable: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/model/Subscription.java:[68] (javadoc) JavadocStyle: Der erste Satz sollte mit einem Punkt enden.
+[ERROR] src/main/java/org/psesquared/server/model/Subscription.java:[75,9] (javadoc) MissingJavadocMethod: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/model/Subscription.java:[75,9] (design) DesignForExtension: Klasse 'Subscription' sieht wie zur Erweiterung entworfen aus (kann subclassed werden), aber die Methode 'addEpisode' besitzt keinen Javadoc-Kommentar, der erklärt, wie Sie das sicher tun. Wenn die Klasse nicht für Erweiterungen ausgelegt ist, sollten sie die Klasse 'Subscription' final oder die Methode 'addEpisode' static/final/abstract/empty machen oder die zugelassene Annotation für die Methode hinzufügen.
+[ERROR] src/main/java/org/psesquared/server/model/Subscription.java:[75,32] (misc) FinalParameters: Der Parameter episode sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/model/Role.java:[3] (javadoc) JavadocStyle: Der erste Satz sollte mit einem Punkt enden.
+[ERROR] src/main/java/org/psesquared/server/model/Role.java:[8] (javadoc) JavadocStyle: Der erste Satz sollte mit einem Punkt enden.
+[ERROR] src/main/java/org/psesquared/server/model/Role.java:[12] (javadoc) JavadocStyle: Der erste Satz sollte mit einem Punkt enden.
+[ERROR] src/main/java/org/psesquared/server/model/Role.java:[17,5] (javadoc) JavadocVariable: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/model/EpisodeAction.java:[22] (javadoc) JavadocStyle: Der erste Satz sollte mit einem Punkt enden.
+[ERROR] src/main/java/org/psesquared/server/model/EpisodeAction.java:[33] (javadoc) JavadocStyle: Der erste Satz sollte mit einem Punkt enden.
+[ERROR] src/main/java/org/psesquared/server/model/EpisodeAction.java:[42] (javadoc) JavadocStyle: Der erste Satz sollte mit einem Punkt enden.
+[ERROR] src/main/java/org/psesquared/server/model/EpisodeAction.java:[49] (javadoc) JavadocStyle: Der erste Satz sollte mit einem Punkt enden.
+[ERROR] src/main/java/org/psesquared/server/model/EpisodeAction.java:[56] (javadoc) JavadocStyle: Der erste Satz sollte mit einem Punkt enden.
+[ERROR] src/main/java/org/psesquared/server/model/EpisodeAction.java:[64] (javadoc) JavadocStyle: Der erste Satz sollte mit einem Punkt enden.
+[ERROR] src/main/java/org/psesquared/server/model/EpisodeAction.java:[73] (javadoc) JavadocStyle: Der erste Satz sollte mit einem Punkt enden.
+[ERROR] src/main/java/org/psesquared/server/model/EpisodeAction.java:[80] (javadoc) JavadocStyle: Der erste Satz sollte mit einem Punkt enden.
+[ERROR] src/main/java/org/psesquared/server/model/EpisodeAction.java:[88] (javadoc) JavadocStyle: Der erste Satz sollte mit einem Punkt enden.
+[ERROR] src/main/java/org/psesquared/server/model/EpisodeAction.java:[92] (javadoc) JavadocMethod: @return-Tag sollte vorhanden sein und eine Beschreibung haben.
+[ERROR] src/main/java/org/psesquared/server/model/EpisodeAction.java:[93] (sizes) LineLength: Zeile ist 81 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/model/EpisodeAction.java:[98] (sizes) LineLength: Zeile ist 95 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/model/SubscriptionAction.java:[16] (javadoc) JavadocStyle: Der erste Satz sollte mit einem Punkt enden.
+[ERROR] src/main/java/org/psesquared/server/model/SubscriptionAction.java:[27] (javadoc) JavadocStyle: Der erste Satz sollte mit einem Punkt enden.
+[ERROR] src/main/java/org/psesquared/server/model/SubscriptionAction.java:[36] (javadoc) JavadocStyle: Der erste Satz sollte mit einem Punkt enden.
+[ERROR] src/main/java/org/psesquared/server/model/SubscriptionAction.java:[42] (javadoc) JavadocStyle: Der erste Satz sollte mit einem Punkt enden.
+[ERROR] src/main/java/org/psesquared/server/model/SubscriptionAction.java:[50] (javadoc) JavadocStyle: Der erste Satz sollte mit einem Punkt enden.
+[ERROR] src/main/java/org/psesquared/server/model/SubscriptionAction.java:[56] (javadoc) JavadocStyle: Der erste Satz sollte mit einem Punkt enden.
+[ERROR] src/main/java/org/psesquared/server/model/User.java:[6,27] (imports) AvoidStarImport: Stern-Importe der Form '.*' sollten vermieden werden - jakarta.persistence.*.
+[ERROR] src/main/java/org/psesquared/server/model/User.java:[15] (javadoc) JavadocStyle: Der erste Satz sollte mit einem Punkt enden.
+[ERROR] src/main/java/org/psesquared/server/model/User.java:[26] (javadoc) JavadocStyle: Der erste Satz sollte mit einem Punkt enden.
+[ERROR] src/main/java/org/psesquared/server/model/User.java:[35] (javadoc) JavadocStyle: Der erste Satz sollte mit einem Punkt enden.
+[ERROR] src/main/java/org/psesquared/server/model/User.java:[44] (javadoc) JavadocStyle: Der erste Satz sollte mit einem Punkt enden.
+[ERROR] src/main/java/org/psesquared/server/model/User.java:[52] (javadoc) JavadocStyle: Der erste Satz sollte mit einem Punkt enden.
+[ERROR] src/main/java/org/psesquared/server/model/User.java:[59] (javadoc) JavadocStyle: Der erste Satz sollte mit einem Punkt enden.
+[ERROR] src/main/java/org/psesquared/server/model/User.java:[66] (javadoc) JavadocStyle: Der erste Satz sollte mit einem Punkt enden.
+[ERROR] src/main/java/org/psesquared/server/model/User.java:[74] (javadoc) JavadocStyle: Der erste Satz sollte mit einem Punkt enden.
+[ERROR] src/main/java/org/psesquared/server/model/User.java:[81] (javadoc) JavadocStyle: Der erste Satz sollte mit einem Punkt enden.
+[ERROR] src/main/java/org/psesquared/server/model/User.java:[88] (javadoc) JavadocStyle: Der erste Satz sollte mit einem Punkt enden.
+[ERROR] src/main/java/org/psesquared/server/model/User.java:[95,5] (design) DesignForExtension: Klasse 'User' sieht wie zur Erweiterung entworfen aus (kann subclassed werden), aber die Methode 'getAuthorities' besitzt keinen Javadoc-Kommentar, der erklärt, wie Sie das sicher tun. Wenn die Klasse nicht für Erweiterungen ausgelegt ist, sollten sie die Klasse 'User' final oder die Methode 'getAuthorities' static/final/abstract/empty machen oder die zugelassene Annotation für die Methode hinzufügen.
+[ERROR] src/main/java/org/psesquared/server/model/User.java:[100,5] (design) DesignForExtension: Klasse 'User' sieht wie zur Erweiterung entworfen aus (kann subclassed werden), aber die Methode 'isAccountNonExpired' besitzt keinen Javadoc-Kommentar, der erklärt, wie Sie das sicher tun. Wenn die Klasse nicht für Erweiterungen ausgelegt ist, sollten sie die Klasse 'User' final oder die Methode 'isAccountNonExpired' static/final/abstract/empty machen oder die zugelassene Annotation für die Methode hinzufügen.
+[ERROR] src/main/java/org/psesquared/server/model/User.java:[105,5] (design) DesignForExtension: Klasse 'User' sieht wie zur Erweiterung entworfen aus (kann subclassed werden), aber die Methode 'isAccountNonLocked' besitzt keinen Javadoc-Kommentar, der erklärt, wie Sie das sicher tun. Wenn die Klasse nicht für Erweiterungen ausgelegt ist, sollten sie die Klasse 'User' final oder die Methode 'isAccountNonLocked' static/final/abstract/empty machen oder die zugelassene Annotation für die Methode hinzufügen.
+[ERROR] src/main/java/org/psesquared/server/model/User.java:[110,5] (design) DesignForExtension: Klasse 'User' sieht wie zur Erweiterung entworfen aus (kann subclassed werden), aber die Methode 'isCredentialsNonExpired' besitzt keinen Javadoc-Kommentar, der erklärt, wie Sie das sicher tun. Wenn die Klasse nicht für Erweiterungen ausgelegt ist, sollten sie die Klasse 'User' final oder die Methode 'isCredentialsNonExpired' static/final/abstract/empty machen oder die zugelassene Annotation für die Methode hinzufügen.
+[ERROR] src/main/java/org/psesquared/server/model/Action.java:[5] (javadoc) JavadocStyle: Der erste Satz sollte mit einem Punkt enden.
+[ERROR] src/main/java/org/psesquared/server/model/Action.java:[7] (regexp) RegexpSingleline: Line has trailing spaces.
+[ERROR] src/main/java/org/psesquared/server/model/Action.java:[10] (regexp) RegexpSingleline: Line has trailing spaces.
+[ERROR] src/main/java/org/psesquared/server/model/Action.java:[11,5] (javadoc) JavadocVariable: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/model/Action.java:[12,5] (javadoc) JavadocVariable: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/model/Action.java:[13,5] (javadoc) JavadocVariable: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/model/Action.java:[14,5] (javadoc) JavadocVariable: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/model/Action.java:[15,5] (javadoc) JavadocVariable: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/model/Action.java:[17,5] (javadoc) MissingJavadocMethod: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/model/Episode.java:[19] (javadoc) JavadocStyle: Der erste Satz sollte mit einem Punkt enden.
+[ERROR] src/main/java/org/psesquared/server/model/Episode.java:[30] (javadoc) JavadocStyle: Der erste Satz sollte mit einem Punkt enden.
+[ERROR] src/main/java/org/psesquared/server/model/Episode.java:[38] (javadoc) JavadocStyle: Der erste Satz sollte mit einem Punkt enden.
+[ERROR] src/main/java/org/psesquared/server/model/Episode.java:[44] (javadoc) JavadocStyle: Der erste Satz sollte mit einem Punkt enden.
+[ERROR] src/main/java/org/psesquared/server/model/Episode.java:[50] (javadoc) JavadocStyle: Der erste Satz sollte mit einem Punkt enden.
+[ERROR] src/main/java/org/psesquared/server/model/Episode.java:[56] (javadoc) JavadocStyle: Der erste Satz sollte mit einem Punkt enden.
+[ERROR] src/main/java/org/psesquared/server/model/Episode.java:[62] (javadoc) JavadocStyle: Der erste Satz sollte mit einem Punkt enden.
+[ERROR] src/main/java/org/psesquared/server/model/Episode.java:[68] (javadoc) JavadocStyle: Der erste Satz sollte mit einem Punkt enden.
+[ERROR] src/main/java/org/psesquared/server/util/UpdateURLsWrapper.java:[1] (javadoc) JavadocPackage: Es fehlt eine package-info.java.
+[ERROR] src/main/java/org/psesquared/server/util/UpdateURLsWrapper.java:[10] (javadoc) JavadocStyle: Der erste Satz sollte mit einem Punkt enden.
+[ERROR] src/main/java/org/psesquared/server/util/UpdateURLsWrapper.java:[15,5] (javadoc) JavadocVariable: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/util/UpdateURLsWrapper.java:[16,5] (javadoc) JavadocVariable: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/util/UpdateURLsWrapper.java:[18] (javadoc) JavadocStyle: Der erste Satz sollte mit einem Punkt enden.
+[ERROR] src/main/java/org/psesquared/server/util/UpdateURLsWrapper.java:[26,5] (javadoc) MissingJavadocMethod: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/util/UpdateURLsWrapper.java:[26,5] (design) DesignForExtension: Klasse 'UpdateURLsWrapper' sieht wie zur Erweiterung entworfen aus (kann subclassed werden), aber die Methode 'getTimestamp' besitzt keinen Javadoc-Kommentar, der erklärt, wie Sie das sicher tun. Wenn die Klasse nicht für Erweiterungen ausgelegt ist, sollten sie die Klasse 'UpdateURLsWrapper' final oder die Methode 'getTimestamp' static/final/abstract/empty machen oder die zugelassene Annotation für die Methode hinzufügen.
+[ERROR] src/main/java/org/psesquared/server/util/UpdateURLsWrapper.java:[30,5] (javadoc) MissingJavadocMethod: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/util/UpdateURLsWrapper.java:[30,5] (design) DesignForExtension: Klasse 'UpdateURLsWrapper' sieht wie zur Erweiterung entworfen aus (kann subclassed werden), aber die Methode 'getUpdateURLs' besitzt keinen Javadoc-Kommentar, der erklärt, wie Sie das sicher tun. Wenn die Klasse nicht für Erweiterungen ausgelegt ist, sollten sie die Klasse 'UpdateURLsWrapper' final oder die Methode 'getUpdateURLs' static/final/abstract/empty machen oder die zugelassene Annotation für die Methode hinzufügen.
+[ERROR] src/main/java/org/psesquared/server/util/Scheduler.java:[10] (javadoc) JavadocStyle: Der erste Satz sollte mit einem Punkt enden.
+[ERROR] src/main/java/org/psesquared/server/util/Scheduler.java:[16,5] (javadoc) JavadocVariable: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/util/Scheduler.java:[19] (sizes) LineLength: Zeile ist 137 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/util/Scheduler.java:[24] (sizes) LineLength: Zeile ist 126 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/util/Scheduler.java:[24,112] (coding) MagicNumber: Die magische Zahl '24' sollte als Konstante definiert werden.
+[ERROR] src/main/java/org/psesquared/server/util/Scheduler.java:[24,117] (coding) MagicNumber: Die magische Zahl '60' sollte als Konstante definiert werden.
+[ERROR] src/main/java/org/psesquared/server/util/Scheduler.java:[24,122] (coding) MagicNumber: Die magische Zahl '60' sollte als Konstante definiert werden.
+[ERROR] src/main/java/org/psesquared/server/util/RSSParser.java:[38,5] (javadoc) JavadocVariable: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/util/RSSParser.java:[40,5] (javadoc) JavadocVariable: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/util/RSSParser.java:[41,5] (javadoc) JavadocVariable: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/util/RSSParser.java:[43,5] (javadoc) MissingJavadocMethod: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/util/RSSParser.java:[43,5] (design) DesignForExtension: Klasse 'RSSParser' sieht wie zur Erweiterung entworfen aus (kann subclassed werden), aber die Methode 'validate' besitzt keinen Javadoc-Kommentar, der erklärt, wie Sie das sicher tun. Wenn die Klasse nicht für Erweiterungen ausgelegt ist, sollten sie die Klasse 'RSSParser' final oder die Methode 'validate' static/final/abstract/empty machen oder die zugelassene Annotation für die Methode hinzufügen.
+[ERROR] src/main/java/org/psesquared/server/util/RSSParser.java:[44,5] (javadoc) InvalidJavadocPosition: Javadoc-Kommentar ist an der falschen Stelle platziert.
+[ERROR] src/main/java/org/psesquared/server/util/RSSParser.java:[48] (sizes) LineLength: Zeile ist 84 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/util/RSSParser.java:[51] (regexp) RegexpSingleline: Line has trailing spaces.
+[ERROR] src/main/java/org/psesquared/server/util/RSSParser.java:[54,26] (misc) FinalParameters: Der Parameter subscription sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/util/RSSParser.java:[66] (sizes) LineLength: Zeile ist 101 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/util/RSSParser.java:[73] (sizes) LineLength: Zeile ist 89 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/util/RSSParser.java:[87] (sizes) LineLength: Zeile ist 83 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/util/RSSParser.java:[87,56] (misc) FinalParameters: Der Parameter subscription sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/util/RSSParser.java:[126] (sizes) LineLength: Zeile ist 82 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/util/RSSParser.java:[126,34] (misc) FinalParameters: Der Parameter syndEntry sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/util/RSSParser.java:[126,55] (misc) FinalParameters: Der Parameter subscription sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/util/RSSParser.java:[158] (sizes) LineLength: Zeile ist 114 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/util/RSSParser.java:[161] (sizes) LineLength: Zeile ist 95 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/util/RSSParser.java:[161,45] (misc) FinalParameters: Der Parameter episodeURL sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/util/RSSParser.java:[161,64] (misc) FinalParameters: Der Parameter episodes sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/util/RSSParser.java:[168,5] (design) DesignForExtension: Klasse 'RSSParser' sieht wie zur Erweiterung entworfen aus (kann subclassed werden), aber die Methode 'saveEpisodes' besitzt keinen Javadoc-Kommentar, der erklärt, wie Sie das sicher tun. Wenn die Klasse nicht für Erweiterungen ausgelegt ist, sollten sie die Klasse 'RSSParser' final oder die Methode 'saveEpisodes' static/final/abstract/empty machen oder die zugelassene Annotation für die Methode hinzufügen.
+[ERROR] src/main/java/org/psesquared/server/util/RSSParser.java:[169,33] (misc) FinalParameters: Der Parameter episodes sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/util/RSSParser.java:[173,5] (design) DesignForExtension: Klasse 'RSSParser' sieht wie zur Erweiterung entworfen aus (kann subclassed werden), aber die Methode 'deleteEpisodes' besitzt keinen Javadoc-Kommentar, der erklärt, wie Sie das sicher tun. Wenn die Klasse nicht für Erweiterungen ausgelegt ist, sollten sie die Klasse 'RSSParser' final oder die Methode 'deleteEpisodes' static/final/abstract/empty machen oder die zugelassene Annotation für die Methode hinzufügen.
+[ERROR] src/main/java/org/psesquared/server/util/RSSParser.java:[174,35] (misc) FinalParameters: Der Parameter episodes sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/util/RSSParser.java:[179,5] (design) DesignForExtension: Klasse 'RSSParser' sieht wie zur Erweiterung entworfen aus (kann subclassed werden), aber die Methode 'saveSubscription' besitzt keinen Javadoc-Kommentar, der erklärt, wie Sie das sicher tun. Wenn die Klasse nicht für Erweiterungen ausgelegt ist, sollten sie die Klasse 'RSSParser' final oder die Methode 'saveSubscription' static/final/abstract/empty machen oder die zugelassene Annotation für die Methode hinzufügen.
+[ERROR] src/main/java/org/psesquared/server/util/RSSParser.java:[180,37] (misc) FinalParameters: Der Parameter subscription sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/util/RSSParser.java:[184,5] (design) DesignForExtension: Klasse 'RSSParser' sieht wie zur Erweiterung entworfen aus (kann subclassed werden), aber die Methode 'deleteSubscription' besitzt keinen Javadoc-Kommentar, der erklärt, wie Sie das sicher tun. Wenn die Klasse nicht für Erweiterungen ausgelegt ist, sollten sie die Klasse 'RSSParser' final oder die Methode 'deleteSubscription' static/final/abstract/empty machen oder die zugelassene Annotation für die Methode hinzufügen.
+[ERROR] src/main/java/org/psesquared/server/util/RSSParser.java:[185,39] (misc) FinalParameters: Der Parameter subscription sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/util/RSSParser.java:[190,43] (misc) FinalParameters: Der Parameter time sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/util/RSSParser.java:[208,31] (misc) ArrayTypeStyle: Array-Klammern an ungültiger Position.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/controller/AuthenticationResponse.java:[1] (javadoc) JavadocPackage: Es fehlt eine package-info.java.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/controller/AuthenticationResponse.java:[7,1] (javadoc) JavadocType: Im Javadoc des Typs fehlt das Tag @param token.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/controller/AuthenticationResponse.java:[7,52] (whitespace) WhitespaceAround: Nach '{' fehlt ein Leerzeichen.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/controller/AuthenticationResponse.java:[7,53] (whitespace) WhitespaceAround: Vor '}' fehlt ein Leerzeichen.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/controller/AuthenticationController.java:[9,47] (imports) AvoidStarImport: Stern-Importe der Form '.*' sollten vermieden werden - org.springframework.web.bind.annotation.*.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/controller/AuthenticationController.java:[15] (sizes) LineLength: Zeile ist 98 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/authentication_api/controller/AuthenticationController.java:[23,5] (javadoc) JavadocVariable: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/controller/AuthenticationController.java:[25,5] (javadoc) JavadocVariable: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/controller/AuthenticationController.java:[26,5] (javadoc) JavadocVariable: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/controller/AuthenticationController.java:[29] (sizes) LineLength: Zeile ist 117 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/authentication_api/controller/AuthenticationController.java:[30] (sizes) LineLength: Zeile ist 109 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/authentication_api/controller/AuthenticationController.java:[31] (sizes) LineLength: Zeile ist 99 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/authentication_api/controller/AuthenticationController.java:[34] (sizes) LineLength: Zeile ist 91 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/authentication_api/controller/AuthenticationController.java:[41,36] (misc) FinalParameters: Der Parameter userInfo sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/controller/AuthenticationController.java:[46] (sizes) LineLength: Zeile ist 118 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/authentication_api/controller/AuthenticationController.java:[47] (sizes) LineLength: Zeile ist 101 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/authentication_api/controller/AuthenticationController.java:[51] (sizes) LineLength: Zeile ist 99 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/authentication_api/controller/AuthenticationController.java:[56] (regexp) RegexpSingleline: Line has trailing spaces.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/controller/AuthenticationController.java:[60,42] (misc) FinalParameters: Der Parameter username sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/controller/AuthenticationController.java:[61,42] (misc) FinalParameters: Der Parameter token sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/controller/AuthenticationController.java:[62] (sizes) LineLength: Zeile ist 81 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/authentication_api/controller/AuthenticationController.java:[62,42] (misc) FinalParameters: Der Parameter response sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/controller/AuthenticationController.java:[63] (sizes) LineLength: Zeile ist 86 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/authentication_api/controller/AuthenticationController.java:[69] (sizes) LineLength: Zeile ist 112 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/authentication_api/controller/AuthenticationController.java:[71] (sizes) LineLength: Zeile ist 85 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/authentication_api/controller/AuthenticationController.java:[74] (sizes) LineLength: Zeile ist 89 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/authentication_api/controller/AuthenticationController.java:[81,29] (misc) FinalParameters: Der Parameter username sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/controller/AuthenticationController.java:[82,29] (misc) FinalParameters: Der Parameter response sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/controller/AuthenticationController.java:[87] (sizes) LineLength: Zeile ist 120 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/authentication_api/controller/AuthenticationController.java:[89] (sizes) LineLength: Zeile ist 85 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/authentication_api/controller/AuthenticationController.java:[92] (sizes) LineLength: Zeile ist 90 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/authentication_api/controller/AuthenticationController.java:[99,30] (misc) FinalParameters: Der Parameter username sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/controller/AuthenticationController.java:[100,30] (misc) FinalParameters: Der Parameter response sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/controller/AuthenticationController.java:[100,68] (whitespace) WhitespaceAround: Vor '{' fehlt ein Leerzeichen.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/controller/AuthenticationController.java:[105] (sizes) LineLength: Zeile ist 119 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/authentication_api/controller/AuthenticationController.java:[108] (sizes) LineLength: Zeile ist 83 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/authentication_api/controller/AuthenticationController.java:[115,38] (misc) FinalParameters: Der Parameter email sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/controller/AuthenticationController.java:[119,5] (javadoc) MissingJavadocMethod: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/controller/AuthenticationController.java:[119,5] (design) DesignForExtension: Klasse 'AuthenticationController' sieht wie zur Erweiterung entworfen aus (kann subclassed werden), aber die Methode 'resetPassword' besitzt keinen Javadoc-Kommentar, der erklärt, wie Sie das sicher tun. Wenn die Klasse nicht für Erweiterungen ausgelegt ist, sollten sie die Klasse 'AuthenticationController' final oder die Methode 'resetPassword' static/final/abstract/empty machen oder die zugelassene Annotation für die Methode hinzufügen.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/controller/AuthenticationController.java:[120,37] (misc) FinalParameters: Der Parameter username sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/controller/AuthenticationController.java:[121,37] (misc) FinalParameters: Der Parameter token sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/controller/AuthenticationController.java:[122,37] (misc) FinalParameters: Der Parameter requestBody sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/controller/AuthenticationController.java:[123] (sizes) LineLength: Zeile ist 81 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/authentication_api/controller/AuthenticationController.java:[126,5] (javadoc) MissingJavadocMethod: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/controller/AuthenticationController.java:[126,5] (design) DesignForExtension: Klasse 'AuthenticationController' sieht wie zur Erweiterung entworfen aus (kann subclassed werden), aber die Methode 'changePassword' besitzt keinen Javadoc-Kommentar, der erklärt, wie Sie das sicher tun. Wenn die Klasse nicht für Erweiterungen ausgelegt ist, sollten sie die Klasse 'AuthenticationController' final oder die Methode 'changePassword' static/final/abstract/empty machen oder die zugelassene Annotation für die Methode hinzufügen.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/controller/AuthenticationController.java:[127,38] (misc) FinalParameters: Der Parameter username sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/controller/AuthenticationController.java:[128] (sizes) LineLength: Zeile ist 86 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/authentication_api/controller/AuthenticationController.java:[128,38] (misc) FinalParameters: Der Parameter requestBody sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/controller/AuthenticationController.java:[132,5] (javadoc) MissingJavadocMethod: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/controller/AuthenticationController.java:[132,5] (design) DesignForExtension: Klasse 'AuthenticationController' sieht wie zur Erweiterung entworfen aus (kann subclassed werden), aber die Methode 'deleteUser' besitzt keinen Javadoc-Kommentar, der erklärt, wie Sie das sicher tun. Wenn die Klasse nicht für Erweiterungen ausgelegt ist, sollten sie die Klasse 'AuthenticationController' final oder die Methode 'deleteUser' static/final/abstract/empty machen oder die zugelassene Annotation für die Methode hinzufügen.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/controller/AuthenticationController.java:[133,34] (misc) FinalParameters: Der Parameter username sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/controller/AuthenticationController.java:[134,34] (misc) FinalParameters: Der Parameter requestBody sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/controller/AuthenticationController.java:[138,5] (javadoc) MissingJavadocMethod: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/controller/AuthenticationController.java:[138,5] (design) DesignForExtension: Klasse 'AuthenticationController' sieht wie zur Erweiterung entworfen aus (kann subclassed werden), aber die Methode 'getDeviceList' besitzt keinen Javadoc-Kommentar, der erklärt, wie Sie das sicher tun. Wenn die Klasse nicht für Erweiterungen ausgelegt ist, sollten sie die Klasse 'AuthenticationController' final oder die Methode 'getDeviceList' static/final/abstract/empty machen oder die zugelassene Annotation für die Methode hinzufügen.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/controller/AuthenticationController.java:[139] (sizes) LineLength: Zeile ist 91 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/authentication_api/controller/AuthenticationController.java:[139,62] (misc) FinalParameters: Der Parameter username sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/controller/AuthenticationController.java:[140] (sizes) LineLength: Zeile ist 101 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/authentication_api/controller/AuthenticationController.java:[140,62] (misc) FinalParameters: Der Parameter response sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/controller/AuthenticationController.java:[142] (sizes) LineLength: Zeile ist 107 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/authentication_api/controller/ForgotPasswordRequest.java:[5] (javadoc) JavadocStyle: Der erste Satz sollte mit einem Punkt enden.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/controller/ForgotPasswordRequest.java:[8] (sizes) LineLength: Zeile ist 83 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/authentication_api/controller/ForgotPasswordRequest.java:[8,1] (javadoc) JavadocType: Im Javadoc des Typs fehlt das Tag @param email.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/controller/ForgotPasswordRequest.java:[8,82] (whitespace) WhitespaceAround: Nach '{' fehlt ein Leerzeichen.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/controller/ForgotPasswordRequest.java:[8,83] (whitespace) WhitespaceAround: Vor '}' fehlt ein Leerzeichen.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/controller/DeviceWrapper.java:[3,8] (imports) UnusedImports: Nicht verwendeter Import - jakarta.servlet.http.HttpServletResponse.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/controller/DeviceWrapper.java:[14] (sizes) LineLength: Zeile ist 88 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/authentication_api/controller/DeviceWrapper.java:[16,5] (javadoc) JavadocVariable: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/controller/DeviceWrapper.java:[17,5] (javadoc) JavadocVariable: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/controller/DeviceWrapper.java:[18,5] (javadoc) JavadocVariable: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/controller/DeviceWrapper.java:[19,5] (javadoc) JavadocVariable: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/controller/DeviceWrapper.java:[21,5] (javadoc) MissingJavadocMethod: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/controller/ChangePasswordRequest.java:[5] (javadoc) JavadocStyle: Der erste Satz sollte mit einem Punkt enden.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/controller/ChangePasswordRequest.java:[9] (sizes) LineLength: Zeile ist 106 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/authentication_api/controller/ChangePasswordRequest.java:[9,1] (javadoc) JavadocType: Im Javadoc des Typs fehlt das Tag @param newPassword.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/controller/ChangePasswordRequest.java:[9,1] (javadoc) JavadocType: Im Javadoc des Typs fehlt das Tag @param oldPassword.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/controller/ChangePasswordRequest.java:[10] (sizes) LineLength: Zeile ist 84 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/authentication_api/controller/UserInfoRequest.java:[9,1] (javadoc) JavadocType: Im Javadoc des Typs fehlt das Tag @param email.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/controller/UserInfoRequest.java:[9,1] (javadoc) JavadocType: Im Javadoc des Typs fehlt das Tag @param password.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/controller/UserInfoRequest.java:[9,1] (javadoc) JavadocType: Im Javadoc des Typs fehlt das Tag @param username.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/controller/UserInfoRequest.java:[11,79] (whitespace) WhitespaceAround: Nach '{' fehlt ein Leerzeichen.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/controller/UserInfoRequest.java:[11,80] (whitespace) WhitespaceAround: Vor '}' fehlt ein Leerzeichen.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/controller/PasswordRequest.java:[9,1] (javadoc) JavadocType: Im Javadoc des Typs fehlt das Tag @param password.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/controller/PasswordRequest.java:[9,79] (whitespace) WhitespaceAround: Nach '{' fehlt ein Leerzeichen.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/controller/PasswordRequest.java:[9,80] (whitespace) WhitespaceAround: Vor '}' fehlt ein Leerzeichen.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/AuthenticationService.java:[1] (javadoc) JavadocPackage: Es fehlt eine package-info.java.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/AuthenticationService.java:[6,59] (imports) AvoidStarImport: Stern-Importe der Form '.*' sollten vermieden werden - org.psesquared.server.authentication_api.controller.*.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/AuthenticationService.java:[25,5] (javadoc) JavadocVariable: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/AuthenticationService.java:[26,5] (javadoc) JavadocVariable: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/AuthenticationService.java:[27,5] (javadoc) JavadocVariable: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/AuthenticationService.java:[28,5] (javadoc) JavadocVariable: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/AuthenticationService.java:[29,5] (javadoc) JavadocVariable: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/AuthenticationService.java:[30,5] (javadoc) JavadocVariable: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/AuthenticationService.java:[32,5] (javadoc) JavadocVariable: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/AuthenticationService.java:[33,5] (javadoc) JavadocVariable: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/AuthenticationService.java:[34,5] (javadoc) JavadocVariable: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/AuthenticationService.java:[35,5] (javadoc) JavadocVariable: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/AuthenticationService.java:[36,5] (javadoc) JavadocVariable: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/AuthenticationService.java:[37,5] (javadoc) JavadocVariable: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/AuthenticationService.java:[39,5] (javadoc) MissingJavadocMethod: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/AuthenticationService.java:[39,5] (design) DesignForExtension: Klasse 'AuthenticationService' sieht wie zur Erweiterung entworfen aus (kann subclassed werden), aber die Methode 'registerUser' besitzt keinen Javadoc-Kommentar, der erklärt, wie Sie das sicher tun. Wenn die Klasse nicht für Erweiterungen ausgelegt ist, sollten sie die Klasse 'AuthenticationService' final oder die Methode 'registerUser' static/final/abstract/empty machen oder die zugelassene Annotation für die Methode hinzufügen.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/AuthenticationService.java:[39,36] (misc) FinalParameters: Der Parameter userInfo sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/AuthenticationService.java:[55] (sizes) LineLength: Zeile ist 91 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/AuthenticationService.java:[56] (sizes) LineLength: Zeile ist 85 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/AuthenticationService.java:[66] (sizes) LineLength: Zeile ist 81 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/AuthenticationService.java:[75,5] (javadoc) MissingJavadocMethod: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/AuthenticationService.java:[75,5] (design) DesignForExtension: Klasse 'AuthenticationService' sieht wie zur Erweiterung entworfen aus (kann subclassed werden), aber die Methode 'verifyRegistration' besitzt keinen Javadoc-Kommentar, der erklärt, wie Sie das sicher tun. Wenn die Klasse nicht für Erweiterungen ausgelegt ist, sollten sie die Klasse 'AuthenticationService' final oder die Methode 'verifyRegistration' static/final/abstract/empty machen oder die zugelassene Annotation für die Methode hinzufügen.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/AuthenticationService.java:[75,42] (misc) FinalParameters: Der Parameter username sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/AuthenticationService.java:[75,59] (misc) FinalParameters: Der Parameter token sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/AuthenticationService.java:[95,5] (javadoc) MissingJavadocMethod: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/AuthenticationService.java:[95,5] (design) DesignForExtension: Klasse 'AuthenticationService' sieht wie zur Erweiterung entworfen aus (kann subclassed werden), aber die Methode 'login' besitzt keinen Javadoc-Kommentar, der erklärt, wie Sie das sicher tun. Wenn die Klasse nicht für Erweiterungen ausgelegt ist, sollten sie die Klasse 'AuthenticationService' final oder die Methode 'login' static/final/abstract/empty machen oder die zugelassene Annotation für die Methode hinzufügen.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/AuthenticationService.java:[95,29] (misc) FinalParameters: Der Parameter username sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/AuthenticationService.java:[96,36] (misc) FinalParameters: Der Parameter response sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/AuthenticationService.java:[110,5] (javadoc) MissingJavadocMethod: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/AuthenticationService.java:[110,5] (design) DesignForExtension: Klasse 'AuthenticationService' sieht wie zur Erweiterung entworfen aus (kann subclassed werden), aber die Methode 'logout' besitzt keinen Javadoc-Kommentar, der erklärt, wie Sie das sicher tun. Wenn die Klasse nicht für Erweiterungen ausgelegt ist, sollten sie die Klasse 'AuthenticationService' final oder die Methode 'logout' static/final/abstract/empty machen oder die zugelassene Annotation für die Methode hinzufügen.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/AuthenticationService.java:[110,30] (misc) FinalParameters: Der Parameter username sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/AuthenticationService.java:[111,30] (misc) FinalParameters: Der Parameter response sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/AuthenticationService.java:[112,58] (whitespace) WhitespaceAround: Vor '{' fehlt ein Leerzeichen.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/AuthenticationService.java:[122,5] (javadoc) MissingJavadocMethod: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/AuthenticationService.java:[122,5] (design) DesignForExtension: Klasse 'AuthenticationService' sieht wie zur Erweiterung entworfen aus (kann subclassed werden), aber die Methode 'forgotPassword' besitzt keinen Javadoc-Kommentar, der erklärt, wie Sie das sicher tun. Wenn die Klasse nicht für Erweiterungen ausgelegt ist, sollten sie die Klasse 'AuthenticationService' final oder die Methode 'forgotPassword' static/final/abstract/empty machen oder die zugelassene Annotation für die Methode hinzufügen.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/AuthenticationService.java:[122,38] (misc) FinalParameters: Der Parameter email sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/AuthenticationService.java:[124] (sizes) LineLength: Zeile ist 95 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/AuthenticationService.java:[128,11] (whitespace) WhitespaceAround: Nach 'catch' fehlt ein Leerzeichen.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/AuthenticationService.java:[133,5] (javadoc) MissingJavadocMethod: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/AuthenticationService.java:[133,5] (design) DesignForExtension: Klasse 'AuthenticationService' sieht wie zur Erweiterung entworfen aus (kann subclassed werden), aber die Methode 'resetPassword' besitzt keinen Javadoc-Kommentar, der erklärt, wie Sie das sicher tun. Wenn die Klasse nicht für Erweiterungen ausgelegt ist, sollten sie die Klasse 'AuthenticationService' final oder die Methode 'resetPassword' static/final/abstract/empty machen oder die zugelassene Annotation für die Methode hinzufügen.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/AuthenticationService.java:[133,37] (misc) FinalParameters: Der Parameter username sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/AuthenticationService.java:[134,31] (misc) FinalParameters: Der Parameter token sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/AuthenticationService.java:[135,31] (misc) FinalParameters: Der Parameter requestBody sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/AuthenticationService.java:[144] (sizes) LineLength: Zeile ist 81 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/AuthenticationService.java:[153,5] (javadoc) MissingJavadocMethod: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/AuthenticationService.java:[153,5] (design) DesignForExtension: Klasse 'AuthenticationService' sieht wie zur Erweiterung entworfen aus (kann subclassed werden), aber die Methode 'changePassword' besitzt keinen Javadoc-Kommentar, der erklärt, wie Sie das sicher tun. Wenn die Klasse nicht für Erweiterungen ausgelegt ist, sollten sie die Klasse 'AuthenticationService' final oder die Methode 'changePassword' static/final/abstract/empty machen oder die zugelassene Annotation für die Methode hinzufügen.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/AuthenticationService.java:[153,38] (misc) FinalParameters: Der Parameter username sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/AuthenticationService.java:[154,38] (misc) FinalParameters: Der Parameter requestBody sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/AuthenticationService.java:[158] (sizes) LineLength: Zeile ist 89 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/AuthenticationService.java:[168,5] (javadoc) MissingJavadocMethod: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/AuthenticationService.java:[168,5] (design) DesignForExtension: Klasse 'AuthenticationService' sieht wie zur Erweiterung entworfen aus (kann subclassed werden), aber die Methode 'deleteUser' besitzt keinen Javadoc-Kommentar, der erklärt, wie Sie das sicher tun. Wenn die Klasse nicht für Erweiterungen ausgelegt ist, sollten sie die Klasse 'AuthenticationService' final oder die Methode 'deleteUser' static/final/abstract/empty machen oder die zugelassene Annotation für die Methode hinzufügen.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/AuthenticationService.java:[168,34] (misc) FinalParameters: Der Parameter username sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/AuthenticationService.java:[169,34] (misc) FinalParameters: Der Parameter requestBody sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/AuthenticationService.java:[173] (sizes) LineLength: Zeile ist 86 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/AuthenticationService.java:[183,5] (javadoc) MissingJavadocMethod: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/AuthenticationService.java:[183,5] (design) DesignForExtension: Klasse 'AuthenticationService' sieht wie zur Erweiterung entworfen aus (kann subclassed werden), aber die Methode 'deleteInvalidUsersOlderThan' besitzt keinen Javadoc-Kommentar, der erklärt, wie Sie das sicher tun. Wenn die Klasse nicht für Erweiterungen ausgelegt ist, sollten sie die Klasse 'AuthenticationService' final oder die Methode 'deleteInvalidUsersOlderThan' static/final/abstract/empty machen oder die zugelassene Annotation für die Methode hinzufügen.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/AuthenticationService.java:[183,45] (misc) FinalParameters: Der Parameter timestamp sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/AuthenticationService.java:[184] (sizes) LineLength: Zeile ist 81 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/ResourceReader.java:[8,1] (design) HideUtilityClassConstructor: Hilfsklassen sollten keinen Standard-Konstruktur und keinen als public deklarierten Konstruktor haben.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/ResourceReader.java:[9] (sizes) LineLength: Zeile ist 83 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/ResourceReader.java:[9,5] (javadoc) MissingJavadocMethod: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/ResourceReader.java:[9,43] (misc) FinalParameters: Der Parameter path sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/ResourceReader.java:[10] (sizes) LineLength: Zeile ist 95 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/EMailServiceImpl.java:[16,5] (javadoc) JavadocVariable: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/EMailServiceImpl.java:[17,5] (javadoc) JavadocVariable: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/EMailServiceImpl.java:[18,5] (javadoc) JavadocVariable: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/EMailServiceImpl.java:[20,5] (javadoc) JavadocVariable: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/EMailServiceImpl.java:[23,5] (javadoc) JavadocVariable: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/EMailServiceImpl.java:[24] (sizes) LineLength: Zeile ist 110 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/EMailServiceImpl.java:[25,5] (javadoc) JavadocVariable: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/EMailServiceImpl.java:[26] (sizes) LineLength: Zeile ist 102 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/EMailServiceImpl.java:[28,5] (javadoc) JavadocVariable: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/EMailServiceImpl.java:[29] (sizes) LineLength: Zeile ist 82 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/EMailServiceImpl.java:[29,5] (javadoc) JavadocVariable: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/EMailServiceImpl.java:[30] (sizes) LineLength: Zeile ist 85 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/EMailServiceImpl.java:[30,5] (javadoc) JavadocVariable: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/EMailServiceImpl.java:[32,5] (javadoc) JavadocVariable: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/EMailServiceImpl.java:[33,5] (javadoc) JavadocVariable: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/EMailServiceImpl.java:[34,5] (javadoc) JavadocVariable: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/EMailServiceImpl.java:[35,5] (javadoc) JavadocVariable: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/EMailServiceImpl.java:[37] (sizes) LineLength: Zeile ist 83 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/EMailServiceImpl.java:[37,5] (javadoc) JavadocVariable: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/EMailServiceImpl.java:[37,83] (whitespace) OperatorWrap: '+' sollte in einer neuen Zeile stehen.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/EMailServiceImpl.java:[41] (sizes) LineLength: Zeile ist 83 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/EMailServiceImpl.java:[41,5] (javadoc) JavadocVariable: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/EMailServiceImpl.java:[41,83] (whitespace) OperatorWrap: '+' sollte in einer neuen Zeile stehen.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/EMailServiceImpl.java:[46] (sizes) LineLength: Zeile ist 119 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/EMailServiceImpl.java:[47] (sizes) LineLength: Zeile ist 134 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/EMailServiceImpl.java:[52,27] (misc) FinalParameters: Der Parameter to sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/EMailServiceImpl.java:[52,38] (misc) FinalParameters: Der Parameter mailSubject sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/EMailServiceImpl.java:[52,58] (misc) FinalParameters: Der Parameter body sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/EMailServiceImpl.java:[52,65] (javadoc) JavadocMethod: Erwartetes Tag @param für 'body'.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/EMailServiceImpl.java:[53] (sizes) LineLength: Zeile ist 87 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/EMailServiceImpl.java:[62] (sizes) LineLength: Zeile ist 90 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/EMailServiceImpl.java:[62,43] (misc) FinalParameters: Der Parameter template sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/EMailServiceImpl.java:[62,60] (misc) FinalParameters: Der Parameter user sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/EMailServiceImpl.java:[62,78] (misc) FinalParameters: Der Parameter url sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/EMailServiceImpl.java:[69] (sizes) LineLength: Zeile ist 81 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/EMailServiceImpl.java:[71] (sizes) LineLength: Zeile ist 115 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/EMailServiceImpl.java:[76] (sizes) LineLength: Zeile ist 82 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/EMailServiceImpl.java:[79,58] (whitespace) OperatorWrap: '+' sollte in einer neuen Zeile stehen.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/EMailServiceImpl.java:[80,54] (whitespace) OperatorWrap: '+' sollte in einer neuen Zeile stehen.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/EMailServiceImpl.java:[81,33] (whitespace) OperatorWrap: '+' sollte in einer neuen Zeile stehen.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/EMailServiceImpl.java:[82,32] (whitespace) OperatorWrap: '+' sollte in einer neuen Zeile stehen.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/EMailServiceImpl.java:[83,43] (whitespace) OperatorWrap: '+' sollte in einer neuen Zeile stehen.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/EMailServiceImpl.java:[84,33] (whitespace) OperatorWrap: '+' sollte in einer neuen Zeile stehen.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/EMailServiceImpl.java:[85,29] (whitespace) OperatorWrap: '+' sollte in einer neuen Zeile stehen.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/EMailServiceImpl.java:[91] (sizes) LineLength: Zeile ist 89 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/EMailServiceImpl.java:[92] (sizes) LineLength: Zeile ist 112 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/EMailServiceImpl.java:[95,34] (misc) FinalParameters: Der Parameter to sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/EMailServiceImpl.java:[95,41] (javadoc) JavadocMethod: Erwartetes Tag @param für 'to'.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/EMailServiceImpl.java:[95,45] (misc) FinalParameters: Der Parameter userDetails sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/EMailServiceImpl.java:[97] (sizes) LineLength: Zeile ist 89 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/EMailServiceImpl.java:[103] (sizes) LineLength: Zeile ist 102 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/EMailServiceImpl.java:[104] (sizes) LineLength: Zeile ist 118 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/EMailServiceImpl.java:[107,35] (misc) FinalParameters: Der Parameter to sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/EMailServiceImpl.java:[107,42] (javadoc) JavadocMethod: Erwartetes Tag @param für 'to'.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/EMailServiceImpl.java:[107,46] (misc) FinalParameters: Der Parameter userDetails sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/EMailServiceImpl.java:[109] (sizes) LineLength: Zeile ist 90 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/EncryptionService.java:[16,5] (javadoc) JavadocVariable: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/EncryptionService.java:[18,5] (javadoc) JavadocVariable: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/EncryptionService.java:[21] (sizes) LineLength: Zeile ist 96 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/EncryptionService.java:[26,36] (misc) FinalParameters: Der Parameter email sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/EncryptionService.java:[29] (sizes) LineLength: Zeile ist 81 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/EncryptionService.java:[34] (sizes) LineLength: Zeile ist 85 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/EncryptionService.java:[34,53] (coding) MagicNumber: Die magische Zahl '0xff' sollte als Konstante definiert werden.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/EncryptionService.java:[34,61] (coding) MagicNumber: Die magische Zahl '0x100' sollte als Konstante definiert werden.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/EncryptionService.java:[34,68] (coding) MagicNumber: Die magische Zahl '16' sollte als Konstante definiert werden.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/EncryptionService.java:[44] (sizes) LineLength: Zeile ist 118 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/EncryptionService.java:[49] (sizes) LineLength: Zeile ist 82 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/InputCheckService.java:[14,5] (javadoc) JavadocVariable: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/InputCheckService.java:[15,5] (javadoc) JavadocVariable: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/InputCheckService.java:[16,5] (javadoc) JavadocVariable: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/InputCheckService.java:[24] (sizes) LineLength: Zeile ist 101 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/InputCheckService.java:[44] (sizes) LineLength: Zeile ist 124 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/InputCheckService.java:[49] (sizes) LineLength: Zeile ist 174 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/InputCheckService.java:[59] (javadoc) JavadocStyle: Der erste Satz sollte mit einem Punkt enden.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/InputCheckService.java:[60] (sizes) LineLength: Zeile ist 93 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/InputCheckService.java:[63] (sizes) LineLength: Zeile ist 96 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/InputCheckService.java:[65] (javadoc) JavadocStyle: Der erste Satz sollte mit einem Punkt enden.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/InputCheckService.java:[66] (sizes) LineLength: Zeile ist 93 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/InputCheckService.java:[67] (sizes) LineLength: Zeile ist 177 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/InputCheckService.java:[69] (sizes) LineLength: Zeile ist 157 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/InputCheckService.java:[71] (javadoc) JavadocStyle: Der erste Satz sollte mit einem Punkt enden.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/InputCheckService.java:[72] (sizes) LineLength: Zeile ist 82 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/InputCheckService.java:[73] (sizes) LineLength: Zeile ist 94 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/InputCheckService.java:[77] (sizes) LineLength: Zeile ist 91 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/InputCheckService.java:[79,37] (misc) FinalParameters: Der Parameter username sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/InputCheckService.java:[87] (sizes) LineLength: Zeile ist 114 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/InputCheckService.java:[89] (sizes) LineLength: Zeile ist 91 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/InputCheckService.java:[91,34] (misc) FinalParameters: Der Parameter email sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/InputCheckService.java:[93] (sizes) LineLength: Zeile ist 81 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/InputCheckService.java:[101] (javadoc) JavadocStyle: Der erste Satz sollte mit einem Punkt enden.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/InputCheckService.java:[102] (sizes) LineLength: Zeile ist 82 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/InputCheckService.java:[106] (sizes) LineLength: Zeile ist 104 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/InputCheckService.java:[107] (sizes) LineLength: Zeile ist 106 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/InputCheckService.java:[109] (sizes) LineLength: Zeile ist 91 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/authentication_api/service/InputCheckService.java:[111,37] (misc) FinalParameters: Der Parameter password sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/data_access/AuthenticationDao.java:[1] (javadoc) JavadocPackage: Es fehlt eine package-info.java.
+[ERROR] src/main/java/org/psesquared/server/authentication_api/data_access/AuthenticationDao.java:[18] (sizes) LineLength: Zeile ist 82 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/authentication_api/data_access/AuthenticationDao.java:[27] (sizes) LineLength: Zeile ist 81 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/authentication_api/data_access/AuthenticationDao.java:[40] (sizes) LineLength: Zeile ist 96 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/authentication_api/data_access/AuthenticationDao.java:[42] (sizes) LineLength: Zeile ist 97 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/controller/EpisodeActionController.java:[1] (javadoc) JavadocPackage: Es fehlt eine package-info.java.
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/controller/EpisodeActionController.java:[7,47] (imports) AvoidStarImport: Stern-Importe der Form '.*' sollten vermieden werden - org.springframework.web.bind.annotation.*.
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/controller/EpisodeActionController.java:[12] (sizes) LineLength: Zeile ist 98 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/controller/EpisodeActionController.java:[21,5] (javadoc) JavadocVariable: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/controller/EpisodeActionController.java:[24] (sizes) LineLength: Zeile ist 82 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/controller/EpisodeActionController.java:[25] (regexp) RegexpSingleline: Line has trailing spaces.
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/controller/EpisodeActionController.java:[31] (sizes) LineLength: Zeile ist 93 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/controller/EpisodeActionController.java:[31,64] (misc) FinalParameters: Der Parameter username sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/controller/EpisodeActionController.java:[32] (sizes) LineLength: Zeile ist 121 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/controller/EpisodeActionController.java:[32,64] (misc) FinalParameters: Der Parameter episodeActionPosts sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/controller/EpisodeActionController.java:[37] (javadoc) JavadocStyle: Der erste Satz sollte mit einem Punkt enden.
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/controller/EpisodeActionController.java:[38] (sizes) LineLength: Zeile ist 113 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/controller/EpisodeActionController.java:[39] (regexp) RegexpSingleline: Line has trailing spaces.
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/controller/EpisodeActionController.java:[40] (sizes) LineLength: Zeile ist 82 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/controller/EpisodeActionController.java:[41] (sizes) LineLength: Zeile ist 91 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/controller/EpisodeActionController.java:[44] (sizes) LineLength: Zeile ist 102 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/controller/EpisodeActionController.java:[44,71] (misc) FinalParameters: Der Parameter username sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/controller/EpisodeActionController.java:[45] (sizes) LineLength: Zeile ist 127 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/controller/EpisodeActionController.java:[49] (javadoc) JavadocStyle: Der erste Satz sollte mit einem Punkt enden.
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/controller/EpisodeActionController.java:[50] (sizes) LineLength: Zeile ist 112 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/controller/EpisodeActionController.java:[51] (regexp) RegexpSingleline: Line has trailing spaces.
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/controller/EpisodeActionController.java:[52] (sizes) LineLength: Zeile ist 82 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/controller/EpisodeActionController.java:[54] (sizes) LineLength: Zeile ist 91 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/controller/EpisodeActionController.java:[57] (sizes) LineLength: Zeile ist 109 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/controller/EpisodeActionController.java:[57,80] (misc) FinalParameters: Der Parameter username sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/controller/EpisodeActionController.java:[58] (sizes) LineLength: Zeile ist 103 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/controller/EpisodeActionController.java:[58,59] (misc) FinalParameters: Der Parameter podcastURL sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/controller/EpisodeActionController.java:[59] (sizes) LineLength: Zeile ist 148 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/controller/EpisodeActionController.java:[63] (javadoc) JavadocStyle: Der erste Satz sollte mit einem Punkt enden.
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/controller/EpisodeActionController.java:[64] (sizes) LineLength: Zeile ist 116 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/controller/EpisodeActionController.java:[65] (regexp) RegexpSingleline: Line has trailing spaces.
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/controller/EpisodeActionController.java:[66] (sizes) LineLength: Zeile ist 82 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/controller/EpisodeActionController.java:[67] (sizes) LineLength: Zeile ist 89 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/controller/EpisodeActionController.java:[68] (sizes) LineLength: Zeile ist 91 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/controller/EpisodeActionController.java:[71] (sizes) LineLength: Zeile ist 105 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/controller/EpisodeActionController.java:[71,76] (misc) FinalParameters: Der Parameter username sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/controller/EpisodeActionController.java:[72] (sizes) LineLength: Zeile ist 95 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/controller/EpisodeActionController.java:[72,60] (misc) FinalParameters: Der Parameter since sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/controller/EpisodeActionController.java:[73] (sizes) LineLength: Zeile ist 139 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/controller/EpisodeActionController.java:[77] (javadoc) JavadocStyle: Der erste Satz sollte mit einem Punkt enden.
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/controller/EpisodeActionController.java:[78] (sizes) LineLength: Zeile ist 132 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/controller/EpisodeActionController.java:[79] (regexp) RegexpSingleline: Line has trailing spaces.
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/controller/EpisodeActionController.java:[80] (sizes) LineLength: Zeile ist 82 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/controller/EpisodeActionController.java:[82] (sizes) LineLength: Zeile ist 89 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/controller/EpisodeActionController.java:[83] (sizes) LineLength: Zeile ist 91 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/controller/EpisodeActionController.java:[86] (sizes) LineLength: Zeile ist 114 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/controller/EpisodeActionController.java:[86,85] (misc) FinalParameters: Der Parameter username sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/controller/EpisodeActionController.java:[87] (sizes) LineLength: Zeile ist 106 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/controller/EpisodeActionController.java:[87,64] (misc) FinalParameters: Der Parameter podcastURL sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/controller/EpisodeActionController.java:[88] (sizes) LineLength: Zeile ist 99 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/controller/EpisodeActionController.java:[88,64] (misc) FinalParameters: Der Parameter since sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/controller/EpisodeActionController.java:[89] (sizes) LineLength: Zeile ist 160 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/controller/EpisodeActionGetResponse.java:[13,5] (javadoc) JavadocVariable: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/controller/EpisodeActionGetResponse.java:[14,5] (javadoc) JavadocVariable: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/controller/EpisodeActionGetResponse.java:[19,37] (misc) FinalParameters: Der Parameter actions sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/controller/EpisodeActionGetResponse.java:[19,61] (coding) HiddenField: Die Variable 'actions' verbirgt ein Feld.
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/controller/EpisodeActionGetResponse.java:[24,5] (javadoc) MissingJavadocMethod: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/controller/EpisodeActionGetResponse.java:[24,5] (design) DesignForExtension: Klasse 'EpisodeActionGetResponse' sieht wie zur Erweiterung entworfen aus (kann subclassed werden), aber die Methode 'getActions' besitzt keinen Javadoc-Kommentar, der erklärt, wie Sie das sicher tun. Wenn die Klasse nicht für Erweiterungen ausgelegt ist, sollten sie die Klasse 'EpisodeActionGetResponse' final oder die Methode 'getActions' static/final/abstract/empty machen oder die zugelassene Annotation für die Methode hinzufügen.
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/controller/EpisodeActionGetResponse.java:[28,5] (javadoc) MissingJavadocMethod: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/controller/EpisodeActionGetResponse.java:[28,5] (design) DesignForExtension: Klasse 'EpisodeActionGetResponse' sieht wie zur Erweiterung entworfen aus (kann subclassed werden), aber die Methode 'getTimestamp' besitzt keinen Javadoc-Kommentar, der erklärt, wie Sie das sicher tun. Wenn die Klasse nicht für Erweiterungen ausgelegt ist, sollten sie die Klasse 'EpisodeActionGetResponse' final oder die Methode 'getTimestamp' static/final/abstract/empty machen oder die zugelassene Annotation für die Methode hinzufügen.
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/controller/EpisodeActionPost.java:[14] (sizes) LineLength: Zeile ist 94 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/controller/EpisodeActionPost.java:[22,5] (javadoc) JavadocVariable: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/controller/EpisodeActionPost.java:[26,5] (javadoc) JavadocVariable: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/controller/EpisodeActionPost.java:[30,5] (javadoc) JavadocVariable: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/controller/EpisodeActionPost.java:[32,5] (javadoc) JavadocVariable: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/controller/EpisodeActionPost.java:[34,5] (javadoc) JavadocVariable: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/controller/EpisodeActionPost.java:[36,5] (javadoc) JavadocVariable: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/service/EpisodeActionService.java:[1] (javadoc) JavadocPackage: Es fehlt eine package-info.java.
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/service/EpisodeActionService.java:[30,5] (javadoc) JavadocVariable: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/service/EpisodeActionService.java:[32,5] (javadoc) JavadocVariable: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/service/EpisodeActionService.java:[34,5] (javadoc) JavadocVariable: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/service/EpisodeActionService.java:[36,5] (javadoc) JavadocVariable: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/service/EpisodeActionService.java:[38,5] (javadoc) JavadocVariable: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/service/EpisodeActionService.java:[40,5] (javadoc) JavadocVariable: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/service/EpisodeActionService.java:[42,5] (javadoc) JavadocVariable: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/service/EpisodeActionService.java:[44] (javadoc) JavadocStyle: Der erste Satz sollte mit einem Punkt enden.
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/service/EpisodeActionService.java:[45] (sizes) LineLength: Zeile ist 84 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/service/EpisodeActionService.java:[50] (sizes) LineLength: Zeile ist 82 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/service/EpisodeActionService.java:[53] (sizes) LineLength: Zeile ist 96 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/service/EpisodeActionService.java:[53,35] (misc) FinalParameters: Der Parameter username sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/service/EpisodeActionService.java:[53,52] (misc) FinalParameters: Der Parameter episodeActionPosts sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/service/EpisodeActionService.java:[55] (sizes) LineLength: Zeile ist 106 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/service/EpisodeActionService.java:[59,68] (misc) FinalParameters: Der Parameter user sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/service/EpisodeActionService.java:[60,13] (misc) FinalParameters: Der Parameter episodeActionPosts sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/service/EpisodeActionService.java:[63] (sizes) LineLength: Zeile ist 90 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/service/EpisodeActionService.java:[68] (sizes) LineLength: Zeile ist 108 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/service/EpisodeActionService.java:[68,60] (misc) FinalParameters: Der Parameter user sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/service/EpisodeActionService.java:[68,71] (misc) FinalParameters: Der Parameter episodeActionPost sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/service/EpisodeActionService.java:[75] (sizes) LineLength: Zeile ist 89 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/service/EpisodeActionService.java:[82] (sizes) LineLength: Zeile ist 109 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/service/EpisodeActionService.java:[83] (sizes) LineLength: Zeile ist 81 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/service/EpisodeActionService.java:[87] (sizes) LineLength: Zeile ist 102 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/service/EpisodeActionService.java:[96] (sizes) LineLength: Zeile ist 81 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/service/EpisodeActionService.java:[96,44] (misc) FinalParameters: Der Parameter episodeActionPost sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/service/EpisodeActionService.java:[103,9] (blocks) RightCurly: '}' an Position 9 sollte in der gleichen Zeile stehen wie der nächste Teil der Multi-Block-Anweisung (eine Anweisung, die mehrere Blöcke enthält: if/else-if/else, do/while oder try/catch/finally).
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/service/EpisodeActionService.java:[112,9] (blocks) RightCurly: '}' an Position 9 sollte in der gleichen Zeile stehen wie der nächste Teil der Multi-Block-Anweisung (eine Anweisung, die mehrere Blöcke enthält: if/else-if/else, do/while oder try/catch/finally).
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/service/EpisodeActionService.java:[120,35] (misc) FinalParameters: Der Parameter episodeActionPost sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/service/EpisodeActionService.java:[125] (sizes) LineLength: Zeile ist 105 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/service/EpisodeActionService.java:[134] (sizes) LineLength: Zeile ist 93 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/service/EpisodeActionService.java:[134,46] (misc) FinalParameters: Der Parameter user sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/service/EpisodeActionService.java:[134,57] (misc) FinalParameters: Der Parameter episodeActions sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/service/EpisodeActionService.java:[140] (sizes) LineLength: Zeile ist 85 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/service/EpisodeActionService.java:[140,45] (misc) FinalParameters: Der Parameter user sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/service/EpisodeActionService.java:[140,56] (misc) FinalParameters: Der Parameter episodeAction sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/service/EpisodeActionService.java:[141] (sizes) LineLength: Zeile ist 106 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/service/EpisodeActionService.java:[149] (sizes) LineLength: Zeile ist 91 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/service/EpisodeActionService.java:[149,51] (misc) FinalParameters: Der Parameter user sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/service/EpisodeActionService.java:[149,62] (misc) FinalParameters: Der Parameter episodeAction sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/service/EpisodeActionService.java:[150] (sizes) LineLength: Zeile ist 96 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/service/EpisodeActionService.java:[153] (sizes) LineLength: Zeile ist 84 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/service/EpisodeActionService.java:[159] (javadoc) JavadocStyle: Der erste Satz sollte mit einem Punkt enden.
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/service/EpisodeActionService.java:[163] (sizes) LineLength: Zeile ist 82 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/service/EpisodeActionService.java:[164] (sizes) LineLength: Zeile ist 83 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/service/EpisodeActionService.java:[166,54] (misc) FinalParameters: Der Parameter username sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/service/EpisodeActionService.java:[167] (sizes) LineLength: Zeile ist 91 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/service/EpisodeActionService.java:[175] (sizes) LineLength: Zeile ist 84 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/service/EpisodeActionService.java:[177] (sizes) LineLength: Zeile ist 83 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/service/EpisodeActionService.java:[179] (sizes) LineLength: Zeile ist 99 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/service/EpisodeActionService.java:[179,63] (misc) FinalParameters: Der Parameter username sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/service/EpisodeActionService.java:[179,80] (misc) FinalParameters: Der Parameter podcastURL sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/service/EpisodeActionService.java:[180] (sizes) LineLength: Zeile ist 115 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/service/EpisodeActionService.java:[185] (javadoc) JavadocStyle: Der erste Satz sollte mit einem Punkt enden.
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/service/EpisodeActionService.java:[186] (sizes) LineLength: Zeile ist 82 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/service/EpisodeActionService.java:[189] (sizes) LineLength: Zeile ist 82 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/service/EpisodeActionService.java:[192] (sizes) LineLength: Zeile ist 83 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/service/EpisodeActionService.java:[194] (sizes) LineLength: Zeile ist 88 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/service/EpisodeActionService.java:[194,59] (misc) FinalParameters: Der Parameter username sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/service/EpisodeActionService.java:[194,76] (misc) FinalParameters: Der Parameter since sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/service/EpisodeActionService.java:[195] (sizes) LineLength: Zeile ist 114 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/service/EpisodeActionService.java:[196] (sizes) LineLength: Zeile ist 118 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/service/EpisodeActionService.java:[201] (javadoc) JavadocStyle: Der erste Satz sollte mit einem Punkt enden.
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/service/EpisodeActionService.java:[202] (sizes) LineLength: Zeile ist 83 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/service/EpisodeActionService.java:[206] (sizes) LineLength: Zeile ist 84 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/service/EpisodeActionService.java:[210] (sizes) LineLength: Zeile ist 83 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/service/EpisodeActionService.java:[212] (sizes) LineLength: Zeile ist 116 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/service/EpisodeActionService.java:[212,68] (misc) FinalParameters: Der Parameter username sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/service/EpisodeActionService.java:[212,85] (misc) FinalParameters: Der Parameter podcastURL sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/service/EpisodeActionService.java:[212,104] (misc) FinalParameters: Der Parameter since sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/service/EpisodeActionService.java:[213] (sizes) LineLength: Zeile ist 114 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/service/EpisodeActionService.java:[215] (sizes) LineLength: Zeile ist 114 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/service/EpisodeActionService.java:[220] (sizes) LineLength: Zeile ist 108 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/service/EpisodeActionService.java:[220,72] (misc) FinalParameters: Der Parameter episodeActions sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/data_access/EpisodeActionDao.java:[1] (javadoc) JavadocPackage: Es fehlt eine package-info.java.
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/data_access/EpisodeActionDao.java:[16] (javadoc) JavadocStyle: Der erste Satz sollte mit einem Punkt enden.
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/data_access/EpisodeActionDao.java:[22] (javadoc) JavadocStyle: Der erste Satz sollte mit einem Punkt enden.
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/data_access/EpisodeActionDao.java:[30] (javadoc) JavadocStyle: Der erste Satz sollte mit einem Punkt enden.
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/data_access/EpisodeActionDao.java:[31] (sizes) LineLength: Zeile ist 82 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/data_access/EpisodeActionDao.java:[36] (sizes) LineLength: Zeile ist 82 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/data_access/EpisodeActionDao.java:[38] (sizes) LineLength: Zeile ist 97 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/data_access/EpisodeActionDao.java:[40] (sizes) LineLength: Zeile ist 84 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/data_access/EpisodeActionDao.java:[40,5] (javadoc) MissingJavadocMethod: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/data_access/EpisodeActionDao.java:[42] (sizes) LineLength: Zeile ist 85 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/data_access/EpisodeActionDao.java:[42,5] (javadoc) MissingJavadocMethod: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/data_access/EpisodeActionDao.java:[44] (sizes) LineLength: Zeile ist 99 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/data_access/EpisodeActionDao.java:[44,5] (javadoc) MissingJavadocMethod: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/data_access/EpisodeActionDao.java:[46] (javadoc) JavadocStyle: Der erste Satz sollte mit einem Punkt enden.
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/data_access/EpisodeActionDao.java:[50] (sizes) LineLength: Zeile ist 84 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/data_access/EpisodeActionDao.java:[54] (sizes) LineLength: Zeile ist 113 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/data_access/EpisodeActionDao.java:[56] (javadoc) JavadocStyle: Der erste Satz sollte mit einem Punkt enden.
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/data_access/EpisodeActionDao.java:[57] (sizes) LineLength: Zeile ist 83 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/data_access/EpisodeActionDao.java:[60] (sizes) LineLength: Zeile ist 84 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/data_access/EpisodeActionDao.java:[64] (sizes) LineLength: Zeile ist 82 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/data_access/EpisodeActionDao.java:[67] (sizes) LineLength: Zeile ist 112 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/data_access/EpisodeActionDao.java:[72,5] (javadoc) MissingJavadocMethod: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/data_access/EpisodeDao.java:[9] (javadoc) JavadocStyle: Der erste Satz sollte mit einem Punkt enden.
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/data_access/EpisodeDao.java:[15] (javadoc) JavadocStyle: Der erste Satz sollte mit einem Punkt enden.
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/data_access/EpisodeDao.java:[23] (javadoc) JavadocStyle: Der erste Satz sollte mit einem Punkt enden.
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/data_access/EpisodeDao.java:[31] (javadoc) JavadocStyle: Der erste Satz sollte mit einem Punkt enden.
+[ERROR] src/main/java/org/psesquared/server/episode_actions_api/data_access/EpisodeDao.java:[39] (javadoc) JavadocStyle: Der erste Satz sollte mit einem Punkt enden.
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/controller/SubscriptionTitles.java:[1] (javadoc) JavadocPackage: Es fehlt eine package-info.java.
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/controller/SubscriptionTitles.java:[9] (javadoc) JavadocStyle: Der erste Satz sollte mit einem Punkt enden.
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/controller/SubscriptionTitles.java:[12] (sizes) LineLength: Zeile ist 110 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/controller/SubscriptionTitles.java:[12,1] (javadoc) JavadocType: Im Javadoc des Typs fehlt das Tag @param episodes.
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/controller/SubscriptionTitles.java:[12,1] (javadoc) JavadocType: Im Javadoc des Typs fehlt das Tag @param subscription.
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/controller/SubscriptionController.java:[7,47] (imports) AvoidStarImport: Stern-Importe der Form '.*' sollten vermieden werden - org.springframework.web.bind.annotation.*.
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/controller/SubscriptionController.java:[12] (sizes) LineLength: Zeile ist 96 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/controller/SubscriptionController.java:[13] (sizes) LineLength: Zeile ist 97 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/controller/SubscriptionController.java:[20,5] (javadoc) JavadocVariable: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/controller/SubscriptionController.java:[22,5] (javadoc) JavadocVariable: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/controller/SubscriptionController.java:[25] (sizes) LineLength: Zeile ist 81 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/controller/SubscriptionController.java:[27] (regexp) RegexpSingleline: Line has trailing spaces.
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/controller/SubscriptionController.java:[29] (sizes) LineLength: Zeile ist 127 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/controller/SubscriptionController.java:[30] (sizes) LineLength: Zeile ist 111 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/controller/SubscriptionController.java:[34] (sizes) LineLength: Zeile ist 84 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/controller/SubscriptionController.java:[34,55] (misc) FinalParameters: Der Parameter username sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/controller/SubscriptionController.java:[35,48] (misc) FinalParameters: Der Parameter deviceID sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/controller/SubscriptionController.java:[36] (sizes) LineLength: Zeile ist 89 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/controller/SubscriptionController.java:[36,48] (misc) FinalParameters: Der Parameter subscriptions sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/controller/SubscriptionController.java:[43] (regexp) RegexpSingleline: Line has trailing spaces.
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/controller/SubscriptionController.java:[44] (sizes) LineLength: Zeile ist 88 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/controller/SubscriptionController.java:[45] (sizes) LineLength: Zeile ist 113 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/controller/SubscriptionController.java:[47] (sizes) LineLength: Zeile ist 102 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/controller/SubscriptionController.java:[48] (sizes) LineLength: Zeile ist 88 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/controller/SubscriptionController.java:[50] (sizes) LineLength: Zeile ist 103 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/controller/SubscriptionController.java:[51] (sizes) LineLength: Zeile ist 87 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/controller/SubscriptionController.java:[51,58] (misc) FinalParameters: Der Parameter username sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/controller/SubscriptionController.java:[52] (sizes) LineLength: Zeile ist 98 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/controller/SubscriptionController.java:[52,51] (misc) FinalParameters: Der Parameter deviceID sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/controller/SubscriptionController.java:[53] (sizes) LineLength: Zeile ist 122 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/controller/SubscriptionController.java:[53,51] (misc) FinalParameters: Der Parameter functionJSONP sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/controller/SubscriptionController.java:[54] (sizes) LineLength: Zeile ist 84 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/controller/SubscriptionController.java:[59] (sizes) LineLength: Zeile ist 128 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/controller/SubscriptionController.java:[61] (regexp) RegexpSingleline: Line has trailing spaces.
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/controller/SubscriptionController.java:[62] (sizes) LineLength: Zeile ist 92 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/controller/SubscriptionController.java:[63] (sizes) LineLength: Zeile ist 121 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/controller/SubscriptionController.java:[64] (sizes) LineLength: Zeile ist 92 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/controller/SubscriptionController.java:[65] (regexp) RegexpSingleline: Line has trailing spaces.
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/controller/SubscriptionController.java:[65] (sizes) LineLength: Zeile ist 100 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/controller/SubscriptionController.java:[68] (sizes) LineLength: Zeile ist 98 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/controller/SubscriptionController.java:[68,69] (misc) FinalParameters: Der Parameter username sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/controller/SubscriptionController.java:[69] (sizes) LineLength: Zeile ist 98 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/controller/SubscriptionController.java:[69,69] (misc) FinalParameters: Der Parameter deviceID sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/controller/SubscriptionController.java:[70] (sizes) LineLength: Zeile ist 107 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/controller/SubscriptionController.java:[70,69] (misc) FinalParameters: Der Parameter delta sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/controller/SubscriptionController.java:[76] (sizes) LineLength: Zeile ist 94 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/controller/SubscriptionController.java:[77] (regexp) RegexpSingleline: Line has trailing spaces.
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/controller/SubscriptionController.java:[78] (sizes) LineLength: Zeile ist 92 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/controller/SubscriptionController.java:[79] (sizes) LineLength: Zeile ist 120 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/controller/SubscriptionController.java:[80] (sizes) LineLength: Zeile ist 81 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/controller/SubscriptionController.java:[81] (sizes) LineLength: Zeile ist 105 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/controller/SubscriptionController.java:[84] (sizes) LineLength: Zeile ist 96 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/controller/SubscriptionController.java:[84,67] (misc) FinalParameters: Der Parameter username sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/controller/SubscriptionController.java:[85] (sizes) LineLength: Zeile ist 96 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/controller/SubscriptionController.java:[85,67] (misc) FinalParameters: Der Parameter deviceID sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/controller/SubscriptionController.java:[86] (sizes) LineLength: Zeile ist 102 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/controller/SubscriptionController.java:[86,67] (misc) FinalParameters: Der Parameter since sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/controller/SubscriptionController.java:[87] (sizes) LineLength: Zeile ist 92 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/controller/SubscriptionController.java:[93] (sizes) LineLength: Zeile ist 97 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/controller/SubscriptionController.java:[94] (regexp) RegexpSingleline: Line has trailing spaces.
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/controller/SubscriptionController.java:[95] (sizes) LineLength: Zeile ist 82 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/controller/SubscriptionController.java:[96] (sizes) LineLength: Zeile ist 100 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/controller/SubscriptionController.java:[99] (sizes) LineLength: Zeile ist 94 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/controller/SubscriptionController.java:[99,63] (misc) FinalParameters: Der Parameter username sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/controller/SubscriptionController.java:[100] (sizes) LineLength: Zeile ist 88 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/controller/SubscriptionDelta.java:[10] (javadoc) JavadocStyle: Der erste Satz sollte mit einem Punkt enden.
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/controller/SubscriptionDelta.java:[11] (sizes) LineLength: Zeile ist 114 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/controller/SubscriptionDelta.java:[16,5] (javadoc) JavadocVariable: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/controller/SubscriptionDelta.java:[20,5] (javadoc) JavadocVariable: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/controller/SubscriptionDelta.java:[24,5] (javadoc) JavadocVariable: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/controller/SubscriptionDelta.java:[28] (sizes) LineLength: Zeile ist 84 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/controller/SubscriptionDelta.java:[29] (sizes) LineLength: Zeile ist 89 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/controller/SubscriptionDelta.java:[31,30] (misc) FinalParameters: Der Parameter add sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/controller/SubscriptionDelta.java:[31,43] (coding) HiddenField: Die Variable 'add' verbirgt ein Feld.
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/controller/SubscriptionDelta.java:[31,48] (misc) FinalParameters: Der Parameter remove sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/controller/SubscriptionDelta.java:[31,61] (coding) HiddenField: Die Variable 'remove' verbirgt ein Feld.
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/controller/SubscriptionDelta.java:[37] (javadoc) JavadocStyle: Der erste Satz sollte mit einem Punkt enden.
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/controller/SubscriptionDelta.java:[39] (regexp) RegexpSingleline: Line has trailing spaces.
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/controller/SubscriptionDelta.java:[46] (javadoc) JavadocStyle: Der erste Satz sollte mit einem Punkt enden.
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/controller/SubscriptionDelta.java:[48] (regexp) RegexpSingleline: Line has trailing spaces.
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/controller/SubscriptionDelta.java:[55] (javadoc) JavadocStyle: Der erste Satz sollte mit einem Punkt enden.
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/controller/SubscriptionDelta.java:[57] (regexp) RegexpSingleline: Line has trailing spaces.
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/service/SubscriptionService.java:[1] (javadoc) JavadocPackage: Es fehlt eine package-info.java.
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/service/SubscriptionService.java:[12,35] (imports) AvoidStarImport: Stern-Importe der Form '.*' sollten vermieden werden - org.psesquared.server.model.*.
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/service/SubscriptionService.java:[28,5] (javadoc) JavadocVariable: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/service/SubscriptionService.java:[29,5] (javadoc) JavadocVariable: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/service/SubscriptionService.java:[31,5] (javadoc) JavadocVariable: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/service/SubscriptionService.java:[33,5] (javadoc) JavadocVariable: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/service/SubscriptionService.java:[35,5] (javadoc) JavadocVariable: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/service/SubscriptionService.java:[37,5] (javadoc) JavadocVariable: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/service/SubscriptionService.java:[47] (regexp) RegexpSingleline: Line has trailing spaces.
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/service/SubscriptionService.java:[49] (sizes) LineLength: Zeile ist 84 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/service/SubscriptionService.java:[52] (sizes) LineLength: Zeile ist 87 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/service/SubscriptionService.java:[52,36] (misc) FinalParameters: Der Parameter username sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/service/SubscriptionService.java:[52,53] (misc) FinalParameters: Der Parameter subscriptionStrings sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/service/SubscriptionService.java:[60] (sizes) LineLength: Zeile ist 85 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/service/SubscriptionService.java:[65] (sizes) LineLength: Zeile ist 118 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/service/SubscriptionService.java:[67] (sizes) LineLength: Zeile ist 84 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/service/SubscriptionService.java:[70] (sizes) LineLength: Zeile ist 98 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/service/SubscriptionService.java:[71] (sizes) LineLength: Zeile ist 85 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/service/SubscriptionService.java:[76] (sizes) LineLength: Zeile ist 102 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/service/SubscriptionService.java:[80] (sizes) LineLength: Zeile ist 99 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/service/SubscriptionService.java:[89] (javadoc) JavadocStyle: Der erste Satz sollte mit einem Punkt enden.
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/service/SubscriptionService.java:[90] (sizes) LineLength: Zeile ist 82 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/service/SubscriptionService.java:[92] (regexp) RegexpSingleline: Line has trailing spaces.
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/service/SubscriptionService.java:[97,42] (misc) FinalParameters: Der Parameter username sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/service/SubscriptionService.java:[98] (sizes) LineLength: Zeile ist 118 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/service/SubscriptionService.java:[106] (javadoc) JavadocStyle: Der erste Satz sollte mit einem Punkt enden.
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/service/SubscriptionService.java:[108] (regexp) RegexpSingleline: Line has trailing spaces.
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/service/SubscriptionService.java:[109] (sizes) LineLength: Zeile ist 84 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/service/SubscriptionService.java:[110] (sizes) LineLength: Zeile ist 82 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/service/SubscriptionService.java:[114] (sizes) LineLength: Zeile ist 81 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/service/SubscriptionService.java:[114,39] (misc) FinalParameters: Der Parameter username sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/service/SubscriptionService.java:[114,56] (misc) FinalParameters: Der Parameter delta sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/service/SubscriptionService.java:[121,56] (whitespace) OperatorWrap: '&&' sollte in einer neuen Zeile stehen.
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/service/SubscriptionService.java:[122] (sizes) LineLength: Zeile ist 112 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/service/SubscriptionService.java:[125] (sizes) LineLength: Zeile ist 93 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/service/SubscriptionService.java:[132] (sizes) LineLength: Zeile ist 100 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/service/SubscriptionService.java:[139] (javadoc) JavadocStyle: Der erste Satz sollte mit einem Punkt enden.
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/service/SubscriptionService.java:[142] (regexp) RegexpSingleline: Line has trailing spaces.
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/service/SubscriptionService.java:[143] (sizes) LineLength: Zeile ist 84 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/service/SubscriptionService.java:[145] (sizes) LineLength: Zeile ist 82 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/service/SubscriptionService.java:[147] (sizes) LineLength: Zeile ist 82 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/service/SubscriptionService.java:[149,51] (misc) FinalParameters: Der Parameter username sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/service/SubscriptionService.java:[149,68] (misc) FinalParameters: Der Parameter since sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/service/SubscriptionService.java:[154] (sizes) LineLength: Zeile ist 81 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/service/SubscriptionService.java:[167] (sizes) LineLength: Zeile ist 82 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/service/SubscriptionService.java:[169] (regexp) RegexpSingleline: Line has trailing spaces.
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/service/SubscriptionService.java:[172] (sizes) LineLength: Zeile ist 82 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/service/SubscriptionService.java:[175,47] (misc) FinalParameters: Der Parameter username sollte als 'final' deklariert sein.
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/service/SubscriptionService.java:[176] (sizes) LineLength: Zeile ist 118 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/service/SubscriptionService.java:[189] (sizes) LineLength: Zeile ist 109 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/data_access/SubscriptionActionDao.java:[1] (javadoc) JavadocPackage: Es fehlt eine package-info.java.
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/data_access/SubscriptionActionDao.java:[12] (javadoc) JavadocStyle: Der erste Satz sollte mit einem Punkt enden.
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/data_access/SubscriptionActionDao.java:[16] (sizes) LineLength: Zeile ist 88 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/data_access/SubscriptionActionDao.java:[34] (sizes) LineLength: Zeile ist 83 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/data_access/SubscriptionActionDao.java:[37] (sizes) LineLength: Zeile ist 97 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/data_access/SubscriptionActionDao.java:[45] (sizes) LineLength: Zeile ist 84 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/data_access/SubscriptionActionDao.java:[49] (sizes) LineLength: Zeile ist 109 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/data_access/SubscriptionActionDao.java:[54] (sizes) LineLength: Zeile ist 81 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/data_access/SubscriptionActionDao.java:[60] (sizes) LineLength: Zeile ist 83 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/data_access/SubscriptionActionDao.java:[63] (sizes) LineLength: Zeile ist 82 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/data_access/SubscriptionActionDao.java:[64] (sizes) LineLength: Zeile ist 82 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/data_access/SubscriptionActionDao.java:[68] (sizes) LineLength: Zeile ist 104 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/data_access/SubscriptionActionDao.java:[70] (regexp) RegexpSingleline: Line has trailing spaces.
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/data_access/SubscriptionDao.java:[10] (javadoc) JavadocStyle: Der erste Satz sollte mit einem Punkt enden.
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/data_access/SubscriptionDao.java:[16,5] (javadoc) MissingJavadocMethod: Es fehlt ein Javadoc-Kommentar.
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/data_access/SubscriptionDao.java:[17,5] (javadoc) InvalidJavadocPosition: Javadoc-Kommentar ist an der falschen Stelle platziert.
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/data_access/SubscriptionDao.java:[25] (javadoc) JavadocStyle: Der erste Satz sollte mit einem Punkt enden.
+[ERROR] src/main/java/org/psesquared/server/subscriptions_api/data_access/SubscriptionDao.java:[26] (sizes) LineLength: Zeile ist 81 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/ServerApplication.java:[1] (javadoc) JavadocPackage: Es fehlt eine package-info.java.
+[ERROR] src/main/java/org/psesquared/server/ServerApplication.java:[9] (javadoc) JavadocStyle: Der erste Satz sollte mit einem Punkt enden.
+[ERROR] src/main/java/org/psesquared/server/ServerApplication.java:[12,1] (design) HideUtilityClassConstructor: Hilfsklassen sollten keinen Standard-Konstruktur und keinen als public deklarierten Konstruktor haben.
+[ERROR] src/main/java/org/psesquared/server/ServerApplication.java:[13] (sizes) LineLength: Zeile ist 95 Zeichen lang (Obergrenze ist 80).
+[ERROR] src/main/java/org/psesquared/server/ServerApplication.java:[16] (javadoc) JavadocStyle: Der erste Satz sollte mit einem Punkt enden.
+[ERROR] src/main/java/org/psesquared/server/ServerApplication.java:[16,1] (whitespace) FileTabCharacter: Die Datei enthält Tabulatorzeichen (dies ist das erste Vorkommen).
+[ERROR] src/main/java/org/psesquared/server/ServerApplication.java:[18] (regexp) RegexpSingleline: Line has trailing spaces.
+[ERROR] src/main/java/org/psesquared/server/ServerApplication.java:[21,33] (misc) FinalParameters: Der Parameter args sollte als 'final' deklariert sein.
+[ERROR] src/main/resources/security.properties:[1] (misc) NewlineAtEndOfFile: Datei endet nicht mit einem Zeilenumbruch.
+[INFO] ------------------------------------------------------------------------
+[INFO] BUILD FAILURE
+[INFO] ------------------------------------------------------------------------
+[INFO] Total time: 13.946 s
+[INFO] Finished at: 2023-03-18T08:10:57+01:00
+[INFO] ------------------------------------------------------------------------
+[ERROR] Failed to execute goal org.apache.maven.plugins:maven-checkstyle-plugin:3.2.1:check (default-cli) on project server: You have 799 Checkstyle violations. -> [Help 1]
+[ERROR]
+[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
+[ERROR] Re-run Maven using the -X switch to enable full debug logging.
+[ERROR]
+[ERROR] For more information about the errors and possible solutions, please read the following articles:
+[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoFailureException
diff --git a/31-qualitaetsheft-kolloquium/assets/sources/linter-dashboard-after-processed.txt b/31-qualitaetsheft-kolloquium/assets/sources/linter-dashboard-after-processed.txt
new file mode 100644
index 0000000..cab82f3
--- /dev/null
+++ b/31-qualitaetsheft-kolloquium/assets/sources/linter-dashboard-after-processed.txt
@@ -0,0 +1 @@
+1 warning vue/no-v-html
diff --git a/31-qualitaetsheft-kolloquium/assets/sources/linter-dashboard-after.txt b/31-qualitaetsheft-kolloquium/assets/sources/linter-dashboard-after.txt
new file mode 100644
index 0000000..f9bda3b
--- /dev/null
+++ b/31-qualitaetsheft-kolloquium/assets/sources/linter-dashboard-after.txt
@@ -0,0 +1,10 @@
+
+> pse-dashboard@0.0.0 lint
+> eslint 'src/**/*.{js,vue}'
+
+
+/home/gero/documents/uni/pse/pse-dashboard/src/components/HelpModal.vue
+ 25:21 warning 'v-html' directive can lead to XSS attack vue/no-v-html
+
+✖ 1 problem (0 errors, 1 warning)
+
diff --git a/31-qualitaetsheft-kolloquium/assets/sources/linter-dashboard-before-processed.txt b/31-qualitaetsheft-kolloquium/assets/sources/linter-dashboard-before-processed.txt
new file mode 100644
index 0000000..150ea46
--- /dev/null
+++ b/31-qualitaetsheft-kolloquium/assets/sources/linter-dashboard-before-processed.txt
@@ -0,0 +1,22 @@
+26 error vue/html-indent
+17 error vue/script-indent
+6 error vue/require-v-for-key
+5 error vue/multi-word-component-names
+1 error vue/valid-v-for
+1 error vue/valid-template-root
+125 warning vue/max-attributes-per-line
+34 warning vue/attributes-order
+26 warning vue/singleline-html-element-content-newline
+12 warning vue/require-default-prop
+12 warning vue/html-self-closing
+11 warning vue/first-attribute-linebreak
+10 warning vue/html-closing-bracket-newline
+8 warning vue/multiline-html-element-content-newline
+5 warning vue/html-closing-bracket-spacing
+3 warning vue/require-prop-types
+3 warning vue/attribute-hyphenation
+2 warning vue/html-self-closing
+1 warning vue/v-on-event-hyphenation
+1 warning vue/no-v-html
+1 warning vue/mustache-interpolation-spacing
+
diff --git a/31-qualitaetsheft-kolloquium/assets/sources/linter-dashboard-before.txt b/31-qualitaetsheft-kolloquium/assets/sources/linter-dashboard-before.txt
new file mode 100644
index 0000000..04a8317
--- /dev/null
+++ b/31-qualitaetsheft-kolloquium/assets/sources/linter-dashboard-before.txt
@@ -0,0 +1,358 @@
+
+> pse-dashboard@0.0.0 lint
+> eslint 'src/**/*.{js,vue}'
+
+
+/home/gero/documents/uni/pse/pse-dashboard/src/components/Episode.vue
+ 1:1 error Component name "Episode" should always be multi-word vue/multi-word-component-names
+ 5:5 warning Prop 'action' requires default value to be set vue/require-default-prop
+ 5:5 warning Prop "action" should define at least its type vue/require-prop-types
+ 20:17 warning 'class' should be on a new line vue/max-attributes-per-line
+ 20:69 warning 'aria-current' should be on a new line vue/max-attributes-per-line
+ 23:67 warning 'style' should be on a new line vue/max-attributes-per-line
+ 38:51 warning 'style' should be on a new line vue/max-attributes-per-line
+ 39:17 warning Require self-closing on HTML elements (<div>) vue/html-self-closing
+ 39:43 warning ':style' should be on a new line vue/max-attributes-per-line
+
+/home/gero/documents/uni/pse/pse-dashboard/src/components/ErrorLog.vue
+ 14:1 error Expected indentation of 8 spaces but found 4 spaces vue/html-indent
+ 15:1 error Expected indentation of 12 spaces but found 8 spaces vue/html-indent
+ 15:9 error Elements in iteration expect to have 'v-bind:key' directives vue/require-v-for-key
+ 15:14 warning Expected a linebreak before this attribute vue/first-attribute-linebreak
+ 15:43 warning 'class' should be on a new line vue/max-attributes-per-line
+ 16:29 warning ':class' should be on a new line vue/max-attributes-per-line
+ 16:58 warning Expected 1 line break before closing bracket, but no line breaks found vue/html-closing-bracket-newline
+ 17:1 error Expected indentation of 16 spaces but found 12 spaces vue/html-indent
+ 17:13 warning Require self-closing on HTML elements (<button>) vue/html-self-closing
+ 17:35 warning 'class' should be on a new line vue/max-attributes-per-line
+ 17:53 warning '@click' should be on a new line vue/max-attributes-per-line
+ 18:1 error Expected indentation of 16 spaces but found 12 spaces vue/html-indent
+ 18:13 warning Require self-closing on HTML elements (<i>) vue/html-self-closing
+ 18:37 warning ':class' should be on a new line vue/max-attributes-per-line
+ 19:1 error Expected indentation of 12 spaces but found 8 spaces vue/html-indent
+ 20:1 error Expected indentation of 8 spaces but found 4 spaces vue/html-indent
+
+/home/gero/documents/uni/pse/pse-dashboard/src/components/FloatingLabelInput.vue
+ 7:5 warning Prop 'label' requires default value to be set vue/require-default-prop
+ 8:5 warning Prop 'modelValue' requires default value to be set vue/require-default-prop
+ 15:16 warning Expected a linebreak before this attribute vue/first-attribute-linebreak
+ 15:29 warning 'class' should be on a new line vue/max-attributes-per-line
+ 15:50 warning Attribute ":id" should go before "class" vue/attributes-order
+ 15:50 warning ':id' should be on a new line vue/max-attributes-per-line
+ 15:62 warning ':value' should be on a new line vue/max-attributes-per-line
+ 16:1 error Expected indentation of 15 spaces but found 12 spaces vue/html-indent
+ 17:1 error Expected indentation of 15 spaces but found 12 spaces vue/html-indent
+ 17:13 warning Attribute ":placeholder" should go before "@input" vue/attributes-order
+ 17:34 warning Attribute "required" should go before "@input" vue/attributes-order
+ 17:34 warning 'required' should be on a new line vue/max-attributes-per-line
+ 17:42 warning Expected 1 line break before closing bracket, but no line breaks found vue/html-closing-bracket-newline
+
+/home/gero/documents/uni/pse/pse-dashboard/src/components/FormLayout.vue
+ 9:35 warning 'src' should be on a new line vue/max-attributes-per-line
+ 9:60 warning 'alt' should be on a new line vue/max-attributes-per-line
+ 9:67 warning 'width' should be on a new line vue/max-attributes-per-line
+ 9:79 warning 'height' should be on a new line vue/max-attributes-per-line
+
+/home/gero/documents/uni/pse/pse-dashboard/src/components/Help.vue
+ 1:1 error Component name "Help" should always be multi-word vue/multi-word-component-names
+ 4:29 warning Attribute "id" should go before "class" vue/attributes-order
+ 4:29 warning 'id' should be on a new line vue/max-attributes-per-line
+ 9:45 warning Expected 1 line break after opening tag (`<h5>`), but no line breaks found vue/singleline-html-element-content-newline
+ 9:69 warning Expected 1 line break before closing tag (`</h5>`), but no line breaks found vue/singleline-html-element-content-newline
+ 10:21 warning Require self-closing on HTML elements (<button>) vue/html-self-closing
+ 10:43 warning 'class' should be on a new line vue/max-attributes-per-line
+ 10:61 warning 'data-bs-dismiss' should be on a new line vue/max-attributes-per-line
+ 14:41 warning 'v-html' should be on a new line vue/max-attributes-per-line
+ 14:41 warning 'v-html' directive can lead to XSS attack vue/no-v-html
+ 18:43 warning 'class' should be on a new line vue/max-attributes-per-line
+ 18:69 warning 'data-bs-dismiss' should be on a new line vue/max-attributes-per-line
+ 18:93 warning Expected 1 line break after opening tag (`<button>`), but no line breaks found vue/singleline-html-element-content-newline
+ 18:118 warning Expected 1 line break before closing tag (`</button>`), but no line breaks found vue/singleline-html-element-content-newline
+
+/home/gero/documents/uni/pse/pse-dashboard/src/components/LastUpdate.vue
+ 12:5 warning Prop 'iso' requires default value to be set vue/require-default-prop
+ 13:5 warning Prop 'unix' requires default value to be set vue/require-default-prop
+ 36:1 error Expected indentation of 4 spaces but found 0 spaces vue/html-indent
+
+/home/gero/documents/uni/pse/pse-dashboard/src/components/Loading.vue
+ 1:1 error Component name "Loading" should always be multi-word vue/multi-word-component-names
+ 9:30 warning Attribute "v-else" should go before "class" vue/attributes-order
+ 9:30 warning 'v-else' should be on a new line vue/max-attributes-per-line
+
+/home/gero/documents/uni/pse/pse-dashboard/src/components/LogEntry.vue
+ 3:1 error The template requires child element vue/valid-template-root
+ 3:1 warning Require self-closing on HTML elements (<template>) vue/html-self-closing
+
+/home/gero/documents/uni/pse/pse-dashboard/src/components/Navbar.vue
+ 1:1 error Component name "Navbar" should always be multi-word vue/multi-word-component-names
+ 6:32 warning Expected 1 line break after opening tag (`<div>`), but 2 line breaks found vue/multiline-html-element-content-newline
+ 9:47 warning 'to' should be on a new line vue/max-attributes-per-line
+ 10:1 error Expected indentation of 16 spaces but found 20 spaces vue/html-indent
+ 10:50 warning 'alt' should be on a new line vue/max-attributes-per-line
+ 10:57 warning 'width' should be on a new line vue/max-attributes-per-line
+ 10:69 warning 'height' should be on a new line vue/max-attributes-per-line
+ 14:44 warning 'type' should be on a new line vue/max-attributes-per-line
+ 14:58 warning 'data-bs-toggle' should be on a new line vue/max-attributes-per-line
+ 14:84 warning 'data-bs-target' should be on a new line vue/max-attributes-per-line
+ 15:17 warning Require self-closing on HTML elements (<span>) vue/html-self-closing
+ 17:51 warning Attribute "id" should go before "class" vue/attributes-order
+ 17:51 warning 'id' should be on a new line vue/max-attributes-per-line
+ 17:65 warning Expected 1 line break after opening tag (`<div>`), but 2 line breaks found vue/multiline-html-element-content-newline
+ 21:49 warning 'class' should be on a new line vue/max-attributes-per-line
+ 23:62 warning 'class' should be on a new line vue/max-attributes-per-line
+ 28:57 warning 'class' should be on a new line vue/max-attributes-per-line
+ 40:61 warning 'href' should be on a new line vue/max-attributes-per-line
+ 40:70 warning 'role' should be on a new line vue/max-attributes-per-line
+ 40:84 warning 'data-bs-toggle' should be on a new line vue/max-attributes-per-line
+ 41:29 warning Require self-closing on HTML elements (<i>) vue/html-self-closing
+ 44:29 error Elements in iteration expect to have 'v-bind:key' directives vue/require-v-for-key
+ 45:58 warning ':class' should be on a new line vue/max-attributes-per-line
+ 45:100 warning '@click' should be on a new line vue/max-attributes-per-line
+ 51:24 warning Expected a linebreak before this attribute vue/first-attribute-linebreak
+ 51:33 warning 'class' should be on a new line vue/max-attributes-per-line
+ 52:1 error Expected indentation of 23 spaces but found 24 spaces vue/html-indent
+ 52:48 warning 'data-bs-target' should be on a new line vue/max-attributes-per-line
+ 52:70 warning Expected 1 line break before closing bracket, but no line breaks found vue/html-closing-bracket-newline
+ 55:50 warning 'class' should be on a new line vue/max-attributes-per-line
+ 56:37 warning 'class' should be on a new line vue/max-attributes-per-line
+ 56:70 warning 'role' should be on a new line vue/max-attributes-per-line
+ 56:84 warning 'data-bs-toggle' should be on a new line vue/max-attributes-per-line
+ 57:64 warning Require self-closing on HTML elements (<i>) vue/html-self-closing
+ 60:61 warning 'class' should be on a new line vue/max-attributes-per-line
+ 60:83 warning Expected 1 line break after opening tag (`<router-link>`), but no line breaks found vue/singleline-html-element-content-newline
+ 60:111 warning Expected 1 line break before closing tag (`</router-link>`), but no line breaks found vue/singleline-html-element-content-newline
+ 62:58 warning '@click' should be on a new line vue/max-attributes-per-line
+ 62:82 warning Attribute "class" should go before "@click" vue/attributes-order
+ 62:82 warning 'class' should be on a new line vue/max-attributes-per-line
+ 62:104 warning Expected 1 line break after opening tag (`<router-link>`), but no line breaks found vue/singleline-html-element-content-newline
+ 62:130 warning Expected 1 line break before closing tag (`</router-link>`), but no line breaks found vue/singleline-html-element-content-newline
+
+/home/gero/documents/uni/pse/pse-dashboard/src/components/PasswordInput.vue
+ 6:5 warning Prop 'modelValue' requires default value to be set vue/require-default-prop
+ 7:5 warning Prop 'label' requires default value to be set vue/require-default-prop
+ 14:29 warning Expected a linebreak before this attribute vue/first-attribute-linebreak
+ 15:1 error Expected indentation of 28 spaces but found 8 spaces vue/html-indent
+ 15:24 warning ':modelValue' should be on a new line vue/max-attributes-per-line
+ 15:24 warning Attribute ':modelValue' must be hyphenated vue/attribute-hyphenation
+ 15:49 warning '@update:modelValue' should be on a new line vue/max-attributes-per-line
+ 15:49 warning v-on event '@update:modelValue' must be hyphenated vue/v-on-event-hyphenation
+ 16:1 error Expected indentation of 32 spaces but found 8 spaces vue/html-indent
+ 16:46 warning Expected 1 line break before closing bracket, but no line breaks found vue/html-closing-bracket-newline
+ 19:13 warning Disallow self-closing on HTML void elements (<input/>) vue/html-self-closing
+ 19:36 warning 'class' should be on a new line vue/max-attributes-per-line
+ 19:54 warning 'autocomplete' should be on a new line vue/max-attributes-per-line
+ 19:73 warning Attribute "v-model" should go before "autocomplete" vue/attributes-order
+ 19:73 warning 'v-model' should be on a new line vue/max-attributes-per-line
+ 19:100 warning Expected a space before '/>', but not found vue/html-closing-bracket-spacing
+ 20:27 warning ':class' should be on a new line vue/max-attributes-per-line
+
+/home/gero/documents/uni/pse/pse-dashboard/src/components/PasswordValidator.vue
+ 6:14 warning Prop "modelValue" should define at least its type vue/require-prop-types
+ 16:1 error Expected indentation of 4 spaces but found 8 spaces vue/script-indent
+ 17:1 error Expected indentation of 0 spaces but found 8 spaces vue/script-indent
+ 21:1 error Expected indentation of 4 spaces but found 8 spaces vue/script-indent
+ 22:1 error Expected indentation of 0 spaces but found 8 spaces vue/script-indent
+ 26:1 error Expected indentation of 4 spaces but found 8 spaces vue/script-indent
+ 27:1 error Expected indentation of 4 spaces but found 8 spaces vue/script-indent
+ 32:1 error Expected indentation of 4 spaces but found 8 spaces vue/script-indent
+ 33:1 error Expected indentation of 4 spaces but found 8 spaces vue/script-indent
+ 34:1 error Expected indentation of 0 spaces but found 8 spaces vue/script-indent
+ 38:1 error Expected indentation of 4 spaces but found 8 spaces vue/script-indent
+ 39:1 error Expected indentation of 4 spaces but found 8 spaces vue/script-indent
+ 40:1 error Expected indentation of 0 spaces but found 8 spaces vue/script-indent
+ 44:1 error Expected indentation of 4 spaces but found 8 spaces vue/script-indent
+ 45:1 error Expected indentation of 4 spaces but found 8 spaces vue/script-indent
+ 46:1 error Expected indentation of 4 spaces but found 8 spaces vue/script-indent
+ 47:1 error Expected indentation of 4 spaces but found 8 spaces vue/script-indent
+ 48:1 error Expected indentation of 4 spaces but found 8 spaces vue/script-indent
+ 72:49 warning Attribute "v-model" should go before ":label" vue/attributes-order
+ 72:49 warning 'v-model' should be on a new line vue/max-attributes-per-line
+ 75:58 warning Attribute "v-model" should go before ":label" vue/attributes-order
+ 75:58 warning 'v-model' should be on a new line vue/max-attributes-per-line
+ 81:9 error Elements in iteration expect to have 'v-bind:key' directives vue/require-v-for-key
+ 81:50 warning 'class' should be on a new line vue/max-attributes-per-line
+ 82:1 error Expected indentation of 12 spaces but found 11 spaces vue/html-indent
+
+/home/gero/documents/uni/pse/pse-dashboard/src/components/ProgressTime.vue
+ 8:5 warning Prop 'unix' requires default value to be set vue/require-default-prop
+ 16:1 error Expected indentation of 4 spaces but found 0 spaces vue/html-indent
+
+/home/gero/documents/uni/pse/pse-dashboard/src/components/Subscription.vue
+ 1:1 error Component name "Subscription" should always be multi-word vue/multi-word-component-names
+ 6:5 warning Prop 'sub' requires default value to be set vue/require-default-prop
+ 6:5 warning Prop "sub" should define at least its type vue/require-prop-types
+ 58:14 warning Expected a linebreak before this attribute vue/first-attribute-linebreak
+ 58:52 warning 'data-bs-toggle' should be on a new line vue/max-attributes-per-line
+ 59:1 error Expected indentation of 13 spaces but found 8 spaces vue/html-indent
+ 59:39 warning Expected 1 line break before closing bracket, but no line breaks found vue/html-closing-bracket-newline
+ 61:13 warning Require self-closing on HTML elements (<i>) vue/html-self-closing
+ 61:67 warning 'style' should be on a new line vue/max-attributes-per-line
+ 63:69 warning Expected 1 line break after opening tag (`<div>`), but 2 line breaks found vue/multiline-html-element-content-newline
+ 67:38 warning Expected 1 line break after opening tag (`<h6>`), but no line breaks found vue/singleline-html-element-content-newline
+ 67:64 warning Expected 1 line break before closing tag (`</h6>`), but no line breaks found vue/singleline-html-element-content-newline
+ 77:29 warning Expected a linebreak before this attribute vue/first-attribute-linebreak
+ 78:1 error Expected indentation of 28 spaces but found 20 spaces vue/html-indent
+ 78:44 warning 'data-bs-target' should be on a new line vue/max-attributes-per-line
+ 79:1 error Expected indentation of 28 spaces but found 20 spaces vue/html-indent
+ 85:60 warning '@click' should be on a new line vue/max-attributes-per-line
+ 93:32 warning 'class' should be on a new line vue/max-attributes-per-line
+ 93:49 warning 'data-bs-parent' should be on a new line vue/max-attributes-per-line
+ 96:21 error Elements in iteration expect to have 'v-bind:key' directives vue/require-v-for-key
+
+/home/gero/documents/uni/pse/pse-dashboard/src/views/EpisodesView.vue
+ 22:29 warning Expected 1 line break after opening tag (`<h1>`), but no line breaks found vue/singleline-html-element-content-newline
+ 22:74 warning Expected 1 line break before closing tag (`</h1>`), but no line breaks found vue/singleline-html-element-content-newline
+ 24:18 warning Attribute ':waitingFor' must be hyphenated vue/attribute-hyphenation
+ 26:17 error Custom elements in iteration require 'v-bind:key' directives vue/valid-v-for
+ 26:61 warning ':action' should be on a new line vue/max-attributes-per-line
+
+/home/gero/documents/uni/pse/pse-dashboard/src/views/ForgotPasswordView.vue
+ 21:39 warning Expected 1 line break after opening tag (`<h1>`), but no line breaks found vue/singleline-html-element-content-newline
+ 21:78 warning Expected 1 line break before closing tag (`</h1>`), but no line breaks found vue/singleline-html-element-content-newline
+ 25:46 warning Attribute "v-model" should go before "type" vue/attributes-order
+ 25:46 warning 'v-model' should be on a new line vue/max-attributes-per-line
+ 25:62 warning ':label' should be on a new line vue/max-attributes-per-line
+ 28:35 warning 'class' should be on a new line vue/max-attributes-per-line
+
+/home/gero/documents/uni/pse/pse-dashboard/src/views/LoginView.vue
+ 26:39 warning Expected 1 line break after opening tag (`<h1>`), but no line breaks found vue/singleline-html-element-content-newline
+ 26:71 warning Expected 1 line break before closing tag (`</h1>`), but no line breaks found vue/singleline-html-element-content-newline
+ 28:39 warning Expected 1 line break after opening tag (`<form>`), but 2 line breaks found vue/multiline-html-element-content-newline
+ 31:62 warning Attribute "v-model" should go before ":label" vue/attributes-order
+ 31:62 warning 'v-model' should be on a new line vue/max-attributes-per-line
+ 34:57 warning Attribute "v-model" should go before ":label" vue/attributes-order
+ 34:57 warning 'v-model' should be on a new line vue/max-attributes-per-line
+ 41:52 warning 'value' should be on a new line vue/max-attributes-per-line
+ 41:72 warning Attribute "v-model" should go before "value" vue/attributes-order
+ 41:72 warning 'v-model' should be on a new line vue/max-attributes-per-line
+ 56:35 warning 'class' should be on a new line vue/max-attributes-per-line
+ 66:17 warning Expected 1 line break before closing tag (`</form>`), but 2 line breaks found vue/multiline-html-element-content-newline
+ 71:41 warning Expected 1 line break after opening tag (`<p>`), but no line breaks found vue/singleline-html-element-content-newline
+ 71:52 warning Expected 1 line break before closing tag (`</p>`), but no line breaks found vue/singleline-html-element-content-newline
+
+/home/gero/documents/uni/pse/pse-dashboard/src/views/RegistrationView.vue
+ 38:39 warning Expected 1 line break after opening tag (`<h1>`), but no line breaks found vue/singleline-html-element-content-newline
+ 38:71 warning Expected 1 line break before closing tag (`</h1>`), but no line breaks found vue/singleline-html-element-content-newline
+ 42:52 warning 'type' should be on a new line vue/max-attributes-per-line
+ 42:64 warning ':label' should be on a new line vue/max-attributes-per-line
+ 45:49 warning 'type' should be on a new line vue/max-attributes-per-line
+ 45:62 warning ':label' should be on a new line vue/max-attributes-per-line
+ 51:35 warning 'class' should be on a new line vue/max-attributes-per-line
+
+/home/gero/documents/uni/pse/pse-dashboard/src/views/ResetPasswordView.vue
+ 9:5 warning Prop 'token' requires default value to be set vue/require-default-prop
+ 10:5 warning Prop 'username' requires default value to be set vue/require-default-prop
+ 41:43 warning Expected 1 line break after opening tag (`<h1>`), but no line breaks found vue/singleline-html-element-content-newline
+ 41:77 warning Expected 1 line break before closing tag (`</h1>`), but no line breaks found vue/singleline-html-element-content-newline
+ 47:35 warning 'class' should be on a new line vue/max-attributes-per-line
+
+/home/gero/documents/uni/pse/pse-dashboard/src/views/SettingsView.vue
+ 176:29 warning Expected 1 line break after opening tag (`<h1>`), but no line breaks found vue/singleline-html-element-content-newline
+ 176:57 warning Expected 1 line break before closing tag (`</h1>`), but no line breaks found vue/singleline-html-element-content-newline
+ 179:52 warning Attribute "class" should go before "@submit.prevent" vue/attributes-order
+ 179:52 warning 'class' should be on a new line vue/max-attributes-per-line
+ 182:63 warning Attribute "v-model" should go before ":label" vue/attributes-order
+ 182:63 warning 'v-model' should be on a new line vue/max-attributes-per-line
+ 182:90 warning Expected a space before '/>', but not found vue/html-closing-bracket-spacing
+ 187:35 warning 'class' should be on a new line vue/max-attributes-per-line
+ 193:51 warning Attribute "class" should go before "@submit.prevent" vue/attributes-order
+ 193:51 warning 'class' should be on a new line vue/max-attributes-per-line
+ 196:1 error Expected indentation of 12 spaces but found 17 spaces vue/html-indent
+ 197:33 warning Expected a linebreak before this attribute vue/first-attribute-linebreak
+ 198:1 error Expected indentation of 32 spaces but found 16 spaces vue/html-indent
+ 198:17 warning Attribute "v-model" should go before ":label" vue/attributes-order
+ 198:42 warning Expected 1 line break before closing bracket, but no line breaks found vue/html-closing-bracket-newline
+ 198:42 warning Expected a space before '/>', but not found vue/html-closing-bracket-spacing
+ 200:1 error Expected indentation of 12 spaces but found 17 spaces vue/html-indent
+ 201:33 warning Expected a linebreak before this attribute vue/first-attribute-linebreak
+ 202:1 error Expected indentation of 32 spaces but found 16 spaces vue/html-indent
+ 202:17 warning Attribute "v-model" should go before ":label" vue/attributes-order
+ 202:42 warning Expected 1 line break before closing bracket, but no line breaks found vue/html-closing-bracket-newline
+ 205:57 warning Attribute "v-model" should go before ":label" vue/attributes-order
+ 205:57 warning 'v-model' should be on a new line vue/max-attributes-per-line
+ 205:82 warning Expected a space before '/>', but not found vue/html-closing-bracket-spacing
+ 207:35 warning 'class' should be on a new line vue/max-attributes-per-line
+ 215:31 warning 'class' should be on a new line vue/max-attributes-per-line
+ 218:13 warning Disallow self-closing on HTML void elements (<input/>) vue/html-self-closing
+ 218:20 warning Expected a linebreak before this attribute vue/first-attribute-linebreak
+ 218:32 warning Attribute "id" should go before "type" vue/attributes-order
+ 218:32 warning 'id' should be on a new line vue/max-attributes-per-line
+ 218:42 warning 'accept' should be on a new line vue/max-attributes-per-line
+ 218:72 warning 'hidden' should be on a new line vue/max-attributes-per-line
+ 219:1 error Expected indentation of 19 spaces but found 16 spaces vue/html-indent
+ 219:37 warning Expected 1 line break before closing bracket, but no line breaks found vue/html-closing-bracket-newline
+ 220:41 warning Attribute "class" should go before "@click" vue/attributes-order
+ 220:41 warning 'class' should be on a new line vue/max-attributes-per-line
+ 226:44 warning Attribute "class" should go before "@submit.prevent" vue/attributes-order
+ 226:44 warning 'class' should be on a new line vue/max-attributes-per-line
+ 229:57 warning Attribute "v-model" should go before ":label" vue/attributes-order
+ 229:57 warning 'v-model' should be on a new line vue/max-attributes-per-line
+ 229:81 warning Expected a space before '/>', but not found vue/html-closing-bracket-spacing
+ 231:35 warning 'class' should be on a new line vue/max-attributes-per-line
+
+/home/gero/documents/uni/pse/pse-dashboard/src/views/SubscriptionsView.vue
+ 9:5 warning Prop 'url' requires default value to be set vue/require-default-prop
+ 83:29 warning Expected 1 line break after opening tag (`<h1>`), but no line breaks found vue/singleline-html-element-content-newline
+ 83:66 warning Expected 1 line break before closing tag (`</h1>`), but no line breaks found vue/singleline-html-element-content-newline
+ 86:49 warning Attribute "class" should go before "@submit.prevent" vue/attributes-order
+ 86:49 warning 'class' should be on a new line vue/max-attributes-per-line
+ 87:72 warning Attribute "v-model" should go before ":label" vue/attributes-order
+ 87:72 warning 'v-model' should be on a new line vue/max-attributes-per-line
+ 88:45 warning 'type' should be on a new line vue/max-attributes-per-line
+ 93:18 warning Attribute ':waitingFor' must be hyphenated vue/attribute-hyphenation
+ 101:53 warning '@click' should be on a new line vue/max-attributes-per-line
+ 104:25 warning Expected a linebreak before this attribute vue/first-attribute-linebreak
+ 105:1 error Expected indentation of 24 spaces but found 16 spaces vue/html-indent
+ 106:1 error Expected indentation of 24 spaces but found 16 spaces vue/html-indent
+ 106:40 warning 'data-bs-target' should be on a new line vue/max-attributes-per-line
+ 106:69 warning Expected 1 line break before closing bracket, but no line breaks found vue/html-closing-bracket-newline
+ 111:21 error Elements in iteration expect to have 'v-bind:key' directives vue/require-v-for-key
+ 111:48 warning 'class' should be on a new line vue/max-attributes-per-line
+ 112:32 warning Expected a linebreak before this attribute vue/first-attribute-linebreak
+ 113:1 error Expected indentation of 31 spaces but found 24 spaces vue/html-indent
+ 113:41 warning ':value' should be on a new line vue/max-attributes-per-line
+ 113:54 warning Attribute "v-model" should go before ":value" vue/attributes-order
+ 113:54 warning 'v-model' should be on a new line vue/max-attributes-per-line
+ 113:84 warning Expected 1 line break before closing bracket, but no line breaks found vue/html-closing-bracket-newline
+ 114:50 warning '@unsubscribe' should be on a new line vue/max-attributes-per-line
+ 117:19 warning Expected 1 line break before closing tag (`</loading>`), but 2 line breaks found vue/multiline-html-element-content-newline
+ 123:24 warning Attribute "id" should go before "class" vue/attributes-order
+ 123:24 warning 'id' should be on a new line vue/max-attributes-per-line
+ 123:37 warning 'tabindex' should be on a new line vue/max-attributes-per-line
+ 125:40 warning Expected 1 line break after opening tag (`<div>`), but 2 line breaks found vue/multiline-html-element-content-newline
+ 132:21 warning Require self-closing on HTML elements (<button>) vue/html-self-closing
+ 132:43 warning 'class' should be on a new line vue/max-attributes-per-line
+ 132:61 warning 'data-bs-dismiss' should be on a new line vue/max-attributes-per-line
+ 132:85 warning 'aria-label' should be on a new line vue/max-attributes-per-line
+ 137:80 warning Attribute "v-model" should go before ":label" vue/attributes-order
+ 137:80 warning 'v-model' should be on a new line vue/max-attributes-per-line
+ 142:43 warning 'class' should be on a new line vue/max-attributes-per-line
+ 142:69 warning 'data-bs-dismiss' should be on a new line vue/max-attributes-per-line
+ 145:43 warning '@click' should be on a new line vue/max-attributes-per-line
+ 145:68 warning Attribute "data-bs-dismiss" should go before "@click" vue/attributes-order
+ 145:68 warning 'data-bs-dismiss' should be on a new line vue/max-attributes-per-line
+ 145:92 warning Attribute "class" should go before "@click" vue/attributes-order
+ 145:92 warning 'class' should be on a new line vue/max-attributes-per-line
+ 154:24 warning Attribute "id" should go before "class" vue/attributes-order
+ 154:24 warning 'id' should be on a new line vue/max-attributes-per-line
+ 154:41 warning 'tabindex' should be on a new line vue/max-attributes-per-line
+ 156:40 warning Expected 1 line break after opening tag (`<div>`), but 2 line breaks found vue/multiline-html-element-content-newline
+ 163:21 warning Require self-closing on HTML elements (<button>) vue/html-self-closing
+ 163:43 warning 'class' should be on a new line vue/max-attributes-per-line
+ 163:61 warning 'data-bs-dismiss' should be on a new line vue/max-attributes-per-line
+ 163:85 warning 'aria-label' should be on a new line vue/max-attributes-per-line
+ 168:80 warning 'role' should be on a new line vue/max-attributes-per-line
+ 169:25 warning Require self-closing on HTML elements (<i>) vue/html-self-closing
+ 176:25 error Elements in iteration expect to have 'v-bind:key' directives vue/require-v-for-key
+ 177:52 warning Expected 1 space before '}}', but not found vue/mustache-interpolation-spacing
+ 187:43 warning 'class' should be on a new line vue/max-attributes-per-line
+ 187:69 warning 'data-bs-dismiss' should be on a new line vue/max-attributes-per-line
+ 190:43 warning '@click' should be on a new line vue/max-attributes-per-line
+ 190:76 warning Attribute "data-bs-dismiss" should go before "@click" vue/attributes-order
+ 190:76 warning 'data-bs-dismiss' should be on a new line vue/max-attributes-per-line
+ 190:100 warning Attribute "class" should go before "@click" vue/attributes-order
+ 190:100 warning 'class' should be on a new line vue/max-attributes-per-line
+
+✖ 310 problems (56 errors, 254 warnings)
+ 43 errors and 194 warnings potentially fixable with the `--fix` option.
+
diff --git a/31-qualitaetsheft-kolloquium/assets/subscription.png b/31-qualitaetsheft-kolloquium/assets/subscription.png
new file mode 100644
index 0000000..58a84f9
--- /dev/null
+++ b/31-qualitaetsheft-kolloquium/assets/subscription.png
Binary files differ
diff --git a/31-qualitaetsheft-kolloquium/logos/banner_2020_kit.jpg b/31-qualitaetsheft-kolloquium/logos/banner_2020_kit.jpg
new file mode 100644
index 0000000..70ae1d0
--- /dev/null
+++ b/31-qualitaetsheft-kolloquium/logos/banner_2020_kit.jpg
Binary files differ
diff --git a/31-qualitaetsheft-kolloquium/logos/kitlogo_de_rgb.pdf b/31-qualitaetsheft-kolloquium/logos/kitlogo_de_rgb.pdf
new file mode 100644
index 0000000..ce31797
--- /dev/null
+++ b/31-qualitaetsheft-kolloquium/logos/kitlogo_de_rgb.pdf
Binary files differ
diff --git a/31-qualitaetsheft-kolloquium/logos/kitlogo_en_rgb.pdf b/31-qualitaetsheft-kolloquium/logos/kitlogo_en_rgb.pdf
new file mode 100644
index 0000000..dd59fa6
--- /dev/null
+++ b/31-qualitaetsheft-kolloquium/logos/kitlogo_en_rgb.pdf
Binary files differ
diff --git a/31-qualitaetsheft-kolloquium/logos/pse_logo.pdf b/31-qualitaetsheft-kolloquium/logos/pse_logo.pdf
new file mode 100644
index 0000000..91fd334
--- /dev/null
+++ b/31-qualitaetsheft-kolloquium/logos/pse_logo.pdf
Binary files differ
diff --git a/31-qualitaetsheft-kolloquium/notizen b/31-qualitaetsheft-kolloquium/notizen
new file mode 100644
index 0000000..70ac63b
--- /dev/null
+++ b/31-qualitaetsheft-kolloquium/notizen
@@ -0,0 +1,40 @@
+Titelseite:
+- Begrüßung
+
+Einführung:
+- Podcast: RSS-Feed, Episoden, Audio/Video
+- Podcatcher: lokale Verwaltung von Podcasts, API Unterstützung,
+Abspielen von Episoden
+- Synchronisationsserver (das soll unser Produkt werden): Hörfortschritte,
+Abonnements, Discovery (bei AntennaPod z.B. iTunes)
+
+Zielsetzung:
+
+Synchronisation (die Art, die wir bei uns anwenden):
+- alle Aktionen werden auf den Server und infolge dessen auf alle Podcatcher
+übertragen
+
+Features:
+- Synchronisation: Abos, Hörfortschritt
+- Weboberfläche: Aboliste, Zuletzt gehört
+- Account-Verwaltung: Registrieren, Anmelden, Passwort ändern/zurücksetzen,
+Account löschen, Daten importieren/exportieren
+
+UI-Journey:
+- login.html:
+ - Sprache ändern
+ - OAuth (kann)
+ - Registrieren (muss): neues Fenster, E-Mail + 2-mal Passwort (sicher?),
+ vergeben? -> Fehler / Bestätigungslink per E-Mail (gültig 24h)
+ - Anmelden (muss): E-Mail + Passwort eingeben, Login merken,
+ login, Fehlermeldung oder Dashboard
+ - Passwort vergessen: neues Fenster, E-Mail eingeben, falls Account wird
+ Link versendet, 24h gültig, nach betätigen PW zweimal eingeben & bestätigen
+ (Anforderungen)
+
+- podcasts.html: Abonnements, Eisoden, Hörfortschritte
+
+- listening.html: Zuletzt gehörte Episoden, Hörfortschritt, Wann gehört
+
+- settings.html: PW ändern, Gpodder Import, pers. Daten imp./exp.,
+ Account löschen
diff --git a/31-qualitaetsheft-kolloquium/presentation.tex b/31-qualitaetsheft-kolloquium/presentation.tex
new file mode 100644
index 0000000..8e198fb
--- /dev/null
+++ b/31-qualitaetsheft-kolloquium/presentation.tex
@@ -0,0 +1,62 @@
+%% Beispiel-Präsentation mit LaTeX Beamer im KIT-Design
+%% entsprechend den Gestaltungsrichtlinien vom 1. August 2020
+%%
+%% Siehe https://sdqweb.ipd.kit.edu/wiki/Dokumentvorlagen
+
+%% Beispiel-Präsentation
+\documentclass[table]{sdqbeamer}
+
+\usepackage{calc}
+\usepackage{multicol}
+\usepackage{fontawesome}
+\usepackage{ulem}
+\usepackage{pgfplots, pgfplotstable}
+\usepackage{tabularx}
+\usepgfplotslibrary{dateplot}
+\pgfplotsset{compat=newest}
+
+%% Titelbild
+\titleimage{banner_2020_kit}
+
+%% Gruppenlogo
+\grouplogo{kitlogo_de_rgb}
+
+%% Gruppenname und Breite (Standard: 50 mm)
+\groupname{Praxis der Softwareentwicklung}
+%\groupnamewidth{50mm}
+
+% Beginn der Präsentation
+
+\title[Kolloquium Qualitätssicherung]{
+ PSE\textsuperscript{2} - Podcast Synchronisation made Efficient
+}
+\subtitle{Kolloquium Qualitätssicherung}
+\author[Daniel Hönlinger]{Daniel Hönlinger}
+
+\date[23.\,03.\,2023]{23. März 2023}
+
+\begin{document}
+
+%Titelseite
+\KITtitleframe
+
+% Änderungen zum Pflichtenheft
+\include{slides/changes}
+
+% Testfälle aus dem Pflichtenheft
+\include{slides/testing}
+
+% Codeabdeckung
+\include{slides/coverage}
+
+% Lasttests
+\include{slides/performance}
+
+% Probleme
+\include{slides/problems}
+
+% Codestil
+\include{slides/codestyle}
+
+
+\end{document}
diff --git a/31-qualitaetsheft-kolloquium/sdqbeamer.cls b/31-qualitaetsheft-kolloquium/sdqbeamer.cls
new file mode 100644
index 0000000..1b9c2b8
--- /dev/null
+++ b/31-qualitaetsheft-kolloquium/sdqbeamer.cls
@@ -0,0 +1,975 @@
+%% Vorlage für Präsentationen mit LaTeX Beamer im KIT-Design
+%% entsprechend den Gestaltungsrichtlinien vom 1. August 2020
+%%
+%% Siehe https://sdqweb.ipd.kit.edu/wiki/Dokumentvorlagen
+
+
+\NeedsTeXFormat{LaTeX2e}
+\ProvidesClass{sdqbeamer}[2022-05-03 v3.1.3 SDQ Beamer class]
+
+\RequirePackage[utf8]{inputenc}
+\RequirePackage[T1]{fontenc}
+
+\newif\ifsectionnavigation
+\newif\ifnavbarinfoot
+\newif\ifnavbarinline
+\newif\ifnavbarside
+\newif\iffourtothree
+\newif\ifsixteentonine
+\newif\ifsixteentoten
+\newif\ifgerman
+\newif\ifsmallfooterfont
+
+\def\kitslogan#1{\def\@kitslogan{#1}}
+\def\kitlogo#1{\def\@kitlogo{#1}}
+\def\groupname#1{\def\@groupname{#1}}
+\def\groupnamewidth#1{\def\@groupnamewidth{#1}}
+
+% siehe README.md
+\DeclareOption{de}{
+ \kitslogan{KIT -- Die Forschungsuniversität in der Helmholtz-Gemeinschaft}
+ \kitlogo{pse_logo}
+ \germantrue
+ \PassOptionsToPackage{autostyle}{csquotes}
+ }
+\DeclareOption{en}{
+ \kitslogan{KIT -- The Research University in the Helmholtz Association}
+ \kitlogo{kitlogo_en_rgb}
+ \germanfalse
+ }
+\DeclareOption{4:3}{
+ \fourtothreetrue
+ \sixteentoninefalse
+ \sixteentotenfalse
+}
+\DeclareOption{16:9}{
+ \fourtothreefalse
+ \sixteentoninetrue
+ \sixteentotenfalse
+}
+\DeclareOption{16:10}{
+ \fourtothreefalse
+ \sixteentoninefalse
+ \sixteentotentrue
+}
+\DeclareOption{navbarside}{
+ \sectionnavigationtrue
+ \navbarsidetrue
+ \navbarinlinefalse
+ \navbarinfootfalse
+}
+\DeclareOption{navbarinline}{
+ \sectionnavigationtrue
+ \navbarsidefalse
+ \navbarinlinetrue
+ \navbarinfootfalse
+}
+\DeclareOption{navbarinfooter}{
+ \sectionnavigationtrue
+ \navbarsidefalse
+ \navbarinlinefalse
+ \navbarinfoottrue
+}
+\DeclareOption{navbaroff}{
+ \sectionnavigationfalse
+}
+\DeclareOption{navbarkit}{
+ \sectionnavigationfalse
+ \smallfooterfonttrue
+}
+\DeclareOption{smallfoot}{
+ \smallfooterfonttrue
+}
+\DeclareOption{bigfoot}{
+ \smallfooterfontfalse
+}
+
+\ExecuteOptions{de,16:9,navbarinline,bigfoot}
+
+\DeclareOption*{\PassOptionsToClass{\CurrentOption}{beamer}}
+
+\ProcessOptions\relax
+
+\LoadClass[10pt,utf8]{beamer}
+
+% Babel-Paket wird nur bei deutscher Sprache benötigt
+\ifgerman
+ \RequirePackage[ngerman]{babel}
+\fi
+\RequirePackage{csquotes}
+\RequirePackage{hyperref}
+\RequirePackage[absolute,overlay]{textpos}
+
+%% ---------------
+%% | Typographie |
+%% ---------------
+
+\RequirePackage{microtype}
+
+\RequirePackage[scaled=.92]{helvet}
+\RequirePackage[scaled=.78]{beramono}
+\RequirePackage{libertineRoman}
+
+\setbeamerfont{title}{series=\bfseries,size=\Large}
+\setbeamerfont{frametitle}{series=\bfseries,size=\Large}
+\setbeamerfont{framesubtitle}{series=\bfseries,size=\normalsize}
+
+%% -----------------
+%% | Folien-Layout |
+%% -----------------
+
+% Seitenverhältnis
+%
+% Die Folien sind auf die Standardhöhe in LaTeX Beamer (9,6 cm) normiert.
+% Die Maße der KIT-Gestaltungsrichtlinien (Folienhöhe 14,3 cm) wurden durch
+% den Quotienten 1,5 geteilt.
+
+\RequirePackage{geometry}
+\iffourtothree
+ \geometry{papersize={12.8cm,9.6cm}}
+\fi
+\ifsixteentoten
+ \geometry{papersize={15.36cm,9.6cm}}
+\fi
+\ifsixteentonine
+ \geometry{papersize={17.07cm,9.6cm}}
+\fi
+
+% Ränder laut Gestaltungsrichtlinen; 3 mm -> 2 mm, 11 mm -> 7,3 mm
+\newlength{\kitoutermargin}
+\setlength{\kitoutermargin}{2mm}
+\newlength{\kitinnermargin}
+\setlength{\kitinnermargin}{7.3mm}
+\newlength{\kitbottommargin}
+\setlength{\kitbottommargin}{\kitinnermargin}
+
+% Ränder außen
+\setbeamersize{text margin left=\kitinnermargin,text margin right=\kitinnermargin}
+
+% keine Navigationssymbole
+\setbeamertemplate{navigation symbols}{}
+\setbeamercovered{invisible}
+\useinnertheme{rounded}
+\beamer@compresstrue % Miniframes (Navigations-Punkte) für Subsections immer in einer Zeile, ohne Umbrüche
+
+% Folientitel
+\setbeamertemplate{frametitle}{
+ \ifbeamer@plainframe\else%
+ % Unterkante Titeltext: 22,5 mm -> 15 mm von Seitenkopf
+ \begin{textblock*}{\dimexpr\paperwidth-30mm-2\kitinnermargin}[0,1](\kitinnermargin,15mm)%
+ \usebeamerfont{frametitle}\insertframetitle%
+ \ifx\insertframesubtitle\@empty\else\\[.1em]\fi
+ \usebeamerfont{framesubtitle}\insertframesubtitle%
+ \end{textblock*}%
+ \begin{textblock*}{20mm}[1,1](\dimexpr\paperwidth-\kitinnermargin\relax,15mm)%j
+ \includegraphics[width=20mm]{logos/\@kitlogo}%
+ \end{textblock*}%
+ \fi
+% Rand oben (ergibt Beginn des Textes bei 34 mm -> 22,7 mm)
+ \vspace {18mm}
+}
+
+%% Fußzeile
+\newlength{\kitbottom}
+ % Navbar in Footer: Schmale Fußzeile
+\ifnavbarinfoot
+ % Bei Navbar in Footer immer kleiner Font in der Fußzeile
+ \setbeamerfont{footer}{size=\fontsize{6pt}{7.2pt}\selectfont}
+ \setlength{\kitbottom}{4mm}
+\else
+ % Ansonsten kleiner Text nur, wenn "smallfoot" gewählt
+ \ifsmallfooterfont
+ \setbeamerfont{footer}{size=\fontsize{6pt}{7.2pt}\selectfont}
+ \else
+ \setbeamerfont{footer}{size=\scriptsize}
+ \fi
+ \setlength{\kitbottom}{\kitbottommargin}
+\fi
+\setbeamerfont{page number in head/foot}{series=\bfseries}
+
+\newlength{\kitbottomdepth}
+\newlength{\kitbottomheight}
+\newlength{\kitfootergroupwidth}
+
+\setbeamertemplate{footline}{%
+\setlength{\kitbottomdepth}{\dimexpr.5\kitbottom-.5em\relax}%
+\setlength{\kitbottomheight}{\dimexpr.5\kitbottom+.5em\relax}%
+ %% die "%" am Ende sind nötig, damit keine Abstände eingefügt werden
+ %
+ % Falls kein Gruppenname angegeben, die ganze Breite der Fußzeile für den Titel nutzen.
+ \ifdefined\@groupname%
+ \ifx\@groupname\empty%
+ \setlength{\kitfootergroupwidth}{0mm}%
+ \else%
+ % Falls die Breite des Gruppenlogos definiert ist, diese nehmen, sonst 50 mm
+ \ifdefined\@groupnamewidth%
+ \setlength{\kitfootergroupwidth}{\@groupnamewidth}%
+ \else%
+ \setlength{\kitfootergroupwidth}{50mm}%
+ \fi%
+ \fi%
+ \else
+ \setlength{\kitfootergroupwidth}{0mm}%
+ \fi
+ \usebeamerfont{footer}%
+ \ifsectionnavigation%
+ % Option "navbarinline"
+ \ifnavbarinline%
+ \begin{beamercolorbox}[wd=\paperwidth, leftskip=2mm, rightskip=2mm]{}
+ \insertnavigation{\dimexpr\paperwidth-4mm\relax}
+ \vspace{1mm}
+ \end{beamercolorbox}%
+ \fi%
+ % Option "navbarinfooter"
+ \ifnavbarinfoot%
+ % Punkte für Subsections deaktivieren
+ \setbeamertemplate{mini frames}{}%
+ \begin{beamercolorbox}[wd=\paperwidth, leftskip=1mm, rightskip=1mm]{}%
+ \insertsectionnavigationhorizontal{\dimexpr\paperwidth-\kitoutermargin\relax}{}{}
+ \end{beamercolorbox}%
+ \fi%
+ \fi%
+ \leavevmode%
+ \begin{beamercolorbox}[wd=13mm, ht=\kitbottomheight, dp=\kitbottomdepth, leftskip=4mm]{}
+ \usebeamerfont{page number in head/foot}%
+ \strut\insertframenumber{}/\inserttotalframenumber%
+ \end{beamercolorbox}%
+ \begin{beamercolorbox}[wd=20mm, ht=\kitbottomheight, dp=\kitbottomdepth]{}
+ \usebeamerfont{date in head/foot}%
+ \strut\insertshortdate%
+ \end{beamercolorbox}%
+ % Die Boxen mit dem Titel und dem Gruppennamen sind vertikal zentriert, damit auch zweizeilige Texte schön aussehen
+ % Daher müssen sie um \kitbottomdepth nach unten verschoben werden
+ \raisebox{-\kitbottomdepth}{
+ % Die Box hat daher auch Höhe \kitbottom und Tiefe 0mm
+ \begin{beamercolorbox}[wd=\dimexpr\paperwidth-37mm-\kitfootergroupwidth, ht=\kitbottom, dp=0mm]{}%
+ % Inhalt vertikal zentrieren; Anpassung um 1.5 pt, damit bei einzeiligem Inhalt genau die Baseline der Blöcke mit Seitenzahl und Datum getroffen wird
+ \vbox to\kitbottom{\vfill\vskip1.5pt%
+ \beamer@shortauthor\ifx\beamer@shortauthor\empty\else: \fi\beamer@shorttitle%
+ \vfill}%
+ \end{beamercolorbox}%
+ \ifdefined\@groupname%
+ \begin{beamercolorbox}[wd=\kitfootergroupwidth, ht=\kitbottom, dp=0mm, rightskip=\kitinnermargin]{}
+ \vbox to\kitbottom{\vfill\vskip1.5pt%
+ \raggedleft\@groupname%
+ \vfill}%
+ \end{beamercolorbox}%
+ \fi%
+ }%
+}
+
+%% Option "navbarside"
+\ifnavbarside
+\useoutertheme[height=0cm,width=3.5cm,left]{sidebar}
+
+\setbeamerfont{title in sidebar}{family=\sffamily,series=\mdseries,size={\fontsize{10pt}{11pt}}}
+\setbeamerfont{section in sidebar}{family=\sffamily,series=\mdseries,size={\fontsize{9pt}{9.9pt}}}
+\setbeamerfont{subsection in sidebar}{family=\sffamily,series=\mdseries,size={\fontsize{8pt}{8.8pt}}}
+
+\setbeamertemplate{sidebar \beamer@sidebarside}
+ {\vskip1.5cm%
+ \hskip6.5mm%
+ \advance\beamer@sidebarwidth by -5mm%
+ \insertverticalnavigation{\beamer@sidebarwidth}%
+ }%
+\fi
+
+%% Hintergrund
+\usebackgroundtemplate{
+ % Trennlinie nicht bei "plain"-Frames
+ \ifbeamer@plainframe\else\kitseparationline\fi
+}
+
+% Trennlinie
+\newcommand{\kitseparationline}{
+ \begin{pgfpicture}{0mm}{0mm}{\paperwidth}{\paperheight}
+ \pgfsetstrokecolor{black!15}
+ \pgfsetlinewidth{.5pt}
+ \pgfpathmoveto{\pgfpoint{\kitoutermargin}{\kitinnermargin}}
+ \pgfpathlineto{\pgfpoint{\paperwidth-\kitoutermargin}{\kitinnermargin}}
+ \pgfusepath{stroke}
+ \end{pgfpicture}%
+}
+
+
+%% --------------
+%% | Titelseite |
+%% --------------
+
+\def\titleimage#1{\def\@titleimage{#1}}
+\def\grouplogo#1{\def\@grouplogo{#1}}
+
+\newcommand{\KITtitleframe}{
+ \begin{frame}[plain]
+ \titlepage
+ \end{frame}
+}
+
+\newlength{\kittitleimageheight}
+\setbeamertemplate{title page}{
+ % From textpos documentation (https://ctan.org/pkg/textpos)
+ %
+ % \begin{textblock}{<hsize>}[<ho>,<vo>](<hpos>,<vpos>)
+ % The coordinates <ho> and <vo> are fractions of the width and height of the text
+ % box, respectively, and state that the box is to be placed so that the reference point
+ % (<ho>,<vo>) within the box is to be placed at the point (<hpos>,<vpos>) on the page.
+
+ % KIT-Logo
+ \begin{textblock*}{30mm}(\kitinnermargin,6.7mm)
+ \includegraphics[width=30mm]{logos/\@kitlogo}
+ \end{textblock*}
+
+ % Gruppenlogo
+ \ifdefined\@grouplogo
+ \ifx\@grouplogo\empty \else
+ \begin{textblock*}{20mm}(\dimexpr\paperwidth-24mm\relax,6.7mm)
+ \includegraphics[width=20mm,height=20mm,keepaspectratio]{logos/\@grouplogo}
+ \end{textblock*}
+ \fi % falls \grouplogo{} aufgerufen wird, kein Gruppenlogo einbinden
+ \else
+ \begin{textblock*}{20mm}(\dimexpr\paperwidth-24mm\relax,6.7mm)
+ \colorbox{kit-purple100!20}{\parbox[t][12mm][c]{19mm}{\color{kit-purple100}\scriptsize\centering
+ \ifgerman
+ Bitte Logo über \texttt{\textbackslash grouplogo\{\}} festlegen.
+ \else
+ Please set a logo using \texttt{\textbackslash grouplogo\{\}}.
+ \fi
+ }}
+ \end{textblock*}
+ \fi
+
+ % Titel
+ \begin{textblock*}{\dimexpr\paperwidth-8mm\relax}[0,.5](\kitinnermargin,28mm)
+ \usebeamerfont*{title}\inserttitle
+ \end{textblock*}
+
+ % Untertitel
+ \begin{textblock*}{\dimexpr\paperwidth-8mm\relax}(\kitinnermargin,36mm)
+ \small\textbf{\insertsubtitle}
+ \end{textblock*}
+
+ % Autor
+ \begin{textblock*}{\dimexpr\paperwidth-8mm\relax}(\kitinnermargin,41mm)
+ \small\insertauthor~\textbar~\insertdate
+ \end{textblock*}
+
+ % Titelbild
+ \setlength{\kittitleimageheight}{40mm}
+ \begin{textblock*}{\paperwidth}(\kitoutermargin,\dimexpr\paperheight-\kitbottommargin-\kittitleimageheight)
+ \begin{pgfpicture}{0mm}{0mm}{\paperwidth}{\kittitleimageheight}
+ % Clipping-Pfad um titelbild
+ \pgfsetstrokecolor{black!15}
+ \pgfsetlinewidth{1pt}
+ \pgfsetcornersarced{\pgfpoint{3mm}{3mm}}
+ \pgfpathmoveto{\pgfpoint{\paperwidth-2\kitoutermargin}{0mm}}
+ \pgfpathlineto{\pgfpoint{\paperwidth-2\kitoutermargin}{\kittitleimageheight}}
+ \pgfsetcornersarced{\pgfpointorigin}
+ \pgfpathlineto{\pgfpoint{0mm}{\kittitleimageheight}}
+ \pgfsetcornersarced{\pgfpoint{3mm}{3mm}}
+ \pgfpathlineto{\pgfpointorigin}
+ \pgfsetcornersarced{\pgfpointorigin}
+ \pgfpathclose
+ \pgfusepath{stroke,clip}
+ \pgfsetstrokecolor{black}
+
+ % Titelbild
+ \ifdefined\@titleimage
+ \ifx\@titleimage\empty \else%
+ \pgftext[at=\pgfpoint{.5\paperwidth}{0mm},center,bottom]{%
+ \includegraphics[height=40mm]{logos/\@titleimage}
+ }
+ \fi % Bei Aufruf von \titleimage{} leeren Rahmen anzeigen.
+ \else
+ \pgftext[at=\pgfpoint{.5\paperwidth}{.5\kittitleimageheight},center,base]{%
+ \colorbox{kit-purple100!20}{\parbox[c][\kittitleimageheight][c]{\paperwidth}{\color{kit-purple100}\centering Bitte Titelbild über \texttt{\textbackslash titleimage\{\}} festlegen.
+ }}%
+ }
+ \fi
+
+
+ \end{pgfpicture}%
+ \end{textblock*}
+
+
+ % KIT slogan
+ \begin{textblock*}{80mm}[0,.5](\kitoutermargin,\dimexpr\paperheight-.5\kitbottommargin)
+ \fontsize{5.5pt}{5.5pt}\selectfont\@kitslogan
+ \end{textblock*}
+
+ \begin{textblock*}{30mm}[1,.5](\dimexpr\paperwidth-\kitoutermargin\relax,\dimexpr\paperheight-.5\kitbottommargin)
+ \fontsize{11pt}{11pt}\selectfont\bfseries\raggedleft%
+ {\href{https://www.kit.edu}{www.kit.edu}}
+ \end{textblock*}
+
+}
+%% ---------------
+%% | /Titelseite |
+%% ---------------
+
+%% ----------
+%% | Farben |
+%% ----------
+%% KIT-Farbschema
+
+% KIT color green :
+\definecolor{kit-green}{RGB}{0, 150, 130}
+\definecolor{kit-green100}{RGB}{0, 150, 130}
+\definecolor{kit-green90}{rgb}{0.1, 0.6294, 0.5588}
+\definecolor{kit-green80}{rgb}{0.2, 0.6706, 0.6078}
+\definecolor{kit-green75}{rgb}{0.25, 0.6912, 0.6324}
+\definecolor{kit-green70}{rgb}{0.3, 0.7118, 0.6569}
+\definecolor{kit-green60}{rgb}{0.4, 0.7529, 0.7059}
+\definecolor{kit-green50}{rgb}{0.5, 0.7941, 0.7549}
+\definecolor{kit-green40}{rgb}{0.6, 0.8353, 0.8039}
+\definecolor{kit-green30}{rgb}{0.7, 0.8765, 0.8529}
+\definecolor{kit-green25}{rgb}{0.75, 0.8971, 0.8775}
+\definecolor{kit-green20}{rgb}{0.8, 0.9176, 0.902}
+\definecolor{kit-green15}{rgb}{0.85, 0.9382, 0.9265}
+\definecolor{kit-green10}{rgb}{0.9, 0.9588, 0.951}
+\definecolor{kit-green5}{rgb}{0.95, 0.9794, 0.9755}
+
+% KIT color blue:
+\definecolor{kit-blue}{RGB}{70, 100, 170}
+\definecolor{kit-blue100}{RGB}{70, 100, 170}
+\definecolor{kit-blue90}{rgb}{0.3471, 0.4529, 0.7}
+\definecolor{kit-blue80}{rgb}{0.4196, 0.5137, 0.7333}
+\definecolor{kit-blue75}{rgb}{0.4559, 0.5441, 0.75}
+\definecolor{kit-blue70}{rgb}{0.4922, 0.5745, 0.7667}
+\definecolor{kit-blue60}{rgb}{0.5647, 0.6353, 0.8}
+\definecolor{kit-blue50}{rgb}{0.6373, 0.6961, 0.8333}
+\definecolor{kit-blue40}{rgb}{0.7098, 0.7569, 0.8667}
+\definecolor{kit-blue30}{rgb}{0.7824, 0.8176, 0.9}
+\definecolor{kit-blue25}{rgb}{0.8186, 0.848, 0.9167}
+\definecolor{kit-blue20}{rgb}{0.8549, 0.8784, 0.9333}
+\definecolor{kit-blue15}{rgb}{0.8912, 0.9088, 0.95}
+\definecolor{kit-blue10}{rgb}{0.9275, 0.9392, 0.9667}
+\definecolor{kit-blue5}{rgb}{0.9637, 0.9696, 0.9833}
+
+% KIT color red :
+\definecolor{kit-red}{RGB}{162, 34, 35}
+\definecolor{kit-red100}{RGB}{162, 34, 35}
+\definecolor{kit-red90}{rgb}{0.6718, 0.22, 0.2235}
+\definecolor{kit-red80}{rgb}{0.7082, 0.3067, 0.3098}
+\definecolor{kit-red75}{rgb}{0.7265, 0.35, 0.3529}
+\definecolor{kit-red70}{rgb}{0.7447, 0.3933, 0.3961}
+\definecolor{kit-red60}{rgb}{0.7812, 0.48, 0.4824}
+\definecolor{kit-red50}{rgb}{0.8176, 0.5667, 0.5686}
+\definecolor{kit-red40}{rgb}{0.8541, 0.6533, 0.6549}
+\definecolor{kit-red30}{rgb}{0.8906, 0.74, 0.7412}
+\definecolor{kit-red25}{rgb}{0.9088, 0.7833, 0.7843}
+\definecolor{kit-red20}{rgb}{0.9271, 0.8267, 0.8275}
+\definecolor{kit-red15}{rgb}{0.9453, 0.87, 0.8706}
+\definecolor{kit-red10}{rgb}{0.9635, 0.9133, 0.9137}
+\definecolor{kit-red5}{rgb}{0.9818, 0.9567, 0.9569}
+
+% KIT color yellow :
+\definecolor{kit-yellow}{RGB}{252, 229, 0}
+\definecolor{kit-yellow100}{RGB}{252, 229, 0}
+\definecolor{kit-yellow90}{rgb}{0.9894, 0.9082, 0.1}
+\definecolor{kit-yellow80}{rgb}{0.9906, 0.9184, 0.2}
+\definecolor{kit-yellow75}{rgb}{0.9912, 0.9235, 0.25}
+\definecolor{kit-yellow70}{rgb}{0.9918, 0.9286, 0.3}
+\definecolor{kit-yellow60}{rgb}{0.9929, 0.9388, 0.4}
+\definecolor{kit-yellow50}{rgb}{0.9941, 0.949, 0.5}
+\definecolor{kit-yellow40}{rgb}{0.9953, 0.9592, 0.6}
+\definecolor{kit-yellow30}{rgb}{0.9965, 0.9694, 0.7}
+\definecolor{kit-yellow25}{rgb}{0.9971, 0.9745, 0.75}
+\definecolor{kit-yellow20}{rgb}{0.9976, 0.9796, 0.8}
+\definecolor{kit-yellow15}{rgb}{0.9982, 0.9847, 0.85}
+\definecolor{kit-yellow10}{rgb}{0.9988, 0.9898, 0.9}
+\definecolor{kit-yellow5}{rgb}{0.9994, 0.9949, 0.95}
+
+% KIT color orange :
+\definecolor{kit-orange}{RGB}{223, 155, 27}
+\definecolor{kit-orange100}{RGB}{223, 155, 27}
+\definecolor{kit-orange90}{rgb}{0.8871, 0.6471, 0.1953}
+\definecolor{kit-orange80}{rgb}{0.8996, 0.6863, 0.2847}
+\definecolor{kit-orange75}{rgb}{0.9059, 0.7059, 0.3294}
+\definecolor{kit-orange70}{rgb}{0.9122, 0.7255, 0.3741}
+\definecolor{kit-orange60}{rgb}{0.9247, 0.7647, 0.4635}
+\definecolor{kit-orange50}{rgb}{0.9373, 0.8039, 0.5529}
+\definecolor{kit-orange40}{rgb}{0.9498, 0.8431, 0.6424}
+\definecolor{kit-orange30}{rgb}{0.9624, 0.8824, 0.7318}
+\definecolor{kit-orange25}{rgb}{0.9686, 0.902, 0.7765}
+\definecolor{kit-orange20}{rgb}{0.9749, 0.9216, 0.8212}
+\definecolor{kit-orange15}{rgb}{0.9812, 0.9412, 0.8659}
+\definecolor{kit-orange10}{rgb}{0.9875, 0.9608, 0.9106}
+\definecolor{kit-orange5}{rgb}{0.9937, 0.9804, 0.9553}
+
+% KIT color lightgreen :
+\definecolor{kit-lightgreen}{RGB}{140, 182, 60}
+\definecolor{kit-lightgreen100}{RGB}{140, 182, 60}
+\definecolor{kit-lightgreen90}{rgb}{0.5941, 0.7424, 0.3118}
+\definecolor{kit-lightgreen80}{rgb}{0.6392, 0.771, 0.3882}
+\definecolor{kit-lightgreen75}{rgb}{0.6618, 0.7853, 0.4265}
+\definecolor{kit-lightgreen70}{rgb}{0.6843, 0.7996, 0.4647}
+\definecolor{kit-lightgreen60}{rgb}{0.7294, 0.8282, 0.5412}
+\definecolor{kit-lightgreen50}{rgb}{0.7745, 0.8569, 0.6176}
+\definecolor{kit-lightgreen40}{rgb}{0.8196, 0.8855, 0.6941}
+\definecolor{kit-lightgreen30}{rgb}{0.8647, 0.9141, 0.7706}
+\definecolor{kit-lightgreen25}{rgb}{0.8873, 0.9284, 0.8088}
+\definecolor{kit-lightgreen20}{rgb}{0.9098, 0.9427, 0.8471}
+\definecolor{kit-lightgreen15}{rgb}{0.9324, 0.9571, 0.8853}
+\definecolor{kit-lightgreen10}{rgb}{0.9549, 0.9714, 0.9235}
+\definecolor{kit-lightgreen5}{rgb}{0.9775, 0.9857, 0.9618}
+
+
+% KIT color purple :
+\definecolor{kit-purple}{RGB}{163, 16, 124}
+\definecolor{kit-purple100}{RGB}{163, 16, 124}
+\definecolor{kit-purple90}{rgb}{0.6753, 0.1565, 0.5376}
+\definecolor{kit-purple80}{rgb}{0.7114, 0.2502, 0.589}
+\definecolor{kit-purple75}{rgb}{0.7294, 0.2971, 0.6147}
+\definecolor{kit-purple70}{rgb}{0.7475, 0.3439, 0.6404}
+\definecolor{kit-purple60}{rgb}{0.7835, 0.4376, 0.6918}
+\definecolor{kit-purple50}{rgb}{0.8196, 0.5314, 0.7431}
+\definecolor{kit-purple40}{rgb}{0.8557, 0.6251, 0.7945}
+\definecolor{kit-purple30}{rgb}{0.8918, 0.7188, 0.8459}
+\definecolor{kit-purple25}{rgb}{0.9098, 0.7657, 0.8716}
+\definecolor{kit-purple20}{rgb}{0.9278, 0.8125, 0.8973}
+\definecolor{kit-purple15}{rgb}{0.9459, 0.8594, 0.9229}
+\definecolor{kit-purple10}{rgb}{0.9639, 0.9063, 0.9486}
+\definecolor{kit-purple5}{rgb}{0.982, 0.9531, 0.9743}
+
+% KIT color brown :
+\definecolor{kit-brown}{RGB}{167, 130, 46}
+\definecolor{kit-brown100}{RGB}{167, 130, 46}
+\definecolor{kit-brown90}{rgb}{0.6894, 0.5588, 0.2624}
+\definecolor{kit-brown80}{rgb}{0.7239, 0.6078, 0.3443}
+\definecolor{kit-brown75}{rgb}{0.7412, 0.6324, 0.3853}
+\definecolor{kit-brown70}{rgb}{0.7584, 0.6569, 0.4263}
+\definecolor{kit-brown60}{rgb}{0.7929, 0.7059, 0.5082}
+\definecolor{kit-brown50}{rgb}{0.8275, 0.7549, 0.5902}
+\definecolor{kit-brown40}{rgb}{0.862, 0.8039, 0.6722}
+\definecolor{kit-brown30}{rgb}{0.8965, 0.8529, 0.7541}
+\definecolor{kit-brown25}{rgb}{0.9137, 0.8775, 0.7951}
+\definecolor{kit-brown20}{rgb}{0.931, 0.902, 0.8361}
+\definecolor{kit-brown15}{rgb}{0.9482, 0.9265, 0.8771}
+\definecolor{kit-brown10}{rgb}{0.9655, 0.951, 0.918}
+\definecolor{kit-brown5}{rgb}{0.9827, 0.9755, 0.959}
+
+% KIT color cyan :
+\definecolor{kit-cyan}{RGB}{35, 161, 224}
+\definecolor{kit-cyan100}{RGB}{35, 161, 224}
+\definecolor{kit-cyan90}{rgb}{0.2235, 0.6682, 0.8906}
+\definecolor{kit-cyan80}{rgb}{0.3098, 0.7051, 0.9027}
+\definecolor{kit-cyan75}{rgb}{0.3529, 0.7235, 0.9088}
+\definecolor{kit-cyan70}{rgb}{0.3961, 0.742, 0.9149}
+\definecolor{kit-cyan60}{rgb}{0.4824, 0.7788, 0.9271}
+\definecolor{kit-cyan50}{rgb}{0.5686, 0.8157, 0.9392}
+\definecolor{kit-cyan40}{rgb}{0.6549, 0.8525, 0.9514}
+\definecolor{kit-cyan30}{rgb}{0.7412, 0.8894, 0.9635}
+\definecolor{kit-cyan25}{rgb}{0.7843, 0.9078, 0.9696}
+\definecolor{kit-cyan20}{rgb}{0.8275, 0.9263, 0.9757}
+\definecolor{kit-cyan15}{rgb}{0.8706, 0.9447, 0.9818}
+\definecolor{kit-cyan10}{rgb}{0.9137, 0.9631, 0.9878}
+\definecolor{kit-cyan5}{rgb}{0.9569, 0.9816, 0.9939}
+
+% KIT color gray :
+\definecolor{kit-gray}{RGB}{0, 0, 0}
+\definecolor{kit-gray100}{RGB}{0, 0, 0}
+\definecolor{kit-gray90}{rgb}{0.1, 0.1, 0.1}
+\definecolor{kit-gray80}{rgb}{0.2, 0.2, 0.2}
+\definecolor{kit-gray75}{rgb}{0.25, 0.25, 0.25}
+\definecolor{kit-gray70}{rgb}{0.3, 0.3, 0.3}
+\definecolor{kit-gray60}{rgb}{0.4, 0.4, 0.4}
+\definecolor{kit-gray50}{rgb}{0.5, 0.5, 0.5}
+\definecolor{kit-gray40}{rgb}{0.6, 0.6, 0.6}
+\definecolor{kit-gray30}{rgb}{0.7, 0.7, 0.7}
+\definecolor{kit-gray25}{rgb}{0.75, 0.75, 0.75}
+\definecolor{kit-gray20}{rgb}{0.8, 0.8, 0.8}
+\definecolor{kit-gray15}{rgb}{0.85, 0.85, 0.85}
+\definecolor{kit-gray10}{rgb}{0.9, 0.9, 0.9}
+\definecolor{kit-gray5}{rgb}{0.95, 0.95, 0.95}
+
+
+
+\setbeamercolor*{normal text}{fg=black}
+\setbeamercolor*{alerted text}{fg=kit-red100}
+\setbeamercolor*{example text}{fg=black}
+\setbeamercolor*{structure}{fg=black}
+
+\setbeamercolor*{palette primary}{fg=black,bg=black!15}
+\setbeamercolor*{palette secondary}{fg=black,bg=black!15}
+\setbeamercolor*{palette tertiary}{fg=black,bg=black!15}
+\setbeamercolor*{palette quaternary}{fg=black,bg=black!15}
+
+\setbeamercolor*{palette sidebar primary}{fg=black!75}
+\setbeamercolor*{palette sidebar secondary}{fg=black!75}
+\setbeamercolor*{palette sidebar tertiary}{fg=black!75}
+\setbeamercolor*{palette sidebar quaternary}{fg=black!75}
+
+\setbeamercolor*{item projected}{fg=white,bg=kit-green100}
+
+\setbeamercolor*{block title}{fg=white,bg=kit-green100}
+\setbeamercolor*{block title alerted}{use=alerted text,fg=white,bg=alerted text.fg!75!black}
+\setbeamercolor*{block title example}{fg=white,bg=kit-blue100}
+
+\setbeamercolor*{block body}{fg=black,bg=kit-green15}
+\setbeamercolor*{block body alerted}{parent=normal text,use=block title alerted,bg=block title alerted.bg!10!bg}
+\setbeamercolor*{block body example}{fg=black,bg=kit-blue15}
+
+\setbeamercolor*{separation line}{}
+\setbeamercolor*{fine separation line}{}
+
+\setbeamercolor*{background canvas}{bg=white}
+
+%% -----------
+%% | /Farben |
+%% -----------
+
+%% -----------------------------------
+%% | halbgerundete Aufzählungspunkte |
+%% -----------------------------------
+
+\newcommand{\itemizeColor}{kit-green100}
+
+% KIT-Aufzählungszeichen
+\newcommand{\KITmark}{%
+ \begin{pgfpicture}{0mm}{0mm}{1ex}{1ex}
+ {\pgfsetcornersarced{\pgfpoint{.3ex}{.3ex}}
+ \pgfpathmoveto{\pgfpoint{0cm}{1ex}}
+ \pgfpathlineto{\pgfpoint{1ex}{1ex}}
+ \pgfpathlineto{\pgfpoint{1ex}{0cm}}}
+ {\pgfsetcornersarced{\pgfpoint{.3ex}{.3ex}}
+ \pgfpathmoveto{\pgfpoint{1ex}{0cm}}
+ \pgfpathlineto{\pgfpointorigin}
+ \pgfpathlineto{\pgfpoint{0cm}{1ex}}}
+ \color{\itemizeColor}
+ \pgfusepath{fill}
+ \end{pgfpicture}%
+}
+
+% \setbeamertemplate{itemize items}{\raisebox{.2ex}{\KITmark}}
+\setbeamertemplate{itemize items}[square]
+\setbeamercolor{itemize item}{fg=kit-green100}
+
+%% ----------------------
+%% | Inhaltsverzeichnis |
+%% ----------------------
+
+\setbeamertemplate{section in toc}{\normalsize\textbf{\textcolor{kit-blue}{\inserttocsectionnumber.~\inserttocsection}}\par}
+\setbeamertemplate{subsection in toc}{\small\hspace{1.2em}\raisebox{.2ex}{\KITmark}\hspace{\labelsep}\inserttocsubsection\par}
+
+%% ------------------------------
+%% | halbgerundete Beamer-Boxen |
+%% ------------------------------
+
+\renewcommand\beamerboxesrounded[2][]{%
+ \global\let\beamer@firstlineitemizeunskip=\relax%
+ \vbox\bgroup%
+ \setkeys{beamerboxes}{upper=block title,lower=block body,width=\textwidth,shadow=false}%
+ \setkeys{beamerboxes}{#1}%
+ {%
+ \usebeamercolor{\bmb@lower}%
+ \globalcolorstrue%
+ \colorlet{lower.bg}{bg}%
+ }%
+ {%
+ \usebeamercolor{\bmb@upper}%
+ \globalcolorstrue%
+ \colorlet{upper.bg}{bg}%
+ }%
+ %
+ % Typeset head
+ %
+ \vskip4bp
+ \setbox\bmb@box=\hbox{%
+ \begin{minipage}[b]{\bmb@width}%
+ \usebeamercolor[fg]{\bmb@upper}%
+ #2%
+ \end{minipage}}%
+ \ifdim\wd\bmb@box=0pt%
+ \setbox\bmb@box=\hbox{}%
+ \ht\bmb@box=1.5pt%
+ \bmb@prevheight=-4.5pt%
+ \else%
+ \wd\bmb@box=\bmb@width%
+ \bmb@temp=\dp\bmb@box%
+ \ifdim\bmb@temp<1.5pt%
+ \bmb@temp=1.5pt%
+ \fi%
+ \setbox\bmb@box=\hbox{\raise\bmb@temp\hbox{\box\bmb@box}}%
+ \dp\bmb@box=0pt%
+ \bmb@prevheight=\ht\bmb@box%
+ \fi%
+ \bmb@temp=\bmb@width%
+ \bmb@dima=\bmb@temp\advance\bmb@dima by2.2bp%
+ \bmb@dimb=\bmb@temp\advance\bmb@dimb by4bp%
+ \hbox{%
+ \begin{pgfpicture}{0bp}{+-\ht\bmb@box}{0bp}{+-\ht\bmb@box}
+ \ifdim\wd\bmb@box=0pt%
+ \color{lower.bg}%
+ \else%
+ \color{upper.bg}%
+ \fi%
+ \pgfpathqmoveto{-4bp}{-1bp}
+ % Adaption for "KIT-Design"
+ \pgfpathlineto{\pgfpoint{-4bp}{3bp}}
+ %\pgfpathqcurveto{-4bp}{1.2bp}{-2.2bp}{3bp}{0bp}{3bp}
+ \pgfpathlineto{\pgfpoint{\bmb@temp}{3bp}}
+ \pgfpathcurveto%
+ {\pgfpoint{\bmb@dima}{3bp}}%
+ {\pgfpoint{\bmb@dimb}{1.2bp}}%
+ {\pgfpoint{\bmb@dimb}{-1bp}}%
+ \bmb@dima=-\ht\bmb@box%
+ \advance\bmb@dima by-2pt%
+ \pgfpathlineto{\pgfpoint{\bmb@dimb}{\bmb@dima}}
+ \pgfpathlineto{\pgfpoint{-4bp}{\bmb@dima}}
+ \pgfusepath{fill}
+ \end{pgfpicture}%
+ \copy\bmb@box%
+ }%
+ \nointerlineskip%
+ \vskip-1pt%
+ \ifdim\wd\bmb@box=0pt%
+ \else%
+ \hbox{%
+ \begin{pgfpicture}{0pt}{0pt}{\bmb@width}{6pt}
+ \bmb@dima=\bmb@width%
+ \advance\bmb@dima by8bp%
+ \pgfpathrectangle{\pgfpoint{-4bp}{-1bp}}{\pgfpoint{\bmb@dima}{8bp}}
+ \pgfusepath{clip}
+ {\pgftransformshift{\pgfpoint{-4bp}{0bp}}\pgftext[left,base]{\pgfuseshading{bmb@transition}}}%
+ \end{pgfpicture}%
+ }%
+ \nointerlineskip%
+ \vskip-0.5pt%
+ \fi%
+ \ifbmb@shadow%
+ \setbox\bmb@boxshadow=\hbox{\pgfuseshading{bmb@shadow}}%
+ \setbox\bmb@boxshadowball=\hbox{\pgfuseshading{bmb@shadowball}}%
+ \setbox\bmb@boxshadowballlarge=\hbox{\pgfuseshading{bmb@shadowballlarge}}%
+ \fi%
+ \setbox\bmb@colorbox=\hbox{{\pgfpicturetrue\pgfsetcolor{lower.bg}}}%
+ \setbox\bmb@box=\hbox\bgroup\begin{minipage}[b]{\bmb@width}%
+ \vskip2pt%
+ \usebeamercolor[fg]{\bmb@lower}%
+ \colorlet{beamerstructure}{upper.bg}%
+ \colorlet{structure}{upper.bg}%
+ %\color{.}%
+ }
+
+\def\endbeamerboxesrounded{%
+ \end{minipage}\egroup%
+ \wd\bmb@box=\bmb@width%
+ \bmb@temp=\dp\bmb@box%
+ \advance\bmb@temp by.5pt%
+ \setbox\bmb@box=\hbox{\raise\bmb@temp\hbox{\box\bmb@box}}%
+ \dp\bmb@box=0pt%
+ \bmb@temp=\wd\bmb@box%
+ \bmb@dima=\bmb@temp\advance\bmb@dima by2.2bp%
+ \bmb@dimb=\bmb@temp\advance\bmb@dimb by4bp%
+ \hbox{%
+ \begin{pgfpicture}{0bp}{0bp}{0bp}{0bp}
+ \ifbmb@shadow%
+ {\pgftransformshift{\pgfpoint{4bp}{-3bp}}\pgftext{\copy\bmb@boxshadowball}}
+ \begin{pgfscope}
+ {%
+ \advance\bmb@temp by-1bp%
+ \pgfpathrectangle{\pgfpoint{\bmb@temp}{-7bp}}{\pgfpoint{9bp}{9bp}}%
+ \pgfusepath{clip}
+ }%
+ {\pgftransformshift{\pgfpoint{\bmb@temp}{1bp}}\pgftext{\box\bmb@boxshadowballlarge}}
+ \end{pgfscope}
+ \begin{pgfscope}
+ \advance\bmb@temp by-4bp%
+ \pgfpathrectangle{\pgfpoint{4bp}{-7bp}}{\pgfpoint{\bmb@temp}{5bp}}
+ \pgfusepath{clip}
+ {\pgftransformshift{\pgfpoint{4bp}{-7bp}}\pgftext[left,base]{\copy\bmb@boxshadow}}%
+ \end{pgfscope}
+ \begin{pgfscope}
+ \advance\bmb@temp by 4bp%
+ \bmb@dima=\ht\bmb@box%
+ \advance\bmb@dima by\bmb@prevheight%
+ \advance\bmb@dima by 4bp%
+ \pgfpathrectangle{\pgfpoint{\bmb@temp}{1bp}}{\pgfpoint{4bp}{\bmb@dima}}
+ \pgfusepath{clip}
+ \advance\bmb@dima by-4bp%
+ {\pgftransformshift{\pgfpoint{\bmb@temp}{\bmb@dima}}\pgftext{\box\bmb@boxshadowball}}
+ \advance\bmb@dima by-1bp%
+ \pgfpathrectangle{\pgfpoint{\bmb@temp}{1bp}}{\pgfpoint{4bp}{\bmb@dima}}
+ \pgfusepath{clip}
+ \advance\bmb@temp by4bp%
+ {\pgftransformshift{\pgfpoint{\bmb@temp}{-3bp}}%
+ \pgftransformrotate{90}%
+ \pgftext[left,base]{\box\bmb@boxshadow}}%
+ \end{pgfscope}
+ \fi%
+ \unhbox\bmb@colorbox%
+ \pgfpathqmoveto{-4bp}{1bp}
+ \pgfpathqcurveto{-4bp}{-1.2bp}{-2.2bp}{-3bp}{0bp}{-3bp}
+ \pgfpathlineto{\pgfpoint{\the\bmb@dimb}{-3bp}}
+ {
+ \bmb@dima=\ht\bmb@box%
+ \pgfpathlineto{\pgfpoint{\bmb@dimb}{\bmb@dima}}
+ \pgfpathlineto{\pgfpoint{-4bp}{\bmb@dima}}
+ \pgfusepath{fill}
+ }
+ \ifbmb@shadow%
+ {
+ \color{black!50!bg}
+ \pgfsetlinewidth{0pt}
+ \pgfpathmoveto{\pgfpoint{\bmb@dimb}{-.5bp}}
+ \bmb@dima=\ht\bmb@box%
+ \advance\bmb@dima by\bmb@prevheight%
+ \advance\bmb@dima by 1bp%
+ \pgfpathlineto{\pgfpoint{\bmb@dimb}{\bmb@dima}}
+ \pgfusepath{stroke}
+ \bmb@temp=\bmb@dima
+ \advance\bmb@dima by 1bp%
+ \color{black!31!bg}
+ \pgfpathmoveto{\pgfpoint{\bmb@dimb}{\bmb@temp}}
+ \pgfpathlineto{\pgfpoint{\bmb@dimb}{\bmb@dima}}
+ \pgfusepath{stroke}
+ \advance\bmb@dima by 1bp%
+ \advance\bmb@temp by 1bp%
+ \color{black!19!bg}
+ \pgfpathmoveto{\pgfpoint{\bmb@dimb}{\bmb@temp}}
+ \pgfpathlineto{\pgfpoint{\bmb@dimb}{\bmb@dima}}
+ \pgfusepath{stroke}
+ \advance\bmb@dima by 1bp%
+ \advance\bmb@temp by 1bp%
+ \color{black!6!bg}
+ \pgfpathmoveto{\pgfpoint{\bmb@dimb}{\bmb@temp}}
+ \pgfpathlineto{\pgfpoint{\bmb@dimb}{\bmb@dima}}
+ \pgfusepath{stroke}
+ \advance\bmb@dima by 1.5bp%
+ \advance\bmb@temp by 1bp%
+ \color{bg}
+ \pgfpathmoveto{\pgfpoint{\bmb@dimb}{\bmb@temp}}
+ \pgfpathlineto{\pgfpoint{\bmb@dimb}{\bmb@dima}}
+ \pgfusepath{stroke}
+ }
+ \fi
+ \end{pgfpicture}%
+ \box\bmb@box%
+ }%
+ \ifbmb@shadow%
+ \vskip4bp minus 2bp%
+ \else%
+ \vskip2bp%
+ \fi%
+ \egroup% of \vbox\bgroup
+}
+
+
+%% -------------------------------
+%% | /halbgerundete Beamer-Boxen |
+%% -------------------------------
+
+
+%% ----------------------
+%% | Block-Definitionen |
+%% ----------------------
+
+% Content environment for structuring. Basically a headline followed by text
+\newenvironment<>{contentblock}[1]{\begingroup%
+ \setbeamertemplate{blocks}[default]
+ \setbeamercolor{block body}{fg=black,bg=}%
+ \setbeamercolor{block title}{fg=black,bg=}%
+ \setbeamerfont*{block title}{family=\sffamily,series=\bfseries,size=\large}
+ \begin{block}#2{#1}%
+ }{\end{block}%
+\endgroup}
+
+
+\newenvironment<>{greenblock}[1]{\begingroup%
+ \setbeamercolor{block body}{fg=black,bg=kit-green15}%
+ \setbeamercolor{block title}{fg=white,bg=kit-green100}%
+ \begin{block}#2{#1}%
+ }{\end{block}
+\endgroup}
+
+\newenvironment<>{blueblock}[1]{\begingroup%
+ \setbeamercolor{block body}{fg=black,bg=kit-blue15}%
+ \setbeamercolor{block title}{fg=white,bg=kit-blue100}%
+ \setbeamercolor{itemize item}{fg=kit-blue100}
+ \begin{block}#2{#1}%
+ }{\end{block}
+\endgroup}
+
+\newenvironment<>{redblock}[1]{\begingroup%
+ \setbeamercolor{block body}{fg=black,bg=kit-red15}%
+ \setbeamercolor{block title}{fg=white,bg=kit-red100}%
+ \setbeamercolor{itemize item}{fg=kit-red100}%
+ \begin{block}#2{#1}%
+ }{\end{block}%
+\endgroup}
+
+\newenvironment<>{brownblock}[1]{\begingroup%
+ \setbeamercolor{block body}{fg=black,bg=kit-brown15}%
+ \setbeamercolor{block title}{fg=white,bg=kit-brown100}%
+ \setbeamercolor{itemize item}{fg=kit-brown100}%
+ \begin{block}#2{#1}%
+ }{\end{block}%
+\endgroup}
+
+\newenvironment<>{purpleblock}[1]{\begingroup%
+ \setbeamercolor{block body}{fg=black,bg=kit-purple15}%
+ \setbeamercolor{block title}{fg=white,bg=kit-purple100}%
+ \setbeamercolor{itemize item}{fg=kit-purple100}%
+ \begin{block}#2{#1}%
+ }{\end{block}%
+\endgroup}
+
+\newenvironment<>{grayblock}[1]{\begingroup%
+ \setbeamercolor{block body}{fg=black,bg=kit-gray15}%
+ \setbeamercolor{block title}{fg=white,bg=kit-gray70}%
+ \setbeamercolor{itemize item}{fg=kit-gray70}%
+ \begin{block}#2{#1}%
+ }{\end{block}%
+\endgroup}
+
+\newenvironment<>{yellowblock}[1]{\begingroup%
+ \setbeamercolor{block body}{fg=black,bg=kit-yellow30}%
+ \setbeamercolor{block title}{fg=black,bg=kit-yellow100}%
+ \setbeamercolor{itemize item}{fg=kit-yellow100}%
+ \begin{block}#2{#1}%
+ }{\end{block}%
+\endgroup}
+
+\newenvironment<>{lightgreenblock}[1]{\begingroup%
+ \setbeamercolor{block body}{fg=black,bg=kit-lightgreen15}%
+ \setbeamercolor{block title}{fg=white,bg=kit-lightgreen100}%
+ \setbeamercolor{itemize item}{fg=kit-lightgreen100}%
+ \begin{block}#2{#1}%
+ }{\end{block}%
+\endgroup}
+
+\newenvironment<>{orangeblock}[1]{\begingroup%
+ \setbeamercolor{block body}{fg=black,bg=kit-orange15}%
+ \setbeamercolor{block title}{fg=white,bg=kit-orange100}%
+ \setbeamercolor{itemize item}{fg=kit-orange100}%
+ \begin{block}#2{#1}%
+ }{\end{block}%
+\endgroup}
+
+\newenvironment<>{cyanblock}[1]{\begingroup%
+ \setbeamercolor{block body}{fg=black,bg=kit-cyan15}%
+ \setbeamercolor{block title}{fg=white,bg=kit-cyan100}%
+ \setbeamercolor{itemize item}{fg=kit-cyan100}%
+ \begin{block}#2{#1}%
+ }{\end{block}%
+\endgroup}
+
+\newenvironment<>{maroonblock}[1]{\begingroup%
+\setbeamercolor{block body}{fg=black,bg=Maroon!15}%
+\setbeamercolor{block title}{fg=white,bg=Maroon}%
+ \setbeamercolor{itemize item}{fg=Maroon}%
+\begin{block}#2{#1}%
+}{\end{block}%
+\endgroup}
+%% ------------------------------
+%% | /Block-Definitionen |
+%% ------------------------------
+
+%% use this for setting the total page number
+\newcommand{\beginbackup}{
+ \newcounter{framenumbervorappendix}
+ \setcounter{framenumbervorappendix}{\value{framenumber}}
+}
+\newcommand{\backupend}{
+ \addtocounter{framenumbervorappendix}{-\value{framenumber}}
+ \addtocounter{framenumber}{\value{framenumbervorappendix}}
+}
diff --git a/31-qualitaetsheft-kolloquium/slides/changes.tex b/31-qualitaetsheft-kolloquium/slides/changes.tex
new file mode 100644
index 0000000..e90113a
--- /dev/null
+++ b/31-qualitaetsheft-kolloquium/slides/changes.tex
@@ -0,0 +1,146 @@
+\begin{frame}{Änderungen zur Implementierung}
+
+%\vspace{-.4cm}
+%\begin{orangeblock}{Kompatibilität}
+% \begin{minipage}{1.7cm}
+% \centering
+% \fontsize{23pt}{0pt}
+% \selectfont
+% \textcolor{orange}
+% \faPlug
+% \end{minipage}
+% \hspace{-.5cm}
+% \begin{minipage}{.7\textwidth}
+% \begin{itemize}
+% \item Benutzernamen und E-Mail-Adresse speichern
+% \item Device API
+% \end{itemize}
+% \end{minipage}
+%\end{orangeblock}
+%
+%\begin{greenblock}{E-Mail-Verifizierung}
+% \begin{minipage}{1.7cm}
+% \centering
+% \fontsize{23pt}{0pt}
+% \selectfont
+% \textcolor{kit-green}
+% \faUserCheck
+% \end{minipage}
+% \hspace{-.5cm}
+% \begin{minipage}{.7\textwidth}
+% \begin{itemize}
+% \item Neuer Endpunkt zur Verifizierung der E-Mail-Adresse
+% \item Anmelden nur mit bestätigter E-Mail-Adresse
+% \end{itemize}
+% \end{minipage}
+%\end{greenblock}
+%
+%\begin{blueblock}{RSS Parser}
+% \begin{minipage}{1.7cm}
+% \centering
+% \fontsize{23pt}{0pt}
+% \selectfont
+% \textcolor{kit-blue}
+% \faRssSquare
+% \end{minipage}
+% \hspace{-.5cm}
+% \begin{minipage}{.7\textwidth}
+% \begin{itemize}
+% \item Asynchroner RSS Parser nach \enquote{Fire and Forget} Prinzip
+% \item Speichern/Löschen über Referenzen in DAO-Schicht
+% \end{itemize}
+% \end{minipage}
+%\end{blueblock}
+%
+%\begin{redblock}{Datenzugriffsschicht}
+% \begin{minipage}{1.7cm}
+% \centering
+% \fontsize{23pt}{0pt}
+% \selectfont
+% \textcolor{kit-red}
+% \faDatabase
+% \end{minipage}
+% \hspace{-.5cm}
+% \begin{minipage}{.7\textwidth}
+% \begin{itemize}
+% \item \sout{DAO-Implementierungen} (JPA-Repository)
+% \end{itemize}
+% \end{minipage}
+%\end{redblock}
+
+%
+% Original
+%
+%\begin{itemize}
+% \item Kompatibilität mit Podcatchern \begin{itemize}
+% \item Speicherung von Benutzernamen und E-Mail-Adressen
+% \item Device API
+% \end{itemize}
+% \item Verifizierung der E-Mail-Adresse
+% \item RSSParser
+% \item Reduzierte Datenzugriffsschicht
+%\end{itemize}
+
+%
+% Konzept
+%
+%\begin{itemize}
+% \item Neu erfüllte Kriterien \begin{itemize}
+% \item 50 Anfragen / Sekunde (bedingt)
+% \item Abonnements in Weboberfläche deabonnieren
+% \end{itemize}
+% \item Aussagekräftige Benachrichtigungen im Frontend
+%\end{itemize}
+
+\begin{orangeblock}{Performance}
+ \begin{minipage}{1.7cm}
+ \centering
+ \fontsize{23pt}{0pt}
+ \selectfont
+ \textcolor{orange}
+ \faTachometer
+ \end{minipage}
+ \hspace{-.5cm}
+ \begin{minipage}{.7\textwidth}
+ \begin{itemize}
+ \item 50 Anfragen / Sekunde bedingt möglich
+ \item Die Systemanforderungen für dieses Kriterium liegen über den Mindestanforderungen
+ \end{itemize}
+ \end{minipage}
+\end{orangeblock}
+
+\begin{redblock}{Deabonnieren in der Weboberfläche}
+ \begin{minipage}{1.7cm}
+ \centering
+ \fontsize{23pt}{0pt}
+ \selectfont
+ \textcolor{kit-red}
+ \faMinusCircle
+ \end{minipage}
+ \hspace{-.5cm}
+ \begin{minipage}{.7\textwidth}
+ \begin{itemize}
+ \item Deabonnieren von Podcasts im Dashboard nun möglich
+ \item Über Checkboxen auch mehrere auf einmal deabonnieren
+ \end{itemize}
+ \end{minipage}
+\end{redblock}
+
+\begin{blueblock}{Aussagekräftige Benachrichtigungen im Frontend}
+ \begin{minipage}{1.7cm}
+ \centering
+ \fontsize{23pt}{0pt}
+ \selectfont
+ \textcolor{kit-blue}
+ \faExclamationCircle
+ \end{minipage}
+ \hspace{-.5cm}
+ \begin{minipage}{.7\textwidth}
+ \begin{itemize}
+ \item Fehlermeldungen sind nun verständlicher
+ \item Erfolgreiche Aktionen werden Nutzer über Meldungen mitgeteilt
+ \end{itemize}
+ \end{minipage}
+\end{blueblock}
+
+\end{frame}
diff --git a/31-qualitaetsheft-kolloquium/slides/classdiagram.tex b/31-qualitaetsheft-kolloquium/slides/classdiagram.tex
new file mode 100644
index 0000000..3186a53
--- /dev/null
+++ b/31-qualitaetsheft-kolloquium/slides/classdiagram.tex
@@ -0,0 +1,36 @@
+\begin{frame}[t]{Einführung}
+ \centering
+ \includegraphics[width=\textwidth]{assets/diagrams/classdiagram}
+\end{frame}
+
+% sub
+% episode
+% auth
+% model
+% util
+
+\begin{frame}[t]{Subscriptions-API}
+ \centering
+ \includegraphics[width=\textwidth]{assets/diagrams/classdiagram-subscriptions}
+\end{frame}
+
+\begin{frame}[t]{EpisodeActions-API}
+ \centering
+ \includegraphics[width=\textwidth]{assets/diagrams/classdiagram-episode-actions}
+\end{frame}
+
+\begin{frame}[t]{Authentication-API}
+ \centering
+ \includegraphics[width=.75\textwidth]{assets/diagrams/classdiagram-authentication}
+\end{frame}
+
+\begin{frame}[t]{Model-Paket}
+ \centering
+ \includegraphics[width=\textwidth]{assets/diagrams/classdiagram-model}
+\end{frame}
+
+\begin{frame}[t]{Util-Paket}
+ \centering
+ \includegraphics[width=\textwidth]{assets/diagrams/classdiagram-util}
+\end{frame}
+
diff --git a/31-qualitaetsheft-kolloquium/slides/codestyle.tex b/31-qualitaetsheft-kolloquium/slides/codestyle.tex
new file mode 100644
index 0000000..5c82885
--- /dev/null
+++ b/31-qualitaetsheft-kolloquium/slides/codestyle.tex
@@ -0,0 +1,179 @@
+\definecolor{error00}{RGB}{255, 0, 0}
+\definecolor{error01}{RGB}{204, 0, 0}
+\definecolor{error02}{RGB}{153, 0, 0}
+\definecolor{error03}{RGB}{102, 0, 0}
+\definecolor{error04}{RGB}{51, 0, 0}
+\definecolor{error05}{RGB}{25, 0, 0}
+
+\definecolor{warning00}{RGB}{255, 255, 0}
+\definecolor{warning01}{RGB}{255, 215, 0}
+\definecolor{warning02}{RGB}{139, 117, 0}
+\definecolor{warning03}{RGB}{238, 201, 0}
+\definecolor{warning04}{RGB}{255, 215, 0}
+\definecolor{warning05}{RGB}{238, 238, 0}
+\definecolor{warning06}{RGB}{139, 139, 0}
+\definecolor{warning07}{RGB}{255, 255, 0}
+\definecolor{warning08}{RGB}{238, 201, 0}
+\definecolor{warning09}{RGB}{205, 173, 0}
+\definecolor{warning10}{RGB}{205, 205, 0}
+\definecolor{warning11}{RGB}{205, 173, 0}
+\definecolor{warning12}{RGB}{238, 238, 0}
+\definecolor{warning13}{RGB}{139, 117, 0}
+\definecolor{warning14}{RGB}{139, 139, 0}
+
+\begin{frame}{Codestil: Server}
+% Balkendiagram:
+% zwei Balken: vorher, nachher
+% eine Balken besteht aus verschiedenen Ebenen für jeden Linter Fehler
+
+\vspace{-.7cm}
+\begin{multicols}{2}
+\hspace{-0.5cm}
+\begin{tikzpicture}
+\begin{axis}[
+ title={Code-Stil-Anmerkungen durch Checkstyle Sun-Checks},
+ title style={align=left, at={(.45,1)}},
+ ybar stacked, ymin=0,
+ bar width=10mm,
+ symbolic x coords={Vorher,Nachher},
+ xtick=data,
+ xticklabel style={text width=2cm,align=center},
+ nodes near coords={}
+]
+
+\addplot [fill=error02] coordinates { ({Vorher}, 285 ) ({Nachher}, 0)}; % (sizes) LineLength
+\addplot [fill=error00] coordinates { ({Vorher}, 143 ) ({Nachher}, 0)}; % (misc) FinalParameters
+\addplot [fill=error03] coordinates { ({Vorher}, 101 ) ({Nachher}, 0)}; % (javadoc) JavadocVariable
+\addplot [fill=error04] coordinates { ({Vorher}, 83 ) ({Nachher}, 0)}; % (javadoc) JavadocStyle
+\addplot [fill=error02] coordinates { ({Vorher}, 43 ) ({Nachher}, 0)}; % (design) DesignForExtension
+\addplot [fill=error01] coordinates { ({Vorher}, 39 ) ({Nachher}, 0)}; % (javadoc) MissingJavadocMethod
+\addplot [fill=error01] coordinates { ({Vorher}, 26 ) ({Nachher}, 0)}; % (regexp) RegexpSingleline
+\addplot [fill=error02] coordinates { ({Vorher}, 15 ) ({Nachher}, 0)}; % (whitespace) WhitespaceAround
+\addplot [fill=error01] coordinates { ({Vorher}, 13 ) ({Nachher}, 0)}; % (javadoc) JavadocPackage
+\addplot [fill=error03] coordinates { ({Vorher}, 10 ) ({Nachher}, 0)}; % (whitespace) OperatorWrap
+\addplot [fill=error00] coordinates { ({Vorher}, 10 ) ({Nachher}, 0)}; % (javadoc) JavadocType
+\addplot [fill=error05] coordinates { ({Vorher}, 7 ) ({Nachher}, 0)}; % (imports) AvoidStarImport
+\addplot [fill=error05] coordinates { ({Vorher}, 6 ) ({Nachher}, 0)}; % (coding) MagicNumber
+\addplot [fill=error05] coordinates { ({Vorher}, 4 ) ({Nachher}, 0)}; % (javadoc) JavadocMethod
+\addplot [fill=error04] coordinates { ({Vorher}, 3 ) ({Nachher}, 0)}; % (coding) HiddenField
+\addplot [fill=error02] coordinates { ({Vorher}, 2 ) ({Nachher}, 0)}; % (javadoc) InvalidJavadocPosition
+\addplot [fill=error00] coordinates { ({Vorher}, 2 ) ({Nachher}, 0)}; % (blocks) RightCurly
+\addplot [fill=error03] coordinates { ({Vorher}, 1 ) ({Nachher}, 0)}; % (whitespace) WhitespaceAfter
+\addplot [fill=error04] coordinates { ({Vorher}, 1 ) ({Nachher}, 0)}; % (whitespace) FileTabCharacter
+\addplot [fill=error04] coordinates { ({Vorher}, 1 ) ({Nachher}, 0)}; % (misc) NewlineAtEndOfFile
+\addplot [fill=error01] coordinates { ({Vorher}, 1 ) ({Nachher}, 0)}; % (misc) ArrayTypeStyle
+\addplot [fill=error00] coordinates { ({Vorher}, 1 ) ({Nachher}, 0)}; % (imports) UnusedImports
+\addplot [fill=error03, point meta=y,nodes near coords,nodes near coords align={anchor=south}] coordinates { ({Vorher}, 2 ) ({Nachher}, 1)}; % (design) HideUtilityClassConstructor
+
+\end{axis}
+\end{tikzpicture}
+
+\small
+\renewcommand{\arraystretch}{0.8}
+\begin{tabularx}{.5\textwidth}{X | c | c}
+ Regel & Vorher & Nacher \\ \hline
+ sizes: LineLength & 285 & 0 \\
+ misc: FinalParameters & 143 & 0 \\
+ javadoc: JavadocVariable & 101 & 0 \\
+ javadoc: JavadocStyle & 83 & 0 \\
+ design: DesignForExtension & 43 & 0 \\
+ javadoc: MissingJavadocMethod & 39 & 0 \\
+ regexp: RegexpSingleline & 26 & 0 \\
+ whitespace: WhitespaceAround & 15 & 0 \\
+ javadoc: JavadocPackage & 13 & 0 \\
+ whitespace: OperatorWrap & 10 & 0 \\
+ javadoc: JavadocType & 10 & 0 \\
+ imports: AvoidStarImport & 7 & 0 \\
+ coding: MagicNumber & 6 & 0 \\
+ javadoc: JavadocMethod & 4 & 0 \\
+ coding: HiddenField & 3 & 0 \\
+ javadoc: InvalidJavadocPosition & 2 & 0 \\
+ blocks: RightCurly & 2 & 0 \\
+ whitespace: WhitespaceAfter & 1 & 0 \\
+ whitespace: FileTabCharacter & 1 & 0 \\
+ misc: NewlineAtEndOfFile & 1 & 0 \\
+ misc: ArrayTypeStyle & 1 & 0 \\
+ imports: UnusedImports & 1 & 0 \\
+ design: HideUtilityClassConstructor & 2 & 1 \\
+\end{tabularx}
+\end{multicols}
+
+\end{frame}
+
+
+\begin{frame}{Codestil: Dashboard}
+% Balkendiagram:
+% zwei Balken: vorher, nachher
+% eine Balken besteht aus verschiedenen Ebenen für jeden Linter Fehler
+
+\vspace{-.7cm}
+\begin{multicols}{2}
+\hspace{-0.5cm}
+\begin{tikzpicture}
+\begin{axis}[
+ title={Code-Stil-Anmerkungen durch ESLint},
+ title style={align=left, at={(.3,1)}},
+ ybar stacked, ymin=0,
+ bar width=10mm,
+ symbolic x coords={Vorher,Nachher},
+ xtick=data,
+ xticklabel style={text width=2cm,align=center},
+ nodes near coords={},
+ legend style={draw=none}
+]
+
+\addplot [fill=error00] coordinates { ({Vorher}, 26 ) ({Nachher}, 0)}; % error vue/html-indent
+\addplot [fill=error01] coordinates { ({Vorher}, 17 ) ({Nachher}, 0)}; % error vue/script-indent
+\addplot [fill=error02] coordinates { ({Vorher}, 6 ) ({Nachher}, 0)}; % error vue/require-v-for-key
+\addplot [fill=error03] coordinates { ({Vorher}, 5 ) ({Nachher}, 0)}; % error vue/multi-word-component-names
+\addplot [fill=error04] coordinates { ({Vorher}, 1 ) ({Nachher}, 0)}; % error vue/valid-v-for
+\addplot [fill=error05] coordinates { ({Vorher}, 1 ) ({Nachher}, 0)}; % error vue/valid-template-root
+\addplot [fill=warning00] coordinates { ({Vorher}, 125 ) ({Nachher}, 0)}; % warning vue/max-attributes-per-line
+\addplot [fill=warning01] coordinates { ({Vorher}, 34 ) ({Nachher}, 0)}; % warning vue/attributes-order
+\addplot [fill=warning02] coordinates { ({Vorher}, 26 ) ({Nachher}, 0)}; % warning vue/singleline-html-element-content-newline
+\addplot [fill=warning03] coordinates { ({Vorher}, 12 ) ({Nachher}, 0)}; % warning vue/require-default-prop
+\addplot [fill=warning04] coordinates { ({Vorher}, 12 ) ({Nachher}, 0)}; % warning vue/html-self-closing
+\addplot [fill=warning05] coordinates { ({Vorher}, 11 ) ({Nachher}, 0)}; % warning vue/first-attribute-linebreak
+\addplot [fill=warning06] coordinates { ({Vorher}, 10 ) ({Nachher}, 0)}; % warning vue/html-closing-bracket-newline
+\addplot [fill=warning07] coordinates { ({Vorher}, 8 ) ({Nachher}, 0)}; % warning vue/multiline-html-element-content-newline
+\addplot [fill=warning08] coordinates { ({Vorher}, 5 ) ({Nachher}, 0)}; % warning vue/html-closing-bracket-spacing
+\addplot [fill=warning09] coordinates { ({Vorher}, 3 ) ({Nachher}, 0)}; % warning vue/require-prop-types
+\addplot [fill=warning10] coordinates { ({Vorher}, 3 ) ({Nachher}, 0)}; % warning vue/attribute-hyphenation
+\addplot [fill=warning11] coordinates { ({Vorher}, 2 ) ({Nachher}, 0)}; % warning vue/html-self-closing
+\addplot [fill=warning12] coordinates { ({Vorher}, 1 ) ({Nachher}, 0)}; % warning vue/v-on-event-hyphenation
+\addplot [fill=warning13] coordinates { ({Vorher}, 1 ) ({Nachher}, 0)}; % warning vue/no-v-html
+\addplot +[fill=warning14, point meta=y,nodes near coords,nodes near coords align={anchor=south}]coordinates { ({Vorher}, 1 ) ({Nachher}, 1)}; % warning vue/mustache-interpolation-spacing
+
+\end{axis}
+\end{tikzpicture}
+
+\small
+\renewcommand{\arraystretch}{0.8}
+\setlength{\tabcolsep}{1pt}
+\begin{tabularx}{.54\textwidth}{X | c | c}
+ Regel & Vorher & Nachher \\ \hline
+ error: html-indent & 26 & 0 \\
+ error: script-indent & 17 & 0 \\
+ error: require-v-for-key & 6 & 0 \\
+ error: multi-word-component-names & 5 & 0 \\
+ error: valid-v-for & 1 & 0 \\
+ error: valid-template-root & 1 & 0 \\
+ warning: max-attributes-per-line & 125 & 0 \\
+ warning: attributes-order & 34 & 0 \\
+ warning: singleline-html-element-content-newline & 26 & 0 \\
+ warning: require-default-prop & 12 & 0 \\
+ warning: html-self-closing & 12 & 0 \\
+ warning: first-attribute-linebreak & 11 & 0 \\
+ warning: html-closing-bracket-newline & 10 & 0 \\
+ warning: multiline-html-element-content-newline & 8 & 0 \\
+ warning: html-closing-bracket-spacing & 5 & 0 \\
+ warning: require-prop-types & 3 & 0 \\
+ warning: attribute-hyphenation & 3 & 0 \\
+ warning: html-self-closing & 2 & 0 \\
+ warning: v-on-event-hyphenation & 1 & 0 \\
+ warning: mustache-interpolation-spacing & 1 & 0 \\
+ warning: no-v-html & 1 & 1 \\
+\end{tabularx}
+\end{multicols}
+
+\end{frame}
diff --git a/31-qualitaetsheft-kolloquium/slides/components.tex b/31-qualitaetsheft-kolloquium/slides/components.tex
new file mode 100644
index 0000000..5a6afe6
--- /dev/null
+++ b/31-qualitaetsheft-kolloquium/slides/components.tex
@@ -0,0 +1,7 @@
+\begin{frame}[t]{Komponenten Backend}
+
+ \begin{figure}[h]
+ \includegraphics[width=0.7\textwidth]{assets/diagrams/backendComponentDiagram}
+ \end{figure}
+
+\end{frame} \ No newline at end of file
diff --git a/31-qualitaetsheft-kolloquium/slides/coverage.tex b/31-qualitaetsheft-kolloquium/slides/coverage.tex
new file mode 100644
index 0000000..51d39ea
--- /dev/null
+++ b/31-qualitaetsheft-kolloquium/slides/coverage.tex
@@ -0,0 +1,23 @@
+\begin{frame}{Codeüberdeckung}
+ \vspace{-.4cm}
+ \begin{figure}[t]
+ \centering
+ \includegraphics[width=\textwidth,height=\textheight,keepaspectratio]{assets/coverage/server.png}
+ \end{figure}
+ \begin{redblock}{Lücken}
+ \begin{minipage}{1.7cm}
+ \centering
+ \fontsize{23pt}{0pt}
+ \selectfont
+ \textcolor{kit-red}
+ \faCode
+ \end{minipage}
+ \hspace{-.5cm}
+ \begin{minipage}{.7\textwidth}
+ \begin{itemize}
+ \item Model-Klassen (intern) und Controller (extern) implizit abgedeckt
+ \item Lombok, Spring und JPA Repositories
+ \end{itemize}
+ \end{minipage}
+ \end{redblock}
+\end{frame} \ No newline at end of file
diff --git a/31-qualitaetsheft-kolloquium/slides/difficulties.tex b/31-qualitaetsheft-kolloquium/slides/difficulties.tex
new file mode 100644
index 0000000..d3e64dd
--- /dev/null
+++ b/31-qualitaetsheft-kolloquium/slides/difficulties.tex
@@ -0,0 +1,34 @@
+\begin{frame}{Schwierigkeiten}
+
+ \begin{columns}[t]
+
+ \begin{column}{.5\textwidth}
+ \centering{\fontsize{30pt}{36pt}\selectfont\faDesktop}
+ \vspace{.2cm}
+ \begin{blueblock}{Dashboard}
+ \begin{itemize}
+ \item CORS Einschränkung
+ \item Error-Handling
+ \item Kommunikation zwischen Komponenten
+ \end{itemize}
+ \end{blueblock}
+ \end{column}
+
+ \begin{column}{.5\textwidth}
+ \centering{\fontsize{30pt}{36pt}\selectfont\faServer}
+ \vspace{.2cm}
+ \begin{orangeblock}{Server}
+ \begin{itemize}
+ \item Authentifizierung
+ \item API
+ \item EpisodeActionService (AntennaPod)
+ \end{itemize}
+ \end{orangeblock}
+ \end{column}
+
+
+ \end{columns}
+
+
+\end{frame}
+
diff --git a/31-qualitaetsheft-kolloquium/slides/einführung.tex b/31-qualitaetsheft-kolloquium/slides/einführung.tex
new file mode 100644
index 0000000..d818cd3
--- /dev/null
+++ b/31-qualitaetsheft-kolloquium/slides/einführung.tex
@@ -0,0 +1,40 @@
+\begin{frame}[t]{Einführung}
+
+
+ \begin{columns}[t]
+ \begin{column}{.3\textwidth}
+ \centering{\fontsize{30pt}{36pt}\selectfont\faPodcast}
+ \vspace{.2cm}
+ \begin{block}{Podcast}
+ \begin{itemize}
+ \item RSS-Feed
+ \item Episoden
+ \item Audio/Video
+ \end{itemize}
+ \end{block}
+ \end{column}
+ \begin{column}{.3\textwidth}
+ \centering{\fontsize{30pt}{36pt}\selectfont\faArrowCircleDown}
+ \vspace{.2cm}
+ \begin{block}{Podcatcher}
+ \begin{itemize}
+ \item lokale Verwaltung von Podcasts
+ \item API Unterstützung
+ \item Abspielen von Episoden
+ \end{itemize}
+ \end{block}
+ \end{column}
+ \begin{column}{.3\textwidth}
+ \centering{\fontsize{30pt}{36pt}\selectfont\faSync}
+ \vspace{.2cm}
+ \begin{block}{Synchronisationsserver}
+ \begin{itemize}
+ \item Hörfortschritte
+ \item Abonnements
+ \item Discovery
+ \end{itemize}
+ \end{block}
+ \end{column}
+ \end{columns}
+
+\end{frame} \ No newline at end of file
diff --git a/31-qualitaetsheft-kolloquium/slides/features.tex b/31-qualitaetsheft-kolloquium/slides/features.tex
new file mode 100644
index 0000000..6ec435b
--- /dev/null
+++ b/31-qualitaetsheft-kolloquium/slides/features.tex
@@ -0,0 +1,37 @@
+\begin{frame}{Features}
+\begin{columns}[t]
+\begin{column}{.3\textwidth}
+\centering{\fontsize{30pt}{36pt}\selectfont\faSync}
+\vspace{.2cm}
+\begin{block}{Synchronisation}
+\begin{itemize}
+ \item Abos
+ \item Hörfortschritt
+\end{itemize}
+\end{block}
+\end{column}
+\begin{column}{.3\textwidth}
+\centering{\fontsize{30pt}{36pt}\selectfont\faGlobe}
+\vspace{.2cm}
+\begin{block}{Weboberfläche}
+\begin{itemize}
+ \item Aboliste
+ \item Zuletzt gehört
+\end{itemize}
+\end{block}
+\end{column}
+\begin{column}{.3\textwidth}
+\centering{\fontsize{30pt}{36pt}\selectfont\faUser}
+\vspace{.2cm}
+\begin{block}{Account-Verwaltung}
+\begin{itemize}
+ \item Registrieren und Anmelden
+ \item Passwort ändern und zurücksetzen
+ \item Account löschen
+ \item Daten importieren/exportieren
+\end{itemize}
+\end{block}
+\end{column}
+\end{columns}
+\end{frame}
+
diff --git a/31-qualitaetsheft-kolloquium/slides/gantt.tex b/31-qualitaetsheft-kolloquium/slides/gantt.tex
new file mode 100644
index 0000000..31ed9b9
--- /dev/null
+++ b/31-qualitaetsheft-kolloquium/slides/gantt.tex
@@ -0,0 +1,11 @@
+\begin{frame}{Geplanter Zeitplan}
+
+\includegraphics[width=\textwidth]{assets/gantt-plan.eps}
+
+\end{frame}
+\begin{frame}{Tatsächlicher Zeitplan}
+
+\includegraphics[width=\textwidth]{assets/gantt-reality.eps}
+
+\end{frame}
+
diff --git a/31-qualitaetsheft-kolloquium/slides/integrationstrategie.tex b/31-qualitaetsheft-kolloquium/slides/integrationstrategie.tex
new file mode 100644
index 0000000..0564b5f
--- /dev/null
+++ b/31-qualitaetsheft-kolloquium/slides/integrationstrategie.tex
@@ -0,0 +1,82 @@
+\begin{frame}{Integrationsstrategie}
+
+\vspace{-.5cm}
+\begin{minipage}[t]{.47\textwidth}
+ \begin{orangeblock}{Top-Down}
+ \begin{minipage}{1.6cm}
+ \centering
+ \vspace{.15cm}
+ \fontsize{30pt}{36pt}
+ \selectfont
+ \faSortAmountDown
+ \vspace{.2cm}
+ \end{minipage}
+ \hspace{-.5cm}
+ \begin{minipage}{\textwidth - 1.4cm}
+ \begin{itemize}
+ \item Schnelle anschauliche Ergebnisse
+ \item Integration von Dashboard aus zum Server
+ \item spätes Zusammenspiel mit Backend
+ \item Aufwendige/Schwere Tests
+ \end{itemize}
+ \end{minipage}
+ \end{orangeblock}
+\end{minipage}
+\hfill
+\begin{minipage}[t]{.47\textwidth}
+ \begin{greenblock}{Bottom-Up}
+ \begin{minipage}{1.6cm}
+ \centering
+ \vspace{.2cm}
+ \fontsize{30pt}{36pt}
+ \selectfont
+ {\faSortAmountUp*}
+ \vspace{.25cm}
+ \end{minipage}
+ \hspace{-.5cm}
+ \begin{minipage}{\textwidth - 1.4cm}
+ \begin{itemize}
+ \item Integration von Datenbank aus zum Dashboard
+ \item viele einfache Tests sind erforderlich
+ \item spätes Zusammenspiel mit Frontend
+ \end{itemize}
+ \end{minipage}
+ \end{greenblock}
+\end{minipage}
+\vspace{.3cm}
+
+\begin{blueblock}{Outside-In}
+ \begin{minipage}{2cm}
+ \centering
+ \vspace{.2cm}
+ \fontsize{30pt}{36pt}
+ \selectfont
+ \faCompressArrows*
+ \vspace{.3cm}
+ \end{minipage}
+ \hspace{-.5cm}
+ \begin{minipage}{\textwidth - 2cm}
+ \begin{itemize}
+ \item Vereinigt Vorteile von Bottom-Up und Top-Down
+ \item Implementierung von Dashboard und Server gleichzeitig
+ \item Schnelle Tests + anschauliche Ergebnisse
+ \item Gut Parallelisierbar auf ganze Team
+ \end{itemize}
+ \end{minipage}
+\end{blueblock}
+
+% \begin{greenblock}{Outside-In Prinzip}
+% \begin{itemize}
+% \item Eine Kombination aus dem Bottom-Up und Top-Down Prinzip
+% \item Beginnt gleichzeitig auf höchster und niedrigster Logischer Ebene
+% \item Schrittweise Integration aus beiden Richtungen
+% \begin{itemize}
+% \item Model und Datenbank
+% \item Controller und Frontend
+% \end{itemize}
+% \item Frühzeitiges testen der Endpunkte und Unit Tests
+% \item Gut Parallelisierbar auf ganze Team
+% \end{itemize}
+% \end{greenblock}
+
+\end{frame}
diff --git a/31-qualitaetsheft-kolloquium/slides/pattern.tex b/31-qualitaetsheft-kolloquium/slides/pattern.tex
new file mode 100644
index 0000000..141954b
--- /dev/null
+++ b/31-qualitaetsheft-kolloquium/slides/pattern.tex
@@ -0,0 +1,12 @@
+\begin{frame}{Entwurfsmuster}
+ \begin{columns}
+ \column{.5\textwidth}
+ \begin{greenblock}{Dependency Injection}
+ Standard (\texttt{block})
+ \end{greenblock}
+ \column{.5\textwidth}
+ \begin{blueblock}{Data Access Object (DAO)}
+ = \texttt{exampleblock}
+ \end{blueblock}
+ \end{columns}
+\end{frame} \ No newline at end of file
diff --git a/31-qualitaetsheft-kolloquium/slides/performance.tex b/31-qualitaetsheft-kolloquium/slides/performance.tex
new file mode 100644
index 0000000..dd27226
--- /dev/null
+++ b/31-qualitaetsheft-kolloquium/slides/performance.tex
@@ -0,0 +1,56 @@
+\begin{frame}{Lasttests}
+ \begin{columns}[t]
+ \begin{column}{.48\textwidth}
+ \begin{orangeblock}{2 Kerne / 2GB RAM (mind. Anforderung)}
+ \begin{minipage}{.2\textwidth}
+ \centering
+ \vspace{.15cm}
+ \fontsize{30pt}{36pt}
+ \selectfont
+ \vspace{.2cm}
+ \end{minipage}
+ \begin{tabular}{l l}
+ \textbf{Antwortszeit} & 713,25 ms \\
+ \textbf{Durchsatz} & 10,85 Trans./s \\
+ \textbf{Apdex} & 0,563
+ \end{tabular}
+ \end{orangeblock}
+ \end{column}
+
+ \begin{column}{.48\textwidth}
+ \begin{greenblock}{8 Kerne / 32GB RAM}
+ \begin{minipage}{.2\textwidth}
+ \centering
+ \vspace{.2cm}
+ \fontsize{30pt}{36pt}
+ \selectfont
+ \vspace{.25cm}
+ \end{minipage}
+ \begin{tabular}{l l}
+ \textbf{Antwortszeit} & 81,15 ms \\
+ \textbf{Durchsatz} & 88,93 Trans./s \\
+ \textbf{Apdex} & 1,000
+ \end{tabular}
+ \end{greenblock}
+ \end{column}
+ \end{columns}
+ \vspace{.3cm}
+
+ \begin{blueblock}{Schlussfolgerung}
+ \begin{minipage}{1.7cm}
+ \centering
+ \fontsize{23pt}{0pt}
+ \selectfont
+ \textcolor{kit-blue}
+ \faArrowRight
+ \end{minipage}
+ \hspace{-.5cm}
+ \begin{minipage}{.7\textwidth}
+ \begin{itemize}
+ \item Mindestanforderungen bieten unter Last keine optimale Performance
+ \item Mit stärkerer Hardware kann Durchsatz von 50 Trans./s erreicht werden
+ \end{itemize}
+ \end{minipage}
+ \end{blueblock}
+
+\end{frame} \ No newline at end of file
diff --git a/31-qualitaetsheft-kolloquium/slides/problems.tex b/31-qualitaetsheft-kolloquium/slides/problems.tex
new file mode 100644
index 0000000..b3343a6
--- /dev/null
+++ b/31-qualitaetsheft-kolloquium/slides/problems.tex
@@ -0,0 +1,59 @@
+\begin{frame}{Herausforderungen}
+
+\vspace{-.4cm}
+
+\begin{orangeblock}{Falsche Zeitangaben}
+ \begin{minipage}{1.7cm}
+ \centering
+ \fontsize{23pt}{0pt}
+ \selectfont
+ \textcolor{orange}
+ \faClockO
+ \end{minipage}
+ \hspace{-.5cm}
+ \begin{minipage}{.7\textwidth}
+ \begin{itemize}
+ \item \textbf{Problem:} Zeit der letzten Podcastinteraktion falsch
+ \item \textbf{Ursache:} Lokale statt universelle Zeit zur Berechnung
+ \item \textbf{Behebung:} Explizite Verwendung von UTC
+ \end{itemize}
+ \end{minipage}
+\end{orangeblock}
+
+\begin{redblock}{AntennaPod Fehlermeldung}
+ \begin{minipage}{1.7cm}
+ \centering
+ \fontsize{23pt}{0pt}
+ \selectfont
+ \textcolor{kit-red}
+ \faWarning
+ \end{minipage}
+ \hspace{-.5cm}
+ \begin{minipage}{.7\textwidth}
+ \begin{itemize}
+ \item \textbf{Problem:} Bei Uploads gibt AntennaPod Fehler aus
+ \item \textbf{Ursache:} Falscher Parametername gesendet
+ \item \textbf{Behebung:} JsonProperty \texttt{updateURLs} zu \texttt{update\textunderscore urls} umbenannt
+ \end{itemize}
+ \end{minipage}
+\end{redblock}
+
+\begin{blueblock}{Doppelte Sicherung von EpisodeActions}
+ \begin{minipage}{1.7cm}
+ \centering
+ \fontsize{23pt}{0pt}
+ \selectfont
+ \textcolor{kit-blue}
+ \faClone
+ \end{minipage}
+ \hspace{-.5cm}
+ \begin{minipage}{.8\textwidth}
+ \begin{itemize}
+ \item \textbf{Problem:} Mehrere EpisodeActions pro Benutzer für eine Episode gespeichert
+ \item \textbf{Ursache:} Aufgrund von Effizienz - Spring ersetzt erst nach Sammeln der Daten
+ \item \textbf{Behebung:} EpisodeActions vor Speichern aussortieren
+ \end{itemize}
+ \end{minipage}
+\end{blueblock}
+
+\end{frame} \ No newline at end of file
diff --git a/31-qualitaetsheft-kolloquium/slides/requirements.tex b/31-qualitaetsheft-kolloquium/slides/requirements.tex
new file mode 100644
index 0000000..e660bb9
--- /dev/null
+++ b/31-qualitaetsheft-kolloquium/slides/requirements.tex
@@ -0,0 +1,58 @@
+\begin{frame}{Muss-Kriterien}
+\rowcolors{1}{kit-orange60}{kit-orange30}
+\begin{tabular}{ >{\bfseries}l l l}
+ \rowcolor{kit-orange}
+ Bezeichner & Zusammenfassung & Implementiert\\\hline
+ \textlangle RM1 \textrangle & Registrierung, Bestätigung und Anmeldung eines Accounts über das Frontend & Ja\\
+ \textlangle RM2 \textrangle & Speichern von Abonnements und Episoden auf dem Server & Ja\\
+ \textlangle RM3 \textrangle & Synchronisierung zwischen Podcatchern & Ja\\
+ \textlangle RM4 \textrangle & Eine Weboberfläche & Ja\\
+ \textlangle RM5 \textrangle & Möglichkeit das eigene Passwort zu ändern / zurückzusetzen & Ja\\
+ \textlangle RM6 \textrangle & Abonnementliste in der Weboberfläche & Ja\\
+ \textlangle RM7 \textrangle & 50 Anfragen / Sekunde bearbeiten & Zu testen\\
+ \textlangle RM8 \textrangle & Primäre Auslegung des Webfrontends für Desktop-Nutzer & Ja\\
+ \textlangle RM9 \textrangle & Unterstützung der gpodder.net RESTful-API & Ja\\
+ \textlangle RM10\textrangle & Das Nutzen einer Datenbank zur Speicherung von Daten & Ja\\
+ \textlangle RM11\textrangle & Erweiterte API für Kommunikation zwischen Front- und Backend & Ja
+\end{tabular}
+\end{frame}
+
+\begin{frame}{Soll-Kriterien}
+\rowcolors{1}{kit-green60}{kit-green30}
+\begin{tabular}{ >{\bfseries}l l l}
+ \rowcolor{kit-green}
+ Bezeichner & Zusammenfassung & Implementiert\\\hline
+ \textlangle RS1 \textrangle & Eine Anleitung (Platzhalter) & Ja\\
+ \textlangle RS2 \textrangle & Die Möglichkeit einen Account zu löschen & Ja\\
+ \textlangle RS3 \textrangle & Spring für das Backend und MariaDB als Datenbank & Ja\\
+ \textlangle RS4 \textrangle & Vue.js und Bootstrap für das Frontend & Ja\\
+ \textlangle RS5 \textrangle & npm und vite für das Frontend & Ja\\
+ \textlangle RS6 \textrangle & Eine Single-Page-Application als Frontend mit dynamischer Aktualisierung & Ja\\
+ \textlangle RS7 \textrangle & Ein RSS-Parser um Daten aus einem RSS-Feed zu lesen & Ja\\
+ \textlangle RS8 \textrangle & Mindestanforderungen an ein Passwort & Ja\\
+ \textlangle RS9 \textrangle & Salting und Hashing für Verschlüsselung der Personenbezogenen Daten & Ja\\
+ \textlangle RS10\textrangle & Nutzer bleibt über JWT angemeldet und authentifiziert & Ja
+\end{tabular}
+\end{frame}
+
+\begin{frame}{Kann-Kriterien}
+
+\rowcolors{1}{kit-blue60}{kit-blue30}
+\begin{tabular}{ >{\bfseries}l l l }
+ \rowcolor{kit-blue}
+ Bezeichner & Zusammenfassung & Implementiert\\\hline
+ \textlangle RC1 \textrangle & Abonnierten Podcast in Weboberfläche über Link teilen und hinzufügen & Ja\\
+ \textlangle RC2 \textrangle & Abonnements in Weboberfläche deabonnieren & Nein\\
+ \textlangle RC3 \textrangle & Importieren und Exportieren aller benutzerbezogenen Daten & Ja\\
+ \textlangle RC4 \textrangle & Umsiedeln von anderen Gpodder-Plattformen & Ja\\
+ \textlangle RC5 \textrangle & Kompatible Weboberfläche für beliebige gpodder.net APIs & Entfernt\\
+ \textlangle RC6 \textrangle & Responsive designte Weboberfläche & Ja\\
+ \textlangle RC7 \textrangle & Administratorkonten mit privilegierten Funktionen & Nein\\
+ \textlangle RC8 \textrangle & OAuth 2.0 im Webfrontend & Nein\\
+ \textlangle RC9 \textrangle & Bei Ausfall des Backends im Frontend angemeldet bleiben & Ja\\
+ \textlangle RC10\textrangle & Mehrsprachige Weboberfläche & Ja\\
+ \textlangle RC11\textrangle & Erfüllung der DSGVO & Teils\\
+ \textlangle RC12\textrangle & Docker für einfaches Deployment und Sicherheit & Ja
+\end{tabular}
+\end{frame}
+
diff --git a/31-qualitaetsheft-kolloquium/slides/statistics.tex b/31-qualitaetsheft-kolloquium/slides/statistics.tex
new file mode 100644
index 0000000..ed9b143
--- /dev/null
+++ b/31-qualitaetsheft-kolloquium/slides/statistics.tex
@@ -0,0 +1,85 @@
+\begin{frame}{Statistiken}
+
+\begin{columns}[t]
+ \begin{column}{.4\textwidth}
+ \begin{orangeblock}{Dashboard}
+ \centering
+ \begin{minipage}{.2\textwidth}
+ \centering
+ \vspace{.15cm}
+ \fontsize{30pt}{36pt}
+ \selectfont
+ \faDesktop
+ \vspace{.2cm}
+ \end{minipage}
+ \begin{tabular}{l l}
+ \textbf{SLOC} & 2020 Zeilen \\
+ \textbf{Commits} & 191 \\
+ \textbf{Dateien} & 38
+ \end{tabular}
+ \end{orangeblock}
+ \end{column}
+
+ \begin{column}{.4\textwidth}
+ \begin{greenblock}{Server}
+ \centering
+ \begin{minipage}{.2\textwidth}
+ \centering
+ \vspace{.2cm}
+ \fontsize{30pt}{36pt}
+ \selectfont
+ \faServer
+ \vspace{.25cm}
+ \end{minipage}
+ \begin{tabular}{l l}
+ \textbf{SLOC} & 3812 Zeilen \\
+ \textbf{Commits} & 305 \\
+ \textbf{Dateien} & 60
+ \end{tabular}
+ \end{greenblock}
+ \end{column}
+\end{columns}
+\vspace{.3cm}
+
+\centering
+\begin{minipage}{.9\textwidth}
+ \begin{blueblock}{Insgesamt}
+ \centering
+ \begin{minipage}{.5\textwidth}
+ \centering
+ \begin{minipage}{.2\textwidth}
+ \centering
+ \vspace{.2cm}
+ \fontsize{30pt}{36pt}
+ \selectfont
+ \faChartLine
+ \vspace{.3cm}
+ \end{minipage}
+ \begin{tabular}{l l}
+ \textbf{SLOC} & 5832 Zeilen \\
+ \textbf{Commits} & 486 \\
+ \textbf{Dateien} & 98
+ \end{tabular}
+
+ \end{minipage}
+ \end{blueblock}
+ \small SLOC und Anzahl der Dateien würden basierend der Inhalte des
+ Quellordners \texttt{src/} berechnet und beinhalten keine automatisch
+ generierten Dateien.
+\end{minipage}
+\end{frame}
+
+\begin{frame}{Zeitlicher Verlauf der Commits}
+ \textbf{Dashboard}
+ \includegraphics[width=\textwidth]{assets/commits-dashboard.png}
+ \textbf{Server}
+ \includegraphics[width=\textwidth]{assets/commits-server.png}
+\end{frame}
+
+\begin{frame}{Commit-Verteilung Server}
+ \includegraphics[width=\textwidth]{assets/contributors-server.png}
+\end{frame}
+
+\begin{frame}{Commit-Verteilung Dashboard}
+ \includegraphics[width=\textwidth]{assets/contributors-dashboard.png}
+\end{frame}
diff --git a/31-qualitaetsheft-kolloquium/slides/synchronisation.tex b/31-qualitaetsheft-kolloquium/slides/synchronisation.tex
new file mode 100644
index 0000000..0849279
--- /dev/null
+++ b/31-qualitaetsheft-kolloquium/slides/synchronisation.tex
@@ -0,0 +1,36 @@
+\begin{frame}{Synchronisation}
+
+ \tikzstyle{line} = [draw, -latex']
+
+ \begin{figure}[H]
+
+ \begin{tikzpicture}
+
+ \tikzset{focus/.style={rectangle, minimum width = 1cm, minimum height = 0.5cm, rounded corners, draw}};
+ \tikzset{hyperfocus/.style={rectangle, minimum width = 1cm, minimum height = 0.5cm, draw}};
+
+ \node[hyperfocus, text width = 2.6cm, fill = green!25](s){Synchronisations-\\\quad \quad Server};
+ \node[focus, left = 3cm of s, text width = 3.1cm, orange](p1){\quad \underline{p1:Podcatcher}
+ \begin{itemize}
+ \vspace{0.2cm}
+ \item Abonnements
+ \item Hörfortschritt
+ \vspace{0.1cm}
+ \end{itemize}};
+ \node[focus, above = 1.8cm of s, orange](p2){p2};
+ \node[focus, right = 2.5cm of s, orange](p3){p3};
+ \node[below = 1.7cm of s](p4){\textbf{...}};
+ \umlactor[left = 2.7cm of p2, blue!60]{Benutzer};
+
+ \draw[] (p1) -- (s);
+ \draw[] (p2) -- (s);
+ \draw[] (s) -- (p3);
+ \draw[] (s) -- (p4);
+ \path [line, thick, blue!60] (Benutzer) -- node [text width=2.5cm, midway, above=0.1cm, align=center] {Podcast abonnieren} (p2);
+ \path [line, thick, blue!60] (Benutzer) -| node [text width=2.5cm, midway, above=0.1cm, align=center] {Episode anhören} (p1);
+
+ \end{tikzpicture}
+
+ \end{figure}
+
+\end{frame} \ No newline at end of file
diff --git a/31-qualitaetsheft-kolloquium/slides/testing.tex b/31-qualitaetsheft-kolloquium/slides/testing.tex
new file mode 100644
index 0000000..0cc862b
--- /dev/null
+++ b/31-qualitaetsheft-kolloquium/slides/testing.tex
@@ -0,0 +1,59 @@
+\begin{frame}{Testfälle}
+
+ \begin{orangeblock}{Unit-Tests}
+ \begin{minipage}{1.7cm}
+ \centering
+ \fontsize{23pt}{0pt}
+ \selectfont
+ \textcolor{orange}
+ \faGears
+ \end{minipage}
+ \hspace{-.5cm}
+ \begin{minipage}{.9\textwidth}
+ \begin{itemize}
+ \item Grundlage für alle weiteren Testfälle
+ \item Nur für selbst geschriebene Klassen erstellt
+ \begin{itemize}
+ \item[\textbf{Vorher:}] 38 Testfälle in 610 Codezeilen für 1780 Quellcodezeilen
+ \item[\textbf{Nachher:}] 48 Testfälle in 1035 Codezeilen für 2081 Quellcodezeilen
+ \end{itemize}
+ \end{itemize}
+ \end{minipage}
+ \end{orangeblock}
+
+ \begin{greenblock}{Frontend-Testfälle aus dem Pflichtenheft}
+ \begin{minipage}{1.7cm}
+ \centering
+ \fontsize{23pt}{0pt}
+ \selectfont
+ \textcolor{kit-green}
+ \faDesktop
+ \end{minipage}
+ \hspace{-.5cm}
+ \begin{minipage}{.9\textwidth}
+ \begin{itemize}
+ \item Manuell ausgeführt
+ \item Nicht zu 100\% erfüllt
+ \item Link für das Zurücksetzen des Passworts bleibt nach Benutzung gültig (technisch bedingt)
+ \end{itemize}
+ \end{minipage}
+ \end{greenblock}
+
+ \begin{blueblock}{Synchronisations-Testfälle aus dem Pflichtenheft}
+ \begin{minipage}{1.7cm}
+ \centering
+ \fontsize{23pt}{0pt}
+ \selectfont
+ \textcolor{kit-blue}
+ \faRefresh
+ \end{minipage}
+ \hspace{-.5cm}
+ \begin{minipage}{.7\textwidth}
+ \begin{itemize}
+ \item Manuell (Podcatcher und Frontend) und automatisiert (Unit-Tests)
+ \item Ohne Einschränkungen erfüllt
+ \end{itemize}
+ \end{minipage}
+ \end{blueblock}
+
+\end{frame} \ No newline at end of file
diff --git a/31-qualitaetsheft-kolloquium/slides/zielsetzung.tex b/31-qualitaetsheft-kolloquium/slides/zielsetzung.tex
new file mode 100644
index 0000000..84e1064
--- /dev/null
+++ b/31-qualitaetsheft-kolloquium/slides/zielsetzung.tex
@@ -0,0 +1,39 @@
+\begin{frame}{Zielsetzung}
+
+\begin{figure}[H]
+
+\raggedright
+
+\begin{tikzpicture}
+
+\tikzset{focus/.style={rectangle, minimum width=1cm, minimum height=0.5cm, rounded corners=7pt, draw}};
+
+\tikzset{hyperfocus/.style={rectangle, minimum width=1cm, minimum height=0.5cm, draw}};
+
+\node[hyperfocus] (main) {gPodder};
+\node[focus, right = 2cm of main] (sync) {Synchronisation};
+\node[above = of sync] (share) {Inhalt teilen};
+\node[above = 0.5cm of share] (discover) {Podcasts entdecken};
+\node[text width = 3cm, below = of sync] (create) {Listen erstellen und teilen};
+\node[text width = 3cm, below = 0.5cm of create] (popular) {Publisher:\\ Was ist beliebt?};
+
+\node[hyperfocus, right = 3cm of sync, text width = 4cm] (PSE) {\underline{PSE\textsuperscript{2}}\begin{itemize}
+ \item Schlankes Design
+ \item Effizient
+ \item Intuitiv
+\end{itemize}
+};
+
+\draw[] (main) -- (sync);
+\draw[] (main) -- (share);
+\draw[] (main) |- (discover);
+\draw[] (main) -- (create);
+\draw[] (main) |- (popular);
+\draw[stealth-, thick] (sync.east) -- ($(PSE.north west) + (0, -0.3)$);
+
+
+\end{tikzpicture}
+
+\end{figure}
+
+\end{frame} \ No newline at end of file
diff --git a/31-qualitaetsheft-kolloquium/tikz-uml.sty b/31-qualitaetsheft-kolloquium/tikz-uml.sty
new file mode 100644
index 0000000..c6e8e0d
--- /dev/null
+++ b/31-qualitaetsheft-kolloquium/tikz-uml.sty
@@ -0,0 +1,5377 @@
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% Start of tikz-uml.sty
+%
+% Some macros for UML Diagrams.
+% Home page of project :
+% Author: Nicolas Kielbasiewicz
+% Style from :
+% Fixed by Nicolas Kielbasiewicz (nicolas.kielbasiewicz@ensta-paristech.fr) in march 2016 to compile with pgf 3.00
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+\NeedsTeXFormat{LaTeX2e}[1995/12/01]%
+\ProvidesPackage{tikz-uml}[2011/01/26]%
+%
+\RequirePackage{etoolbox}%
+\RequirePackage{ifthen}%
+\RequirePackage{tikz}%
+\RequirePackage{xstring}%
+\RequirePackage{calc}%
+\RequirePackage{pgfopts}%
+\usetikzlibrary{backgrounds,arrows,shapes,fit,shadows,decorations.markings}%
+%
+\def\tikzumlPackageLayersNum{3}%
+\pgfkeys{/tikzuml/options/.cd, packageLayers/.initial=3}%
+\pgfkeys{/tikzuml/options/.cd, packageLayers/.store in=\tikzumlPackageLayersNum}%
+\def\tikzumlStateLayersNum{3}%
+\pgfkeys{/tikzuml/options/.cd, stateLayers/.initial=3}%
+\pgfkeys{/tikzuml/options/.cd, stateLayers/.store in=\tikzumlStateLayersNum}%
+\def\tikzumlFragmentLayersNum{3}%
+\pgfkeys{/tikzuml/options/.cd, fragmentLayers/.initial=3}%
+\pgfkeys{/tikzuml/options/.cd, fragmentLayers/.store in=\tikzumlFragmentLayersNum}%
+\def\tikzumlComponentLayersNum{3}%
+\pgfkeys{/tikzuml/options/.cd, componentLayers/.initial=3}%
+\pgfkeys{/tikzuml/options/.cd, componentLayers/.store in=\tikzumlComponentLayersNum}%
+%
+\ProcessPgfOptions{/tikzuml/options}%
+%
+\def\pgfsetlayersArg{background}%
+\pgfdeclarelayer{background}%
+\newcounter{tikzumlPackageLayers}%
+\loop \pgfdeclarelayer{package\thetikzumlPackageLayers}%
+ \xdef\pgfsetlayersArg{\pgfsetlayersArg,package\thetikzumlPackageLayers}%
+ \ifnum\tikzumlPackageLayersNum>\thetikzumlPackageLayers%
+ \stepcounter{tikzumlPackageLayers}%
+\repeat%
+%
+\newcounter{tikzumlFragmentLayers}%
+\loop \pgfdeclarelayer{fragment\thetikzumlFragmentLayers}%
+ \xdef\pgfsetlayersArg{\pgfsetlayersArg,fragment\thetikzumlFragmentLayers}%
+ \ifnum\tikzumlFragmentLayersNum>\thetikzumlFragmentLayers%
+ \stepcounter{tikzumlFragmentLayers}%
+\repeat%
+%
+\newcounter{tikzumlStateLayers}%
+\loop \pgfdeclarelayer{state\thetikzumlStateLayers}%
+ \xdef\pgfsetlayersArg{\pgfsetlayersArg,state\thetikzumlStateLayers}%
+ \ifnum\tikzumlStateLayersNum>\thetikzumlStateLayers%
+ \stepcounter{tikzumlStateLayers}%
+\repeat%
+%
+\newcounter{tikzumlComponentLayers}%
+\loop \pgfdeclarelayer{component\thetikzumlComponentLayers}%
+ \xdef\pgfsetlayersArg{\pgfsetlayersArg,component\thetikzumlComponentLayers}%
+ \ifnum\tikzumlComponentLayersNum>\thetikzumlComponentLayers%
+ \stepcounter{tikzumlComponentLayers}%
+\repeat%
+%
+\pgfdeclarelayer{lifelines}%
+\pgfdeclarelayer{activity}%
+\pgfdeclarelayer{connections}%
+\xdef\pgfsetlayersArg{\pgfsetlayersArg,lifelines,activity,connections,main}%
+\pgfsetlayers{\pgfsetlayersArg}%
+%
+\pgfkeys{/tikzuml/.cd, text/.initial=black, draw/.initial=black, font/.initial=\small,%
+ x/.initial=0, y/.initial=0,%
+ package type/.initial=tikzumlEmpty, fill package/.initial=blue!20,%
+ class width/.initial=10ex, simple interface width/.initial=4ex, class type/.initial=class, fill class/.initial=yellow!20, fill template/.initial=yellow!2,%
+ narynode width/.initial=6ex,%
+ relation geometry/.initial=--, relation angle1/.initial=-30, relation angle2/.initial=30, relation loopsize/.initial=3em, relation weight/.initial=0.5, relation pos1/.initial=0.2, relation pos2/.initial=0.8, relation pos stereo/.initial=0.5,%
+ note width/.initial=3cm, fill note/.initial=green!20,%
+ fill system/.initial=white,%
+ fill usecase/.initial=blue!20,%
+ actor below/.initial=0.5cm,%
+ state join width/.initial=3ex,%
+ state decision width/.initial=3ex,%
+ state initial width/.initial=5ex,%
+ state final width/.initial=5.5ex,%
+ state enter width/.initial=5ex,%
+ state exit width/.initial=5ex,%
+ state end width/.initial=5ex,%
+ state history width/.initial=5ex,%
+ state deep history width/.initial=5ex,%
+ state width/.initial=8ex, fill state/.initial=yellow!20,%
+ object stereo/.initial=object, fill object/.initial=yellow!20,%
+ call dt/.initial=tikzumlEmpty, call padding/.initial=2, call type/.initial=synchron, fill call/.initial=white,%
+ fragment type/.initial=opt, fragment inner xsep/.initial=1, fragment inner ysep/.initial=1, fill fragment/.initial= none,%
+ create call dt/.initial=4,%
+ component width/.initial=8ex, fill component/.initial= yellow!20,%
+ required interface distance/.initial=2.5cm, required interface width/.initial=1em, required interface padding/.initial=1cm,%
+ provided interface distance/.initial=3cm, provided interface width/.initial=1em, provided interface padding/.initial=1cm,%
+ port width/.initial=1ex, fill port/.initial= yellow!20,%
+ fill assembly connector/.initial= white,%
+ .unknown/.code={%
+ \let\keyname=\pgfkeyscurrentname%
+ \let\keyvalue=\pgfkeyscurrentvalue%
+ \errmessage{TIKZUML ERROR : in tikzuml global, invalid option \keyname}%
+ }%
+}%
+%
+\pgfkeys{/tikzuml/.cd, text/.get=\tikzumlDefaultTextColor, draw/.get=\tikzumlDefaultDrawColor, font/.get=\tikzumlDefaultFont,%
+ x/.get=\tikzumlDefaultX, y/.get=\tikzumlDefaultY,%
+ package type/.get=\tikzumlPackageDefaultType, fill package/.get=\tikzumlPackageDefaultFillColor,%
+ class width/.get=\tikzumlClassDefaultWidth, simple interface width/.get=\tikzumlSimpleInterfaceDefaultWidth, class type/.get=\tikzumlClassDefaultType, fill class/.get=\tikzumlClassDefaultFillColor, fill template/.get=\tikzumlClassTemplateFillColorDefaultFillColor,%
+ narynode width/.get=\tikzumlNaryNodeDefaultWidth,%
+ relation geometry/.get=\tikzumlRelationDefaultGeometry, relation angle1/.get=\tikzumlRelationDefaultAngleO, relation angle2/.get=\tikzumlRelationDefaultAngleT, relation loopsize/.get=\tikzumlRelationDefaultLoopSize, relation weight/.get=\tikzumlRelationDefaultWeight, relation pos1/.get=\tikzumlRelationDefaultPosO, relation pos2/.get=\tikzumlRelationDefaultPosT, relation pos stereo/.get=\tikzumlRelationDefaultPosStereo,%
+ note width/.get=\tikzumlNoteDefaultWidth, fill note/.get=\tikzumlNoteDefaultFillColor,%
+ fill system/.get=\tikzumlSystemDefaultFillColor,%
+ fill usecase/.get=\tikzumlUseCaseDefaultFillColor,%
+ actor below/.get=\tikzumlActorDefaultBelow,%
+ state join width/.get=\tikzumlStateJoinDefaultWidth,%
+ state decision width/.get=\tikzumlStateDecisionDefaultWidth,%
+ state initial width/.get=\tikzumlStateInitialDefaultWidth,%
+ state final width/.get=\tikzumlStateFinalDefaultWidth,%
+ state enter width/.get=\tikzumlStateEnterDefaultWidth,%
+ state exit width/.get=\tikzumlStateExitDefaultWidth,%
+ state end width/.get=\tikzumlStateEndDefaultWidth,%
+ state history width/.get=\tikzumlStateHistoryDefaultWidth,%
+ state deep history width/.get=\tikzumlStateDeepHistoryDefaultWidth,%
+ state width/.get=\tikzumlStateDefaultWidth, fill state/.get=\tikzumlStateDefaultFillColor,%
+ object stereo/.get=\tikzumlObjectDefaultStereo, fill object/.get=\tikzumlObjectDefaultFillColor,%
+ call dt/.get=\tikzumlCallDefaultDT, call padding/.get=\tikzumlCallDefaultPadding, call type/.get=\tikzumlCallDefaultType, fill call/.get=\tikzumlCallDefaultFillColor,%
+ fragment type/.get=\tikzumlFragmentDefaultType, fragment inner xsep/.get=\tikzumlFragmentDefaultXSep, fragment inner ysep/.get=\tikzumlFragmentDefaultYSep, fill fragment/.get=\tikzumlFragmentDefaultFillColor,%
+ create call dt/.get=\tikzumlCreateCallDefaultDT,%
+ component width/.get=\tikzumlComponentDefaultWidth, fill component/.get=\tikzumlComponentDefaultFillColor,%
+ required interface distance/.get=\tikzumlRequiredInterfaceDefaultDistance, required interface width/.get=\tikzumlRequiredInterfaceDefaultWidth, required interface padding/.get=\tikzumlRequiredInterfaceDefaultPadding,%
+ provided interface distance/.get=\tikzumlProvidedInterfaceDefaultDistance, provided interface width/.get=\tikzumlProvidedInterfaceDefaultWidth, provided interface padding/.get=\tikzumlProvidedInterfaceDefaultPadding,%
+ port width/.get=\tikzumlPortDefaultWidth, fill port/.get=\tikzumlPortDefaultFillColor,%
+ fill assembly connector/.get=\tikzumlAssemblyConnectorDefaultFillColor%
+}%
+%
+% utility : change default colors
+\newcommand{\tikzumlset}[1]{%
+ \pgfkeys{/tikzuml/.cd,#1}%
+ \pgfkeys{/tikzuml/.cd, text/.get=\tikzumlDefaultTextColor, draw/.get=\tikzumlDefaultDrawColor, font/.get=\tikzumlDefaultFont,%
+ x/.get=\tikzumlDefaultX, y/.get=\tikzumlDefaultY,%
+ package type/.get=\tikzumlPackageDefaultType, fill package/.get=\tikzumlPackageDefaultFillColor,%
+ class width/.get=\tikzumlClassDefaultWidth, simple interface width/.get=\tikzumlSimpleInterfaceDefaultWidth, class type/.get=\tikzumlClassDefaultType, fill class/.get=\tikzumlClassDefaultFillColor, fill template/.get=\tikzumlClassTemplateFillColorDefaultFillColor,%
+ narynode width/.get=\tikzumlNaryNodeWidth,%
+ relation geometry/.get=\tikzumlRelationDefaultGeometry, relation angle1/.get=\tikzumlRelationDefaultAngleO, relation angle2/.get=\tikzumlRelationDefaultAngleT, relation loopsize/.get=\tikzumlRelationDefaultLoopSize, relation weight/.get=\tikzumlRelationDefaultWeight, relation pos1/.get=\tikzumlRelationDefaultPosO, relation pos2/.get=\tikzumlRelationDefaultPosT, relation pos stereo/.get=\tikzumlRelationDefaultPosStereo,%
+ note width/.get=\tikzumlNoteDefaultWidth, fill note/.get=\tikzumlNoteDefaultFillColor,%
+ fill system/.get=\tikzumlSystemDefaultFillColor,%
+ fill usecase/.get=\tikzumlUseCaseDefaultFillColor,%
+ actor below/.get=\tikzumlActorDefaultBelow,%
+ state join width/.get=\tikzumlStateJoinDefaultWidth,%
+ state decision width/.get=\tikzumlStateDecisionDefaultWidth,%
+ state initial width/.get=\tikzumlStateInitialDefaultWidth,%
+ state final width/.get=\tikzumlStateFinalDefaultWidth,%
+ state enter width/.get=\tikzumlStateEnterDefaultWidth,%
+ state exit width/.get=\tikzumlStateExitDefaultWidth,%
+ state end width/.get=\tikzumlStateEndDefaultWidth,%
+ state history width/.get=\tikzumlStateHistoryDefaultWidth,%
+ state deep history width/.get=\tikzumlStateDeepHistoryDefaultWidth,%
+ state width/.get=\tikzumlStateDefaultWidth, fill state/.get=\tikzumlStateDefaultFillColor,%
+ object stereo/.get=\tikzumlObjectDefaultStereo, fill object/.get=\tikzumlObjectDefaultFillColor,%
+ call dt/.get=\tikzumlCallDefaultDT, call padding/.get=\tikzumlCallDefaultPadding, call type/.get=\tikzumlCallDefaultType, fill call/.get=\tikzumlCallDefaultFillColor,%
+ fragment type/.get=\tikzumlFragmentDefaultType, fragment inner xsep/.get=\tikzumlFragmentDefaultXSep, fragment inner ysep/.get=\tikzumlFragmentDefaultYSep, fill fragment/.get=\tikzumlFragmentDefaultFillColor,%
+ create call dt/.get=\tikzumlCreateCallDT,%
+ component width/.get=\tikzumlComponentDefaultWidth, fill component/.get=\tikzumlComponentDefaultFillColor,%
+ required interface distance/.get=\tikzumlRequiredInterfaceDefaultDistance, required interface width/.get=\tikzumlRequiredInterfaceDefaultWidth, required interface padding/.get=\tikzumlRequiredInterfaceDefaultPadding,%
+ provided interface distance/.get=\tikzumlProvidedInterfaceDefaultDistance, provided interface width/.get=\tikzumlProvidedInterfaceDefaultWidth, provided interface padding/.get=\tikzumlProvidedInterfaceDefaultPadding,%
+ port width/.get=\tikzumlPortDefaultWidth, fill port/.get=\tikzumlPortDefaultFillColor,%
+ fill assembly connector/.get=\tikzumlAssemblyConnectorDefaultFillColor%
+ }%
+}%
+%
+% define a point
+% arg : node/coordinates of the point
+\newcommand{\umlpoint}[1]{%
+ \begin{pgfonlayer}{connections}%
+ \node[tikzuml control nodes style] at (#1) {};%
+ \end{pgfonlayer}%
+}%
+%
+\newcommand{\tikzumlskipescape}[3][_]{%
+\begingroup%
+ \def\_{#1}\edef\x{\endgroup%
+ \def\noexpand\csname #3\endcsname{#2}}\x%
+}%
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% class diagrams %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+\pgfkeys{/tikzuml/relation/.cd, attr1/.style args={#1|#2}{arg1=#1, mult1=#2},%
+ attr2/.style args={#1|#2}{arg2=#1, mult2=#2},%
+ attr/.style args={#1|#2}{arg=#1, mult=#2},%
+ recursive/.style args={#1|#2|#3}{angle1=#1, angle2=#2, loopsize=#3},%
+ anchors/.style args={#1 and #2}{anchor1=#1, anchor2=#2},%
+ recursive direction/.style args={#1 to #2}{recursive direction start=#1, recursive direction end=#2}%
+}%
+%
+\pgfkeys{/tikzuml/note/.cd, anchors/.style args={#1 and #2}{anchor1=#1, anchor2=#2}}%
+%
+\tikzstyle{tikzuml simpleclass style}=[rectangle, minimum height=2em, node distance=2em]%
+\tikzstyle{tikzuml simpleinterface style}=[circle, minimum height=1em, node distance=1em]%
+\tikzstyle{tikzuml class style}=[rectangle split, rectangle split parts=3, rectangle split part align={center, left, left}, minimum height=2em, node distance=2em]%
+\tikzstyle{tikzuml narynode style}=[diamond]%
+\tikzstyle{tikzuml template style}=[dashed, inner ysep=0.5em, inner xsep=1ex]%
+\tikzstyle{tikzuml control nodes style}=[fill=black, inner sep=1.5pt, circle]%
+%
+\tikzstyle{tikzuml association style}=[color=\tikzumlDefaultDrawColor, -]%
+\tikzstyle{tikzuml bidirectional association style}=[color=\tikzumlDefaultDrawColor, angle45-angle45]%
+\tikzstyle{tikzuml unidirectional association style}=[color=\tikzumlDefaultDrawColor, -angle 45]%
+\tikzstyle{tikzuml aggregation style}=[color=\tikzumlDefaultDrawColor, open diamond-]%
+\tikzstyle{tikzuml unidirectional aggregation style}=[color=\tikzumlDefaultDrawColor, open diamond-angle 45]%
+\tikzstyle{tikzuml composition style}=[color=\tikzumlDefaultDrawColor, diamond-]%
+\tikzstyle{tikzuml unidirectional composition style}=[color=\tikzumlDefaultDrawColor, diamond-angle 45]%
+\tikzstyle{tikzuml nesting style}=[color=\tikzumlDefaultDrawColor]%
+\tikzstyle{tikzuml dependency style}=[color=\tikzumlDefaultDrawColor, -angle 45, dashed]%
+\tikzstyle{tikzuml import style}=[color=\tikzumlDefaultDrawColor, -angle 45, dashed]%
+\tikzstyle{tikzuml inherit style}=[color=\tikzumlDefaultDrawColor, -open triangle 45]%
+\tikzstyle{tikzuml implements style}=[color=\tikzumlDefaultDrawColor, -open triangle 45, dashed]%
+%
+\pgfkeys{/tikzuml/assemblyconnectorrelation/.cd, anchors/.style args={#1 and #2}{anchor1=#1, anchor2=#2}}%
+%
+\newcounter{tikzumlPackageClassNum}%
+\newcounter{tikzumlPackageSubPackageNum}%
+\newcounter{tikzumlRelationNum}%
+\setcounter{tikzumlRelationNum}{1}%
+\newcounter{tikzumlNoteNum}%
+\setcounter{tikzumlNoteNum}{1}%
+%
+\newcounter{pos}%
+\newcounter{posT}%
+\newcounter{posStereo}%
+%
+\newcounter{tikzumlPackageLevel}%
+\setcounter{tikzumlPackageLevel}{0}%
+%
+\newif\iftikzumlpackageSimpleStyle%
+\newif\iftikzumlclassSimpleStyle%
+\newif\iftikzumlclassCircleShape%
+\newif\iftikzumlpackageWithoutCoords%
+\newif\iftikzumlclassWithoutCoords%
+\newif\iftikzumlassocclassWithoutCoords%
+\newif\iftikzumlnoteWithoutCoords%
+%
+% define a uml package
+% arg : package name
+% optional : x, y: coordinates of the package
+% type: stereotype of the package
+% name: name of the package node
+% draw, fill, text: colors
+% style: to manage every default TikZ option
+% no coords: to tell that the package position is defined relatively
+% to another node (automatically used with TikZ options above, below, left, right, below left, ...)
+\newenvironment{umlpackage}[2][]{%
+ \pgfkeys{/tikzuml/package/.cd, x/.initial=\tikzumlDefaultX, y/.initial=\tikzumlDefaultX, style/.style={},%
+ name/.initial=tikzumlEmpty, type/.initial=\tikzumlPackageDefaultType, draw/.initial=\tikzumlDefaultDrawColor,%
+ fill/.initial=\tikzumlPackageDefaultFillColor, text/.initial=\tikzumlDefaultTextColor,%
+ no coords/.is if=tikzumlpackageWithoutCoords,%
+ no coords=false,%
+ .unknown/.code={%
+ \let\keyname=\pgfkeyscurrentname%
+ \let\keyvalue=\pgfkeyscurrentvalue%
+ \ifthenelse{\equal{\keyname}{above}\OR%
+ \equal{\keyname}{left}\OR%
+ \equal{\keyname}{below}\OR%
+ \equal{\keyname}{right}\OR%
+ \equal{\keyname}{above left}\OR%
+ \equal{\keyname}{above right}\OR%
+ \equal{\keyname}{below left}\OR%
+ \equal{\keyname}{below right}}{%
+ \IfSubStr{\keyvalue}{ of }{%
+ \pgfkeys{/tikzuml/package/.cd, no coords}%
+ }{}%
+ }{}%
+ \ifx\keyvalue\pgfkeysnovalue%
+ \pgfkeys{/tikzuml/package/.cd, style/.append style/.expand once={\keyname}}%
+ \else%
+ \pgfkeys{/tikzuml/package/.cd, style/.append style/.expand twice={\expandafter\keyname\expandafter=\keyvalue}}%
+ \fi%
+ %\errmessage{TIKZUML ERROR : in umlpackage, invalid option \keyname}%
+ }%
+ }%
+ \pgfkeys{/tikzuml/package/.cd, #1}%
+ \pgfkeys{/tikzuml/package/.cd, x/.get=\tikzumlPackageXShift, y/.get=\tikzumlPackageYShift, name/.get=\tikzumlPackageName, type/.get=\tikzumlPackageTypeTmp,%
+ draw/.get=\tikzumlPackageDrawColor, fill/.get=\tikzumlPackageFillColor,%
+ text/.get=\tikzumlPackageTextColor%
+ }%
+ %
+
+ %
+ \ifthenelse{\equal{\tikzumlPackageTypeTmp}{tikzumlEmpty}}{%
+ \def\tikzumlPackageType{}%
+ }{%
+ \expandafter\def\expandafter\tikzumlPackageType\expandafter{$\ll$\tikzumlPackageTypeTmp$\gg$ \\}%
+ }%
+ %
+ \ifnum\thetikzumlPackageLevel>0%
+ \let\tikzumlPackage@nameold\tikzumlPackage@fitname%
+ \def\tikzumlPackage@name{#2}%
+ \begingroup%
+ \def\_{@}\edef\x{\endgroup%
+ \def\noexpand\tikzumlPackage@fitname{\tikzumlPackage@name}}\x%
+ \let\tikzumlPackage@parentold\tikzumlPackage@parent%
+ \edef\tikzumlPackage@parent{\tikzumlPackage@parentold @@\tikzumlPackage@nameold}%
+ \else%
+ \def\tikzumlPackage@parent{}%
+ \def\tikzumlPackage@name{#2}%
+ \begingroup%
+ \def\_{@}\edef\x{\endgroup%
+ \def\noexpand\tikzumlPackage@fitname{\tikzumlPackage@name}}\x%
+ \fi%
+ %
+ \let\tikzumlPackage@nodeNameold\tikzumlPackage@nodeName%
+ %
+ \begingroup%
+ \def\_{_}\edef\x{\endgroup%
+ \def\noexpand\tikzumlPackage@nodeName{\tikzumlPackage@name}}\x%
+ %
+ \ifthenelse{\equal{\tikzumlPackageName}{tikzumlEmpty}}{}{%
+ \def\tikzumlPackage@nodeName{\tikzumlPackageName}%
+ }%
+ %
+ \StrSubstitute{\tikzumlPackage@nodeName}{.}{@POINT@}{\tikzumlPackage@nodeName}%
+ %
+ \expandafter\gdef\csname tikzumlPackageFit\tikzumlPackage@parent @@\tikzumlPackage@fitname\endcsname{}%
+ %
+ \setcounter{tikzumlPackageClassNum}{0}%
+ \setcounter{tikzumlPackageSubPackageNum}{0}%
+ \stepcounter{tikzumlPackageLevel}%
+ %
+ \begin{scope}[xshift=\tikzumlPackageXShift cm, yshift=\tikzumlPackageYShift cm]%
+}{%
+ \addtocounter{tikzumlPackageLevel}{-1}%
+ \begin{pgfonlayer}{package\thetikzumlPackageLevel}%
+ %
+ % if contains no class, and not simple, one define a fictive node to enable the fit option
+ \ifnum\c@tikzumlPackageClassNum=0%
+ \ifnum\c@tikzumlPackageSubPackageNum=0%
+ \iftikzumlpackageWithoutCoords%
+ \node[inner sep=1.5ex, /tikzuml/package/style] (\tikzumlPackage@nodeName-root) {\phantom{\tikzumlPackage@nodeName}};%
+ \else%
+ \node[inner sep=1.5ex, /tikzuml/package/style] (\tikzumlPackage@nodeName-root) at (0,0) {\phantom{\tikzumlPackage@nodeName}};%
+ \fi%
+ \expandafter\xdef\csname tikzumlPackageFit\tikzumlPackage@parent @@\tikzumlPackage@fitname\endcsname{(\tikzumlPackage@nodeName-root)}%
+ \fi%
+ \fi%
+ %
+ \ifnum\c@tikzumlPackageLevel>0%
+ \def\tikzumlPackageFitTmp{\csname tikzumlPackageFit\tikzumlPackage@parent\endcsname}%
+ \expandafter\xdef\csname tikzumlPackageFit\tikzumlPackage@parent\endcsname{\tikzumlPackageFitTmp (\tikzumlPackage@nodeName) (\tikzumlPackage@nodeName-caption)}%
+ \stepcounter{tikzumlPackageSubPackageNum}%
+ \fi%
+ %
+ \node[draw=\tikzumlPackageDrawColor, fill=\tikzumlPackageFillColor, text=\tikzumlPackageTextColor, font=\tikzumlDefaultFont, inner sep=1.5ex, /tikzuml/package/style, fit = \csname tikzumlPackageFit\tikzumlPackage@parent @@\tikzumlPackage@fitname\endcsname] (\tikzumlPackage@nodeName) {};%
+ \node[draw=\tikzumlPackageDrawColor, fill=\tikzumlPackageFillColor, text=\tikzumlPackageTextColor, font=\tikzumlDefaultFont, minimum height=1.5em, outer ysep=-0.3, anchor=south west] (\tikzumlPackage@nodeName-caption) at (\tikzumlPackage@nodeName.north west) {\begin{tabular}{c} \tikzumlPackageType \textbf{\tikzumlPackage@name}\end{tabular}};%
+ \end{pgfonlayer}%
+ \end{scope}%
+}%
+%
+% shortcut to define an empty package
+\newcommand{\umlemptypackage}[2][]{\begin{umlpackage}[#1]{#2} \end{umlpackage}}%
+%
+% define a uml class
+% args : name of the class
+% attributes of the class
+% operations of the class
+% optional : x, y: coordinates of the class
+% width: of the class node
+% type: type of class (class, interface, typedef, enum)
+% tags: tagged values of class
+% template: template parameters
+% simple: if used, class is empty and drawn with a rectangle
+% circle: if used with simple, class is empty and drawn with a circle
+% draw, fill, fill template, and text: colors
+% style: to manage every default TikZ option
+% no coords: to tell that the class position is defined relatively
+% to another node (automatically used with TikZ options above, below, left, right, below left, ...)
+\newcommand{\umlclass}[4][]{%
+ \pgfkeys{/tikzuml/class/.cd, x/.initial=\tikzumlDefaultX, y/.initial=\tikzumlDefaultX, width/.initial=\tikzumlClassDefaultWidth, type/.initial=\tikzumlClassDefaultType,%
+ tags/.initial={}, style/.style={},%
+ template/.initial={}, name/.initial=tikzumlEmpty,%
+ draw/.initial=\tikzumlDefaultDrawColor,%
+ fill template/.initial=\tikzumlClassTemplateFillColorDefaultFillColor,%
+ fill/.initial=\tikzumlClassDefaultFillColor,%
+ text/.initial=\tikzumlDefaultTextColor,%
+ simple/.is if=tikzumlclassSimpleStyle, circle/.is if=tikzumlclassCircleShape, no coords/.is if=tikzumlclassWithoutCoords,%
+ simple=false, circle=false, no coords=false,%
+ .unknown/.code={%
+ \let\keyname=\pgfkeyscurrentname%
+ \let\keyvalue=\pgfkeyscurrentvalue%
+ \ifthenelse{\equal{\keyname}{above}\OR%
+ \equal{\keyname}{left}\OR%
+ \equal{\keyname}{below}\OR%
+ \equal{\keyname}{right}\OR%
+ \equal{\keyname}{above left}\OR%
+ \equal{\keyname}{above right}\OR%
+ \equal{\keyname}{below left}\OR%
+ \equal{\keyname}{below right}}{%
+ \IfSubStr{\keyvalue}{ of }{%
+ \pgfkeys{/tikzuml/class/.cd, no coords}%
+ }{}%
+ }{}%
+ \ifx\keyvalue\pgfkeysnovalue%
+ \pgfkeys{/tikzuml/class/.cd, style/.append style/.expand once={\keyname}}%
+ \else%
+ \pgfkeys{/tikzuml/class/.cd, style/.append style/.expand twice={\expandafter\keyname\expandafter=\keyvalue}}%
+ \fi%
+ %\errmessage{TIKZUML ERROR : in umlclass, invalid option \keyname}%
+ }%
+ }%
+ \pgfkeys{/tikzuml/class/.cd,#1}%
+ %
+ \iftikzumlclassSimpleStyle%
+ \iftikzumlclassCircleShape%
+ \pgfkeys{/tikzuml/class/.cd, width/.initial=\tikzumlSimpleInterfaceDefaultWidth}%
+ \fi%
+ \fi%
+ %
+ \pgfkeys{/tikzuml/class/.cd, x/.get=\tikzumlClassX, y/.get=\tikzumlClassY, width/.get=\tikzumlClassMinimumWidth,%
+ type/.get=\tikzumlClassTypeTmp, tags/.get=\tikzumlClassTagsTmp, template/.get=\tikzumlClassTemplateFillColorParam,%
+ name/.get=\tikzumlClassName,%
+ draw/.get=\tikzumlClassDrawColor, fill/.get=\tikzumlClassFillColor,%
+ text/.get=\tikzumlClassTextColor, fill template/.get=\tikzumlClassTemplateFillColor%
+ }%
+ %
+ \ifthenelse{\equal{\tikzumlClassTypeTmp}{class}\OR\equal{\tikzumlClassTypeTmp}{abstract}}{%
+ \def\tikzumlClassType{}%
+ }{%
+ \expandafter\def\expandafter\tikzumlClassType\expandafter{$\ll$\tikzumlClassTypeTmp$\gg$ \\}%
+ }%
+ %
+ \ifthenelse{\equal{\tikzumlClassTagsTmp}{}}{%
+ \def\tikzumlClassTags{}%
+ }{%
+ \def\tikzumlClassTags{\\ \{\tikzumlClassTagsTmp\}}%
+ }%
+ %
+ \ifthenelse{\equal{\tikzumlClassTemplateFillColorParam}{}}{%
+ \def\tikzumlClassVPadding{}%
+ \def\tikzumlClassHPadding{}%
+ }{%
+ \def\tikzumlClassVPadding{\vspace{0.1em} \\}%
+ \def\tikzumlClassHPadding{\hspace{0.5ex} $ $}%
+ }%
+ %
+ \def\tikzumlClassName{#2}%
+ %
+ \begingroup%
+ \def\_{_}\edef\x{\endgroup%
+ \def\noexpand\tikzumlClassNodeName{\tikzumlClassName}}\x%
+ %
+ \ifthenelse{\equal{\tikzumlClassName}{tikzumlEmpty}}{}{%
+ \def\tikzumlClassNodeName{\tikzumlClassName}%
+ }%
+ %
+ \StrSubstitute{\tikzumlClassNodeName}{:}{@COLON@}[\tikzumlClassNodeName]%
+ \StrSubstitute{\tikzumlClassNodeName}{\_}{@UNDERSCORE@}[\tikzumlClassNodeName]%
+ %
+ \ifthenelse{\equal{\tikzumlClassTypeTmp}{abstract}}{%
+ \let\tikzumlClassNameOld\tikzumlClassName%
+ \def\tikzumlClassName{{\it \tikzumlClassNameOld}}%
+ }{}%
+ %
+ \def\tikzumlClassPos{\tikzumlClassX,\tikzumlClassY}%
+ \def\tikzumlClassAttributes{#3}%
+ \def\tikzumlClassOperations{#4}%
+ %
+ \iftikzumlclassSimpleStyle%
+ \iftikzumlclassWithoutCoords%
+ \iftikzumlclassCircleShape%
+ \node[tikzuml simpleinterface style, draw=\tikzumlClassDrawColor, fill=\tikzumlClassFillColor, text=\tikzumlClassTextColor, font=\tikzumlDefaultFont, minimum width=\tikzumlClassMinimumWidth, /tikzuml/class/style] (\tikzumlClassNodeName) {};%
+ \node[anchor=south] (\tikzumlClassNodeName-label) at (\tikzumlClassNodeName.north) {\begin{tabular}{c}\tikzumlClassVPadding \tikzumlClassType \tikzumlClassHPadding \textbf{\tikzumlClassName} \tikzumlClassHPadding \tikzumlClassTags \end{tabular}%
+ };%
+ \else%
+ \node[tikzuml simpleclass style, draw=\tikzumlClassDrawColor, fill=\tikzumlClassFillColor, text=\tikzumlClassTextColor, font=\tikzumlDefaultFont, minimum width=\tikzumlClassMinimumWidth, /tikzuml/class/style] (\tikzumlClassNodeName) {\begin{tabular}{c}\tikzumlClassVPadding \tikzumlClassType \tikzumlClassHPadding \textbf{\tikzumlClassName} \tikzumlClassHPadding \tikzumlClassTags \end{tabular}%
+ };%
+ \fi%
+ \else%
+ \iftikzumlclassCircleShape%
+ \node[tikzuml simpleinterface style, draw=\tikzumlClassDrawColor, fill=\tikzumlClassFillColor, text=\tikzumlClassTextColor, font=\tikzumlDefaultFont, minimum width=\tikzumlClassMinimumWidth, /tikzuml/class/style] (\tikzumlClassNodeName) at (\tikzumlClassPos) {};
+ \node[anchor=south] (\tikzumlClassNodeName-label) at (\tikzumlClassNodeName.north){\begin{tabular}{c}\tikzumlClassVPadding \tikzumlClassType \tikzumlClassHPadding \textbf{\tikzumlClassName} \tikzumlClassHPadding \tikzumlClassTags \end{tabular}%
+ };%
+ \else%
+ \node[tikzuml simpleclass style, draw=\tikzumlClassDrawColor, fill=\tikzumlClassFillColor, text=\tikzumlClassTextColor, font=\tikzumlDefaultFont, minimum width=\tikzumlClassMinimumWidth, /tikzuml/class/style] (\tikzumlClassNodeName) at (\tikzumlClassPos) {\begin{tabular}{c}\tikzumlClassVPadding \tikzumlClassType \tikzumlClassHPadding \textbf{\tikzumlClassName} \tikzumlClassHPadding \tikzumlClassTags \end{tabular}%
+ };%
+ \fi%
+ \fi%
+ \else%
+ \iftikzumlclassWithoutCoords%
+ \node[tikzuml class style, draw=\tikzumlClassDrawColor, fill=\tikzumlClassFillColor, text=\tikzumlClassTextColor, font=\tikzumlDefaultFont, minimum width=\tikzumlClassMinimumWidth, /tikzuml/class/style] (\tikzumlClassNodeName) {\begin{tabular}{c}\tikzumlClassVPadding \tikzumlClassType \tikzumlClassHPadding \textbf{\tikzumlClassName} \tikzumlClassHPadding \tikzumlClassTags \end{tabular}%
+ \nodepart{second}%
+ \begin{tabular}{l}%
+ \tikzumlClassAttributes%
+ \end{tabular}%
+ \nodepart{third}%
+ \begin{tabular}{l}%
+ \tikzumlClassOperations%
+ \end{tabular}%
+ };%
+ \else%
+ \node[tikzuml class style, draw=\tikzumlClassDrawColor, fill=\tikzumlClassFillColor, text=\tikzumlClassTextColor, font=\tikzumlDefaultFont, minimum width=\tikzumlClassMinimumWidth, /tikzuml/class/style] (\tikzumlClassNodeName) at (\tikzumlClassPos) {\begin{tabular}{c}\tikzumlClassVPadding \tikzumlClassType \tikzumlClassHPadding \textbf{\tikzumlClassName} \tikzumlClassHPadding \tikzumlClassTags \end{tabular}%
+ \nodepart{second}%
+ \begin{tabular}{l}%
+ \tikzumlClassAttributes%
+ \end{tabular}%
+ \nodepart{third}%
+ \begin{tabular}{l}%
+ \tikzumlClassOperations%
+ \end{tabular}%
+ };%
+ \fi%
+ \fi%
+ %
+ \ifthenelse{\equal{\tikzumlClassTemplateFillColorParam}{}}{}{%
+ \draw (\tikzumlClassNodeName.north east) node[tikzuml template style, name=\tikzumlClassNodeName-template, draw=\tikzumlClassDrawColor, fill=\tikzumlClassTemplateFillColor, text=\tikzumlClassTextColor, font=\tikzumlDefaultFont] {\tikzumlClassTemplateFillColorParam};%
+ }%
+ %
+ % add to fit
+ \ifnum\c@tikzumlPackageLevel>0%
+ \edef\tikzumlPackageFitOld{\csname tikzumlPackageFit\tikzumlPackage@parent @@\tikzumlPackage@fitname\endcsname}%
+ \ifthenelse{\equal{\tikzumlClassTemplateFillColorParam}{}}{%
+ \expandafter\xdef\csname tikzumlPackageFit\tikzumlPackage@parent @@\tikzumlPackage@fitname\endcsname{\tikzumlPackageFitOld (\tikzumlClassNodeName)}%
+ }{%
+ \expandafter\xdef\csname tikzumlPackageFit\tikzumlPackage@parent @@\tikzumlPackage@fitname\endcsname{\tikzumlPackageFitOld (\tikzumlClassNodeName) (\tikzumlClassNodeName-template)}%
+ }%
+ \stepcounter{tikzumlPackageClassNum}%
+ \fi%
+ \ifnum\c@tikzumlComponentLevel>0%
+ \def\tikzumlComponentFitTmp{\csname tikzumlComponentFit\tikzumlComponent@parent @@\tikzumlComponent@fitname\endcsname}%
+ \ifthenelse{\equal{\tikzumlClassTemplateFillColorParam}{}}{%
+ \expandafter\xdef\csname tikzumlComponentFit\tikzumlComponent@parent @@\tikzumlComponent@fitname\endcsname{\tikzumlComponentFitTmp (\tikzumlClassNodeName)}%
+ }{%
+ \expandafter\xdef\csname tikzumlComponentFit\tikzumlComponent@parent @@\tikzumlComponent@fitname\endcsname{\tikzumlComponentFitTmp (\tikzumlClassNodeName) (\tikzumlClassNodeName-template)}%
+ }%
+ \stepcounter{tikzumlComponentSubComponentNum}%
+ \fi%
+}%
+%
+% shortcuts for interface, enum and typedef environments
+\newcommand{\umlabstract}[4][]{%
+ \pgfkeys{/tikzuml/class/.cd, .unknown/.code={%
+ \let\keyname=\pgfkeyscurrentname%
+ \let\keyvalue=\pgfkeyscurrentvalue%
+ \ifthenelse{\equal{\keyname}{type}}{%
+ \errmessage{TIKZUML ERROR : in umlabstract, forbidden option type}%
+ }{}%
+ }%
+ }%
+ \pgfkeys{/tikzuml/class/.cd, #1}%
+ \umlclass[type=abstract,#1]{#2}{#3}{#4}%
+}%
+\newcommand{\umlinterface}[4][]{%
+ \pgfkeys{/tikzuml/class/.cd, .unknown/.code={%
+ \let\keyname=\pgfkeyscurrentname%
+ \let\keyvalue=\pgfkeyscurrentvalue%
+ \ifthenelse{\equal{\keyname}{type}}{%
+ \errmessage{TIKZUML ERROR : in umlinterface, forbidden option type}%
+ }{}%
+ }%
+ }%
+ \pgfkeys{/tikzuml/class/.cd, #1}%
+ \umlclass[type=interface,#1]{#2}{#3}{#4}%
+}%
+\newcommand{\umltypedef}[4][]{%
+ \pgfkeys{/tikzuml/class/.cd, .unknown/.code={%
+ \let\keyname=\pgfkeyscurrentname%
+ \let\keyvalue=\pgfkeyscurrentvalue%
+ \ifthenelse{\equal{\keyname}{type}}{%
+ \errmessage{TIKZUML ERROR : in umltypedef, forbidden option type}%
+ }{}%
+ }%
+ }%
+ \pgfkeys{/tikzuml/class/.cd, #1}%
+ \umlclass[type=typedef,#1]{#2}{#3}{#4}%
+}%
+\newcommand{\umlenum}[4][]{%
+ \pgfkeys{/tikzuml/class/.cd, .unknown/.code={%
+ \let\keyname=\pgfkeyscurrentname%
+ \let\keyvalue=\pgfkeyscurrentvalue%
+ \ifthenelse{\equal{\keyname}{type}}{%
+ \errmessage{TIKZUML ERROR : in umlenum, forbidden option type}%
+ }{}%
+ }%
+ }%
+ \pgfkeys{/tikzuml/class/.cd, #1}%
+ \umlclass[type=enum,#1]{#2}{#3}{#4}
+}%
+%
+% shortcut to define an empty class
+\newcommand{\umlemptyclass}[2][]{\umlclass[#1]{#2}{}{}}%
+\newcommand{\umlsimpleclass}[2][]{%
+ \pgfkeys{/tikzuml/class/.cd, .unknown/.code={%
+ \let\keyname=\pgfkeyscurrentname%
+ \let\keyvalue=\pgfkeyscurrentvalue%
+ \ifthenelse{\equal{\keyname}{simple}}{%
+ \errmessage{TIKZUML ERROR : in umlsimpleclass, forbidden option simple}%
+ }{}%
+ }%
+ }%
+ \pgfkeys{/tikzuml/class/.cd, #1}%
+ \umlemptyclass[simple, #1]{#2}%
+}%
+%
+\newcommand{\umlsimpleinterface}[2][]{%
+ \pgfkeys{/tikzuml/class/.cd, .unknown/.code={%
+ \let\keyname=\pgfkeyscurrentname%
+ \let\keyvalue=\pgfkeyscurrentvalue%
+ \ifthenelse{\equal{\keyname}{simple}}{%
+ \errmessage{TIKZUML ERROR : in umlsimpleinterface, forbidden option simple}%
+ }{%
+ \ifthenelse{\equal{\keyname}{circle}}{%
+ \errmessage{TIKZUML ERROR : in umlsimpleinterface, forbidden option circle}%
+ }{}%
+ }%
+ }%
+ }%
+ \pgfkeys{/tikzuml/class/.cd, #1}%
+ \umlsimpleclass[circle, #1]{#2}%
+}%
+% underline the text for static arg
+\newcommand{\umlstatic}[1]{\underline{#1}}%
+\newcommand{\umlvirt}[1]{\textit{#1}}%
+%
+% define node for n-ary association
+\newcommand{\umlNarynode}[2][]{%
+ \def\tikzumlNaryNodeAnchor{.north}
+ \def\tikzumlNaryNodeLabelPos{above}
+ \pgfkeys{/tikzuml/narynode/.cd, x/.initial=\tikzumlDefaultX, y/.initial=\tikzumlDefaultX, width/.initial=\tikzumlNaryNodeDefaultWidth, name/.initial=tikzumlEmpty,%
+ draw/.initial=\tikzumlDefaultDrawColor, fill/.initial=\tikzumlClassDefaultFillColor,%
+ text/.initial=\tikzumlDefaultTextColor, style/.style={},%
+ .unknown/.code={%
+ \let\keyname=\pgfkeyscurrentname%
+ \let\keyvalue=\pgfkeyscurrentvalue%
+ \ifthenelse{\equal{\keyname}{above}}{%
+ \def\tikzumlNaryNodeAnchor{.north}%
+ \def\tikzumlNaryNodeLabelPos{above}%
+ }{%
+ \ifthenelse{\equal{\keyname}{above left}}{%
+ \def\tikzumlNaryNodeAnchor{.north west}%
+ \def\tikzumlNaryNodeLabelPos{above left}%
+ }{%
+ \ifthenelse{\equal{\keyname}{left}}{%
+ \def\tikzumlNaryNodeAnchor{.west}%
+ \def\tikzumlNaryNodeLabelPos{left}%
+ }{%
+ \ifthenelse{\equal{\keyname}{below left}}{%
+ \def\tikzumlNaryNodeAnchor{.south west}%
+ \def\tikzumlNaryNodeLabelPos{below left}%
+ }{%
+ \ifthenelse{\equal{\keyname}{below}}{%
+ \def\tikzumlNaryNodeAnchor{.south}%
+ \def\tikzumlNaryNodeLabelPos{below}%
+ }{%
+ \ifthenelse{\equal{\keyname}{below right}}{%
+ \def\tikzumlNaryNodeAnchor{.south east}%
+ \def\tikzumlNaryNodeLabelPos{below right}%
+ }{%
+ \ifthenelse{\equal{\keyname}{right}}{%
+ \def\tikzumlNaryNodeAnchor{.east}%
+ \def\tikzumlNaryNodeLabelPos{right}%
+ }{%
+ \ifthenelse{\equal{\keyname}{above right}}{%
+ \def\tikzumlNaryNodeAnchor{.north east}%
+ \def\tikzumlNaryNodeLabelPos{above right}%
+ }{%
+ \ifx\keyvalue\pgfkeysnovalue%
+ \pgfkeys{/tikzuml/narynode/.cd, style/.append style/.expand once={\keyname}}%
+ \else%
+ \pgfkeys{/tikzuml/narynode/.cd, style/.append style/.expand twice={\expandafter\keyname\expandafter=\keyvalue}}%
+ \fi%
+ %\errmessage{TIKZUML ERROR : in umlNarynode, invalid option \keyname}%
+ }%
+ }%
+ }%
+ }%
+ }%
+ }%
+ }%
+ }%
+ }%
+ }%
+ \pgfkeys{/tikzuml/narynode/.cd,#1}%
+ \pgfkeys{/tikzuml/narynode/.cd, x/.get=\tikzumlNaryNodeX, y/.get=\tikzumlNaryNodeY, width/.get=\tikzumlNaryNodeMinimumWidth,%
+ name/.get=\tikzumlNaryNodeName,%
+ draw/.get=\tikzumlNaryNodeDrawColor, fill/.get=\tikzumlNaryNodeFillColor,%
+ text/.get=\tikzumlNaryNodeTextColor%
+ }%
+ %
+ \def\tikzumlNaryName{#2}%
+ %
+ \ifthenelse{\equal{\tikzumlNaryNodeName}{tikzumlEmpty}}{%
+ \edef\tikzumlNaryNodeName{\tikzumlNaryName}%
+ }{%
+ \edef\tikzumlNaryNodeName{\tikzumlNaryNodeName}%
+ }%
+ %
+ \begingroup%
+ \def\_{_}\edef\x{\endgroup%
+ \def\noexpand\tikzumlNaryNode@nodeName{\tikzumlNaryNodeName}}\x%
+ %
+ \StrSubstitute{\tikzumlNaryNode@nodeName}{:}{@COLON@}[\tikzumlNaryNode@nodeName]%
+ \StrSubstitute{\tikzumlNaryNode@nodeName}{\_}{@UNDERSCORE@}[\tikzumlNaryNode@nodeName]%
+ %
+ \def\tikzumlNarynodePos{\tikzumlNaryNodeX,\tikzumlNaryNodeY}%
+ %
+ \node[tikzuml narynode style, draw=\tikzumlNaryNodeDrawColor, fill=\tikzumlNaryNodeFillColor, text=\tikzumlNaryNodeTextColor, font=\tikzumlDefaultFont, minimum width=\tikzumlNaryNodeMinimumWidth, minimum height=\tikzumlNaryNodeMinimumWidth, /tikzuml/narynode/style] (\tikzumlNaryNode@nodeName) at (\tikzumlNarynodePos) {};%
+ \draw (\tikzumlNaryNode@nodeName\tikzumlNaryNodeAnchor) node[\tikzumlNaryNodeLabelPos] {\tikzumlNaryName};%
+ %
+ % add to fit
+ \ifnum\c@tikzumlPackageLevel>0%
+ \edef\tikzumlPackageFitOld{\csname tikzumlPackageFit\tikzumlPackage@parent @@\tikzumlPackage@fitname\endcsname}%
+ \expandafter\xdef\csname tikzumlPackageFit\tikzumlPackage@parent @@\tikzumlPackage@fitname\endcsname{\tikzumlPackageFitOld (\tikzumlNaryNode@nodeName)}%
+ \stepcounter{tikzumlPackageClassNum}%
+ \fi%
+}%
+%
+\newdimen\tikzumlNestingSymbolSize%
+%
+% main command to define a relation between two classes
+% args : src class
+% dest class
+% optional : geometry: geometry of the line
+% weight: barycentric weight of the middle part when geometry is a 3-line
+% arm1, arm2: lengths of first or last part when geometry id a 3-line
+% arg1, arg2, arg: name of the src/dest/dest side class type attribute defined by the relation
+% mult1, mult2, mult: multiplicity of the src/dest/dest side class type attribute defined by the relation
+% pos1, pos2, pos: position of the src/dest/dest side class type attribute defined by the relation
+% align1, align2, align: text justification of the src/dest/dest side class type attribute defined by the relation
+% anchor1, anchor2: src/dest anchors on linked classes
+% angle1, angle2, loopsize: start angle, end angle and size of the relation (only if recursive)
+% stereo: stereotype of the relation
+% pos stereo: position of the stereotype on the relation
+% style: style of the relation (association, aggregation, composition, inherit, ...)
+% name: rootname used for naming nodes of the relation
+% recursive mode: type of recursive arrow (transition for state diagrams, or default)
+% recursive direction start/end: when transition relation, start/end directions of the relation arrow
+\newcommand{\umlrelation}[3][]{%
+ \pgfkeys{/tikzuml/relation/.cd, geometry/.initial=\tikzumlRelationDefaultGeometry, weight/.initial=\tikzumlRelationDefaultWeight,%
+ arm1/.initial=auto, arm2/.initial=auto,%
+ arg1/.initial={}, arg2/.initial={}, arg/.initial={},%
+ mult1/.initial={}, mult2/.initial={}, mult/.initial={},%
+ pos1/.initial=\tikzumlRelationDefaultPosO, pos2/.initial=\tikzumlRelationDefaultPosT, pos/.initial=tikzumlEmpty,%
+ align1/.initial={}, align2/.initial={}, align/.initial={},%
+ anchor1/.initial=tikzumlEmpty, anchor2/.initial=tikzumlEmpty,%
+ angle1/.initial=\tikzumlRelationDefaultAngleO, angle2/.initial=\tikzumlRelationDefaultAngleT, loopsize/.initial=\tikzumlRelationDefaultLoopSize,%
+ stereo/.initial={}, pos stereo/.initial=\tikzumlRelationDefaultPosStereo,%
+ style/.initial=->, style2/.style={}, name/.initial=relation-\thetikzumlRelationNum,%
+ recursive mode/.initial=default, recursive direction start/.initial=right,%
+ recursive direction end/.initial=bottom,%
+ .unknown/.code={%
+ \let\keyname=\pgfkeyscurrentname%
+ \let\keyvalue=\pgfkeyscurrentvalue%
+ \ifthenelse{\equal{\keyname}{with port}%
+ \OR\equal{\keyname}{interface}%
+ \OR\equal{\keyname}{padding}%
+ \OR\equal{\keyname}{width}%
+ \OR\equal{\keyname}{first arm}%
+ \OR\equal{\keyname}{second arm}%
+ \OR\equal{\keyname}{middle arm}%
+ \OR\equal{\keyname}{last arm}%
+ \OR\equal{\keyname}{distance}}{}{%
+ \ifx\keyvalue\pgfkeysnovalue%
+ \pgfkeys{/tikzuml/relation/.cd, style2/.append style/.expand once={\keyname}}%
+ \else%
+ \pgfkeys{/tikzuml/relation/.cd, style2/.append style/.expand twice={\expandafter\keyname\expandafter=\keyvalue}}%
+ \fi%
+ %\errmessage{TIKZUML ERROR : in umlrelation, invalid option \keyname}%
+ }%
+ }%
+ }%
+ \pgfkeys{/tikzuml/relation/.cd,#1}%
+ \pgfkeys{/tikzuml/relation/.cd, geometry/.get=\tikzumlRelationGeometry, weight/.get=\tikzumlRelationWeight,%
+ arm1/.get=\tikzumlRelationArmO, arm2/.get=\tikzumlRelationArmT,%
+ arg1/.get=\tikzumlRelationAttrName, arg2/.get=\tikzumlRelationAttrNameTO, arg/.get=\tikzumlRelationAttrNameTT,%
+ mult1/.get=\tikzumlRelationMultiplicity, mult2/.get=\tikzumlRelationMultiplicityTO, mult/.get=\tikzumlRelationMultiplicityTT,%
+ pos1/.get=\tikzumlRelationPosition, pos2/.get=\tikzumlRelationPositionTO, pos/.get=\tikzumlRelationPositionTT,%
+ align1/.get=\tikzumlRelationAlign, align2/.get=\tikzumlRelationAlignTO, align/.get=\tikzumlRelationAlignTT,%
+ anchor1/.get=\tikzumlRelationSrcAnchor, anchor2/.get=\tikzumlRelationDestAnchor,%
+ angle1/.get=\tikzumlRelationStartAngle, angle2/.get=\tikzumlRelationEndAngle, loopsize/.get=\tikzumlRelationLoopSize,%
+ stereo/.get=\tikzumlRelationStereoType, pos stereo/.get=\tikzumlRelationPositionStereotype,%
+ style/.get=\tikzumlRelationStyle, name/.get=\tikzumlRelationName,%
+ recursive mode/.get=\tikzumlRelationRecursiveMode,%
+ recursive direction start/.get=\tikzumlRelationRecursiveDirectionStart,%
+ recursive direction end/.get=\tikzumlRelationRecursiveDirectionEnd%
+ }%
+ %
+ \def\tikzumlSrcClassName{#2}%
+ %
+ % managing \_ in class names for node names
+ \begingroup%
+ \def\_{_}\edef\x{\endgroup%
+ \def\noexpand\tikzumlSrcClassNodeName{\tikzumlSrcClassName}}\x%
+ %
+ \StrSubstitute{\tikzumlSrcClassNodeName}{:}{@COLON@}[\tikzumlSrcClassNodeName]%
+ \StrSubstitute{\tikzumlSrcClassNodeName}{\_}{@UNDERSCORE@}[\tikzumlSrcClassNodeName]%
+ %
+ \def\tikzumlDestClassName{#3}%
+ \begingroup%
+ \def\_{_}\edef\x{\endgroup%
+ \def\noexpand\tikzumlDestClassNodeName{\tikzumlDestClassName}}\x%
+ %
+ \StrSubstitute{\tikzumlDestClassNodeName}{:}{@COLON@}[\tikzumlDestClassNodeName]%
+ \StrSubstitute{\tikzumlDestClassNodeName}{\_}{@UNDERSCORE@}[\tikzumlDestClassNodeName]%
+ %
+ % managing alias keys
+ \def\tikzumlRelationAttrNameT{\tikzumlRelationAttrNameTO\tikzumlRelationAttrNameTT}%
+ \def\tikzumlRelationMultiplicityT{\tikzumlRelationMultiplicityTO\tikzumlRelationMultiplicityTT}%
+ \def\tikzumlRelationAlignT{\tikzumlRelationAlignTO\tikzumlRelationAlignTT}%
+ \def\posAttrName{}%
+ \def\posMultiplicity{}%
+ \def\posAttrNameT{}%
+ \def\posMultiplicityT{}%
+ %
+ \ifthenelse{\equal{\tikzumlRelationPositionTT}{tikzumlEmpty}}{%
+ \def\tikzumlRelationPositionT{\tikzumlRelationPositionTO}%
+ }{%
+ \def\tikzumlRelationPositionT{\tikzumlRelationPositionTT}%
+ }%
+ %
+ \def\attrAlign{}%
+ \def\multAlign{}%
+ \def\attrAlignT{}%
+ \def\multAlignT{}%
+ %
+ \ifthenelse{\equal{\tikzumlRelationAlign}{left}}{%
+ \def\attrAlign{above right}%
+ \def\multAlign{below right}%
+ }{%
+ \ifthenelse{\equal{\tikzumlRelationAlign}{right}}{%
+ \def\attrAlign{above left}%
+ \def\multAlign{below left}%
+ }{}%
+ }%
+ %
+ \ifthenelse{\equal{\tikzumlRelationAlignT}{left}}{%
+ \def\attrAlignT{above right}%
+ \def\multAlignT{below right}%
+ }{%
+ \ifthenelse{\equal{\tikzumlRelationAlignT}{right}}{%
+ \def\attrAlignT{above left}%
+ \def\multAlignT{below left}%
+ }{}%
+ }%
+ %
+ % def stereotype
+ \ifthenelse{\equal{\tikzumlRelationStereoType}{}}{%
+ \def\stereotype{}%
+ }{%
+ \def\stereotype{$\ll$\tikzumlRelationStereoType$\gg$}%
+ }%
+
+ % def anchors macros
+ \ifthenelse{\equal{\tikzumlRelationSrcAnchor}{tikzumlEmpty}}{%
+ \def\tikzumlRelationSrcAnchor{}%
+ }{%
+ \let\tikzumlRelationSrcAnchorold\tikzumlRelationSrcAnchor%
+ \def\tikzumlRelationSrcAnchor{.\tikzumlRelationSrcAnchorold}%
+ }%
+ %
+ \ifthenelse{\equal{\tikzumlRelationDestAnchor}{tikzumlEmpty}}{%
+ \def\tikzumlRelationDestAnchor{}%
+ }{%
+ \let\tikzumlRelationDestAnchorold\tikzumlRelationDestAnchor%
+ \def\tikzumlRelationDestAnchor{.\tikzumlRelationDestAnchorold}%
+ }%
+ %
+ \setcounter{pos}{100*\real{\tikzumlRelationPosition}}%
+ \setcounter{posT}{100*\real{\tikzumlRelationPositionT}}%
+ \setcounter{posStereo}{100*\real{\tikzumlRelationPositionStereotype}}%
+ %
+ \pgfmathsetmacro{\tikzumlRelationWeightT}{1.0-\tikzumlRelationWeight}%
+ %
+ %\newcounter{tikzumlControlNodesNum}%
+ %\setcounter{tikzumlControlNodesNum}{0}%
+ %
+ \node[inner sep=0] (\tikzumlRelationName-middle) at (barycentric cs:\tikzumlSrcClassNodeName=\tikzumlRelationWeightT,\tikzumlDestClassNodeName=\tikzumlRelationWeight) {};%
+ %
+ % straight line
+ \ifthenelse{\equal{\tikzumlRelationGeometry}{--}}%
+ {%
+ \ifthenelse{\equal{\tikzumlSrcClassNodeName}{\tikzumlDestClassNodeName}}{%
+ \def\arcNum{1}%
+ \def\arcNumT{1}%
+ %
+ \ifthenelse{\equal{\tikzumlRelationRecursiveMode}{default}}{%
+ \xdef\tikzumlLastArc{node[pos=\tikzumlRelationPosition, \posAttrName, \attrAlign] {\tikzumlRelationAttrName}%
+ node[pos=\tikzumlRelationPosition, swap, \posMultiplicity, \multAlign] {\tikzumlRelationMultiplicity}%
+ node[pos=\tikzumlRelationPositionT, \posAttrNameT, \attrAlignT] {\tikzumlRelationAttrNameT}%
+ node[pos=\tikzumlRelationPositionT, swap, \posMultiplicityT, \multAlignT] {\tikzumlRelationMultiplicityT}%
+ node[pos=\tikzumlRelationPositionStereotype, anchor=center] {\stereotype} }%
+ \xdef\tikzumlPath{(\tikzumlSrcClassNodeName) edge[in=\tikzumlRelationEndAngle, out=\tikzumlRelationStartAngle, distance=\tikzumlRelationLoopSize] \tikzumlLastArc%
+ node[midway, inner sep=0, name=\tikzumlRelationName-1, anchor=center] {} (\tikzumlDestClassNodeName) }%
+ }{%
+ \ifthenelse{\equal{\tikzumlRelationRecursiveMode}{transition}}{%
+ \xdef\tikzumlFirstArc{node[midway, inner sep=0, name=\tikzumlRelationName-1, anchor=center] {}}%
+ \xdef\tikzumlMidOneArc{node[midway, inner sep=0, name=\tikzumlRelationName-3, anchor=center] {}}%
+ %
+ \ifthenelse{\equal{\tikzumlRelationRecursiveDirectionStart}{\tikzumlRelationRecursiveDirectionEnd}}{%
+ \def\numArcs{3}%
+ \xdef\tikzumlLastArc{node[midway, inner sep=0, name=\tikzumlRelationName-5, anchor=center] {}}%
+ %
+ \begin{pgfonlayer}{connections}%
+ \draw (\tikzumlSrcClassNodeName) edge[in=\tikzumlRelationEndAngle, out=\tikzumlRelationStartAngle, distance=\tikzumlRelationLoopSize, draw=none] %
+ node[midway, inner sep=0, name=\tikzumlRelationName-tmp, anchor=center] {} (\tikzumlDestClassNodeName);%
+ \ifthenelse{\equal{\tikzumlRelationRecursiveDirectionStart}{right}\OR\equal{\tikzumlRelationRecursiveDirectionStart}{left}}{%
+ \node[inner sep=0, name=\tikzumlRelationName-2] at (\tikzumlSrcClassNodeName.\tikzumlRelationStartAngle -| \tikzumlRelationName-tmp) {};%
+ \node[inner sep=0, name=\tikzumlRelationName-4] at (\tikzumlDestClassNodeName.\tikzumlRelationEndAngle -| \tikzumlRelationName-tmp) {};%
+ }{%
+ \node[inner sep=0, name=\tikzumlRelationName-2] at (\tikzumlSrcClassNodeName.\tikzumlRelationStartAngle |- \tikzumlRelationName-tmp) {};%
+ \node[inner sep=0, name=\tikzumlRelationName-4] at (\tikzumlDestClassNodeName.\tikzumlRelationEndAngle |- \tikzumlRelationName-tmp) {};%
+ }%
+ \end{pgfonlayer}%
+ }{%
+ \def\numArcs{4}%
+ \xdef\tikzumlMidTwoArc{node[midway, inner sep=0, name=\tikzumlRelationName-5, anchor=center] {}}%
+ \xdef\tikzumlLastArc{node[midway, inner sep=0, name=\tikzumlRelationName-7, anchor=center] {}}%
+ %
+ \begin{pgfonlayer}{connections}%
+ \draw (\tikzumlSrcClassNodeName) edge[in=\tikzumlRelationEndAngle, out=\tikzumlRelationStartAngle, distance=\tikzumlRelationLoopSize, draw=none] %
+ node[midway, name=\tikzumlRelationName-4, anchor=center] {} (\tikzumlDestClassNodeName);%
+ \ifthenelse{\equal{\tikzumlRelationRecursiveDirectionStart}{right}\OR\equal{\tikzumlRelationRecursiveDirectionStart}{left}}{%
+ \node[inner sep=0, name=\tikzumlRelationName-2] at (\tikzumlSrcClassNodeName.\tikzumlRelationStartAngle -| \tikzumlRelationName-4) {};%
+ \node[inner sep=0, name=\tikzumlRelationName-6] at (\tikzumlDestClassNodeName.\tikzumlRelationEndAngle |- \tikzumlRelationName-4) {};%
+ }{%
+ \node[inner sep=0, name=\tikzumlRelationName-2] at (\tikzumlSrcClassNodeName.\tikzumlRelationStartAngle |- \tikzumlRelationName-4) {};%
+ \node[inner sep=0, name=\tikzumlRelationName-6] at (\tikzumlDestClassNodeName.\tikzumlRelationEndAngle -| \tikzumlRelationName-4) {};%
+ }%
+ \end{pgfonlayer}%
+ }%
+ %
+ \ifnum\numArcs=4%
+ \ifnum\theposStereo>300%
+ \pgfmathsetmacro{\tikzumlRelationPositionStereotype}{(\theposStereo-300)/100}%
+ \xdef\tikzumlLastArc{\tikzumlLastArc node[pos=\tikzumlRelationPositionStereotype, anchor=center] {\stereotype}}%
+ \else%
+ \ifnum\theposStereo<100%
+ \xdef\tikzumlFirstArc{\tikzumlFirstArc node[pos=\tikzumlRelationPositionStereotype, anchor=center] {\stereotype}}%
+ \else%
+ \ifnum\theposStereo>200%
+ \pgfmathsetmacro{\tikzumlRelationPositionStereotype}{(\theposStereo-200)/100}%
+ \xdef\tikzumlMidTwoArc{\tikzumlMidTwoArc node[pos=\tikzumlRelationPositionStereotype, anchor=center] {\stereotype}}%
+ \else%
+ \pgfmathsetmacro{\tikzumlRelationPositionStereotype}{(\theposStereo-100)/100}%
+ \xdef\tikzumlMidOneArc{\tikzumlMidOneArc node[pos=\tikzumlRelationPositionStereotype, anchor=center] {\stereotype}}%
+ \fi%
+ \fi%
+ \fi%
+ %
+ \ifthenelse{\thepos=300\OR\thepos=100}{%
+ \ifthenelse{\equal{\tikzumlRelationRecursiveDirectionStart}{right}}{%
+ \ifthenelse{\equal{\tikzumlRelationRecursiveDirectionEnd}{bottom}}{%
+ \def\posAttrName{above right}%
+ \def\posMultiplicity{below left}%
+ }{%
+ \def\posAttrName{above left}%
+ \def\posMultiplicity{below right}%
+ }%
+ }{%
+ \ifthenelse{\equal{\tikzumlRelationRecursiveDirectionStart}{left}}{%
+ \ifthenelse{\equal{\tikzumlRelationRecursiveDirectionEnd}{bottom}}{%
+ \def\posAttrName{above left}%
+ \def\posMultiplicity{below right}%
+ }{%
+ \def\posAttrName{above right}%
+ \def\posMultiplicity{below left}%
+ }%
+ }{%
+ \ifthenelse{\equal{\tikzumlRelationRecursiveDirectionStart}{top}}{%
+ \ifthenelse{\equal{\tikzumlRelationRecursiveDirectionEnd}{left}}{%
+ \def\posAttrName{above right}%
+ \def\posMultiplicity{below left}%
+ }{%
+ \def\posAttrName{above left}%
+ \def\posMultiplicity{below right}%
+ }%
+ }{%
+ \ifthenelse{\equal{\tikzumlRelationRecursiveDirectionEnd}{left}}{%
+ \def\posAttrName{above left}%
+ \def\posMultiplicity{below right}%
+ }{%
+ \def\posAttrName{above right}%
+ \def\posMultiplicity{below left}%
+ }%
+ }%
+ }%
+ }%
+ }{}%
+ %
+ \ifthenelse{\thepos=200}{%
+ \ifthenelse{\equal{\tikzumlRelationRecursiveDirectionStart}{right}}{%
+ \ifthenelse{\equal{\tikzumlRelationRecursiveDirectionEnd}{bottom}}{%
+ \def\posAttrName{above left}%
+ \def\posMultiplicity{below right}%
+ }{%
+ \def\posAttrName{above right}%
+ \def\posMultiplicity{below left}%
+ }%
+ }{%
+ \ifthenelse{\equal{\tikzumlRelationRecursiveDirectionStart}{left}}{%
+ \ifthenelse{\equal{\tikzumlRelationRecursiveDirectionEnd}{bottom}}{%
+ \def\posAttrName{above right}%
+ \def\posMultiplicity{below left}%
+ }{%
+ \def\posAttrName{above left}%
+ \def\posMultiplicity{below right}%
+ }%
+ }{%
+ \ifthenelse{\equal{\tikzumlRelationRecursiveDirectionStart}{top}}{%
+ \ifthenelse{\equal{\tikzumlRelationRecursiveDirectionEnd}{left}}{%
+ \def\posAttrName{above left}%
+ \def\posMultiplicity{below right}%
+ }{%
+ \def\posAttrName{above right}%
+ \def\posMultiplicity{below left}%
+ }%
+ }{%
+ \ifthenelse{\equal{\tikzumlRelationRecursiveDirectionEnd}{left}}{%
+ \def\posAttrName{above right}%
+ \def\posMultiplicity{below left}%
+ }{%
+ \def\posAttrName{above left}%
+ \def\posMultiplicity{below right}%
+ }%
+ }%
+ }%
+ }%
+ }{}%
+ %
+ \ifnum\thepos>300%
+ \pgfmathsetmacro{\tikzumlRelationPosition}{(\thepos-300)/100}%
+ \xdef\tikzumlLastArc{\tikzumlLastArc node[pos=\tikzumlRelationPosition, \posAttrName, \attrAlign] {\tikzumlRelationAttrName}%
+ node[pos=\tikzumlRelationPosition, swap, \posMultiplicity, \multAlign] {\tikzumlRelationMultiplicity}%
+ }%
+ \else%
+ \ifnum\thepos<100%
+ \xdef\tikzumlFirstArc{\tikzumlFirstArc node[pos=\tikzumlRelationPosition, \posAttrName, \attrAlign] {\tikzumlRelationAttrName}%
+ node[pos=\tikzumlRelationPosition, swap, \posMultiplicity, \multAlign] {\tikzumlRelationMultiplicity}%
+ }%
+ \else%
+ \ifnum\thepos>200%
+ \pgfmathsetmacro{\tikzumlRelationPosition}{(\thepos-200)/100}%
+ \xdef\tikzumlMidTwoArc{\tikzumlMidTwoArc node[pos=\tikzumlRelationPosition, \posAttrName, \attrAlign] {\tikzumlRelationAttrName}%
+ node[pos=\tikzumlRelationPosition, swap, \posMultiplicity, \multAlign] {\tikzumlRelationMultiplicity}%
+ }%
+ \else%
+ \pgfmathsetmacro{\tikzumlRelationPosition}{(\thepos-100)/100}%
+ \xdef\tikzumlMidOneArc{\tikzumlMidOneArc node[pos=\tikzumlRelationPosition, \posAttrName, \attrAlign] {\tikzumlRelationAttrName}%
+ node[pos=\tikzumlRelationPosition, swap, \posMultiplicity, \multAlign] {\tikzumlRelationMultiplicity}%
+ }%
+ \fi%
+ \fi%
+ \fi%
+ %
+ \ifthenelse{\theposT=300\OR\theposT=100}{%
+ \ifthenelse{\equal{\tikzumlRelationRecursiveDirectionStart}{right}}{%
+ \ifthenelse{\equal{\tikzumlRelationRecursiveDirectionEnd}{bottom}}{%
+ \def\posAttrNameT{above right}%
+ \def\posMultiplicityT{below left}%
+ }{%
+ \def\posAttrNameT{above left}%
+ \def\posMultiplicityT{below right}%
+ }%
+ }{%
+ \ifthenelse{\equal{\tikzumlRelationRecursiveDirectionStart}{left}}{%
+ \ifthenelse{\equal{\tikzumlRelationRecursiveDirectionEnd}{bottom}}{%
+ \def\posAttrNameT{above left}%
+ \def\posMultiplicityT{below right}%
+ }{%
+ \def\posAttrNameT{above right}%
+ \def\posMultiplicityT{below left}%
+ }%
+ }{%
+ \ifthenelse{\equal{\tikzumlRelationRecursiveDirectionStart}{top}}{%
+ \ifthenelse{\equal{\tikzumlRelationRecursiveDirectionEnd}{left}}{%
+ \def\posAttrNameT{above right}%
+ \def\posMultiplicityT{below left}%
+ }{%
+ \def\posAttrNameT{above left}%
+ \def\posMultiplicityT{below right}%
+ }%
+ }{%
+ \ifthenelse{\equal{\tikzumlRelationRecursiveDirectionEnd}{left}}{%
+ \def\posAttrNameT{above left}%
+ \def\posMultiplicityT{below right}%
+ }{%
+ \def\posAttrNameT{above right}%
+ \def\posMultiplicityT{below left}%
+ }%
+ }%
+ }%
+ }%
+ }{}%
+ \ifthenelse{\theposT=200}{%
+ \ifthenelse{\equal{\tikzumlRelationRecursiveDirectionStart}{right}}{%
+ \ifthenelse{\equal{\tikzumlRelationRecursiveDirectionEnd}{bottom}}{%
+ \def\posAttrNameT{above left}%
+ \def\posMultiplicity{below right}%
+ }{%
+ \def\posAttrNameT{above right}%
+ \def\posMultiplicityT{below left}%
+ }%
+ }{%
+ \ifthenelse{\equal{\tikzumlRelationRecursiveDirectionStart}{left}}{%
+ \ifthenelse{\equal{\tikzumlRelationRecursiveDirectionEnd}{bottom}}{%
+ \def\posAttrNameT{above right}%
+ \def\posMultiplicityT{below left}%
+ }{%
+ \def\posAttrNameT{above left}%
+ \def\posMultiplicityT{below right}%
+ }%
+ }{%
+ \ifthenelse{\equal{\tikzumlRelationRecursiveDirectionStart}{top}}{%
+ \ifthenelse{\equal{\tikzumlRelationRecursiveDirectionEnd}{left}}{%
+ \def\posAttrNameT{above left}%
+ \def\posMultiplicityT{below right}%
+ }{%
+ \def\posAttrNameT{above right}%
+ \def\posMultiplicityT{below left}%
+ }%
+ }{%
+ \ifthenelse{\equal{\tikzumlRelationRecursiveDirectionEnd}{left}}{%
+ \def\posAttrNameT{above right}%
+ \def\posMultiplicityT{below left}%
+ }{%
+ \def\posAttrNameT{above left}%
+ \def\posMultiplicityT{below right}%
+ }%
+ }%
+ }%
+ }%
+ }{}%
+ %
+ \ifnum\theposT>300%
+ \pgfmathsetmacro{\tikzumlRelationPositionT}{(\theposT-300)/100}%
+ \xdef\tikzumlLastArc{\tikzumlLastArc node[pos=\tikzumlRelationPositionT, \posAttrNameT, \attrAlignT] {\tikzumlRelationAttrNameT}%
+ node[pos=\tikzumlRelationPositionT, swap, \posMultiplicityT, \multAlignT] {\tikzumlRelationMultiplicityT}%
+ }%
+ \else%
+ \ifnum\theposT<100%
+ \xdef\tikzumlFirstArc{\tikzumlFirstArc node[pos=\tikzumlRelationPositionT, \posAttrNameT, \attrAlignT] {\tikzumlRelationAttrNameT}%
+ node[pos=\tikzumlRelationPositionT, swap, \posMultiplicityT, \multAlignT] {\tikzumlRelationMultiplicityT}%
+ }%
+ \else%
+ \ifnum\theposT>200%
+ \pgfmathsetmacro{\tikzumlRelationPositionT}{(\theposT-200)/100}%
+ \xdef\tikzumlMidTwoArc{\tikzumlMidTwoArc node[pos=\tikzumlRelationPositionT, \posAttrNameT, \attrAlignT] {\tikzumlRelationAttrNameT}%
+ node[pos=\tikzumlRelationPositionT, swap, \posMultiplicityT, \multAlignT] {\tikzumlRelationMultiplicityT}%
+ }%
+ \else%
+ \pgfmathsetmacro{\tikzumlRelationPositionT}{(\theposT-100)/100}%
+ \xdef\tikzumlMidOneArc{\tikzumlMidOneArc node[pos=\tikzumlRelationPositionT, \posAttrNameT, \attrAlignT] {\tikzumlRelationAttrNameT}%
+ node[pos=\tikzumlRelationPositionT, swap, \posMultiplicityT, \multAlignT] {\tikzumlRelationMultiplicityT}%
+ }%
+ \fi%
+ \fi%
+ \fi%
+ \else%
+ \ifnum\theposStereo>200%
+ \pgfmathsetmacro{\tikzumlRelationPositionStereotype}{(\theposStereo-200)/100}%
+ \xdef\tikzumlLastArc{\tikzumlLastArc node[pos=\tikzumlRelationPositionStereotype, anchor=center] {\stereotype} }%
+ \else%
+ \ifnum\theposStereo<100%
+ \xdef\tikzumlFirstArc{\tikzumlFirstArc node[pos=\tikzumlRelationPositionStereotype, anchor=center] {\stereotype} }%
+ \else%
+ \pgfmathsetmacro{\tikzumlRelationPositionStereotype}{(\theposStereo-100)/100}%
+ \xdef\tikzumlMidOneArc{\tikzumlMidOneArc node[pos=\tikzumlRelationPositionStereotype, anchor=center] {\stereotype} }%
+ \fi%
+ \fi%
+ %
+ \ifthenelse{\thepos=100}{%
+ \ifthenelse{\equal{\tikzumlRelationRecursiveDirectionStart}{right}}{%
+ \ifthenelse{\tikzumlRelationEndAngle<\tikzumlRelationStartAngle}{%
+ \def\posAttrName{above right}%
+ \def\posMultiplicity{below left}%
+ }{%
+ \def\posAttrName{above left}%
+ \def\posMultiplicity{below right}%
+ }%
+ }{%
+ \ifthenelse{\equal{\tikzumlRelationRecursiveDirectionStart}{left}}{%
+ \ifthenelse{\tikzumlRelationEndAngle<\tikzumlRelationStartAngle}{%
+ \def\posAttrName{above left}%
+ \def\posMultiplicity{below right}%
+ }{%
+ \def\posAttrName{above right}%
+ \def\posMultiplicity{below left}%
+ }%
+ }{%
+ \ifthenelse{\equal{\tikzumlRelationRecursiveDirectionStart}{top}}{%
+ \ifthenelse{\tikzumlRelationEndAngle<\tikzumlRelationStartAngle}{%
+ \def\posAttrName{above right}%
+ \def\posMultiplicity{below left}%
+ }{%
+ \def\posAttrName{above left}%
+ \def\posMultiplicity{below right}%
+ }%
+ }{%
+ \ifthenelse{\tikzumlRelationEndAngle<\tikzumlRelationStartAngle}{%
+ \def\posAttrName{above left}%
+ \def\posMultiplicity{below right}%
+ }{%
+ \def\posAttrName{above right}%
+ \def\posMultiplicity{below left}%
+ }%
+ }%
+ }%
+ }%
+ }{}%
+ %
+ \ifthenelse{\thepos=200}{%
+ \ifthenelse{\equal{\tikzumlRelationRecursiveDirectionStart}{right}}{%
+ \ifthenelse{\tikzumlRelationEndAngle<\tikzumlRelationStartAngle}{%
+ \def\posAttrName{above left}%
+ \def\posMultiplicity{below right}%
+ }{%
+ \def\posAttrName{above right}%
+ \def\posMultiplicity{below left}%
+ }%
+ }{%
+ \ifthenelse{\equal{\tikzumlRelationRecursiveDirectionStart}{left}}{%
+ \ifthenelse{\tikzumlRelationEndAngle<\tikzumlRelationStartAngle}{%
+ \def\posAttrName{above right}%
+ \def\posMultiplicity{below left}%
+ }{%
+ \def\posAttrName{above left}%
+ \def\posMultiplicity{below right}%
+ }%
+ }{%
+ \ifthenelse{\equal{\tikzumlRelationRecursiveDirectionStart}{top}}{%
+ \ifthenelse{\tikzumlRelationEndAngle<\tikzumlRelationStartAngle}{%
+ \def\posAttrName{above left}%
+ \def\posMultiplicity{below right}%
+ }{%
+ \def\posAttrName{above right}%
+ \def\posMultiplicity{below left}%
+ }%
+ }{%
+ \ifthenelse{\tikzumlRelationEndAngle<\tikzumlRelationStartAngle}{%
+ \def\posAttrName{above right}%
+ \def\posMultiplicity{below left}%
+ }{%
+ \def\posAttrName{above left}%
+ \def\posMultiplicity{below right}%
+ }%
+ }%
+ }%
+ }%
+ }{}%
+ %
+ \ifnum\thepos>200%
+ \pgfmathsetmacro{\tikzumlRelationPosition}{(\thepos-200)/100}%
+ \xdef\tikzumlLastArc{\tikzumlLastArc node[pos=\tikzumlRelationPosition, \posAttrName, \attrAlign] {\tikzumlRelationAttrName}%
+ node[pos=\tikzumlRelationPosition, swap, \posMultiplicity, \multAlign] {\tikzumlRelationMultiplicity}%
+ }%
+ \else%
+ \ifnum\thepos<100%
+ \xdef\tikzumlFirstArc{\tikzumlFirstArc node[pos=\tikzumlRelationPosition, \posAttrName, \attrAlign] {\tikzumlRelationAttrName}%
+ node[pos=\tikzumlRelationPosition, swap, \posMultiplicity, \multAlign] {\tikzumlRelationMultiplicity}%
+ }%
+ \else%
+ \pgfmathsetmacro{\tikzumlRelationPosition}{(\thepos-100)/100}%
+ \xdef\tikzumlMidOneArc{\tikzumlMidOneArc node[pos=\tikzumlRelationPosition, \posAttrName, \attrAlign] {\tikzumlRelationAttrName}%
+ node[pos=\tikzumlRelationPosition, swap, \posMultiplicity, \multAlign] {\tikzumlRelationMultiplicity}%
+ }%
+ \fi%
+ \fi%
+ %
+ \ifthenelse{\theposT=100}{%
+ \ifthenelse{\equal{\tikzumlRelationRecursiveDirectionStart}{right}}{%
+ \ifthenelse{\tikzumlRelationEndAngle<\tikzumlRelationStartAngle}{%
+ \def\posAttrNameT{above right}%
+ \def\posMultiplicityT{below left}%
+ }{%
+ \def\posAttrNameT{above left}%
+ \def\posMultiplicityT{below right}%
+ }%
+ }{%
+ \ifthenelse{\equal{\tikzumlRelationRecursiveDirectionStart}{left}}{%
+ \ifthenelse{\tikzumlRelationEndAngle<\tikzumlRelationStartAngle}{%
+ \def\posAttrNameT{above left}%
+ \def\posMultiplicityT{below right}%
+ }{%
+ \def\posAttrNameT{above right}%
+ \def\posMultiplicityT{below left}%
+ }%
+ }{%
+ \ifthenelse{\equal{\tikzumlRelationRecursiveDirectionStart}{top}}{%
+ \ifthenelse{\tikzumlRelationEndAngle<\tikzumlRelationStartAngle}{%
+ \def\posAttrNameT{above right}%
+ \def\posMultiplicityT{below left}%
+ }{%
+ \def\posAttrNameT{above left}%
+ \def\posMultiplicityT{below right}%
+ }%
+ }{%
+ \ifthenelse{\tikzumlRelationEndAngle<\tikzumlRelationStartAngle}{%
+ \def\posAttrNameT{above left}%
+ \def\posMultiplicityT{below right}%
+ }{%
+ \def\posAttrNameT{above right}%
+ \def\posMultiplicityT{below left}%
+ }%
+ }%
+ }%
+ }%
+ }{}%
+ %
+ \ifthenelse{\theposT=200}{%
+ \ifthenelse{\equal{\tikzumlRelationRecursiveDirectionStart}{right}}{%
+ \ifthenelse{\tikzumlRelationEndAngle<\tikzumlRelationStartAngle}{%
+ \def\posAttrNameT{above left}%
+ \def\posMultiplicityT{below right}%
+ }{%
+ \def\posAttrNameT{above right}%
+ \def\posMultiplicityT{below left}%
+ }%
+ }{%
+ \ifthenelse{\equal{\tikzumlRelationRecursiveDirectionStart}{left}}{%
+ \ifthenelse{\tikzumlRelationEndAngle<\tikzumlRelationStartAngle}{%
+ \def\posAttrNameT{above right}%
+ \def\posMultiplicityT{below left}%
+ }{%
+ \def\posAttrNameT{above left}%
+ \def\posMultiplicityT{below right}%
+ }%
+ }{%
+ \ifthenelse{\equal{\tikzumlRelationRecursiveDirectionStart}{top}}{%
+ \ifthenelse{\tikzumlRelationEndAngle<\tikzumlRelationStartAngle}{%
+ \def\posAttrNameT{above left}%
+ \def\posMultiplicityT{below right}%
+ }{%
+ \def\posAttrNameT{above right}%
+ \def\posMultiplicityT{below left}%
+ }%
+ }{%
+ \ifthenelse{\tikzumlRelationEndAngle<\tikzumlRelationStartAngle}{%
+ \def\posAttrNameT{above right}%
+ \def\posMultiplicityT{below left}%
+ }{%
+ \def\posAttrNameT{above left}%
+ \def\posMultiplicityT{below right}%
+ }%
+ }%
+ }%
+ }%
+ }{}%
+ %
+ \ifnum\theposT>200%
+ \pgfmathsetmacro{\tikzumlRelationPositionT}{(\theposT-200)/100}%
+ \xdef\tikzumlLastArc{\tikzumlLastArc node[pos=\tikzumlRelationPositionT, \posAttrNameT, \attrAlignT] {\tikzumlRelationAttrNameT}%
+ node[pos=\tikzumlRelationPositionT, swap, \posMultiplicityT, \multAlignT] {\tikzumlRelationMultiplicityT}%
+ }%
+ \else%
+ \ifnum\theposT<100%
+ \xdef\tikzumlFirstArc{\tikzumlFirstArc node[pos=\tikzumlRelationPositionT, \posAttrNameT, \attrAlignT] {\tikzumlRelationAttrNameT}%
+ node[pos=\tikzumlRelationPositionT, swap, \posMultiplicityT, \multAlignT] {\tikzumlRelationMultiplicityT}%
+ }%
+ \else%
+ \pgfmathsetmacro{\tikzumlRelationPositionT}{(\theposT-100)/100}%
+ \xdef\tikzumlMidOneArc{\tikzumlMidOneArc node[pos=\tikzumlRelationPositionT, \posAttrNameT, \attrAlignT] {\tikzumlRelationAttrNameT}%
+ node[pos=\tikzumlRelationPositionT, swap, \posMultiplicityT, \multAlignT] {\tikzumlRelationMultiplicityT}%
+ }%
+ \fi%
+ \fi%
+ \fi%
+ %
+ \ifthenelse{\equal{\tikzumlRelationRecursiveDirectionStart}{\tikzumlRelationRecursiveDirectionEnd}}{%
+ \xdef\tikzumlPath{(\tikzumlSrcClassNodeName.\tikzumlRelationStartAngle) -- \tikzumlFirstArc (\tikzumlRelationName-2.center) -- \tikzumlMidOneArc (\tikzumlRelationName-4.center) -- \tikzumlLastArc (\tikzumlDestClassNodeName.\tikzumlRelationEndAngle) }%
+ \ifnum\thetikzumlStateLevel>0%
+ \def\tikzumlStateFitTmp{\csname tikzumlStateFit\tikzumlState@parent @@\tikzumlState@fitname\endcsname}%
+ \expandafter\xdef\csname tikzumlStateFit\tikzumlState@parent @@\tikzumlState@fitname\endcsname{\tikzumlStateFitTmp (\tikzumlRelationName-1) (\tikzumlRelationName-2) (\tikzumlRelationName-3) (\tikzumlRelationName-4) (\tikzumlRelationName-5)}%
+ \fi%
+ }{%
+ \xdef\tikzumlPath{(\tikzumlSrcClassNodeName.\tikzumlRelationStartAngle) -- \tikzumlFirstArc (\tikzumlRelationName-2.center) -- \tikzumlMidOneArc (\tikzumlRelationName-4.center) -- \tikzumlMidTwoArc (\tikzumlRelationName-6.center) -- \tikzumlLastArc (\tikzumlDestClassNodeName.\tikzumlRelationEndAngle) }%
+ \ifnum\thetikzumlStateLevel>0%
+ \def\tikzumlStateFitTmp{\csname tikzumlStateFit\tikzumlState@parent @@\tikzumlState@fitname\endcsname}%
+ \expandafter\xdef\csname tikzumlStateFit\tikzumlState@parent @@\tikzumlState@fitname\endcsname{\tikzumlStateFitTmp (\tikzumlRelationName-1) (\tikzumlRelationName-2) (\tikzumlRelationName-3) (\tikzumlRelationName-4) (\tikzumlRelationName-5) (\tikzumlRelationName-6) (\tikzumlRelationName-7)}%
+ \fi%
+ }%
+ }{}%
+ }%
+ }{%
+ \def\arcNum{1}%
+ \def\arcNumT{1}%
+ %
+ \node[inner sep=0] (\tikzumlRelationName-1) at (\tikzumlRelationName-middle) {};%
+ \xdef\tikzumlLastArc{node[pos=\tikzumlRelationPosition, \posAttrName, \attrAlign] {\tikzumlRelationAttrName}%
+ node[pos=\tikzumlRelationPosition, swap, \posMultiplicity, \multAlign] {\tikzumlRelationMultiplicity}%
+ node[pos=\tikzumlRelationPositionT, \posAttrNameT, \attrAlignT] {\tikzumlRelationAttrNameT}%
+ node[pos=\tikzumlRelationPositionT, swap, \posMultiplicityT, \multAlignT] {\tikzumlRelationMultiplicityT}%
+ node[pos=\tikzumlRelationPositionStereotype, anchor=center] {\stereotype} }%
+ \xdef\tikzumlPath{(\tikzumlSrcClassNodeName\tikzumlRelationSrcAnchor) -- \tikzumlLastArc (\tikzumlDestClassNodeName\tikzumlRelationDestAnchor) }%
+ \ifnum\thetikzumlStateLevel>0%
+ \def\tikzumlStateFitTmp{\csname tikzumlStateFit\tikzumlState@parent @@\tikzumlState@fitname\endcsname}%
+ \expandafter\xdef\csname tikzumlStateFit\tikzumlState@parent @@\tikzumlState@fitname\endcsname{\tikzumlStateFitTmp (\tikzumlRelationName-1) }%
+ \fi%
+ }%
+ }{%
+ % first vertical then horizontal line
+ \ifthenelse{\equal{\tikzumlRelationGeometry}{|-}}%
+ {%
+ %\setcounter{tikzumlControlNodesNum}{1}%
+ %
+ \def\tikzumlFirstArc{node[midway, inner sep=0, name=\tikzumlRelationName-1, anchor=center] {} }%
+ \def\tikzumlLastArc{node[midway, inner sep=0, name=\tikzumlRelationName-3, anchor=center]{} }%
+ %
+ \begin{pgfonlayer}{connections}%
+ \node[inner sep=0] (\tikzumlRelationName-2) at (\tikzumlSrcClassNodeName\tikzumlRelationSrcAnchor |- \tikzumlDestClassNodeName\tikzumlRelationDestAnchor) {};%
+ \end{pgfonlayer}%
+ %
+ \ifnum\theposStereo>100%
+ \pgfmathsetmacro{\tikzumlRelationPositionStereotype}{(\theposStereo-100)/100}%
+ \xdef\tikzumlLastArc{\tikzumlLastArc node[pos=\tikzumlRelationPositionStereotype, anchor=center] {\stereotype} }%
+ \else%
+ \xdef\tikzumlFirstArc{\tikzumlFirstArc node[pos=\tikzumlRelationPositionStereotype, anchor=center] {\stereotype} }%
+ \fi%
+ %
+ \ifnum\thepos>100%
+ \pgfmathsetmacro{\tikzumlRelationPosition}{(\thepos-100)/100}%
+ \def\arcNum{2}%
+ \else%
+ \def\arcNum{1}%
+ \ifnum\thepos=100%
+ \def\posAttrName{above left}%
+ \def\posMultiplicity{below right}%
+ \fi%
+ \fi%
+ %
+ \ifnum\arcNum=1%
+ \xdef\tikzumlFirstArc{\tikzumlFirstArc node[pos=\tikzumlRelationPosition, \posAttrName, \attrAlign] {\tikzumlRelationAttrName}%
+ node[pos=\tikzumlRelationPosition, swap, \posMultiplicity, \multAlign] {\tikzumlRelationMultiplicity} }%
+ \fi%
+ \ifnum\arcNum=2%
+ \xdef\tikzumlLastArc{\tikzumlLastArc node[pos=\tikzumlRelationPosition, \posAttrName, \attrAlign] {\tikzumlRelationAttrName}%
+ node[pos=\tikzumlRelationPosition, swap, \posMultiplicity, \multAlign] {\tikzumlRelationMultiplicity} }%
+ \fi%
+ %
+ \ifnum\theposT>100%
+ \pgfmathsetmacro{\tikzumlRelationPositionT}{(\theposT-100)/100}%
+ \def\arcNumT{2}%
+ \else%
+ \def\arcNumT{1}%
+ \ifnum\theposT=100%
+ \def\posAttrNameT{above left}%
+ \def\posMultiplicityT{below right}%
+ \fi%
+ \fi%
+ %
+ \ifnum\arcNumT=1%
+ \xdef\tikzumlFirstArc{\tikzumlFirstArc node[pos=\tikzumlRelationPositionT, \posAttrNameT, \attrAlignT] {\tikzumlRelationAttrNameT}%
+ node[pos=\tikzumlRelationPositionT, swap, \posMultiplicityT, \multAlignT] {\tikzumlRelationMultiplicityT} }%
+ \fi%
+ \ifnum\arcNumT=2%
+ \xdef\tikzumlLastArc{\tikzumlLastArc node[pos=\tikzumlRelationPositionT, \posAttrNameT, \attrAlignT] {\tikzumlRelationAttrNameT}%
+ node[pos=\tikzumlRelationPositionT, swap, \posMultiplicityT, \multAlignT] {\tikzumlRelationMultiplicityT} }%
+ \fi%
+ %
+ \xdef\tikzumlPath{(\tikzumlSrcClassNodeName\tikzumlRelationSrcAnchor) -- \tikzumlFirstArc (\tikzumlRelationName-2.base) -- \tikzumlLastArc (\tikzumlDestClassNodeName\tikzumlRelationDestAnchor) }%
+ \ifnum\thetikzumlStateLevel>0%
+ \def\tikzumlStateFitTmp{\csname tikzumlStateFit\tikzumlState@parent @@\tikzumlState@fitname\endcsname}%
+ \expandafter\xdef\csname tikzumlStateFit\tikzumlState@parent @@\tikzumlState@fitname\endcsname{\tikzumlStateFitTmp (\tikzumlRelationName-1) (\tikzumlRelationName-2) (\tikzumlRelationName-3) }%
+ \fi%
+ }{%
+ % first horizontal then vertical line
+ \ifthenelse{\equal{\tikzumlRelationGeometry}{-|}}%
+ {%
+ %\setcounter{tikzumlControlNodesNum}{1}%
+ %
+ \def\tikzumlFirstArc{node[midway, inner sep=0, name=\tikzumlRelationName-1, anchor=center]{} }%
+ \def\tikzumlLastArc{node[midway, inner sep=0, name=\tikzumlRelationName-3, anchor=center] {} }%
+ %
+ \begin{pgfonlayer}{connections}%
+ \node[inner sep=0] (\tikzumlRelationName-2) at (\tikzumlSrcClassNodeName\tikzumlRelationSrcAnchor -| \tikzumlDestClassNodeName\tikzumlRelationDestAnchor) {};%
+ \end{pgfonlayer}%
+ %
+ \ifnum\theposStereo>100%
+ \pgfmathsetmacro{\tikzumlRelationPositionStereotype}{(\theposStereo-100)/100}%
+ \xdef\tikzumlLastArc{\tikzumlLastArc node[pos=\tikzumlRelationPositionStereotype, anchor=center] {\stereotype} }%
+ \else%
+ \xdef\tikzumlFirstArc{\tikzumlFirstArc node[pos=\tikzumlRelationPositionStereotype, anchor=center] {\stereotype} }%
+ \fi%
+ %
+ \ifnum\thepos>100%
+ \pgfmathsetmacro{\tikzumlRelationPosition}{(\thepos-100)/100}%
+ \def\arcNum{2}%
+ \else%
+ \def\arcNum{1}%
+ \ifnum\thepos=100%
+ \def\posAttrName{above left}%
+ \def\posMultiplicity{below right}%
+ \fi%
+ \fi%
+ %
+ \ifnum\arcNum=1%
+ \xdef\tikzumlFirstArc{\tikzumlFirstArc node[pos=\tikzumlRelationPosition, \posAttrName, \attrAlign] {\tikzumlRelationAttrName}%
+ node[pos=\tikzumlRelationPosition, swap, \posMultiplicity, \multAlign] {\tikzumlRelationMultiplicity} }%
+ \fi%
+ \ifnum\arcNum=2%
+ \xdef\tikzumlLastArc{\tikzumlLastArc node[pos=\tikzumlRelationPosition, \posAttrName, \attrAlign] {\tikzumlRelationAttrName}%
+ node[pos=\tikzumlRelationPosition, swap, \posMultiplicity, \multAlign] {\tikzumlRelationMultiplicity} }%
+ \fi%
+ %
+ \ifnum\theposT>100%
+ \pgfmathsetmacro{\tikzumlRelationPositionT}{(\theposT-100)/100}%
+ \def\arcNumT{2}%
+ \else%
+ \def\arcNumT{1}%
+ \ifnum\theposT=100%
+ \def\posAttrNameT{above left}%
+ \def\posMultiplicityT{below right}%
+ \fi%
+ \fi%
+ %
+ \ifnum\arcNumT=1%
+ \xdef\tikzumlFirstArc{\tikzumlFirstArc node[pos=\tikzumlRelationPositionT, \posAttrNameT, \attrAlignT] {\tikzumlRelationAttrNameT}%
+ node[pos=\tikzumlRelationPositionT, swap, \posMultiplicityT, \multAlignT] {\tikzumlRelationMultiplicityT} }%
+ \fi%
+ \ifnum\arcNumT=2%
+ \xdef\tikzumlLastArc{\tikzumlLastArc node[pos=\tikzumlRelationPositionT, \posAttrNameT, \attrAlignT] {\tikzumlRelationAttrNameT}%
+ node[pos=\tikzumlRelationPositionT, swap, \posMultiplicityT, \multAlignT] {\tikzumlRelationMultiplicityT} }%
+ \fi%
+ %
+ \xdef\tikzumlPath{(\tikzumlSrcClassNodeName\tikzumlRelationSrcAnchor) -- \tikzumlFirstArc (\tikzumlRelationName-2.base) -- \tikzumlLastArc (\tikzumlDestClassNodeName\tikzumlRelationDestAnchor) }%
+ \ifnum\thetikzumlStateLevel>0%
+ \def\tikzumlStateFitTmp{\csname tikzumlStateFit\tikzumlState@parent @@\tikzumlState@fitname\endcsname}%
+ \expandafter\xdef\csname tikzumlStateFit\tikzumlState@parent @@\tikzumlState@fitname\endcsname{\tikzumlStateFitTmp (\tikzumlRelationName-1) (\tikzumlRelationName-2) (\tikzumlRelationName-3) }%
+ \fi%
+ }{%
+ % first vertical, then horizontal, finally vertical line
+ \ifthenelse{\equal{\tikzumlRelationGeometry}{|-|}}%
+ {%
+ %\setcounter{tikzumlControlNodesNum}{2}%
+ %
+ \def\tikzumlFirstArc{node[midway, inner sep=0, name=\tikzumlRelationName-1, anchor=center] {} }%
+ \def\tikzumlLastArc{node[midway, inner sep=0, name=\tikzumlRelationName-5, anchor=center] {} }%
+ \def\tikzumlMidOneArc{ }%
+ %
+ \begin{pgfonlayer}{connections}%
+ %
+ \ifthenelse{\equal{\tikzumlRelationArmO}{auto}}{%
+ \ifthenelse{\equal{\tikzumlRelationArmT}{auto}}{%
+ \node[inner sep=0] (\tikzumlRelationName-3) at (\tikzumlRelationName-middle) {};%
+ \node[inner sep=0] (\tikzumlRelationName-2) at (\tikzumlSrcClassNodeName\tikzumlRelationSrcAnchor |- \tikzumlRelationName-3) {};%
+ \node[inner sep=0] (\tikzumlRelationName-4) at (\tikzumlRelationName-3 -| \tikzumlDestClassNodeName\tikzumlRelationDestAnchor) {};%
+ }{%
+ \draw (\tikzumlDestClassNodeName\tikzumlRelationDestAnchor)+(0,\tikzumlRelationArmT) node[inner sep=0, name=\tikzumlRelationName-4] {};%
+ \node[inner sep=0] (\tikzumlRelationName-2) at (\tikzumlRelationName-4 -| \tikzumlSrcClassNodeName\tikzumlRelationSrcAnchor) {};%
+ \node[inner sep=0] (\tikzumlRelationName-3) at (barycentric cs:\tikzumlRelationName-2=0.5,\tikzumlRelationName-4=0.5) {};%
+ }%
+ }{%
+ \draw (\tikzumlSrcClassNodeName\tikzumlRelationSrcAnchor)+(0,\tikzumlRelationArmO) node[inner sep=0, name=\tikzumlRelationName-2] {};%
+ \node[inner sep=0] (\tikzumlRelationName-4) at (\tikzumlRelationName-2 -| \tikzumlDestClassNodeName\tikzumlRelationDestAnchor) {};%
+ \node[inner sep=0] (\tikzumlRelationName-3) at (barycentric cs:\tikzumlRelationName-2=0.5,\tikzumlRelationName-4=0.5) {};%
+ }%
+ \end{pgfonlayer}%
+ %
+ \ifnum\theposStereo>200%
+ \pgfmathsetmacro{\tikzumlRelationPositionStereotype}{(\theposStereo-200)/100}%
+ \xdef\tikzumlLastArc{\tikzumlLastArc node[pos=\tikzumlRelationPositionStereotype, anchor=center] {\stereotype} }%
+ \else%
+ \ifnum\theposStereo<100%
+ \xdef\tikzumlFirstArc{\tikzumlFirstArc node[pos=\tikzumlRelationPositionStereotype, anchor=center] {\stereotype} }%
+ \else%
+ \pgfmathsetmacro{\tikzumlRelationPositionStereotype}{(\theposStereo-100)/100}%
+ \xdef\tikzumlMidOneArc{\tikzumlMidOneArc node[pos=\tikzumlRelationPositionStereotype, anchor=center] {\stereotype} }%
+ \fi%
+ \fi%
+ %
+ \ifthenelse{\thepos=200\OR\thepos=100}{%
+ \def\posAttrName{above left}%
+ \def\posMultiplicity{below right}%
+ }{}%
+ %
+ \ifthenelse{\thepos>200}{%
+ \pgfmathsetmacro{\tikzumlRelationPosition}{(\thepos-200)/100}%
+ \def\arcNum{3}%
+ }{%
+ \ifthenelse{\thepos<100}{%
+ \def\arcNum{1}%
+ }{%
+ \pgfmathsetmacro{\tikzumlRelationPosition}{(\thepos-100)/100}%
+ \def\arcNum{2}%
+ }%
+ }%
+ %
+ \ifnum\arcNum=1%
+ \xdef\tikzumlFirstArc{\tikzumlFirstArc node[pos=\tikzumlRelationPosition, \posAttrName, \attrAlign] {\tikzumlRelationAttrName}%
+ node[pos=\tikzumlRelationPosition, swap, \posMultiplicity, \multAlign] {\tikzumlRelationMultiplicity} }%
+ \fi%
+ \ifnum\arcNum=2%
+ \xdef\tikzumlMidOneArc{\tikzumlMidOneArc node[pos=\tikzumlRelationPosition, \posAttrName, \attrAlign] {\tikzumlRelationAttrName}%
+ node[pos=\tikzumlRelationPosition, swap, \posMultiplicity, \multAlign] {\tikzumlRelationMultiplicity} }%
+ \fi%
+ \ifnum\arcNum=3%
+ \xdef\tikzumlLastArc{\tikzumlLastArc node[pos=\tikzumlRelationPosition, \posAttrName, \attrAlign] {\tikzumlRelationAttrName}%
+ node[pos=\tikzumlRelationPosition, swap, \posMultiplicity, \multAlign] {\tikzumlRelationMultiplicity} }%
+ \fi%
+ %
+ \ifthenelse{\theposT=200\OR\theposT=100}{%
+ \def\posAttrNameT{above left}%
+ \def\posMultiplicityT{below right}%
+ }{}%
+ %
+ \ifthenelse{\theposT>200}{%
+ \pgfmathsetmacro{\tikzumlRelationPositionT}{(\theposT-200)/100}%
+ \def\arcNumT{3}%
+ }{%
+ \ifthenelse{\theposT<100}{%
+ \def\arcNumT{1}%
+ }{%
+ \pgfmathsetmacro{\tikzumlRelationPositionT}{(\theposT-100)/100}%
+ \def\arcNumT{2}%
+ }%
+ }%
+ %
+ \ifnum\arcNumT=1%
+ \xdef\tikzumlFirstArc{\tikzumlFirstArc node[pos=\tikzumlRelationPositionT, \posAttrNameT, \attrAlignT] {\tikzumlRelationAttrNameT}%
+ node[pos=\tikzumlRelationPositionT, swap, \posMultiplicityT, \multAlignT] {\tikzumlRelationMultiplicityT} }%
+ \fi%
+ \ifnum\arcNumT=2%
+ \xdef\tikzumlMidOneArc{\tikzumlMidOneArc node[pos=\tikzumlRelationPositionT, \posAttrNameT, \attrAlignT] {\tikzumlRelationAttrNameT}%
+ node[pos=\tikzumlRelationPositionT, swap, \posMultiplicityT, \multAlignT] {\tikzumlRelationMultiplicityT} }%
+ \fi%
+ \ifnum\arcNumT=3%
+ \xdef\tikzumlLastArc{\tikzumlLastArc node[pos=\tikzumlRelationPositionT, \posAttrNameT, \attrAlignT] {\tikzumlRelationAttrNameT}%
+ node[pos=\tikzumlRelationPositionT, swap, \posMultiplicityT, \multAlignT] {\tikzumlRelationMultiplicityT} }%
+ \fi%
+ %
+ \xdef\tikzumlPath{(\tikzumlSrcClassNodeName\tikzumlRelationSrcAnchor) -- \tikzumlFirstArc (\tikzumlRelationName-2.base) -- \tikzumlMidOneArc (\tikzumlRelationName-4.base) -- \tikzumlLastArc (\tikzumlDestClassNodeName\tikzumlRelationDestAnchor) }%
+ \ifnum\thetikzumlStateLevel>0%
+ \def\tikzumlStateFitTmp{\csname tikzumlStateFit\tikzumlState@parent @@\tikzumlState@fitname\endcsname}%
+ \expandafter\xdef\csname tikzumlStateFit\tikzumlState@parent @@\tikzumlState@fitname\endcsname{\tikzumlStateFitTmp (\tikzumlRelationName-1) (\tikzumlRelationName-2) (\tikzumlRelationName-3) (\tikzumlRelationName-4) (\tikzumlRelationName-5) }%
+ \fi%
+ }{%
+ % first horizontal, then vertical, finally horizontal line
+ \ifthenelse{\equal{\tikzumlRelationGeometry}{-|-}}%
+ {%
+ %\setcounter{tikzumlControlNodesNum}{2}%
+ %
+ \def\tikzumlFirstArc{node[midway, inner sep=0, name=\tikzumlRelationName-1, anchor=center] {} }%
+ \def\tikzumlLastArc{node[midway, inner sep=0, name=\tikzumlRelationName-5, anchor=center] {} }%
+ \def\tikzumlMidOneArc{}%
+ %
+ \begin{pgfonlayer}{connections}%
+ %
+ \ifthenelse{\equal{\tikzumlRelationArmO}{auto}}{%
+ \ifthenelse{\equal{\tikzumlRelationArmT}{auto}}{%
+ \node[inner sep=0] (\tikzumlRelationName-3) at (\tikzumlRelationName-middle) {};%
+ \node[inner sep=0] (\tikzumlRelationName-2) at (\tikzumlSrcClassNodeName\tikzumlRelationSrcAnchor -| \tikzumlRelationName-3) {};%
+ \node[inner sep=0] (\tikzumlRelationName-4) at (\tikzumlRelationName-3 |- \tikzumlDestClassNodeName\tikzumlRelationDestAnchor) {};%
+ }{%
+ \draw (\tikzumlDestClassNodeName\tikzumlRelationDestAnchor)+(\tikzumlRelationArmT,0) node[inner sep=0, name=\tikzumlRelationName-4] {};%
+ \node[inner sep=0] (\tikzumlRelationName-2) at (\tikzumlRelationName-4 |- \tikzumlSrcClassNodeName\tikzumlRelationSrcAnchor) {};%
+ \node[inner sep=0] (\tikzumlRelationName-3) at (barycentric cs:\tikzumlRelationName-2=0.5,\tikzumlRelationName-4=0.5) {};%
+ }%
+ }{%
+ \draw (\tikzumlSrcClassNodeName\tikzumlRelationSrcAnchor)+(\tikzumlRelationArmO,0) node[inner sep=0, name=\tikzumlRelationName-2] {};%
+ \node[inner sep=0] (\tikzumlRelationName-4) at (\tikzumlRelationName-2 |- \tikzumlDestClassNodeName\tikzumlRelationDestAnchor) {};%
+ \node[inner sep=0] (\tikzumlRelationName-3) at (barycentric cs:\tikzumlRelationName-2=0.5,\tikzumlRelationName-4=0.5) {};%
+ }%
+ \end{pgfonlayer}%
+ %
+ \ifnum\theposStereo>200%
+ \pgfmathsetmacro{\tikzumlRelationPositionStereotype}{(\theposStereo-200)/100}%
+ \xdef\tikzumlLastArc{\tikzumlLastArc node[pos=\tikzumlRelationPositionStereotype, anchor=center] {\stereotype} }%
+ \else%
+ \ifnum\theposStereo<100%
+ \xdef\tikzumlFirstArc{\tikzumlFirstArc node[pos=\tikzumlRelationPositionStereotype, anchor=center] {\stereotype} }%
+ \else%
+ \pgfmathsetmacro{\tikzumlRelationPositionStereotype}{(\theposStereo-100)/100}%
+ \xdef\tikzumlMidOneArc{\tikzumlMidOneArc node[pos=\tikzumlRelationPositionStereotype, anchor=center] {\stereotype} }%
+ \fi%
+ \fi%
+ %
+ \ifthenelse{\thepos=200\OR\thepos=100}{%
+ \def\posAttrName{above left}%
+ \def\posMultiplicity{below right}%
+ }{}%
+ %
+ \ifthenelse{\thepos>200}{%
+ \pgfmathsetmacro{\tikzumlRelationPosition}{(\thepos-200)/100}%
+ \def\arcNum{3}%
+ }{%
+ \ifthenelse{\thepos<100}{%
+ \def\arcNum{1}%
+ }{%
+ \pgfmathsetmacro{\tikzumlRelationPosition}{(\thepos-100)/100}%
+ \def\arcNum{2}%
+ }%
+ }%
+ %
+ \ifnum\arcNum=1%
+ \xdef\tikzumlFirstArc{\tikzumlFirstArc node[pos=\tikzumlRelationPosition, \posAttrName, \attrAlign] {\tikzumlRelationAttrName}%
+ node[pos=\tikzumlRelationPosition, swap, \posMultiplicity, \multAlign] {\tikzumlRelationMultiplicity} }%
+ \fi%
+ \ifnum\arcNum=2%
+ \xdef\tikzumlMidOneArc{\tikzumlMidOneArc node[pos=\tikzumlRelationPosition, \posAttrName, \attrAlign] {\tikzumlRelationAttrName}%
+ node[pos=\tikzumlRelationPosition, swap, \posMultiplicity, \multAlign] {\tikzumlRelationMultiplicity} }%
+ \fi%
+ \ifnum\arcNum=3%
+ \xdef\tikzumlLastArc{\tikzumlLastArc node[pos=\tikzumlRelationPosition, \posAttrName, \attrAlign] {\tikzumlRelationAttrName}%
+ node[pos=\tikzumlRelationPosition, swap, \posMultiplicity, \multAlign] {\tikzumlRelationMultiplicity} }%
+ \fi%
+ %
+ \ifthenelse{\theposT=200\OR\theposT=100}{%
+ \def\posAttrNameT{above left}%
+ \def\posMultiplicityT{below right}%
+ }{}%
+ %
+ \ifthenelse{\theposT>200}{%
+ \pgfmathsetmacro{\tikzumlRelationPositionT}{(\theposT-200)/100}%
+ \def\arcNumT{3}%
+ }{%
+ \ifthenelse{\theposT<100}{%
+ \def\arcNumT{1}%
+ }{%
+ \pgfmathsetmacro{\tikzumlRelationPositionT}{(\theposT-100)/100}%
+ \def\arcNumT{2}%
+ }%
+ }%
+ %
+ \ifnum\arcNumT=1%
+ \xdef\tikzumlFirstArc{\tikzumlFirstArc node[pos=\tikzumlRelationPositionT, \posAttrNameT, \attrAlignT] {\tikzumlRelationAttrNameT}%
+ node[pos=\tikzumlRelationPositionT, swap, \posMultiplicityT, \multAlignT] {\tikzumlRelationMultiplicityT} }%
+ \fi%
+ \ifnum\arcNumT=2%
+ \xdef\tikzumlMidOneArc{\tikzumlMidOneArc node[pos=\tikzumlRelationPositionT, \posAttrNameT, \attrAlignT] {\tikzumlRelationAttrNameT}%
+ node[pos=\tikzumlRelationPositionT, swap, \posMultiplicityT, \multAlignT] {\tikzumlRelationMultiplicityT} }%
+ \fi%
+ \ifnum\arcNumT=3%
+ \xdef\tikzumlLastArc{\tikzumlLastArc node[pos=\tikzumlRelationPositionT, \posAttrNameT, \attrAlignT] {\tikzumlRelationAttrNameT}%
+ node[pos=\tikzumlRelationPositionT, swap, \posMultiplicityT, \multAlignT] {\tikzumlRelationMultiplicityT} }%
+ \fi%
+ %
+ \xdef\tikzumlPath{(\tikzumlSrcClassNodeName\tikzumlRelationSrcAnchor) -- \tikzumlFirstArc (\tikzumlRelationName-2.base) -- \tikzumlMidOneArc (\tikzumlRelationName-4.base) -- \tikzumlLastArc (\tikzumlDestClassNodeName\tikzumlRelationDestAnchor) }%
+ \ifnum\thetikzumlStateLevel>0%
+ \def\tikzumlStateFitTmp{\csname tikzumlStateFit\tikzumlState@parent @@\tikzumlState@fitname\endcsname}%
+ \expandafter\xdef\csname tikzumlStateFit\tikzumlState@parent @@\tikzumlState@fitname\endcsname{\tikzumlStateFitTmp (\tikzumlRelationName-1) (\tikzumlRelationName-2) (\tikzumlRelationName-3) (\tikzumlRelationName-4) (\tikzumlRelationName-5) }%
+ \fi%
+ }{%
+ \errmessage{TIKZUML ERROR : Unknown geometry value !!! It should be in the following list : --, |-, -|, |-|, -|-}%
+ }%
+ }%
+ }%
+ }%
+ }%
+ %
+ \begin{pgfonlayer}{connections}%
+ \ifthenelse{\equal{\tikzumlRelationStyle}{tikzuml nesting style}}{%
+ \pgfarrowsdeclare{nested}{nested}{...}
+ {
+ \tikzumlNestingSymbolSize=0.2pt%
+ \advance\tikzumlNestingSymbolSize by .5\pgflinewidth%
+ \pgfsetdash{}{0pt} % do not dash
+ \pgfsetroundjoin % fix join
+ \pgfsetroundcap % fix cap
+ \pgfpathmoveto{\pgfpoint{-16*\tikzumlNestingSymbolSize}{0pt}}%
+ \pgfpatharc{180}{90}{8*\tikzumlNestingSymbolSize}%
+ \pgfpatharc{90}{0}{8*\tikzumlNestingSymbolSize}%
+ \pgfpatharc{0}{-90}{8*\tikzumlNestingSymbolSize}%
+ \pgfpatharc{-90}{-180}{8*\tikzumlNestingSymbolSize}%
+ \pgfpathmoveto{\pgfpoint{-8*\tikzumlNestingSymbolSize}{8*\tikzumlNestingSymbolSize}}%
+ \pgfpathlineto{\pgfpoint{-8*\tikzumlNestingSymbolSize}{-8*\tikzumlNestingSymbolSize}}%
+ \pgfusepathqstroke%
+ }%
+ \draw[auto, nested-, font=\tikzumlDefaultFont, \tikzumlRelationStyle, /tikzuml/relation/style2] \tikzumlPath ;%
+ }{
+ \draw[auto, font=\tikzumlDefaultFont, \tikzumlRelationStyle, /tikzuml/relation/style2] \tikzumlPath ;%
+ }
+ \end{pgfonlayer}%
+ %
+ \stepcounter{tikzumlRelationNum}%
+}%
+%
+% shortcuts of \umlrelation
+\newcommand{\umlHVrelation}[3][]{%
+ \pgfkeys{/tikzuml/HVrelation/.cd,%
+ .unknown/.code={%
+ \let\keyname=\pgfkeyscurrentname%
+ \let\keyvalue=\pgfkeyscurrentvalue%
+ \ifthenelse{\equal{\keyname}{geometry}}{%
+ \errmessage{TIKZUML ERROR : in umlHVrelation, forbidden option geometry}%
+ }{}%
+ }}%
+ \pgfkeys{/tikzuml/HVrelation/.cd, #1}%
+ \umlrelation[geometry=-|, #1]{#2}{#3}%
+}%
+%
+\newcommand{\umlVHrelation}[3][]{%
+ \pgfkeys{/tikzuml/VHrelation/.cd,%
+ .unknown/.code={%
+ \let\keyname=\pgfkeyscurrentname%
+ \let\keyvalue=\pgfkeyscurrentvalue%
+ \ifthenelse{\equal{\keyname}{geometry}}{%
+ \errmessage{TIKZUML ERROR : in umlVHrelation, forbidden option geometry}%
+ }{}%
+ }}%
+ \pgfkeys{/tikzuml/VHrelation/.cd, #1}%
+ \umlrelation[geometry=|-, #1]{#2}{#3}%
+}%
+%
+\newcommand{\umlHVHrelation}[3][]{%
+ \pgfkeys{/tikzuml/HVHrelation/.cd,%
+ .unknown/.code={%
+ \let\keyname=\pgfkeyscurrentname%
+ \let\keyvalue=\pgfkeyscurrentvalue%
+ \ifthenelse{\equal{\keyname}{geometry}}{%
+ \errmessage{TIKZUML ERROR : in umlHVHrelation, forbidden option geometry}%
+ }{}%
+ }}%
+ \pgfkeys{/tikzuml/HVHrelation/.cd, #1}%
+ \umlrelation[geometry=-|-, #1]{#2}{#3}%
+}%
+%
+\newcommand{\umlVHVrelation}[3][]{%
+ \pgfkeys{/tikzuml/VHVrelation/.cd,%
+ .unknown/.code={%
+ \let\keyname=\pgfkeyscurrentname%
+ \let\keyvalue=\pgfkeyscurrentvalue%
+ \ifthenelse{\equal{\keyname}{geometry}}{%
+ \errmessage{TIKZUML ERROR : in umlVHVrelation, forbidden option geometry}%
+ }{}%
+ }}%
+ \pgfkeys{/tikzuml/VHVrelation/.cd, #1}%
+ \umlrelation[geometry=|-|, #1]{#2}{#3}%
+}%
+%
+%
+% shortcuts for relations
+\newcommand{\umlinherit}[3][]{\umlrelation[style={tikzuml inherit style}, #1]{#2}{#3}}%
+\newcommand{\umlimpl}[3][]{\umlrelation[style={tikzuml implements style}, #1]{#2}{#3}}%
+\newcommand{\umlreal}[3][]{\umlrelation[style={tikzuml implements style}, #1]{#2}{#3}}%
+\newcommand{\umlassoc}[3][]{\umlrelation[style={tikzuml association style}, #1]{#2}{#3}}%
+\newcommand{\umlbiassoc}[3][]{\umlrelation[style={tikzuml bidirectional association style}, #1]{#2}{#3}}%
+\newcommand{\umluniassoc}[3][]{\umlrelation[style={tikzuml unidirectional association style}, #1]{#2}{#3}}%
+\newcommand{\umlaggreg}[3][]{\umlrelation[style={tikzuml aggregation style}, #1]{#2}{#3}}%
+\newcommand{\umluniaggreg}[3][]{\umlrelation[style={tikzuml unidirectional aggregation style}, #1]{#2}{#3}}%
+\newcommand{\umlcompo}[3][]{\umlrelation[style={tikzuml composition style}, #1]{#2}{#3}}%
+\newcommand{\umlunicompo}[3][]{\umlrelation[style={tikzuml unidirectional composition style}, #1]{#2}{#3}}%
+\newcommand{\umlimport}[3][]{\umlrelation[style={tikzuml import style}, #1]{#2}{#3}}%
+\newcommand{\umlnest}[3][]{\umlrelation[style={tikzuml nesting style}, #1]{#2}{#3}}%
+\newcommand{\umldep}[3][]{\umlrelation[style={tikzuml dependency style}, #1]{#2}{#3}}%
+\newcommand{\umlfriend}[3][]{%
+ \pgfkeys{/tikzuml/friendrelation/.cd,%
+ .unknown/.code={%
+ \let\keyname=\pgfkeyscurrentname%
+ \let\keyvalue=\pgfkeyscurrentvalue%
+ \ifthenelse{\equal{\keyname}{stereo}}{%
+ \errmessage{TIKZUML ERROR : in umlfriend, forbidden option stereo}%
+ }{}%
+ }}%
+ \pgfkeys{/tikzuml/friendrelation/.cd, #1}%
+ \umlrelation[stereo=friend, style={tikzuml dependency style}, #1]{#2}{#3}%
+}%
+%
+\newcommand{\umlHVinherit}[3][]{\umlHVrelation[style={tikzuml inherit style}, #1]{#2}{#3}}%
+\newcommand{\umlHVimpl}[3][]{\umlHVrelation[style={tikzuml implements style}, #1]{#2}{#3}}%
+\newcommand{\umlHVreal}[3][]{\umlHVrelation[style={tikzuml implements style}, #1]{#2}{#3}}%
+\newcommand{\umlHVassoc}[3][]{\umlHVrelation[style={tikzuml association style}, #1]{#2}{#3}}%
+\newcommand{\umlHVuniassoc}[3][]{\umlHVrelation[style={tikzuml unidirectional association style}, #1]{#2}{#3}}%
+\newcommand{\umlHVaggreg}[3][]{\umlHVrelation[style={tikzuml aggregation style}, #1]{#2}{#3}}%
+\newcommand{\umlHVuniaggreg}[3][]{\umlHVrelation[style={tikzuml unidirectional aggregation style}, #1]{#2}{#3}}%
+\newcommand{\umlHVcompo}[3][]{\umlHVrelation[style={tikzuml composition style}, #1]{#2}{#3}}%
+\newcommand{\umlHVunicompo}[3][]{\umlHVrelation[style={tikzuml unidirectional composition style}, #1]{#2}{#3}}%
+\newcommand{\umlHVimport}[3][]{\umlHVrelation[style={tikzuml import style}, #1]{#2}{#3}}%
+\newcommand{\umlHVnest}[3][]{\umlHVrelation[style={tikzuml nesting style}, #1]{#2}{#3}}%
+\newcommand{\umlHVdep}[3][]{\umlHVrelation[style={tikzuml dependency style}, #1]{#2}{#3}}%
+\newcommand{\umlHVfriend}[3][]{%
+ \pgfkeys{/tikzuml/friendrelation/.cd,%
+ .unknown/.code={%
+ \let\keyname=\pgfkeyscurrentname%
+ \let\keyvalue=\pgfkeyscurrentvalue%
+ \ifthenelse{\equal{\keyname}{stereo}}{%
+ \errmessage{TIKZUML ERROR : in umlHVfriend, forbidden option stereo}%
+ }{%
+ \ifthenelse{\equal{\keyname}{geometry}}{%
+ \errmessage{TIKZUML ERROR : in umlHVfriend, forbidden option geometry}%
+ }{}%
+ }%
+ }}%
+ \pgfkeys{/tikzuml/friendrelation/.cd, #1}%
+ \umlrelation[geometry=-|, stereo=friend, style={tikzuml dependency style}, #1]{#2}{#3}%
+}%
+%
+\newcommand{\umlVHinherit}[3][]{\umlVHrelation[style={tikzuml inherit style}, #1]{#2}{#3}}%
+\newcommand{\umlVHimpl}[3][]{\umlVHrelation[style={tikzuml implements style}, #1]{#2}{#3}}%
+\newcommand{\umlVHreal}[3][]{\umlVHrelation[style={tikzuml implements style}, #1]{#2}{#3}}%
+\newcommand{\umlVHassoc}[3][]{\umlVHrelation[style={tikzuml association style}, #1]{#2}{#3}}%
+\newcommand{\umlVHuniassoc}[3][]{\umlVHrelation[style={tikzuml unidirectional association style}, #1]{#2}{#3}}%
+\newcommand{\umlVHaggreg}[3][]{\umlVHrelation[style={tikzuml aggregation style}, #1]{#2}{#3}}%
+\newcommand{\umlVHuniaggreg}[3][]{\umlVHrelation[style={tikzuml unidirectional aggregation style}, #1]{#2}{#3}}%
+\newcommand{\umlVHcompo}[3][]{\umlVHrelation[style={tikzuml composition style}, #1]{#2}{#3}}%
+\newcommand{\umlVHunicompo}[3][]{\umlVHrelation[style={tikzuml unidirectional composition style}, #1]{#2}{#3}}%
+\newcommand{\umlVHimport}[3][]{\umlVHrelation[style={tikzuml import style}, #1]{#2}{#3}}%
+\newcommand{\umlVHnest}[3][]{\umlVHrelation[style={tikzuml nesting style}, #1]{#2}{#3}}%
+\newcommand{\umlVHdep}[3][]{\umlVHrelation[style={tikzuml dependency style}, #1]{#2}{#3}}%
+\newcommand{\umlVHfriend}[3][]{%
+ \pgfkeys{/tikzuml/friendrelation/.cd,%
+ .unknown/.code={%
+ \let\keyname=\pgfkeyscurrentname%
+ \let\keyvalue=\pgfkeyscurrentvalue%
+ \ifthenelse{\equal{\keyname}{stereo}}{%
+ \errmessage{TIKZUML ERROR : in umlVHfriend, forbidden option stereo}%
+ }{%
+ \ifthenelse{\equal{\keyname}{geometry}}{%
+ \errmessage{TIKZUML ERROR : in umlVHfriend, forbidden option geometry}%
+ }{}%
+ }%
+ }}%
+ \pgfkeys{/tikzuml/friendrelation/.cd, #1}%
+ \umlrelation[geometry=|-, stereo=friend, style={tikzuml dependency style}, #1]{#2}{#3}%
+}%
+%
+\newcommand{\umlHVHinherit}[3][]{\umlHVHrelation[style={tikzuml inherit style}, #1]{#2}{#3}}%
+\newcommand{\umlHVHimpl}[3][]{\umlHVHrelation[style={tikzuml implements style}, #1]{#2}{#3}}%
+\newcommand{\umlHVHreal}[3][]{\umlHVHrelation[style={tikzuml implements style}, #1]{#2}{#3}}%
+\newcommand{\umlHVHassoc}[3][]{\umlHVHrelation[style={tikzuml association style}, #1]{#2}{#3}}%
+\newcommand{\umlHVHuniassoc}[3][]{\umlHVHrelation[style={tikzuml unidirectional association style}, #1]{#2}{#3}}%
+\newcommand{\umlHVHaggreg}[3][]{\umlHVHrelation[style={tikzuml aggregation style}, #1]{#2}{#3}}%
+\newcommand{\umlHVHuniaggreg}[3][]{\umlHVHrelation[style={tikzuml unidirectional aggregation style}, #1]{#2}{#3}}%
+\newcommand{\umlHVHcompo}[3][]{\umlHVHrelation[style={tikzuml composition style}, #1]{#2}{#3}}%
+\newcommand{\umlHVHunicompo}[3][]{\umlHVHrelation[style={tikzuml unidirectional composition style}, #1]{#2}{#3}}%
+\newcommand{\umlHVHimport}[3][]{\umlHVHrelation[style={tikzuml import style}, #1]{#2}{#3}}%
+\newcommand{\umlHVHnest}[3][]{\umlHVHrelation[style={tikzuml nesting style}, #1]{#2}{#3}}%
+\newcommand{\umlHVHdep}[3][]{\umlHVHrelation[style={tikzuml dependency style}, #1]{#2}{#3}}%
+\newcommand{\umlHVHfriend}[3][]{%
+ \pgfkeys{/tikzuml/friendrelation/.cd,%
+ .unknown/.code={%
+ \let\keyname=\pgfkeyscurrentname%
+ \let\keyvalue=\pgfkeyscurrentvalue%
+ \ifthenelse{\equal{\keyname}{stereo}}{%
+ \errmessage{TIKZUML ERROR : in umlHVHfriend, forbidden option stereo}%
+ }{%
+ \ifthenelse{\equal{\keyname}{geometry}}{%
+ \errmessage{TIKZUML ERROR : in umlHVHfriend, forbidden option geometry}%
+ }{}%
+ }%
+ }}%
+ \pgfkeys{/tikzuml/friendrelation/.cd, #1}%
+ \umlrelation[geometry=-|-, stereo=friend, style={tikzuml dependency style}, #1]{#2}{#3}%
+}%
+%
+\newcommand{\umlVHVinherit}[3][]{\umlVHVrelation[style={tikzuml inherit style}, #1]{#2}{#3}}%
+\newcommand{\umlVHVimpl}[3][]{\umlVHVrelation[style={tikzuml implements style}, #1]{#2}{#3}}%
+\newcommand{\umlVHVreal}[3][]{\umlVHVrelation[style={tikzuml implements style}, #1]{#2}{#3}}%
+\newcommand{\umlVHVassoc}[3][]{\umlVHVrelation[style={tikzuml association style}, #1]{#2}{#3}}%
+\newcommand{\umlVHVuniassoc}[3][]{\umlVHVrelation[style={tikzuml unidirectional association style}, #1]{#2}{#3}}%
+\newcommand{\umlVHVaggreg}[3][]{\umlVHVrelation[style={tikzuml aggregation style}, #1]{#2}{#3}}%
+\newcommand{\umlVHVuniaggreg}[3][]{\umlVHVrelation[style={tikzuml unidirectional aggregation style}, #1]{#2}{#3}}%
+\newcommand{\umlVHVcompo}[3][]{\umlVHVrelation[style={tikzuml composition style}, #1]{#2}{#3}}%
+\newcommand{\umlVHVunicompo}[3][]{\umlVHVrelation[style={tikzuml unidirectional composition style}, #1]{#2}{#3}}%
+\newcommand{\umlVHVimport}[3][]{\umlVHVrelation[style={tikzuml import style}, #1]{#2}{#3}}%
+\newcommand{\umlVHVnest}[3][]{\umlVHVrelation[style={tikzuml nesting style}, #1]{#2}{#3}}%
+\newcommand{\umlVHVdep}[3][]{\umlVHVrelation[style={tikzuml dependency style}, #1]{#2}{#3}}%
+\newcommand{\umlVHVfriend}[3][]{%
+ \pgfkeys{/tikzuml/friendrelation/.cd,%
+ .unknown/.code={%
+ \let\keyname=\pgfkeyscurrentname%
+ \let\keyvalue=\pgfkeyscurrentvalue%
+ \ifthenelse{\equal{\keyname}{stereo}}{%
+ \errmessage{TIKZUML ERROR : in umlVHVfriend, forbidden option stereo}%
+ }{%
+ \ifthenelse{\equal{\keyname}{geometry}}{%
+ \errmessage{TIKZUML ERROR : in umlVHVfriend, forbidden option geometry}%
+ }{}%
+ }%
+ }}%
+ \pgfkeys{/tikzuml/friendrelation/.cd, #1}%
+ \umlrelation[geometry=|-|, stereo=friend, style={tikzuml dependency style}, #1]{#2}{#3}%
+}%
+%
+% define a node
+\newcommand{\umlnode}[2]{%
+ \node (#2) at (#1) {};%
+}%
+%
+% main command to define a relation between two classes through a control node
+% args : src class
+% control node
+% dest class
+% optional : arg1, arg2, arg: name of the src/dest/dest side class type attribute defined by the relation
+% mult1, mult2, mult: multiplicity of the src/dest/dest side class type attribute defined by the relation
+% pos1, pos2, pos: position of the src/dest/dest side class type attribute defined by the relation
+% align1, align2, align: text justification of the src/dest/dest side class type attribute defined by the relation
+% anchor1, anchor2: src/dest anchors on linked classes
+% stereo: stereotype of the relation
+% pos stereo: position of the stereotype on the relation
+% style: style of the relation (association, aggregation, composition, inherit, ...)
+% name: rootname used for naming nodes of the relation
+\newcommand{\umlCNrelation}[4][]{%
+ \pgfkeys{/tikzuml/relation/.cd, arg1/.initial={}, arg2/.initial={}, arg/.initial={},%
+ mult1/.initial={}, mult2/.initial={}, mult/.initial={},%
+ pos1/.initial=0.2, pos2/.initial=0.8, pos/.initial=tikzumlEmpty,%
+ align1/.initial={}, align2/.initial={}, align/.initial={},%
+ anchor1/.initial=tikzumlEmpty, anchor2/.initial=tikzumlEmpty,%
+ stereo/.initial={}, pos stereo/.initial=1,%
+ style/.initial=->, name/.initial=relation-\thetikzumlRelationNum,%
+ .unknown/.code={%
+ \let\keyname=\pgfkeyscurrentname%
+ \let\keyvalue=\pgfkeyscurrentvalue%
+ \errmessage{TIKZUML ERROR : in umlCNrelation, invalid option \keyname}%
+ }%
+ }%
+ \pgfkeys{/tikzuml/relation/.cd,#1}%
+ \pgfkeys{/tikzuml/relation/.cd, arg1/.get=\tikzumlCNRelationAttrName, arg2/.get=\tikzumlCNRelationAttrNameTO, arg/.get=\tikzumlCNRelationAttrNameTT,%
+ mult1/.get=\tikzumlCNRelationMultiplicity, mult2/.get=\tikzumlCNRelationMultiplicityTO, mult/.get=\tikzumlCNRelationMultiplicityTT,%
+ pos1/.get=\tikzumlCNRelationPosition, pos2/.get=\tikzumlCNRelationPositionTO, pos/.get=\tikzumlCNRelationPositionTT,%
+ align1/.get=\tikzumlCNRelationAlign, align2/.get=\tikzumlCNRelationAlignTO, align/.get=\tikzumlCNRelationAlignTT,%
+ anchor1/.get=\tikzumlCNRelationSrcAnchor, anchor2/.get=\tikzumlCNRelationDestAnchor,%
+ stereo/.get=\tikzumlCNRelationStereoType, pos stereo/.get=\tikzumlCNRelationPositionStereotype,%
+ style/.get=\tikzumlCNRelationStyle, name/.get=\tikzumlCNRelationName%
+ }%
+ %
+ % managing \_ in class names for node names
+ \def\tikzumlSrcClassName{#2}%
+ \begingroup%
+ \def\_{_}\edef\x{\endgroup%
+ \def\noexpand\tikzumlSrcClassNodeName{\tikzumlSrcClassName}}\x%
+ %
+ \StrSubstitute{\tikzumlSrcClassNodeName}{:}{@COLON@}[\tikzumlSrcClassNodeName]%
+ \StrSubstitute{\tikzumlSrcClassNodeName}{\_}{@UNDERSCORE@}[\tikzumlSrcClassNodeName]%
+ %
+ \def\tikzumlDestClassName{#4}%
+ \begingroup%
+ \def\_{_}\edef\x{\endgroup%
+ \def\noexpand\tikzumlDestClassNodeName{\tikzumlDestClassName}}\x%
+ %
+ \StrSubstitute{\tikzumlDestClassNodeName}{:}{@COLON@}[\tikzumlDestClassNodeName]%
+ \StrSubstitute{\tikzumlDestClassNodeName}{\_}{@UNDERSCORE@}[\tikzumlDestClassNodeName]%
+ %
+ % managing alias keys
+ \def\tikzumlCNRelationAttrNameT{\tikzumlCNRelationAttrNameTO\tikzumlCNRelationAttrNameTT}%
+ \def\tikzumlCNRelationMultiplicityT{\tikzumlCNRelationMultiplicityTO\tikzumlCNRelationMultiplicityTT}%
+ \def\tikzumlCNRelationAlignT{\tikzumlCNRelationAlignTO\tikzumlCNRelationAlignTT}%
+ \def\orientationT{\orientationTO\orientationTT}%
+ %
+ \ifthenelse{\equal{\tikzumlCNRelationPositionTT}{tikzumlEmpty}}{%
+ \def\tikzumlCNRelationPositionT{\tikzumlCNRelationPositionTO}%
+ }{%
+ \def\tikzumlCNRelationPositionT{\tikzumlCNRelationPositionTT}%
+ }%
+ %
+ \def\attrAlign{}%
+ \def\multAlign{}%
+ \def\attrAlignT{}%
+ \def\multAlignT{}%
+ %
+ \ifthenelse{\equal{\tikzumlCNRelationAlign}{left}}{%
+ \def\attrAlign{above right}%
+ \def\multAlign{below right}%
+ }{%
+ \ifthenelse{\equal{\tikzumlCNRelationAlign}{right}}{%
+ \def\attrAlign{above left}%
+ \def\multAlign{below left}%
+ }{}%
+ }%
+ %
+ \ifthenelse{\equal{\tikzumlCNRelationAlignT}{left}}{%
+ \def\attrAlignT{above right}%
+ \def\multAlignT{below right}%
+ }{%
+ \ifthenelse{\equal{\tikzumlCNRelationAlignT}{right}}{%
+ \def\attrAlignT{above left}%
+ \def\multAlignT{below left}%
+ }{}%
+ }%
+ %
+ % def stereotype
+ \ifthenelse{\equal{\tikzumlCNRelationStereoType}{}}{%
+ \def\stereotype{}%
+ }{%
+ \def\stereotype{$\ll$\tikzumlCNRelationStereoType$\gg$}%
+ }%
+ %
+ % def anchors macros
+ \ifthenelse{\equal{\tikzumlCNRelationSrcAnchor}{tikzumlEmpty}}{%
+ \def\tikzumlCNRelationSrcAnchor{}%
+ }{%
+ \let\tikzumlCNRelationSrcAnchorold\tikzumlCNRelationSrcAnchor%
+ \def\tikzumlCNRelationSrcAnchor{.\tikzumlCNRelationSrcAnchorold}%
+ }%
+ %
+ \ifthenelse{\equal{\tikzumlCNRelationDestAnchor}{tikzumlEmpty}}{%
+ \def\tikzumlCNRelationDestAnchor{}%
+ }{%
+ \let\tikzumlCNRelationDestAnchorold\tikzumlCNRelationDestAnchor%
+ \def\tikzumlCNRelationDestAnchor{.\tikzumlCNRelationDestAnchorold}%
+ }%
+ %
+ \setcounter{pos}{100*\real{\tikzumlCNRelationPosition}}%
+ \setcounter{posT}{100*\real{\tikzumlCNRelationPositionT}}%
+ \setcounter{posStereo}{100*\real{\tikzumlCNRelationPositionStereotype}}%
+ %
+ % straight line
+ %\setcounter{tikzumlControlNodesNum}{1}%
+ %
+ \def\tikzumlFirstArc{node[midway, name=\tikzumlCNRelationName-1, anchor=center] {} }%
+ \def\tikzumlLastArc{node[midway, name=\tikzumlCNRelationName-3, anchor=center]{} }%
+ \def\posAttrName{}%
+ \def\posMultiplicity{}%
+ \def\posAttrNameT{}%
+ \def\posMultiplicityT{}%
+ %
+ \begin{pgfonlayer}{connections}%
+ \node (\tikzumlCNRelationName-2) at (#3) {};%
+ \end{pgfonlayer}%
+ %
+ \ifnum\theposStereo>100%
+ \pgfmathsetmacro{\tikzumlCNRelationPositionStereotype}{(\theposStereo-100)/100}%
+ \xdef\tikzumlLastArc{\tikzumlLastArc node[pos=\tikzumlCNRelationPositionStereotype, anchor=center] {\stereotype} }%
+ \else%
+ \xdef\tikzumlFirstArc{\tikzumlFirstArc node[pos=\tikzumlCNRelationPositionStereotype, anchor=center] {\stereotype} }%
+ \fi%
+ %
+ \ifnum\thepos>100%
+ \pgfmathsetmacro{\tikzumlCNRelationPosition}{(\thepos-100)/100}%
+ \def\arcNum{2}%
+ \else%
+ \def\arcNum{1}%
+ \ifnum\thepos=100%
+ \def\posAttrName{above left}%
+ \def\posMultiplicity{below right}%
+ \fi%
+ \fi%
+ %
+ \ifnum\arcNum=1%
+ \xdef\tikzumlFirstArc{\tikzumlFirstArc node[pos=\tikzumlCNRelationPosition, \posAttrName, \attrAlign] {\tikzumlCNRelationAttrName}%
+ node[pos=\tikzumlCNRelationPosition, swap, \posMultiplicity, \multAlign] {\tikzumlCNRelationMultiplicity} }%
+ \fi%
+ \ifnum\arcNum=2%
+ \xdef\tikzumlLastArc{\tikzumlLastArc node[pos=\tikzumlCNRelationPosition, \posAttrName, \attrAlign] {\tikzumlCNRelationAttrName}%
+ node[pos=\tikzumlCNRelationPosition, swap, \posMultiplicity, \multAlign] {\tikzumlCNRelationMultiplicity} }%
+ \fi%
+ %
+ \ifnum\theposT>100%
+ \pgfmathsetmacro{\tikzumlCNRelationPositionT}{(\theposT-100)/100}%
+ \def\arcNumT{2}%
+ \else%
+ \def\arcNumT{1}%
+ \ifnum\theposT=100%
+ \def\posAttrNameT{above left}%
+ \def\posMultiplicityT{below right}%
+ \fi%
+ \fi%
+ %
+ \ifnum\arcNumT=1%
+ \xdef\tikzumlFirstArc{\tikzumlFirstArc node[pos=\tikzumlCNRelationPositionT, \posAttrNameT, \attrAlignT] {\tikzumlCNRelationAttrNameT}%
+ node[pos=\tikzumlCNRelationPositionT, swap, \posMultiplicityT, \multAlignT] {\tikzumlCNRelationMultiplicityT} }%
+ \fi%
+ \ifnum\arcNumT=2%
+ \xdef\tikzumlLastArc{\tikzumlLastArc node[pos=\tikzumlCNRelationPositionT, \posAttrNameT, \attrAlignT] {\tikzumlCNRelationAttrNameT}%
+ node[pos=\tikzumlCNRelationPositionT, swap, \posMultiplicityT, \multAlignT] {\tikzumlCNRelationMultiplicityT} }%
+ \fi%
+ %
+ \xdef\tikzumlPath{(\tikzumlSrcClassNodeName\tikzumlCNRelationSrcAnchor) -- \tikzumlFirstArc (\tikzumlCNRelationName-2.base) -- \tikzumlLastArc (\tikzumlDestClassNodeName\tikzumlCNRelationDestAnchor) }%
+
+ \begin{pgfonlayer}{connections}%
+ \ifthenelse{\equal{\tikzumlCNRelationStyle}{tikzuml nesting style}}{%
+ \pgfarrowsdeclare{nested}{nested}{...}
+ {
+ \tikzumlNestingSymbolSize=0.2pt%
+ \advance\tikzumlNestingSymbolSize by .5\pgflinewidth%
+ \pgfsetdash{}{0pt} % do not dash
+ \pgfsetroundjoin % fix join
+ \pgfsetroundcap % fix cap
+ \pgfpathmoveto{\pgfpoint{-16*\tikzumlNestingSymbolSize}{0pt}}%
+ \pgfpatharc{180}{90}{8*\tikzumlNestingSymbolSize}%
+ \pgfpatharc{90}{0}{8*\tikzumlNestingSymbolSize}%
+ \pgfpatharc{0}{-90}{8*\tikzumlNestingSymbolSize}%
+ \pgfpatharc{-90}{-180}{8*\tikzumlNestingSymbolSize}%
+ \pgfpathmoveto{\pgfpoint{-8*\tikzumlNestingSymbolSize}{8*\tikzumlNestingSymbolSize}}%
+ \pgfpathlineto{\pgfpoint{-8*\tikzumlNestingSymbolSize}{-8*\tikzumlNestingSymbolSize}}%
+ \pgfusepathqstroke%
+ }%
+ \draw[auto, \tikzumlCNRelationStyle, nested-, font=\tikzumlDefaultFont] \tikzumlPath ;%
+ }{
+ \draw[auto, \tikzumlCNRelationStyle, font=\tikzumlDefaultFont] \tikzumlPath ;%
+ }
+ \end{pgfonlayer}%
+ %
+ \stepcounter{tikzumlRelationNum}%
+}%
+%
+% shortcuts for cnrelations
+\newcommand{\umlCNinherit}[4][]{\umlCNrelation[style={tikzuml inherit style}, #1]{#2}{#3}{#4}}%
+\newcommand{\umlCNimpl}[4][]{\umlCNrelation[style={tikzuml implements style}, #1]{#2}{#3}{#4}}%
+\newcommand{\umlCNreal}[4][]{\umlCNrelation[style={tikzuml implements style}, #1]{#2}{#3}{#4}}%
+\newcommand{\umlCNassoc}[4][]{\umlCNrelation[style={tikzuml association style}, #1]{#2}{#3}{#4}}%
+\newcommand{\umlCNuniassoc}[4][]{\umlCNrelation[style={tikzuml unidirectional association style}, #1]{#2}{#3}{#4}}%
+\newcommand{\umlCNaggreg}[4][]{\umlCNrelation[style={tikzuml aggregation style}, #1]{#2}{#3}{#4}}%
+\newcommand{\umlCNuniaggreg}[4][]{\umlCNrelation[style={tikzuml unidirectional aggregation style}, #1]{#2}{#3}{#4}}%
+\newcommand{\umlCNcompo}[4][]{\umlCNrelation[style={tikzuml composition style}, #1]{#2}{#3}{#4}}%
+\newcommand{\umlCNunicompo}[4][]{\umlCNrelation[style={tikzuml unidirectional composition style}, #1]{#2}{#3}{#4}}%
+\newcommand{\umlCNimport}[4][]{\umlCNrelation[style={tikzuml import style}, #1]{#2}{#3}{#4}}%
+\newcommand{\umlCNnest}[4][]{\umlCNrelation[style={tikzuml nesting style}, #1]{#2}{#3}{#4}}%
+\newcommand{\umlCNdep}[4][]{\umlCNrelation[style={tikzuml dependency style}, #1]{#2}{#3}{#4}}%
+\newcommand{\umlCNfriend}[4][]{%
+ \pgfkeys{/tikzuml/friendrelation/.cd,%
+ .unknown/.code={%
+ \let\keyname=\pgfkeyscurrentname%
+ \let\keyvalue=\pgfkeyscurrentvalue%
+ \ifthenelse{\equal{\keyname}{stereo}}{%
+ \errmessage{TIKZUML ERROR : in umlCNfriend, forbidden option stereo}%
+ }{}%
+ }}%
+ \pgfkeys{/tikzuml/friendrelation/.cd, #1}%
+ \umlCNrelation[stereo=friend, style={tikzuml dependency style}, #1]{#2}{#3}{#4}%
+}%
+%
+% define a note
+% arg : attached class
+% label of the note
+% optional : x,y: coordinates of the note
+% width: width of the note
+% geometry: geometry of the relation between the note and what it is about
+% weight: barycentric weight for a 3-line relation
+% arm: length of the first arm
+% anchor1, anchor2: anchors of the relation
+% draw, fill, text: colors
+% style: to manage every default TikZ option
+% no coords: to tell that the note position is defined relatively
+% to another node (automatically used with TikZ options above, below, left, right, below left, ...)
+\newcommand{\umlnote}[3][]{%
+ \pgfkeys{/tikzuml/note/.cd, x/.initial=\tikzumlDefaultX, y/.initial=\tikzumlDefaultX, width/.initial=\tikzumlNoteDefaultWidth,%
+ geometry/.initial=\tikzumlRelationDefaultGeometry,%
+ weight/.initial=\tikzumlRelationDefaultWeight, arm/.initial=auto, style/.style={},%
+ anchor1/.initial=tikzumlEmpty, anchor2/.initial=tikzumlEmpty,%
+ draw/.initial=\tikzumlDefaultDrawColor, fill/.initial=\tikzumlNoteDefaultFillColor,%
+ text/.initial=\tikzumlDefaultTextColor,%
+ no coords/.is if=tikzumlnoteWithoutCoords,%
+ no coords=false,%
+ .unknown/.code={%
+ \let\keyname=\pgfkeyscurrentname%
+ \let\keyvalue=\pgfkeyscurrentvalue%
+ \ifthenelse{\equal{\keyname}{above}\OR%
+ \equal{\keyname}{left}\OR%
+ \equal{\keyname}{below}\OR%
+ \equal{\keyname}{right}\OR%
+ \equal{\keyname}{above left}\OR%
+ \equal{\keyname}{above right}\OR%
+ \equal{\keyname}{below left}\OR%
+ \equal{\keyname}{below right}}{%
+ \IfSubStr{\keyvalue}{ of }{%
+ \pgfkeys{/tikzuml/note/.cd, no coords}%
+ }{}%
+ }{}%
+ \ifx\keyvalue\pgfkeysnovalue%
+ \pgfkeys{/tikzuml/note/.cd, style/.append style/.expand once={\keyname}}%
+ \else%
+ \pgfkeys{/tikzuml/note/.cd, style/.append style/.expand twice={\expandafter\keyname\expandafter=\keyvalue}}%
+ \fi%
+ %\errmessage{TIKZUML ERROR : in umlnote, invalid option \keyname}%
+ }%
+ }%
+ \pgfkeys{/tikzuml/note/.cd, #1}%
+ \pgfkeys{/tikzuml/note/.cd, x/.get=\tikzumlNoteX, y/.get=\tikzumlNoteY, width/.get=\tikzumlNoteTextWidth,%
+ geometry/.get=\tikzumlNoteGeometry,%
+ weight/.get=\tikzumlNoteWeight, arm/.get=\tikzumlNoteArm,%
+ anchor1/.get=\tikzumlNoteSrcAnchor, anchor2/.get=\tikzumlNoteDestAnchor,%
+ draw/.get=\tikzumlNoteDrawColor, fill/.get=\tikzumlNoteFillColor,%
+ text/.get=\tikzumlNoteTextColor%
+ }%
+ %
+ \def\tikzumlClassName{#2}%
+ \begingroup%
+ \def\_{_}\edef\x{\endgroup%
+ \def\noexpand\tikzumlClassNodeName{\tikzumlClassName}}\x%
+ %
+ % def anchors macros
+ \ifthenelse{\equal{\tikzumlNoteSrcAnchor}{tikzumlEmpty}}{%
+ \def\tikzumlNoteSrcAnchor{}%
+ }{%
+ \let\tikzumlNoteSrcAnchorold\tikzumlNoteSrcAnchor%
+ \def\tikzumlNoteSrcAnchor{.\tikzumlNoteSrcAnchorold}%
+ }%
+ %
+ \ifthenelse{\equal{\tikzumlNoteDestAnchor}{tikzumlEmpty}}{%
+ \def\tikzumlNoteDestAnchor{}%
+ }{%
+ \let\tikzumlNoteDestAnchorold\tikzumlNoteDestAnchor%
+ \def\tikzumlNoteDestAnchor{.\tikzumlNoteDestAnchorold}%
+ }%
+ %
+ \iftikzumlnoteWithoutCoords%
+ \node[text=\tikzumlNoteTextColor, text width=\tikzumlNoteTextWidth, font=\tikzumlDefaultFont, outer sep=0, inner xsep=1ex, inner ysep=3ex, /tikzuml/note/style] (note-\thetikzumlNoteNum-coord) {#3};%
+ \else%
+ \node[text=\tikzumlNoteTextColor, text width=\tikzumlNoteTextWidth, font=\tikzumlDefaultFont, outer sep=0, inner xsep=1ex, inner ysep=3ex, /tikzuml/note/style] (note-\thetikzumlNoteNum-coord) at (\tikzumlNoteX, \tikzumlNoteY) {#3};%
+ \fi%
+ \draw (note-\thetikzumlNoteNum-coord.north east) node[name=note-\thetikzumlNoteNum-right-top, below=2ex, coordinate] {};%
+ \draw (note-\thetikzumlNoteNum-coord.north east) node[name=note-\thetikzumlNoteNum-top-right, left=2ex, coordinate] {};%
+ \draw[draw=\tikzumlNoteDrawColor, fill=\tikzumlNoteFillColor] (note-\thetikzumlNoteNum-coord.south west) -- (note-\thetikzumlNoteNum-coord.south east) -- (note-\thetikzumlNoteNum-right-top.base) -- (note-\thetikzumlNoteNum-top-right.base) -- (note-\thetikzumlNoteNum-coord.north west) -- cycle;%
+ \node[text=\tikzumlNoteTextColor, text width=\tikzumlNoteTextWidth, outer sep=0, inner xsep=1ex, inner ysep=3ex, font=\tikzumlDefaultFont] (note-\thetikzumlNoteNum) at (note-\thetikzumlNoteNum-coord) {#3};%
+ \draw[draw=\tikzumlNoteDrawColor] (note-\thetikzumlNoteNum-right-top) -| (note-\thetikzumlNoteNum-top-right);%
+ %
+ \pgfmathsetmacro{\tikzumlNoteWeightT}{1.0-\tikzumlNoteWeight}%
+ \node (note-\thetikzumlNoteNum-middle) at (barycentric cs:note-\thetikzumlNoteNum-coord=\tikzumlNoteWeight,\tikzumlClassNodeName=\tikzumlNoteWeightT) {};%
+ %
+ \ifthenelse{\equal{\tikzumlNoteGeometry}{--}%
+ \OR\equal{\tikzumlNoteGeometry}{-|}%
+ \OR\equal{\tikzumlNoteGeometry}{|-}}{%
+ \edef\tikzumlnotepath{\tikzumlNoteGeometry}
+ }{%
+ \ifthenelse{\equal{\tikzumlNoteGeometry}{-|-}}{%
+ \ifthenelse{\equal{\tikzumlNoteArm}{auto}}{%
+ \edef\tikzumlnotepath{-- (note-\thetikzumlNoteNum-coord\tikzumlNoteSrcAnchor -| note-\thetikzumlNoteNum-middle.center) -- (note-\thetikzumlNoteNum-middle.center) -- (note-\thetikzumlNoteNum-middle.center |- \tikzumlClassNodeName\tikzumlNoteDestAnchor) --}%
+ }{%
+ \draw (note-\thetikzumlNoteNum-coord\tikzumlNoteSrcAnchor)+(\tikzumlNoteArm,0) node[name=note-\thetikzumlNoteNum-tmp] {};
+ \edef\tikzumlnotepath{-- (note-\thetikzumlNoteNum-tmp.center) |-}%
+ }%
+ }{%
+ \ifthenelse{\equal{\tikzumlNoteGeometry}{|-|}}{%
+ \ifthenelse{\equal{\tikzumlNoteArm}{auto}}{%
+ \edef\tikzumlnotepath{-- (note-\thetikzumlNoteNum-coord\tikzumlNoteSrcAnchor |- note-\thetikzumlNoteNum-middle.center) -- (note-\thetikzumlNoteNum-middle.center) -- (note-\thetikzumlNoteNum-middle.center -| \tikzumlClassNodeName\tikzumlNoteDestAnchor) --}%
+ }{%
+ \draw (note-\thetikzumlNoteNum-coord\tikzumlNoteSrcAnchor)+(0,\tikzumlNoteArm) node[name=note-\thetikzumlNoteNum-tmp] {};
+ \edef\tikzumlnotepath{-- (note-\thetikzumlNoteNum-tmp.center) -|}%
+ }%
+
+ }{%
+ \errmessage{TIKZUML ERROR : Unknown geometry value !!! It should be in the following list : --, |-, -|, |-|, -|-}%
+ }%
+ }%
+ }%
+ %
+ \begin{pgfonlayer}{connections}%
+ \draw[dashed] (note-\thetikzumlNoteNum-coord\tikzumlNoteSrcAnchor) \tikzumlnotepath (\tikzumlClassNodeName\tikzumlNoteDestAnchor);%
+ \end{pgfonlayer}%
+ %
+ \stepcounter{tikzumlNoteNum}%
+}%
+%
+% shortcuts for note with geometry
+\newcommand{\umlHVnote}[3][]{%
+ \pgfkeys{/tikzuml/note/.cd,%
+ .unknown/.code={%
+ \let\keyname=\pgfkeyscurrentname%
+ \let\keyvalue=\pgfkeyscurrentvalue%
+ \ifthenelse{\equal{\keyname}{geometry}}{%
+ \errmessage{TIKZUML ERROR : in umlHVnote, forbidden option geometry}%
+ }{}%
+ }}%
+ \pgfkeys{/tikzuml/note/.cd, #1}%
+ \umlnote[geometry=-|, #1]{#2}{#3}%
+}%
+\newcommand{\umlVHnote}[3][]{%
+ \pgfkeys{/tikzuml/note/.cd,%
+ .unknown/.code={%
+ \let\keyname=\pgfkeyscurrentname%
+ \let\keyvalue=\pgfkeyscurrentvalue%
+ \ifthenelse{\equal{\keyname}{geometry}}{%
+ \errmessage{TIKZUML ERROR : in umlVHnote, forbidden option geometry}%
+ }{}%
+ }}%
+ \pgfkeys{/tikzuml/note/.cd, #1}%
+ \umlnote[geometry=|-, #1]{#2}{#3}%
+}%
+\newcommand{\umlVHVnote}[3][]{%
+ \pgfkeys{/tikzuml/note/.cd,%
+ .unknown/.code={%
+ \let\keyname=\pgfkeyscurrentname%
+ \let\keyvalue=\pgfkeyscurrentvalue%
+ \ifthenelse{\equal{\keyname}{geometry}}{%
+ \errmessage{TIKZUML ERROR : in umlVHVnote, forbidden option geometry}%
+ }{}%
+ }}%
+ \pgfkeys{/tikzuml/note/.cd, #1}%
+ \umlnote[geometry=|-|, #1]{#2}{#3}%
+}%
+\newcommand{\umlHVHnote}[3][]{%
+ \pgfkeys{/tikzuml/note/.cd,%
+ .unknown/.code={%
+ \let\keyname=\pgfkeyscurrentname%
+ \let\keyvalue=\pgfkeyscurrentvalue%
+ \ifthenelse{\equal{\keyname}{geometry}}{%
+ \errmessage{TIKZUML ERROR : in umlHVHnote, forbidden option geometry}%
+ }{}%
+ }}%
+ \pgfkeys{/tikzuml/note/.cd, #1}%
+ \umlnote[geometry=-|-, #1]{#2}{#3}%
+}%
+%
+% define a uml association class (command)
+% args : name of the class
+% attributes of the class
+% operations of the class
+% optional : x,y: coordinates of the class
+% width: width of the class node
+% type: type of of class (class, interface, typedef, enum)
+% template: template parameters
+% name: name of the class node
+% geometry: geometry of the line
+% weight: barycentric weight of the middle part when geometry is a 3-line
+% arm: length of first part when geometry id a 3-line
+% anchor1, anchor2: src/dest anchors on linked classes
+% style: style of the association class (association, aggregation, composition, inherit, ...)
+% draw, fill, fill template, text: colors
+% style: to manage every default TikZ option
+% no coords: to tell that the class position is defined relatively
+% to another node (automatically used with TikZ options above, below, left, right, below left, ...)
+\newcommand{\umlassocclass}[5][]{%
+ \pgfkeys{/tikzuml/assocclass/.cd, x/.initial=\tikzumlDefaultX, y/.initial=\tikzumlDefaultX,
+ width/.initial=\tikzumlClassDefaultWidth, type/.initial=\tikzumlClassDefaultType, style/.style={},%
+ template/.initial={}, name/.initial=tikzumlEmpty, geometry/.initial=\tikzumlRelationDefaultGeometry,%
+ weight/.initial=\tikzumlRelationDefaultWeight, arm/.initial=auto,%
+ anchor1/.initial=tikzumlEmpty, anchor2/.initial=tikzumlEmpty,%
+ draw/.initial=\tikzumlDefaultDrawColor,%
+ fill template/.initial=\tikzumlClassTemplateFillColorDefaultFillColor,%
+ fill/.initial=\tikzumlClassDefaultFillColor,%
+ text/.initial=\tikzumlDefaultTextColor,%
+ no coords/.is if=tikzumlassocclassWithoutCoords,%
+ no coords=false,%
+ .unknown/.code={%
+ \let\keyname=\pgfkeyscurrentname%
+ \let\keyvalue=\pgfkeyscurrentvalue%
+ \ifthenelse{\equal{\keyname}{above}\OR%
+ \equal{\keyname}{left}\OR%
+ \equal{\keyname}{below}\OR%
+ \equal{\keyname}{right}\OR%
+ \equal{\keyname}{above left}\OR%
+ \equal{\keyname}{above right}\OR%
+ \equal{\keyname}{below left}\OR%
+ \equal{\keyname}{below right}}{%
+ \IfSubStr{\keyvalue}{ of }{%
+ \pgfkeys{/tikzuml/assocclass/.cd, no coords}%
+ }{}%
+ }{}%
+ \ifx\keyvalue\pgfkeysnovalue%
+ \pgfkeys{/tikzuml/assocclass/.cd, style/.append style/.expand once={\keyname}}%
+ \else%
+ \pgfkeys{/tikzuml/assocclass/.cd, style/.append style/.expand twice={\expandafter\keyname\expandafter=\keyvalue}}%
+ \fi%
+ %\errmessage{TIKZUML ERROR : in umlassocclass, invalid option \keyname}%
+ }%
+ }%
+ %
+ \pgfkeys{/tikzuml/assocclass/.cd,#1}%
+ \pgfkeys{/tikzuml/assocclass/.cd, x/.get=\tikzumlAssocClassX, y/.get=\tikzumlAssocClassY,%
+ width/.get=\tikzumlAssocClassMinimumWidth, type/.get=\tikzumlAssocClassTypeTmp,%
+ template/.get=\tikzumlAssocClassTemplateParam,%
+ name/.get=\tikzumlAssocClassName, geometry/.get=\tikzumlAssocClassGeometry,%
+ weight/.get=\tikzumlAssocClassWeight, arm/.get=\tikzumlAssocClassArm,%
+ anchor1/.get=\tikzumlAssocClassSrcAnchor,%
+ anchor2/.get=\tikzumlAssocClassDestAnchor,%
+ draw/.get=\tikzumlAssocClassDrawColor, fill/.get=\tikzumlAssocClassFillColor,%
+ text/.get=\tikzumlAssocClassTextColor, fill template/.get=\tikzumlAssocClassTemplateFillColor%
+ }%
+ %
+ \ifthenelse{\equal{\tikzumlAssocClassTypeTmp}{class}\OR\equal{\tikzumlAssocClassTypeTmp}{abstract}}{%
+ \def\tikzumlAssocClassType{}%
+ }{%
+ \def\tikzumlAssocClassType{$\ll$\tikzumlAssocClassTypeTmp$\gg$ \\}%
+ }%
+ %
+ \ifthenelse{\equal{\tikzumlAssocClassTemplateParam}{}}{%
+ \def\tikzumlAssocClassVPadding{}%
+ \def\tikzumlAssocClassHPadding{}%
+ }{%
+ \def\tikzumlAssocClassVPadding{\vspace{0.1em} \\}%
+ \def\tikzumlAssocClassHPadding{\hspace{0.5ex} $ $}%
+ }%
+ %
+ \def\tikzumlAssocClassName{#2}%
+ \def\tikzumlAssocClassRelationName{#3}%
+ %
+ \begingroup%
+ \def\_{_}\edef\x{\endgroup%
+ \def\noexpand\tikzumlAssocClassNodeName{\tikzumlAssocClassName}}\x%
+ %
+ \begingroup%
+ \def\_{_}\edef\x{\endgroup%
+ \def\noexpand\tikzumlAssocClassRelationNodeName{\tikzumlAssocClassRelationName}}\x%
+ %
+ \ifthenelse{\equal{\tikzumlAssocClassName}{tikzumlEmpty}}{}{%
+ \def\tikzumlAssocClassNodeName{\tikzumlAssocClassName}%
+ }%
+ %
+ \StrSubstitute{\tikzumlAssocClassNodeName}{:}{@COLON@}[\tikzumlAssocClassNodeName]%
+ \StrSubstitute{\tikzumlAssocClassNodeName}{\_}{@UNDERSCORE@}[\tikzumlAssocClassNodeName]%
+ %
+ \ifthenelse{\equal{\tikzumlAssocClassTypeTmp}{abstract}}{%
+ \let\tikzumlAssocClassNameOld\tikzumlAssocClassName%
+ \def\tikzumlAssocClassName{{\it \tikzumlAssocClassNameOld}}%
+ }{}%
+ %
+ \def\tikzumlAssocClassPos{\tikzumlAssocClassX,\tikzumlAssocClassY}%
+ \def\tikzumlAssocClassAttributes{#4}%
+ \def\tikzumlAssocClassOperations{#5}%
+ %
+ % def anchors macros
+ \ifthenelse{\equal{\tikzumlAssocClassSrcAnchor}{tikzumlEmpty}}{%
+ \def\tikzumlAssocClassSrcAnchor{}%
+ }{%
+ \let\tikzumlAssocClassSrcAnchorold\tikzumlAssocClassSrcAnchor%
+ \def\tikzumlAssocClassSrcAnchor{.\tikzumlAssocClassSrcAnchorold}%
+ }%
+ %
+ \ifthenelse{\equal{\tikzumlAssocClassDestAnchor}{tikzumlEmpty}}{%
+ \def\tikzumlAssocClassDestAnchor{}%
+ }{%
+ \let\tikzumlAssocClassDestAnchorold\tikzumlAssocClassDestAnchor%
+ \def\tikzumlAssocClassDestAnchor{.\tikzumlAssocClassDestAnchorold}%
+ }%
+ %
+ \iftikzumlassocclassWithoutCoords%
+ \node[tikzuml class style, draw=\tikzumlAssocClassDrawColor, fill=\tikzumlAssocClassFillColor, text=\tikzumlAssocClassTextColor, font=\tikzumlDefaultFont, minimum width=\tikzumlAssocClassMinimumWidth, /tikzuml/assocclass/style] (\tikzumlAssocClassNodeName) {\begin{tabular}{c}\tikzumlAssocClassVPadding \tikzumlAssocClassType \tikzumlAssocClassHPadding \textbf{\tikzumlAssocClassName} \tikzumlAssocClassHPadding \end{tabular}%
+ \nodepart{second}%
+ \begin{tabular}{l}%
+ \tikzumlAssocClassAttributes%
+ \end{tabular}%
+ \nodepart{third}%
+ \begin{tabular}{l}%
+ \tikzumlAssocClassOperations%
+ \end{tabular}%
+ };%
+ \else%
+ \node[tikzuml class style, draw=\tikzumlAssocClassDrawColor, fill=\tikzumlAssocClassFillColor, text=\tikzumlAssocClassTextColor, font=\tikzumlDefaultFont, minimum width=\tikzumlAssocClassMinimumWidth, /tikzuml/assocclass/style] (\tikzumlAssocClassNodeName) at (\tikzumlAssocClassPos) {\begin{tabular}{c}\tikzumlAssocClassVPadding \tikzumlAssocClassType \tikzumlAssocClassHPadding \textbf{\tikzumlAssocClassName} \tikzumlAssocClassHPadding \end{tabular}%
+ \nodepart{second}%
+ \begin{tabular}{l}%
+ \tikzumlAssocClassAttributes%
+ \end{tabular}%
+ \nodepart{third}%
+ \begin{tabular}{l}%
+ \tikzumlAssocClassOperations%
+ \end{tabular}%
+ };%
+ \fi%
+ %
+ \ifthenelse{\equal{\tikzumlAssocClassTemplateParam}{}}{}{%
+ \draw (\tikzumlAssocClassNodeName.north east) node[tikzuml template style, name=\tikzumlAssocClassNodeName-template, draw=\tikzumlAssocClassDrawColor, fill=\tikzumlAssocClassTemplateFillColor, text=\tikzumlAssocClassTextColor, font=\tikzumlDefaultFont] {\tikzumlAssocClassTemplateParam};%
+ }%
+ %
+ \pgfmathsetmacro{\tikzumlAssocClassWeightT}{1.0-\tikzumlAssocClassWeight}
+ \node (\tikzumlAssocClassNodeName-middle) at (barycentric cs:\tikzumlAssocClassNodeName=\tikzumlAssocClassWeight,\tikzumlAssocClassRelationNodeName=\tikzumlAssocClassWeightT) {};%
+ %
+ \ifthenelse{\equal{\tikzumlAssocClassGeometry}{--}\OR\equal{\tikzumlAssocClassGeometry}{-|}\OR\equal{\tikzumlAssocClassGeometry}{|-}}{%
+ \edef\tikzumlassocclasspath{\tikzumlAssocClassGeometry}
+ }{%
+ \ifthenelse{\equal{\tikzumlAssocClassGeometry}{-|-}}{%
+ \ifthenelse{\equal{\tikzumlAssocClassArm}{auto}}{%
+ \edef\tikzumlassocclasspath{-- (\tikzumlAssocClassNodeName\tikzumlAssocClassSrcAnchor -| \tikzumlAssocClassNodeName-middle.center) -- (\tikzumlAssocClassNodeName-middle.center) -- (\tikzumlAssocClassNodeName-middle.center |- \tikzumlAssocClassRelationNodeName\tikzumlAssocClassDestAnchor) --}%
+ }{%
+ \draw (\tikzumlAssocClassNodeName\tikzumlAssocClassSrcAnchor)+(\tikzumlAssocClassArm,0) node[name=\tikzumlAssocClassNodeName-tmp] {};
+ \edef\tikzumlnotepath{-- (\tikzumlAssocClassNodeName-tmp.center) |-}%
+ }%
+ }{%
+ \ifthenelse{\equal{\tikzumlAssocClassGeometry}{|-|}}{%
+ \ifthenelse{\equal{\tikzumlAssocClassArm}{auto}}{%
+ \edef\tikzumlassocclasspath{-- (\tikzumlAssocClassNodeName\tikzumlAssocClassSrcAnchor |- \tikzumlAssocClassNodeName-middle.center) -- (\tikzumlAssocClassNodeName-middle.center) -- (\tikzumlAssocClassNodeName-middle.center -| \tikzumlAssocClassRelationNodeName\tikzumlAssocClassDestAnchor) --}%
+ }{%
+ \draw (\tikzumlAssocClassNodeName\tikzumlAssocClassSrcAnchor)+(0,\tikzumlAssocClassArm) node[name=\tikzumlAssocClassNodeName-tmp] {};
+ \edef\tikzumlassocclasspath{-- (\thetikzumlAssocClassNodeName-tmp.center) -|}%
+ }%
+
+ }{%
+ \errmessage{TIKZUML ERROR : Unknown geometry value !!! It should be in the following list : --, |-, -|, |-|, -|-}%
+ }%
+ }%
+ }%
+ %
+ \begin{pgfonlayer}{connections}%
+ \draw[dashed] (\tikzumlAssocClassNodeName\tikzumlAssocClassSrcAnchor) \tikzumlassocclasspath (\tikzumlAssocClassRelationNodeName\tikzumlAssocClassDestAnchor);%
+ \end{pgfonlayer}%
+ %
+ % add to fit
+ \ifnum\c@tikzumlPackageLevel>0%
+ \edef\tikzumlPackageFitOld{\csname tikzumlPackageFit\tikzumlPackage@parent @@\tikzumlPackage@fitname\endcsname}%
+ \ifthenelse{\equal{\tikzumlAssocClassTemplateParam}{}}{%
+ \expandafter\xdef\csname tikzumlPackageFit\tikzumlPackage@parent @@\tikzumlPackage@fitname\endcsname{\tikzumlPackageFitOld (\tikzumlAssocClassNodeName)(\tikzumlAssocClassNodeName-middle)}%
+ }{%
+ \expandafter\xdef\csname tikzumlPackageFit\tikzumlPackage@parent @@\tikzumlPackage@fitname\endcsname{\tikzumlPackageFitOld (\tikzumlAssocClassNodeName) (\tikzumlAssocClassNodeName-template)(\tikzumlAssocClassNodeName-middle)}%
+ }%
+ \stepcounter{tikzumlPackageClassNum}%
+ \fi%
+}%
+%
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% use case diagrams %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+\tikzstyle{tikzuml usecase style}=[ellipse, text centered]%
+\tikzstyle{tikzuml actor style}=[ellipse, inner sep=0, outer sep=0]%
+%
+\newcounter{tikzumlSystemUseCaseNum}%
+\newcounter{tikzumlSystemLevel}%
+\newcounter{tikzumlUseCaseNum}%
+\newcounter{tikzumlActorNum}%
+%
+\newif\iftikzumlusecaseWithoutCoords%
+\newif\iftikzumlactorWithoutCoords%
+%
+% define a system
+% arg : name
+% optional : x, y: coordinates of the system
+% draw, fill, text: colors
+\newenvironment{umlsystem}[2][]{%
+ \gdef\tikzumlSystemFit{}%
+ \def\tikzumlSystemName{#2}%
+ \setcounter{tikzumlSystemUseCaseNum}{0}%
+ %
+ \pgfkeys{/tikzuml/system/.cd, x/.initial=\tikzumlDefaultX, y/.initial=\tikzumlDefaultX,%
+ draw/.initial=\tikzumlDefaultDrawColor, fill/.initial=\tikzumlSystemDefaultFillColor,%
+ text/.initial=\tikzumlDefaultTextColor,%
+ .unknown/.code={%
+ \let\keyname=\pgfkeyscurrentname%
+ \let\keyvalue=\pgfkeyscurrentvalue%
+ \errmessage{TIKZUML ERROR : in umlsystem, invalid option \keyname}%
+ }%
+ }%
+ %
+ \pgfkeys{/tikzuml/system/.cd, #1}%
+ \pgfkeys{/tikzuml/system/.cd, x/.get=\tikzumlSystemXShift, y/.get=\tikzumlSystemYShift,%
+ draw/.get=\tikzumlSystemDrawColor, fill/.get=\tikzumlSystemFillColor,%
+ text/.get=\tikzumlSystemTextColor}%
+ %
+ \stepcounter{tikzumlSystemLevel}%
+ %
+ \begin{scope}[xshift=\tikzumlSystemXShift cm, yshift=\tikzumlSystemYShift cm]%
+}{%
+ \addtocounter{tikzumlSystemLevel}{-1}%
+ % if contains no usecase, one define a fictive node to enable the fit option
+ \ifnum\c@tikzumlSystemUseCaseNum=0%
+ \node[inner xsep=10ex, inner ysep=1em] (\tikzumlSystemName-root) at (0,0) {};%
+ \xdef\tikzumlSystemFit{(\tikzumlSystemName-root)}%
+ \fi%
+ %
+ \begin{pgfonlayer}{background}%
+ \node[inner ysep=1em, inner xsep=2ex, fit = \tikzumlSystemFit] (\tikzumlSystemName-tmp) {};%
+ \node[text=\tikzumlSystemTextColor, font=\tikzumlDefaultFont] (\tikzumlSystemName-caption-tmp) at (\tikzumlSystemName-tmp.north) {\tikzumlSystemName};%
+ \node[draw=\tikzumlSystemDrawColor, fill=\tikzumlSystemFillColor, text=\tikzumlSystemTextColor, font=\tikzumlDefaultFont, inner ysep=1em, inner xsep=2ex, fit = (\tikzumlSystemName-tmp) (\tikzumlSystemName-caption-tmp)] (\tikzumlSystemName) {};%
+ \node[text=\tikzumlSystemTextColor, font=\tikzumlDefaultFont] (\tikzumlSystemName-caption) at (\tikzumlSystemName-caption-tmp.north) {\tikzumlSystemName};%
+ \end{pgfonlayer}%
+ \end{scope}%
+ %
+}%
+%
+% define a use case
+% arg : label of the use case
+% optional : x, y: coordinates of the use case
+% name: name of the node
+% width: node width
+% draw, fill, text: colors
+% style: to manage every default TikZ option
+% no coords: to tell that the use case position is defined relatively
+% to another node (automatically used with TikZ options above, below, left, right, below left, ...)
+\newcommand{\umlusecase}[2][]{%
+ \stepcounter{tikzumlUseCaseNum}%
+ \pgfkeys{/tikzuml/usecase/.cd, x/.initial=\tikzumlDefaultX, y/.initial=\tikzumlDefaultX, width/.initial=auto,%
+ name/.initial=usecase-\thetikzumlUseCaseNum,%
+ draw/.initial=\tikzumlDefaultDrawColor, fill/.initial=\tikzumlUseCaseDefaultFillColor,%
+ text/.initial=\tikzumlDefaultTextColor, style/.style={},%
+ no coords/.is if=tikzumlusecaseWithoutCoords,%
+ no coords=false,%
+ .unknown/.code={%
+ \let\keyname=\pgfkeyscurrentname%
+ \let\keyvalue=\pgfkeyscurrentvalue%
+ \ifthenelse{\equal{\keyname}{above}\OR%
+ \equal{\keyname}{left}\OR%
+ \equal{\keyname}{below}\OR%
+ \equal{\keyname}{right}\OR%
+ \equal{\keyname}{above left}\OR%
+ \equal{\keyname}{above right}\OR%
+ \equal{\keyname}{below left}\OR%
+ \equal{\keyname}{below right}}{%
+ \IfSubStr{\keyvalue}{ of }{%
+ \pgfkeys{/tikzuml/usecase/.cd, no coords}%
+ }{}%
+ }{}%
+ \ifx\keyvalue\pgfkeysnovalue%
+ \pgfkeys{/tikzuml/usecase/.cd, style/.append style/.expand once={\keyname}}%
+ \else%
+ \pgfkeys{/tikzuml/usecase/.cd, style/.append style/.expand twice={\expandafter\keyname\expandafter=\keyvalue}}%
+ \fi%
+ %\errmessage{TIKZUML ERROR : in umlusecase, invalid option \keyname}%
+ }%
+ }%
+ \pgfkeys{/tikzuml/usecase/.cd, #1}%
+ \pgfkeys{/tikzuml/usecase/.cd, x/.get=\tikzumlUseCaseX, y/.get=\tikzumlUseCaseY, width/.get=\tikzumlUseCaseTextWidth,%
+ name/.get=\tikzumlUseCaseName,%
+ draw/.get=\tikzumlUseCaseDrawColor, fill/.get=\tikzumlUseCaseFillColor,%
+ text/.get=\tikzumlUseCaseTextColor%
+ }%
+ %
+ \def\tikzumlUseCaseText{#2}%
+ %
+ \def\tikzumlUseCasePos{\tikzumlUseCaseX,\tikzumlUseCaseY}%
+ %
+ \ifthenelse{\equal{\tikzumlUseCaseTextWidth}{auto}}{%
+ \iftikzumlusecaseWithoutCoords%
+ \node[tikzuml usecase style, draw=\tikzumlUseCaseDrawColor, fill=\tikzumlUseCaseFillColor, text=\tikzumlUseCaseTextColor, font=\tikzumlDefaultFont, /tikzuml/usecase/style] (\tikzumlUseCaseName) {\tikzumlUseCaseText};%
+ \else%
+ \node[tikzuml usecase style, draw=\tikzumlUseCaseDrawColor, fill=\tikzumlUseCaseFillColor, text=\tikzumlUseCaseTextColor, font=\tikzumlDefaultFont, /tikzuml/usecase/style] (\tikzumlUseCaseName) at (\tikzumlUseCasePos) {\tikzumlUseCaseText};%
+ \fi%
+ }{%
+ \iftikzumlusecaseWithoutCoords%
+ \node[tikzuml usecase style, draw=\tikzumlUseCaseDrawColor, fill=\tikzumlUseCaseFillColor, text=\tikzumlUseCaseTextColor, font=\tikzumlDefaultFont, text width=\tikzumlUseCaseTextWidth, /tikzuml/usecase/style] (\tikzumlUseCaseName) {\tikzumlUseCaseText};%
+ \else%
+ \node[tikzuml usecase style, draw=\tikzumlUseCaseDrawColor, fill=\tikzumlUseCaseFillColor, text=\tikzumlUseCaseTextColor, font=\tikzumlDefaultFont, text width=\tikzumlUseCaseTextWidth, /tikzuml/usecase/style] (\tikzumlUseCaseName) at (\tikzumlUseCasePos) {\tikzumlUseCaseText};%
+ \fi%
+ }%
+ %
+ % add to fit
+ \ifnum\c@tikzumlSystemLevel>0%
+ \let\tikzumlSystemFitOld\tikzumlSystemFit%
+ \xdef\tikzumlSystemFit{\tikzumlSystemFitOld (\tikzumlUseCaseName)}%
+ \stepcounter{tikzumlSystemUseCaseNum}%
+ \fi%
+}%
+%
+% define the actor symbol
+% optional : global tikzpicture styles
+\newcommand{\picturedactor}[1]{%
+ \pgfkeys{/tikzuml/picactor/.cd, scale/.initial=1, .unknown/.code={}}%
+ \pgfkeys{/tikzuml/picactor/.cd,#1}%
+ \pgfkeys{/tikzuml/picactor/.cd, scale/.get=\tikzumlPicturedActorScale}%
+ %
+ \begin{tikzpicture}[#1]%
+ \coordinate (head) at (0,4ex);%
+ \coordinate (left-hand) at (-2ex,2ex);%
+ \coordinate (right-hand) at (2ex,2ex);%
+ \coordinate (left-foot) at (-2ex,-2ex);%
+ \coordinate (right-foot) at (2ex,-2ex);%
+ \coordinate (empty) at (0,-3ex);%
+ \draw (empty) (0,0) -- (head);%
+ \draw (left-hand) -- (right-hand);%
+ \draw (0,0) -- (left-foot) (0,0) -- (right-foot);%
+ \node[fill, draw, circle, inner sep=\tikzumlPicturedActorScale*0.3333ex, minimum size=\tikzumlPicturedActorScale*2ex, anchor=base] at (head) {};%
+ \end{tikzpicture}%
+}%
+%
+% define an actor
+% arg : var name
+% optional : x, y: coordinates of the actor
+% scale: scale factor of the actor symbol
+% below: distance between the actor symbol and its name below
+% draw, text: colors
+% style: to manage every default TikZ option
+% no coords: to tell that the actor position is defined relatively
+% to another node (automatically used with TikZ options above, below, left, right, below left, ...)
+\newcommand{\umlactor}[2][]{%
+ \stepcounter{tikzumlActorNum}%
+ \pgfkeys{/tikzuml/actor/.cd, x/.initial=\tikzumlDefaultX, y/.initial=\tikzumlDefaultX, scale/.initial=1, below/.initial=\tikzumlActorDefaultBelow,%
+ draw/.initial=\tikzumlDefaultDrawColor, text/.initial=\tikzumlDefaultTextColor,%
+ style/.style={},%
+ no coords/.is if=tikzumlactorWithoutCoords,%
+ no coords=false,%
+ .unknown/.code={%
+ \let\keyname=\pgfkeyscurrentname%
+ \let\keyvalue=\pgfkeyscurrentvalue%
+ \ifthenelse{\equal{\keyname}{above}\OR%
+ \equal{\keyname}{left}\OR%
+ \equal{\keyname}{below}\OR%
+ \equal{\keyname}{right}\OR%
+ \equal{\keyname}{above left}\OR%
+ \equal{\keyname}{above right}\OR%
+ \equal{\keyname}{below left}\OR%
+ \equal{\keyname}{below right}}{%
+ \IfSubStr{\keyvalue}{ of }{%
+ \pgfkeys{/tikzuml/actor/.cd, no coords}%
+ }{}%
+ }{}%
+ \ifx\keyvalue\pgfkeysnovalue%
+ \pgfkeys{/tikzuml/actor/.cd, style/.append style/.expand once={\keyname}}%
+ \else%
+ \pgfkeys{/tikzuml/actor/.cd, style/.append style/.expand twice={\expandafter\keyname\expandafter=\keyvalue}}%
+ \fi%
+ %\errmessage{TIKZUML ERROR : in umlactor, invalid option \keyname}%
+ }%
+ }%
+ \pgfkeys{/tikzuml/actor/.cd, #1}%
+ \pgfkeys{/tikzuml/actor/.cd,%
+ x/.get=\tikzumlActorX, y/.get=\tikzumlActorY, scale/.get=\tikzumlActorScale,%
+ below/.get=\tikzumlActorBelow,%
+ draw/.get=\tikzumlActorDrawColor, text/.get=\tikzumlActorTextColor}%
+ %
+ \def\tikzumlActorName{#2}%
+ \begingroup%
+ \def\_{_}\edef\x{\endgroup%
+ \def\noexpand\tikzumlActorNodeName{\tikzumlActorName}}\x%
+ %
+ \def\tikzumlActorPos{\tikzumlActorX,\tikzumlActorY}%
+ %
+ \iftikzumlactorWithoutCoords%
+ \node[tikzuml actor style, text=\tikzumlActorTextColor, font=\tikzumlDefaultFont, /tikzuml/actor/style] (\tikzumlActorNodeName) {\picturedactor{scale=\tikzumlActorScale, fill=white, draw=\tikzumlActorDrawColor, thick}};%
+ \else%
+ \node[tikzuml actor style, text=\tikzumlActorTextColor, font=\tikzumlDefaultFont, /tikzuml/actor/style] (\tikzumlActorNodeName) at (\tikzumlActorPos) {\picturedactor{scale=\tikzumlActorScale, fill=white, draw=\tikzumlActorDrawColor, thick}};%
+ \fi%
+ \node[text=\tikzumlActorTextColor, font=\tikzumlDefaultFont, below=\tikzumlActorScale*\tikzumlActorBelow] at (\tikzumlActorNodeName) {\tikzumlActorName};%
+ %
+}%
+
+% shortcuts for include and extend relation
+\newcommand{\umlinclude}[3][]{%
+ \pgfkeys{/tikzuml/includerelation/.cd,%
+ .unknown/.code={%
+ \let\keyname=\pgfkeyscurrentname%
+ \let\keyvalue=\pgfkeyscurrentvalue%
+ \ifthenelse{\equal{\keyname}{stereo}}{%
+ \errmessage{TIKZUML ERROR : in umlinclude, forbidden option stereo}%
+ }{%
+ \ifthenelse{\equal{\keyname}{geometry}}{%
+ \errmessage{TIKZUML ERROR : in umlinclude, forbidden option geometry}%
+ }{}%
+ }%
+ }}%
+ \pgfkeys{/tikzuml/includerelation/.cd, #1}%
+ \umlrelation[stereo=include, style={tikzuml dependency style}, #1]{#2}{#3}%
+}%
+\newcommand{\umlextend}[3][]{%
+ \pgfkeys{/tikzuml/extendrelation/.cd,%
+ .unknown/.code={%
+ \let\keyname=\pgfkeyscurrentname%
+ \let\keyvalue=\pgfkeyscurrentvalue%
+ \ifthenelse{\equal{\keyname}{stereo}}{%
+ \errmessage{TIKZUML ERROR : in umlextend, forbidden option stereo}%
+ }{%
+ \ifthenelse{\equal{\keyname}{geometry}}{%
+ \errmessage{TIKZUML ERROR : in umlextend, forbidden option geometry}%
+ }{}%
+ }%
+ }}%
+ \pgfkeys{/tikzuml/extendrelation/.cd, #1}%
+ \umlrelation[stereo=extend, style={tikzuml dependency style}, #1]{#2}{#3}%
+}%
+%
+\newcommand{\umlHVinclude}[3][]{%
+ \pgfkeys{/tikzuml/includerelation/.cd,%
+ .unknown/.code={%
+ \let\keyname=\pgfkeyscurrentname%
+ \let\keyvalue=\pgfkeyscurrentvalue%
+ \ifthenelse{\equal{\keyname}{stereo}}{%
+ \errmessage{TIKZUML ERROR : in umlHVinclude, forbidden option stereo}%
+ }{%
+ \ifthenelse{\equal{\keyname}{geometry}}{%
+ \errmessage{TIKZUML ERROR : in umlHVinclude, forbidden option geometry}%
+ }{}%
+ }%
+ }}%
+ \pgfkeys{/tikzuml/includerelation/.cd, #1}%
+ \umlrelation[geometry=-|, stereo=include, style={tikzuml dependency style}, #1]{#2}{#3}%
+}%
+\newcommand{\umlHVextend}[3][]{%
+ \pgfkeys{/tikzuml/extendrelation/.cd,%
+ .unknown/.code={%
+ \let\keyname=\pgfkeyscurrentname%
+ \let\keyvalue=\pgfkeyscurrentvalue%
+ \ifthenelse{\equal{\keyname}{stereo}}{%
+ \errmessage{TIKZUML ERROR : in umlHVextend, forbidden option stereo}%
+ }{%
+ \ifthenelse{\equal{\keyname}{geometry}}{%
+ \errmessage{TIKZUML ERROR : in umlHVextend, forbidden option geometry}%
+ }{}%
+ }%
+ }}%
+ \pgfkeys{/tikzuml/extendrelation/.cd, #1}%
+ \umlrelation[geometry=-|, stereo=extend, style={tikzuml dependency style}, #1]{#2}{#3}%
+}%
+%
+\newcommand{\umlVHinclude}[3][]{%
+ \pgfkeys{/tikzuml/includerelation/.cd,%
+ .unknown/.code={%
+ \let\keyname=\pgfkeyscurrentname%
+ \let\keyvalue=\pgfkeyscurrentvalue%
+ \ifthenelse{\equal{\keyname}{stereo}}{%
+ \errmessage{TIKZUML ERROR : in umlVHinclude, forbidden option stereo}%
+ }{%
+ \ifthenelse{\equal{\keyname}{geometry}}{%
+ \errmessage{TIKZUML ERROR : in umlVHinclude, forbidden option geometry}%
+ }{}%
+ }%
+ }}%
+ \pgfkeys{/tikzuml/includerelation/.cd, #1}%
+ \umlrelation[geometry=|-, stereo=include, style={tikzuml dependency style}, #1]{#2}{#3}%
+}%
+\newcommand{\umlVHextend}[3][]{%
+ \pgfkeys{/tikzuml/extendrelation/.cd,%
+ .unknown/.code={%
+ \let\keyname=\pgfkeyscurrentname%
+ \let\keyvalue=\pgfkeyscurrentvalue%
+ \ifthenelse{\equal{\keyname}{stereo}}{%
+ \errmessage{TIKZUML ERROR :in umlVHextend, forbidden option stereo}%
+ }{%
+ \ifthenelse{\equal{\keyname}{geometry}}{%
+ \errmessage{TIKZUML ERROR : in umlVHextend, forbidden option geometry}%
+ }{}%
+ }%
+ }}%
+ \pgfkeys{/tikzuml/extendrelation/.cd, #1}%
+ \umlrelation[geometry=|-, stereo=extend, style={tikzuml dependency style}, #1]{#2}{#3}%
+}%
+%
+\newcommand{\umlHVHinclude}[3][]{%
+ \pgfkeys{/tikzuml/includerelation/.cd,%
+ .unknown/.code={%
+ \let\keyname=\pgfkeyscurrentname%
+ \let\keyvalue=\pgfkeyscurrentvalue%
+ \ifthenelse{\equal{\keyname}{stereo}}{%
+ \errmessage{TIKZUML ERROR : in umlHVHinclude, forbidden option stereo}%
+ }{%
+ \ifthenelse{\equal{\keyname}{geometry}}{%
+ \errmessage{TIKZUML ERROR : in umlHVHinclude, forbidden option geometry}%
+ }{}%
+ }%
+ }}%
+ \pgfkeys{/tikzuml/includerelation/.cd, #1}%
+ \umlrelation[geometry=-|-, stereo=include, style={tikzuml dependency style}, #1]{#2}{#3}%
+}%
+\newcommand{\umlHVHextend}[3][]{%
+ \pgfkeys{/tikzuml/extendrelation/.cd,%
+ .unknown/.code={%
+ \let\keyname=\pgfkeyscurrentname%
+ \let\keyvalue=\pgfkeyscurrentvalue%
+ \ifthenelse{\equal{\keyname}{stereo}}{%
+ \errmessage{TIKZUML ERROR : in umlHVHextend, forbidden option stereo}%
+ }{%
+ \ifthenelse{\equal{\keyname}{geometry}}{%
+ \errmessage{TIKZUML ERROR : in umlHVHextend, forbidden option geometry}%
+ }{}%
+ }%
+ }}%
+ \pgfkeys{/tikzuml/extendrelation/.cd, #1}%
+ \umlrelation[geometry=-|-, stereo=extend, style={tikzuml dependency style}, #1]{#2}{#3}%
+}%
+%
+\newcommand{\umlVHVinclude}[3][]{%
+ \pgfkeys{/tikzuml/includerelation/.cd,%
+ .unknown/.code={%
+ \let\keyname=\pgfkeyscurrentname%
+ \let\keyvalue=\pgfkeyscurrentvalue%
+ \ifthenelse{\equal{\keyname}{stereo}}{%
+ \errmessage{TIKZUML ERROR : in umlVHVinclude, forbidden option stereo}%
+ }{%
+ \ifthenelse{\equal{\keyname}{geometry}}{%
+ \errmessage{TIKZUML ERROR : in umlVHVinclude, forbidden option geometry}%
+ }{}%
+ }%
+ }}%
+ \pgfkeys{/tikzuml/includerelation/.cd, #1}%
+ \umlrelation[geometry=|-|, stereo=include, style={tikzuml dependency style}, #1]{#2}{#3}%
+}%
+\newcommand{\umlVHVextend}[3][]{%
+ \pgfkeys{/tikzuml/extendrelation/.cd,%
+ .unknown/.code={%
+ \let\keyname=\pgfkeyscurrentname%
+ \let\keyvalue=\pgfkeyscurrentvalue%
+ \ifthenelse{\equal{\keyname}{stereo}}{%
+ \errmessage{TIKZUML ERROR : in umlVHVextend, forbidden option stereo}%
+ }{%
+ \ifthenelse{\equal{\keyname}{geometry}}{%
+ \errmessage{TIKZUML ERROR : in umlVHVextend, forbidden option geometry}%
+ }{}%
+ }%
+ }}%
+ \pgfkeys{/tikzuml/extendrelation/.cd, #1}%
+ \umlrelation[geometry=|-|, stereo=extend, style={tikzuml dependency style}, #1]{#2}{#3}%
+}%
+%
+\newcommand{\umlCNinclude}[4][]{%
+ \pgfkeys{/tikzuml/includerelation/.cd,%
+ .unknown/.code={%
+ \let\keyname=\pgfkeyscurrentname%
+ \let\keyvalue=\pgfkeyscurrentvalue%
+ \ifthenelse{\equal{\keyname}{stereo}}{%
+ \errmessage{TIKZUML ERROR : in umlCNinclude, forbidden option stereo}%
+ }{}%
+ }}%
+ \pgfkeys{/tikzuml/includerelation/.cd, #1}%
+ \umlCNrelation[stereo=include, style={tikzuml dependency style}, #1]{#2}{#3}{#4}%
+}%
+\newcommand{\umlCNextend}[4][]{%
+ \pgfkeys{/tikzuml/extendrelation/.cd,%
+ .unknown/.code={%
+ \let\keyname=\pgfkeyscurrentname%
+ \let\keyvalue=\pgfkeyscurrentvalue%
+ \ifthenelse{\equal{\keyname}{stereo}}{%
+ \errmessage{TIKZUML ERROR : in umlCNextend, forbidden option stereo}%
+ }{}%
+ }}%
+ \pgfkeys{/tikzuml/extendrelation/.cd, #1}%
+ \umlCNrelation[stereo=extend, style={tikzuml dependency style}, #1]{#2}{#3}{#4}%
+}%
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% state diagrams %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+\tikzstyle{tikzuml state style}=[rectangle split, rectangle split parts=2, rounded corners, inner xsep=1.5ex]%
+\tikzstyle{tikzuml transition style}=[color=\tikzumlDefaultDrawColor, rounded corners, -angle 45]%
+%
+\newcounter{tikzumlStateJoinNum}%
+\newcounter{tikzumlStateDecisionNum}%
+\newcounter{tikzumlStateInitialNum}%
+\newcounter{tikzumlStateFinalNum}%
+\newcounter{tikzumlStateEnterNum}%
+\newcounter{tikzumlStateExitNum}%
+\newcounter{tikzumlStateEndNum}%
+\newcounter{tikzumlStateHistoryNum}%
+\newcounter{tikzumlStateDeepHistoryNum}%
+\newcounter{tikzumlStateLevel}%
+\newcounter{tikzumlStateSubStateNum}%
+\newcounter{tikzumlStateText}%
+%
+\newif\iftikzumlstatejoinWithoutCoords%
+\newif\iftikzumlstatedecisionWithoutCoords%
+\newif\iftikzumlstateinitialWithoutCoords%
+\newif\iftikzumlstatefinalWithoutCoords%
+\newif\iftikzumlstateenterWithoutCoords%
+\newif\iftikzumlstateexitWithoutCoords%
+\newif\iftikzumlstateendWithoutCoords%
+\newif\iftikzumlstatehistoryWithoutCoords%
+\newif\iftikzumlstatedeephistoryWithoutCoords%
+\newif\iftikzumlstateWithoutCoords%
+%
+% define a uml join state
+% args : name of the state
+% optional : x,y: coordinates of the state
+% width: width of the state node
+% name: name of the state node
+% color: color of the join symbol
+% style: to manage every default TikZ option
+% no coords: to tell that the state position is defined relatively
+% to another node (automatically used with TikZ options above, below, left, right, below left, ...)
+\newcommand{\umlstatejoin}[1][]{%
+ \pgfkeys{/tikzuml/statejoin/.cd, x/.initial=\tikzumlDefaultX, y/.initial=\tikzumlDefaultX, width/.initial=\tikzumlStateJoinDefaultWidth,%
+ name/.initial=statejoin-\thetikzumlStateJoinNum,%
+ color/.initial=\tikzumlDefaultDrawColor, style/.style={},%
+ no coords/.is if=tikzumlstatejoinWithoutCoords,%
+ no coords=false,%
+ .unknown/.code={%
+ \let\keyname=\pgfkeyscurrentname%
+ \let\keyvalue=\pgfkeyscurrentvalue%
+ \ifthenelse{\equal{\keyname}{above}\OR%
+ \equal{\keyname}{left}\OR%
+ \equal{\keyname}{below}\OR%
+ \equal{\keyname}{right}\OR%
+ \equal{\keyname}{above left}\OR%
+ \equal{\keyname}{above right}\OR%
+ \equal{\keyname}{below left}\OR%
+ \equal{\keyname}{below right}}{%
+ \IfSubStr{\keyvalue}{ of }{%
+ \pgfkeys{/tikzuml/statejoin/.cd, no coords}%
+ }{}%
+ }{}%
+ \ifx\keyvalue\pgfkeysnovalue%
+ \pgfkeys{/tikzuml/statejoin/.cd, style/.append style/.expand once={\keyname}}%
+ \else%
+ \pgfkeys{/tikzuml/statejoin/.cd, style/.append style/.expand twice={\expandafter\keyname\expandafter=\keyvalue}}%
+ \fi%
+ %\errmessage{TIKZUML ERROR : in umlstatejoin, invalid option \keyname}%
+ }%
+ }%
+ \pgfkeys{/tikzuml/statejoin/.cd, #1}%
+ \pgfkeys{/tikzuml/statejoin/.cd, x/.get=\tikzumlStateJoinX, y/.get=\tikzumlStateJoinY, width/.get=\tikzumlStateJoinMinimumWidth,%
+ name/.get=\tikzumlStateJoinName, color/.get=\tikzumlStateJoinColor%
+ }%
+ %
+ \def\tikzumlStateJoinPos{\tikzumlStateJoinX,\tikzumlStateJoinY}%
+ %
+ \iftikzumlstatejoinWithoutCoords%
+ \node[circle, minimum size=\tikzumlStateJoinMinimumWidth, draw=\tikzumlStateJoinColor, fill=\tikzumlStateJoinColor, /tikzuml/statejoin/style] (\tikzumlStateJoinName) {};%
+ \else%
+ \node[circle, minimum size=\tikzumlStateJoinMinimumWidth, draw=\tikzumlStateJoinColor, fill=\tikzumlStateJoinColor, /tikzuml/statejoin/style] (\tikzumlStateJoinName) at (\tikzumlStateJoinPos) {};%
+ \fi%
+ %
+ % add to fit
+ \ifnum\c@tikzumlStateLevel>0%
+ \edef\tikzumlStateFitOld{\csname tikzumlStateFit\tikzumlState@parent @@\tikzumlState@fitname\endcsname}%
+ \expandafter\xdef\csname tikzumlStateFit\tikzumlState@parent @@\tikzumlState@fitname\endcsname{\tikzumlStateFitOld (\tikzumlStateJoinName)}%
+ \stepcounter{tikzumlStateSubStateNum}%
+ \fi%
+ \stepcounter{tikzumlStateJoinNum}%
+}%
+%
+% define a uml decision state
+% args : name of the state
+% optional : x,y: coordinates of the state
+% width: width of the state node
+% name: name of the state node
+% color: color of the join symbol
+% style: to manage every default TikZ option
+% no coords: to tell that the state position is defined relatively
+% to another node (automatically used with TikZ options above, below, left, right, below left, ...)
+\newcommand{\umlstatedecision}[1][]{%
+ \pgfkeys{/tikzuml/statedecision/.cd, x/.initial=\tikzumlDefaultX, y/.initial=\tikzumlDefaultX, width/.initial=\tikzumlStateDecisionDefaultWidth,%
+ name/.initial=statedecision-\thetikzumlStateDecisionNum,%
+ color/.initial=\tikzumlDefaultDrawColor, style/.style={},%
+ no coords/.is if=tikzumlstatedecisionWithoutCoords,%
+ no coords=false,%
+ .unknown/.code={%
+ \let\keyname=\pgfkeyscurrentname%
+ \let\keyvalue=\pgfkeyscurrentvalue%
+ \ifthenelse{\equal{\keyname}{above}\OR%
+ \equal{\keyname}{left}\OR%
+ \equal{\keyname}{below}\OR%
+ \equal{\keyname}{right}\OR%
+ \equal{\keyname}{above left}\OR%
+ \equal{\keyname}{above right}\OR%
+ \equal{\keyname}{below left}\OR%
+ \equal{\keyname}{below right}}{%
+ \IfSubStr{\keyvalue}{ of }{%
+ \pgfkeys{/tikzuml/statedecision/.cd, no coords}%
+ }{}%
+ }{}%
+ \ifx\keyvalue\pgfkeysnovalue%
+ \pgfkeys{/tikzuml/statedecision/.cd, style/.append style/.expand once={\keyname}}%
+ \else%
+ \pgfkeys{/tikzuml/statedecision/.cd, style/.append style/.expand twice={\expandafter\keyname\expandafter=\keyvalue}}%
+ \fi%
+ %\errmessage{TIKZUML ERROR : in umlstatedecision, invalid option \keyname}%
+ }%
+ }%
+ \pgfkeys{/tikzuml/statedecision/.cd, #1}%
+ \pgfkeys{/tikzuml/statedecision/.cd, x/.get=\tikzumlStateDecisionX, y/.get=\tikzumlStateDecisionY, width/.get=\tikzumlStateDecisionMinimumWidth,%
+ name/.get=\tikzumlStateDecisionName, color/.get=\tikzumlStateDecisionColor%
+ }%
+ %
+ \def\tikzumlStateDecisionPos{\tikzumlStateDecisionX,\tikzumlStateDecisionY}%
+ %
+ \iftikzumlstatedecisionWithoutCoords%
+ \node[rectangle, rotate=45, minimum size=\tikzumlStateDecisionMinimumWidth, draw=\tikzumlStateDecisionColor, /tikzuml/statedecision/style] (\tikzumlStateDecisionName) {};%
+ \else%
+ \node[rectangle, rotate=45, minimum size=\tikzumlStateDecisionMinimumWidth, draw=\tikzumlStateDecisionColor, /tikzuml/statedecision/style] (\tikzumlStateDecisionName) at (\tikzumlStateDecisionPos) {};%
+ \fi%
+ %
+ % add to fit
+ \ifnum\c@tikzumlStateLevel>0%
+ \edef\tikzumlStateFitOld{\csname tikzumlStateFit\tikzumlState@parent @@\tikzumlState@fitname\endcsname}%
+ \expandafter\xdef\csname tikzumlStateFit\tikzumlState@parent @@\tikzumlState@fitname\endcsname{\tikzumlStateFitOld (\tikzumlStateDecisionName)}%
+ \stepcounter{tikzumlStateSubStateNum}%
+ \fi%
+ \stepcounter{tikzumlStateDecisionNum}%
+}%
+%
+% define a uml initial state
+% args : name of the state
+% optional : x,y: coordinates of the state
+% width: width of the state node
+% name: name of the state node
+% entry, do, exit: entry/do/exit action of the state
+% color: color of the join symbol
+% style: to manage every default TikZ option
+% no coords: to tell that the state position is defined relatively
+% to another node (automatically used with TikZ options above, below, left, right, below left, ...)
+\newcommand{\umlstateinitial}[1][]{%
+ \pgfkeys{/tikzuml/stateinitial/.cd, x/.initial=\tikzumlDefaultX, y/.initial=\tikzumlDefaultX, width/.initial=\tikzumlStateInitialDefaultWidth,%
+ name/.initial=stateinitial-\thetikzumlStateInitialNum,%
+ color/.initial=\tikzumlDefaultDrawColor, style/.style={},%
+ no coords/.is if=tikzumlstateinitialWithoutCoords,%
+ no coords=false,%
+ .unknown/.code={%
+ \let\keyname=\pgfkeyscurrentname%
+ \let\keyvalue=\pgfkeyscurrentvalue%
+ \ifthenelse{\equal{\keyname}{above}\OR%
+ \equal{\keyname}{left}\OR%
+ \equal{\keyname}{below}\OR%
+ \equal{\keyname}{right}\OR%
+ \equal{\keyname}{above left}\OR%
+ \equal{\keyname}{above right}\OR%
+ \equal{\keyname}{below left}\OR%
+ \equal{\keyname}{below right}}{%
+ \IfSubStr{\keyvalue}{ of }{%
+ \pgfkeys{/tikzuml/stateinitial/.cd, no coords}%
+ }{}%
+ }{}%
+ \ifx\keyvalue\pgfkeysnovalue%
+ \pgfkeys{/tikzuml/stateinitial/.cd, style/.append style/.expand once={\keyname}}%
+ \else%
+ \pgfkeys{/tikzuml/stateinitial/.cd, style/.append style/.expand twice={\expandafter\keyname\expandafter=\keyvalue}}%
+ \fi%
+ %\errmessage{TIKZUML ERROR : in umlstateinitial, invalid option \keyname}%
+ }%
+ }%
+ \pgfkeys{/tikzuml/stateinitial/.cd, #1}%
+ \pgfkeys{/tikzuml/stateinitial/.cd, x/.get=\tikzumlStateInitialX, y/.get=\tikzumlStateInitialY, width/.get=\tikzumlStateInitialMinimumWidth,%
+ name/.get=\tikzumlStateInitialName, color/.get=\tikzumlStateInitialColor%
+ }%
+ %
+ \def\tikzumlStateInitialPos{\tikzumlStateInitialX,\tikzumlStateInitialY}%
+ %
+ \iftikzumlstateinitialWithoutCoords%
+ \node[circle, minimum size=\tikzumlStateInitialMinimumWidth, fill=\tikzumlStateInitialColor, /tikzuml/stateinitial/style] (\tikzumlStateInitialName) {};%
+ \else%
+ \node[circle, minimum size=\tikzumlStateInitialMinimumWidth, fill=\tikzumlStateInitialColor, /tikzuml/stateinitial/style] (\tikzumlStateInitialName) at (\tikzumlStateInitialPos) {};%
+ \fi%
+ %
+ % add to fit
+ \ifnum\c@tikzumlStateLevel>0%
+ \edef\tikzumlStateFitOld{\csname tikzumlStateFit\tikzumlState@parent @@\tikzumlState@fitname\endcsname}%
+ \expandafter\xdef\csname tikzumlStateFit\tikzumlState@parent @@\tikzumlState@fitname\endcsname{\tikzumlStateFitOld (\tikzumlStateInitialName)}%
+ \stepcounter{tikzumlStateSubStateNum}%
+ \fi%
+ \stepcounter{tikzumlStateInitialNum}%
+}%
+%
+% define a uml final state
+% args : name of the state
+% optional : x,y: coordinates of the state
+% width: width of the state node
+% name: name of the state node
+% color: color of the join symbol
+% style: to manage every default TikZ option
+% no coords: to tell that the state position is defined relatively
+% to another node (automatically used with TikZ options above, below, left, right, below left, ...)
+\newcommand{\umlstatefinal}[1][]{%
+ \pgfkeys{/tikzuml/statefinal/.cd, x/.initial=\tikzumlDefaultX, y/.initial=\tikzumlDefaultX, width/.initial=\tikzumlStateFinalDefaultWidth,%
+ name/.initial=statefinal-\thetikzumlStateFinalNum,%
+ color/.initial=\tikzumlDefaultDrawColor, style/.style={},%
+ no coords/.is if=tikzumlstatefinalWithoutCoords,%
+ no coords=false,%
+ .unknown/.code={%
+ \let\keyname=\pgfkeyscurrentname%
+ \let\keyvalue=\pgfkeyscurrentvalue%
+ \ifthenelse{\equal{\keyname}{above}\OR%
+ \equal{\keyname}{left}\OR%
+ \equal{\keyname}{below}\OR%
+ \equal{\keyname}{right}\OR%
+ \equal{\keyname}{above left}\OR%
+ \equal{\keyname}{above right}\OR%
+ \equal{\keyname}{below left}\OR%
+ \equal{\keyname}{below right}}{%
+ \IfSubStr{\keyvalue}{ of }{%
+ \pgfkeys{/tikzuml/statefinal/.cd, no coords}%
+ }{}%
+ }{}%
+ \ifx\keyvalue\pgfkeysnovalue%
+ \pgfkeys{/tikzuml/statefinal/.cd, style/.append style/.expand once={\keyname}}%
+ \else%
+ \pgfkeys{/tikzuml/statefinal/.cd, style/.append style/.expand twice={\expandafter\keyname\expandafter=\keyvalue}}%
+ \fi%
+ %\errmessage{TIKZUML ERROR : in umlstatefinal, invalid option \keyname}%
+ }%
+ }%
+ \pgfkeys{/tikzuml/statefinal/.cd, #1}%
+ \pgfkeys{/tikzuml/statefinal/.cd, x/.get=\tikzumlStateFinalX, y/.get=\tikzumlStateFinalY, width/.get=\tikzumlStateFinalMinimumWidth,%
+ name/.get=\tikzumlStateFinalName, color/.get=\tikzumlStateFinalColor%
+ }%
+ %
+ \def\tikzumlStateFinalPos{\tikzumlStateFinalX,\tikzumlStateFinalY}%
+ %
+ \iftikzumlstatefinalWithoutCoords%
+ \node[circle, minimum size=\tikzumlStateFinalMinimumWidth, draw=\tikzumlStateFinalColor, fill=\tikzumlStateFinalColor, double, double distance=0.1cm, /tikzuml/statefinal/style] (\tikzumlStateFinalName) {};%
+ \else%
+ \node[circle, minimum size=\tikzumlStateFinalMinimumWidth, draw=\tikzumlStateFinalColor, fill=\tikzumlStateFinalColor, double, double distance=0.1cm, /tikzuml/statefinal/style] (\tikzumlStateFinalName) at (\tikzumlStateFinalPos) {};%
+ \fi%
+ %
+ % add to fit
+ \ifnum\c@tikzumlStateLevel>0%
+ \edef\tikzumlStateFitOld{\csname tikzumlStateFit\tikzumlState@parent @@\tikzumlState@fitname\endcsname}%
+ \expandafter\xdef\csname tikzumlStateFit\tikzumlState@parent @@\tikzumlState@fitname\endcsname{\tikzumlStateFitOld (\tikzumlStateFinalName)}%
+ \stepcounter{tikzumlStateSubStateNum}%
+ \fi%
+ \stepcounter{tikzumlStateFinalNum}%
+}%
+%
+% define a uml enter state
+% args : name of the state
+% optional : x,y: coordinates of the state
+% width: width of the state node
+% name: name of the state node
+% color: color of the join symbol
+% style: to manage every default TikZ option
+% no coords: to tell that the state position is defined relatively
+% to another node (automatically used with TikZ options above, below, left, right, below left, ...)
+\newcommand{\umlstateenter}[1][]{%
+ \pgfkeys{/tikzuml/stateenter/.cd, x/.initial=\tikzumlDefaultX, y/.initial=\tikzumlDefaultX, width/.initial=\tikzumlStateEnterDefaultWidth,%
+ name/.initial=stateenter-\thetikzumlStateEnterNum,%
+ color/.initial=\tikzumlDefaultDrawColor, style/.style={},%
+ no coords/.is if=tikzumlstateenterWithoutCoords,%
+ no coords=false,%
+ .unknown/.code={%
+ \let\keyname=\pgfkeyscurrentname%
+ \let\keyvalue=\pgfkeyscurrentvalue%
+ \ifthenelse{\equal{\keyname}{above}\OR%
+ \equal{\keyname}{left}\OR%
+ \equal{\keyname}{below}\OR%
+ \equal{\keyname}{right}\OR%
+ \equal{\keyname}{above left}\OR%
+ \equal{\keyname}{above right}\OR%
+ \equal{\keyname}{below left}\OR%
+ \equal{\keyname}{below right}}{%
+ \IfSubStr{\keyvalue}{ of }{%
+ \pgfkeys{/tikzuml/stateenter/.cd, no coords}%
+ }{}%
+ }{}%
+ \ifx\keyvalue\pgfkeysnovalue%
+ \pgfkeys{/tikzuml/stateenter/.cd, style/.append style/.expand once={\keyname}}%
+ \else%
+ \pgfkeys{/tikzuml/stateenter/.cd, style/.append style/.expand twice={\expandafter\keyname\expandafter=\keyvalue}}%
+ \fi%
+ %\errmessage{TIKZUML ERROR : in umlstateenter, invalid option \keyname}%
+ }%
+ }%
+ \pgfkeys{/tikzuml/stateenter/.cd, #1}%
+ \pgfkeys{/tikzuml/stateenter/.cd, x/.get=\tikzumlStateEnterX, y/.get=\tikzumlStateEnterY, width/.get=\tikzumlStateEnterMinimumWidth,%
+ name/.get=\tikzumlStateEnterName, color/.get=\tikzumlStateEnterColor%
+ }%
+ %
+ \def\tikzumlStateEnterPos{\tikzumlStateEnterX,\tikzumlStateEnterY}%
+ %
+ \iftikzumlstateenterWithoutCoords%
+ \node[circle, minimum size=\tikzumlStateEnterMinimumWidth, draw=\tikzumlStateEnterColor, /tikzuml/stateenter/style] (\tikzumlStateEnterName) {};%
+ \else%
+ \node[circle, minimum size=\tikzumlStateEnterMinimumWidth, draw=\tikzumlStateEnterColor, /tikzuml/stateenter/style] (\tikzumlStateEnterName) at (\tikzumlStateEnterPos) {};%
+ \fi%
+ %
+ % add to fit
+ \ifnum\c@tikzumlStateLevel>0%
+ \edef\tikzumlStateFitOld{\csname tikzumlStateFit\tikzumlState@parent @@\tikzumlState@fitname\endcsname}%
+ \expandafter\xdef\csname tikzumlStateFit\tikzumlState@parent @@\tikzumlState@fitname\endcsname{\tikzumlStateFitOld (\tikzumlStateEnterName)}%
+ \stepcounter{tikzumlStateSubStateNum}%
+ \fi%
+ \stepcounter{tikzumlStateEnterNum}%
+}%
+%
+% define a uml exit state
+% args : name of the state
+% optional : x,y: coordinates of the state
+% width: width of the state node
+% name: name of the state node
+% color: color of the join symbol
+% style: to manage every default TikZ option
+% no coords: to tell that the state position is defined relatively
+% to another node (automatically used with TikZ options above, below, left, right, below left, ...)
+\newcommand{\umlstateexit}[1][]{%
+ \pgfkeys{/tikzuml/stateexit/.cd, x/.initial=\tikzumlDefaultX, y/.initial=\tikzumlDefaultX, width/.initial=\tikzumlStateExitDefaultWidth,%
+ name/.initial=stateexit-\thetikzumlStateExitNum,%
+ color/.initial=\tikzumlDefaultDrawColor, style/.style={},%
+ no coords/.is if=tikzumlstateexitWithoutCoords,%
+ no coords=false,%
+ .unknown/.code={%
+ \let\keyname=\pgfkeyscurrentname%
+ \let\keyvalue=\pgfkeyscurrentvalue%
+ \ifthenelse{\equal{\keyname}{above}\OR%
+ \equal{\keyname}{left}\OR%
+ \equal{\keyname}{below}\OR%
+ \equal{\keyname}{right}\OR%
+ \equal{\keyname}{above left}\OR%
+ \equal{\keyname}{above right}\OR%
+ \equal{\keyname}{below left}\OR%
+ \equal{\keyname}{below right}}{%
+ \IfSubStr{\keyvalue}{ of }{%
+ \pgfkeys{/tikzuml/stateexit/.cd, no coords}%
+ }{}%
+ }{}%
+ \ifx\keyvalue\pgfkeysnovalue%
+ \pgfkeys{/tikzuml/stateexit/.cd, style/.append style/.expand once={\keyname}}%
+ \else%
+ \pgfkeys{/tikzuml/stateexit/.cd, style/.append style/.expand twice={\expandafter\keyname\expandafter=\keyvalue}}%
+ \fi%
+ %\errmessage{TIKZUML ERROR : in umlstateexit, invalid option \keyname}%
+ }%
+ }%
+ \pgfkeys{/tikzuml/stateexit/.cd, #1}%
+ \pgfkeys{/tikzuml/stateexit/.cd, x/.get=\tikzumlStateExitX, y/.get=\tikzumlStateExitY, width/.get=\tikzumlStateExitMinimumWidth,%
+ name/.get=\tikzumlStateExitName, color/.get=\tikzumlStateExitColor%
+ }%
+ %
+ \def\tikzumlStateExitPos{\tikzumlStateExitX,\tikzumlStateExitY}%
+ %
+ \iftikzumlstateexitWithoutCoords%
+ \node[circle, minimum size=\tikzumlStateExitMinimumWidth, draw=\tikzumlStateExitColor, /tikzuml/stateexit/style] (\tikzumlStateExitName) {};%
+ \else%
+ \node[circle, minimum size=\tikzumlStateExitMinimumWidth, draw=\tikzumlStateExitColor, /tikzuml/stateexit/style] (\tikzumlStateExitName) at (\tikzumlStateExitPos) {};%
+ \fi%
+ \draw[draw=\tikzumlStateExitColor] (\tikzumlStateExitName.north east) -- (\tikzumlStateExitName.south west) (\tikzumlStateExitName.north west) -- (\tikzumlStateExitName.south east);
+ %
+ % add to fit
+ \ifnum\c@tikzumlStateLevel>0%
+ \edef\tikzumlStateFitOld{\csname tikzumlStateFit\tikzumlState@parent @@\tikzumlState@fitname\endcsname}%
+ \expandafter\xdef\csname tikzumlStateFit\tikzumlState@parent @@\tikzumlState@fitname\endcsname{\tikzumlStateFitOld (\tikzumlStateExitName)}%
+ \stepcounter{tikzumlStateSubStateNum}%
+ \fi%
+ \stepcounter{tikzumlStateExitNum}%
+}%
+%
+% define a uml end state
+% args : name of the state
+% optional : x,y: coordinates of the state
+% width: width of the state node
+% name: name of the state node
+% color: color of the join symbol
+% style: to manage every default TikZ option
+% no coords: to tell that the state position is defined relatively
+% to another node (automatically used with TikZ options above, below, left, right, below left, ...)
+\newcommand{\umlstateend}[1][]{%
+ \pgfkeys{/tikzuml/stateend/.cd, x/.initial=\tikzumlDefaultX, y/.initial=\tikzumlDefaultX, width/.initial=\tikzumlStateEndDefaultWidth,%
+ name/.initial=stateend-\thetikzumlStateEndNum,%
+ color/.initial=\tikzumlDefaultDrawColor, style/.style={},%
+ no coords/.is if=tikzumlstateendWithoutCoords,%
+ no coords=false,%
+ .unknown/.code={%
+ \let\keyname=\pgfkeyscurrentname%
+ \let\keyvalue=\pgfkeyscurrentvalue%
+ \ifthenelse{\equal{\keyname}{above}\OR%
+ \equal{\keyname}{left}\OR%
+ \equal{\keyname}{below}\OR%
+ \equal{\keyname}{right}\OR%
+ \equal{\keyname}{above left}\OR%
+ \equal{\keyname}{above right}\OR%
+ \equal{\keyname}{below left}\OR%
+ \equal{\keyname}{below right}}{%
+ \IfSubStr{\keyvalue}{ of }{%
+ \pgfkeys{/tikzuml/stateend/.cd, no coords}%
+ }{}%
+ }{}%
+ \ifx\keyvalue\pgfkeysnovalue%
+ \pgfkeys{/tikzuml/stateend/.cd, style/.append style/.expand once={\keyname}}%
+ \else%
+ \pgfkeys{/tikzuml/stateend/.cd, style/.append style/.expand twice={\expandafter\keyname\expandafter=\keyvalue}}%
+ \fi%
+ %\errmessage{TIKZUML ERROR : in umlstateend, invalid option \keyname}%
+ }%
+ }%
+ \pgfkeys{/tikzuml/stateend/.cd, #1}%
+ \pgfkeys{/tikzuml/stateend/.cd, x/.get=\tikzumlStateEndX, y/.get=\tikzumlStateEndY, width/.get=\tikzumlStateEndMinimumWidth,%
+ name/.get=\tikzumlStateEndName, color/.get=\tikzumlStateEndColor%
+ }%
+ %
+ \def\tikzumlStateEndPos{\tikzumlStateEndX,\tikzumlStateEndY}%
+ %
+ \iftikzumlstateendWithoutCoords%
+ \node[circle, minimum size=\tikzumlStateEndMinimumWidth, /tikzuml/stateend/style] (\tikzumlStateEndName) {};%
+ \else%
+ \node[circle, minimum size=\tikzumlStateEndMinimumWidth, /tikzuml/stateend/style] (\tikzumlStateEndName) at (\tikzumlStateEndPos) {};%
+ \fi%
+ \draw[draw=\tikzumlStateEndColor] (\tikzumlStateEndName.north east) -- (\tikzumlStateEndName.south west) (\tikzumlStateEndName.north west) -- (\tikzumlStateEndName.south east);
+ %
+ % add to fit
+ \ifnum\c@tikzumlStateLevel>0%
+ \edef\tikzumlStateFitOld{\csname tikzumlStateFit\tikzumlState@parent @@\tikzumlState@fitname\endcsname}%
+ \expandafter\xdef\csname tikzumlStateFit\tikzumlState@parent @@\tikzumlState@fitname\endcsname{\tikzumlStateFitOld (\tikzumlStateEndName)}%
+ \stepcounter{tikzumlStateSubStateNum}%
+ \fi%
+ \stepcounter{tikzumlStateEndNum}%
+}%
+%
+\newcommand{\picturedhistory}[1]{%
+ \begin{tikzpicture}[#1]%
+ \draw[thick] (-0.1cm,-0.15cm) -- (-0.1cm,0.15cm)
+ (-0.1cm,0) -- (0.1cm,0)
+ (0.1cm,-0.15cm) -- (0.1cm,0.15cm);%
+ \end{tikzpicture}%
+}%
+%
+% define a uml history state
+% args : name of the state
+% optional : x,y: coordinates of the state
+% width: width of the state node
+% name: name of the state node
+% color: color of the join symbol
+% style: to manage every default TikZ option
+% no coords: to tell that the state position is defined relatively
+% to another node (automatically used with TikZ options above, below, left, right, below left, ...)
+\newcommand{\umlstatehistory}[1][]{%
+ \pgfkeys{/tikzuml/statehistory/.cd, x/.initial=\tikzumlDefaultX, y/.initial=\tikzumlDefaultX, width/.initial=\tikzumlStateHistoryDefaultWidth,%
+ name/.initial=statehistory-\thetikzumlStateHistoryNum,%
+ color/.initial=\tikzumlDefaultDrawColor, style/.style={},%
+ no coords/.is if=tikzumlstatehistoryWithoutCoords,%
+ no coords=false,%
+ .unknown/.code={%
+ \let\keyname=\pgfkeyscurrentname%
+ \let\keyvalue=\pgfkeyscurrentvalue%
+ \ifthenelse{\equal{\keyname}{above}\OR%
+ \equal{\keyname}{left}\OR%
+ \equal{\keyname}{below}\OR%
+ \equal{\keyname}{right}\OR%
+ \equal{\keyname}{above left}\OR%
+ \equal{\keyname}{above right}\OR%
+ \equal{\keyname}{below left}\OR%
+ \equal{\keyname}{below right}}{%
+ \IfSubStr{\keyvalue}{ of }{%
+ \pgfkeys{/tikzuml/statehistory/.cd, no coords}%
+ }{}%
+ }{}%
+ \ifx\keyvalue\pgfkeysnovalue%
+ \pgfkeys{/tikzuml/statehistory/.cd, style/.append style/.expand once={\keyname}}%
+ \else%
+ \pgfkeys{/tikzuml/statehistory/.cd, style/.append style/.expand twice={\expandafter\keyname\expandafter=\keyvalue}}%
+ \fi%
+ %\errmessage{TIKZUML ERROR : in umlstatehistory, invalid option \keyname}%
+ }%
+ }%
+ \pgfkeys{/tikzuml/statehistory/.cd, #1}%
+ \pgfkeys{/tikzuml/statehistory/.cd, x/.get=\tikzumlStateHistoryX, y/.get=\tikzumlStateHistoryY, width/.get=\tikzumlStateHistoryMinimumWidth,%
+ name/.get=\tikzumlStateHistoryName, color/.get=\tikzumlStateHistoryColor%
+ }%
+ %
+ \def\tikzumlStateHistoryPos{\tikzumlStateHistoryX,\tikzumlStateHistoryY}%
+ %
+ \iftikzumlstatehistoryWithoutCoords%
+ \node[circle, minimum size=\tikzumlStateHistoryMinimumWidth, draw=\tikzumlStateHistoryColor, /tikzuml/statehistory/style] (\tikzumlStateHistoryName) {\picturedhistory{draw=\tikzumlStateHistoryColor}};%
+ \else%
+ \node[circle, minimum size=\tikzumlStateHistoryMinimumWidth, draw=\tikzumlStateHistoryColor, /tikzuml/statehistory/style] (\tikzumlStateHistoryName) at (\tikzumlStateHistoryPos) {\picturedhistory{draw=\tikzumlStateHistoryColor}};%
+ \fi%
+ %
+ % add to fit
+ \ifnum\c@tikzumlStateLevel>0%
+ \edef\tikzumlStateFitOld{\csname tikzumlStateFit\tikzumlState@parent @@\tikzumlState@fitname\endcsname}%
+ \expandafter\xdef\csname tikzumlStateFit\tikzumlState@parent @@\tikzumlState@fitname\endcsname{\tikzumlStateFitOld (\tikzumlStateHistoryName)}%
+ \stepcounter{tikzumlStateSubStateNum}%
+ \fi%
+ \stepcounter{tikzumlStateHistoryNum}%
+}%
+%
+\newcommand{\pictureddeephistory}[1]{%
+ \begin{tikzpicture}[#1]%
+ \draw[thick] (-0.1cm,-0.15cm) -- (-0.1cm,0.15cm)
+ (-0.1cm,0) -- (0.1cm,0)
+ (0.1cm,-0.15cm) -- (0.1cm,0.15cm)
+ (0.23cm,0.19cm) -- (0.23cm,0.11cm)
+ (0.20cm,0.17cm) -- (0.26cm,0.13cm)
+ (0.20cm,0.13cm) -- (0.26cm,0.17cm);%
+ \end{tikzpicture}%
+}%
+%
+% define a uml deep-history state
+% args : name of the state
+% optional : x,y: coordinates of the state
+% width: width of the state node
+% name: name of the state node
+% color: color of the join symbol
+% style: to manage every default TikZ option
+% no coords: to tell that the state position is defined relatively
+% to another node (automatically used with TikZ options above, below, left, right, below left, ...)
+\newcommand{\umlstatedeephistory}[1][]{%
+ \pgfkeys{/tikzuml/statedeephistory/.cd, x/.initial=\tikzumlDefaultX, y/.initial=\tikzumlDefaultX, width/.initial=\tikzumlStateDeepHistoryDefaultWidth,%
+ name/.initial=statedeephistory-\thetikzumlStateDeepHistoryNum,%
+ color/.initial=\tikzumlDefaultDrawColor, style/.style={},%
+ no coords/.is if=tikzumlstatedeephistoryWithoutCoords,%
+ no coords=false,%
+ .unknown/.code={%
+ \let\keyname=\pgfkeyscurrentname%
+ \let\keyvalue=\pgfkeyscurrentvalue%
+ \ifthenelse{\equal{\keyname}{above}\OR%
+ \equal{\keyname}{left}\OR%
+ \equal{\keyname}{below}\OR%
+ \equal{\keyname}{right}\OR%
+ \equal{\keyname}{above left}\OR%
+ \equal{\keyname}{above right}\OR%
+ \equal{\keyname}{below left}\OR%
+ \equal{\keyname}{below right}}{%
+ \IfSubStr{\keyvalue}{ of }{%
+ \pgfkeys{/tikzuml/statedeephistory/.cd, no coords}%
+ }{}%
+ }{}%
+ \ifx\keyvalue\pgfkeysnovalue%
+ \pgfkeys{/tikzuml/statedeephistory/.cd, style/.append style/.expand once={\keyname}}%
+ \else%
+ \pgfkeys{/tikzuml/statedeephistory/.cd, style/.append style/.expand twice={\expandafter\keyname\expandafter=\keyvalue}}%
+ \fi%
+ %\errmessage{TIKZUML ERROR : in umlstatedeephistory, invalid option \keyname}%
+ }%
+ }%
+ \pgfkeys{/tikzuml/statedeephistory/.cd, #1}%
+ \pgfkeys{/tikzuml/statedeephistory/.cd, x/.get=\tikzumlStateDeepHistoryX, y/.get=\tikzumlStateDeepHistoryY, width/.get=\tikzumlStateDeepHistoryMinimumWidth,%
+ name/.get=\tikzumlStateDeepHistoryName, color/.get=\tikzumlStateDeepHistoryColor%
+ }%
+ %
+ \def\tikzumlStateDeepHistoryPos{\tikzumlStateDeepHistoryX,\tikzumlStateDeepHistoryY}%
+ %
+ \iftikzumlstatedeephistoryWithoutCoords%
+ \node[circle, minimum size=\tikzumlStateDeepHistoryMinimumWidth, draw=\tikzumlStateDeepHistoryColor, /tikzuml/statedeephistory/style] (\tikzumlStateDeepHistoryName) {\pictureddeephistory{draw=\tikzumlStateDeepHistoryColor}};%
+ \else%
+ \node[circle, minimum size=\tikzumlStateDeepHistoryMinimumWidth, draw=\tikzumlStateDeepHistoryColor, /tikzuml/statedeephistory/style] (\tikzumlStateDeepHistoryName) at (\tikzumlStateDeepHistoryPos) {\pictureddeephistory{draw=\tikzumlStateDeepHistoryColor}};%
+ \fi%
+ %
+ % add to fit
+ \ifnum\c@tikzumlStateLevel>0%
+ \edef\tikzumlStateFitOld{\csname tikzumlStateFit\tikzumlState@parent @@\tikzumlState@fitname\endcsname}%
+ \expandafter\xdef\csname tikzumlStateFit\tikzumlState@parent @@\tikzumlState@fitname\endcsname{\tikzumlStateFitOld (\tikzumlStateDeepHistoryName)}%
+ \stepcounter{tikzumlStateSubStateNum}%
+ \fi%
+ \stepcounter{tikzumlStateDeepHistoryNum}%
+}%
+%
+% define a uml state
+% args : name of the state
+% content of the state
+% optional : x,y: coordinates of the state
+% width: width of the state node
+% name: name of the state node
+% entry, do, exit: entry/do/exit action of the state
+% draw, fill, text: colors
+% style: to manage every default TikZ option
+% no coords: to tell that the state position is defined relatively
+% to another node (automatically used with TikZ options above, below, left, right, below left, ...)
+\newenvironment{umlstate}[2][]{%
+ \ifnum\thetikzumlStateLevel>0%
+ \let\tikzumlState@nameold\tikzumlState@fitname%
+ \let\tikzumlState@parentold\tikzumlState@parent%
+ \edef\tikzumlState@parent{\tikzumlState@parentold @@\tikzumlState@nameold}%
+ \else%
+ \def\tikzumlState@parent{}%
+ \fi%
+ %
+ \stepcounter{tikzumlStateLevel}%
+ %
+ \pgfkeys{/tikzuml/state/.cd, x/.initial=\tikzumlDefaultX, y/.initial=\tikzumlDefaultX, width/.initial=\tikzumlStateDefaultWidth,%
+ name/.initial={},%
+ entry/.initial={}, do/.initial={}, exit/.initial={},%
+ draw/.initial=\tikzumlDefaultDrawColor, fill/.initial=\tikzumlStateDefaultFillColor,%
+ text/.initial=\tikzumlDefaultTextColor, style/.style={},%
+ no coords/.is if=tikzumlstateWithoutCoords,%
+ no coords=false,%
+ .unknown/.code={%
+ \let\keyname=\pgfkeyscurrentname%
+ \let\keyvalue=\pgfkeyscurrentvalue%
+ \ifthenelse{\equal{\keyname}{above}\OR%
+ \equal{\keyname}{left}\OR%
+ \equal{\keyname}{below}\OR%
+ \equal{\keyname}{right}\OR%
+ \equal{\keyname}{above left}\OR%
+ \equal{\keyname}{above right}\OR%
+ \equal{\keyname}{below left}\OR%
+ \equal{\keyname}{below right}}{%
+ \IfSubStr{\keyvalue}{ of }{%
+ \pgfkeys{/tikzuml/state/.cd, no coords}%
+ }{}%
+ }{}%
+ \ifx\keyvalue\pgfkeysnovalue%
+ \pgfkeys{/tikzuml/state/.cd, style/.append style/.expand once={\keyname}}%
+ \else%
+ \pgfkeys{/tikzuml/state/.cd, style/.append style/.expand twice={\expandafter\keyname\expandafter=\keyvalue}}%
+ \fi%
+ % \errmessage{TIKZUML ERROR : in umlstate, invalid option \keyname}%
+ }%
+ }%
+ \pgfkeys{/tikzuml/state/.cd, #1}%
+ \pgfkeys{/tikzuml/state/.cd, x/.get=\tikzumlStateXShift, y/.get=\tikzumlStateYShift, width/.get=\tikzumlStateMinimumWidth, name/.get=\tikzumlStateName,%
+ entry/.get=\tikzumlStateEntry, do/.get=\tikzumlStateDo, exit/.get=\tikzumlStateExit,%
+ draw/.get=\tikzumlStateDrawColor, fill/.get=\tikzumlStateFillColor,%
+ text/.get=\tikzumlStateTextColor%
+ }%
+ %
+ \ifthenelse{\equal{\tikzumlStateName}{}}{%
+ \edef\tikzumlState@name{#2}%
+ }{%
+ \edef\tikzumlState@name{\tikzumlStateName}%
+ }%
+ %
+ \begingroup%
+ \def\_{@}\edef\x{\endgroup%
+ \def\noexpand\tikzumlState@fitname{\tikzumlState@name}}\x%
+ %
+ \let\tikzumlState@nodeNameold\tikzumlState@nodeName%
+ \def\tikzumlState@caption{#2}%
+ %
+ \begingroup%
+ \def\_{_}\edef\x{\endgroup%
+ \def\noexpand\tikzumlState@nodeName{\tikzumlState@name}}\x%
+ %
+ \expandafter\gdef\csname tikzumlStateFit\tikzumlState@parent @@\tikzumlState@fitname\endcsname{}%
+ %
+ \setcounter{tikzumlStateSubStateNum}{0}%
+ \setcounter{tikzumlStateText}{0}%
+ %
+ \def\tikzumlStateText{tikzumlEmpty}%
+ \begin{scope}[xshift=\tikzumlStateXShift cm, yshift=\tikzumlStateYShift cm]%
+}{%
+ %
+ \def\tikzumlstaterootlabel{\phantom{\tikzumlState@nodeName}}%
+ %
+ \def\tikzumlstaterootinnerysep{0.5ex}%
+ \def\tikzumlstatebodyinnerysep{2ex}%
+ %
+ \ifthenelse{\equal{\tikzumlStateEntry}{}}{}{%
+ \ifnum\c@tikzumlStateText=0%
+ \def\tikzumlStateText{entry/\tikzumlStateEntry}%
+ \else%
+ \let\tikzumlStateTextOld\tikzumlStateText%
+ \ifthenelse{\equal{\tikzumlStateText}{tikzumlEmpty}}{%
+ \def\tikzumlStateText{entry/\tikzumlStateEntry}%
+ }{%
+ \expandafter\def\expandafter\tikzumlStateText\expandafter{\tikzumlStateTextOld \\ entry/\tikzumlStateEntry}%
+ }%
+ \fi%
+ \setcounter{tikzumlStateText}{1}%
+ \ifnum\c@tikzumlStateSubStateNum=0%
+ \def\tikzumlstatebodyinnerysep{0}%
+ \def\tikzumlstaterootinnerysep{0}%
+ \fi%
+ }%
+ \ifthenelse{\equal{\tikzumlStateDo}{}}{}{%
+ \ifnum\c@tikzumlStateText=0%
+ \def\tikzumlStateText{do/\tikzumlStateDo}%
+ \else%
+ \let\tikzumlStateTextOld\tikzumlStateText%
+ \ifthenelse{\equal{\tikzumlStateText}{tikzumlEmpty}}{%
+ \def\tikzumlStateText{do/\tikzumlStateDo}%
+ }{%
+ \expandafter\def\expandafter\tikzumlStateText\expandafter{\tikzumlStateTextOld \\ do/\tikzumlStateDo}%
+ }%
+ \fi%
+ \setcounter{tikzumlStateText}{1}%
+ \ifnum\c@tikzumlStateSubStateNum=0%
+ \def\tikzumlstatebodyinnerysep{0}%
+ \def\tikzumlstaterootinnerysep{0}%
+ \fi%
+ }%
+ \ifthenelse{\equal{\tikzumlStateExit}{}}{}{%
+ \ifnum\c@tikzumlStateText=0%
+ \def\tikzumlStateText{exit/\tikzumlStateExit}%
+ \else%
+ \let\tikzumlStateTextOld\tikzumlStateText%
+ \ifthenelse{\equal{\tikzumlStateText}{tikzumlEmpty}}{%
+ \def\tikzumlStateText{exit/\tikzumlStateExit}%
+ }{%
+ \expandafter\def\expandafter\tikzumlStateText\expandafter{\tikzumlStateTextOld \\ exit/\tikzumlStateExit}%
+ }%
+ \fi%
+ \setcounter{tikzumlStateText}{1}%
+ \ifnum\c@tikzumlStateSubStateNum=0%
+ \def\tikzumlstatebodyinnerysep{0}%
+ \def\tikzumlstaterootinnerysep{0}%
+ \fi%
+ }%
+ %
+ \addtocounter{tikzumlStateLevel}{-1}%
+ \begin{pgfonlayer}{state\thetikzumlStateLevel}%
+ %
+ % if contains nothing, one define a fictive node to enable the fit option
+ \ifnum\c@tikzumlStateSubStateNum=0%
+ \iftikzumlstateWithoutCoords%
+ \node[inner ysep=\tikzumlstaterootinnerysep, minimum width=\tikzumlStateMinimumWidth, /tikzuml/state/style] (\tikzumlState@nodeName-root) {\tikzumlstaterootlabel};%
+ \else%
+ \node[inner ysep=\tikzumlstaterootinnerysep, minimum width=\tikzumlStateMinimumWidth, /tikzuml/state/style] (\tikzumlState@nodeName-root) at (0,0) {\tikzumlstaterootlabel};%
+ \fi%
+ \expandafter\xdef\csname tikzumlStateFit\tikzumlState@parent @@\tikzumlState@fitname\endcsname{(\tikzumlState@nodeName-root)}%
+ \fi%
+ %
+ \ifnum\c@tikzumlStateLevel>0%
+ \def\tikzumlStateFitTmp{\csname tikzumlStateFit\tikzumlState@parent\endcsname}%
+ \expandafter\xdef\csname tikzumlStateFit\tikzumlState@parent\endcsname{\tikzumlStateFitTmp (\tikzumlState@nodeName-body) (\tikzumlState@nodeName-caption)}%
+ \stepcounter{tikzumlStateSubStateNum}%
+ \fi%
+ %
+ \node[inner xsep=2ex, inner ysep=\tikzumlstatebodyinnerysep, fit = \csname tikzumlStateFit\tikzumlState@parent @@\tikzumlState@fitname\endcsname, /tikzuml/state/style ] (\tikzumlState@nodeName-body) {};%
+ \def\tikzumlState@orig{body}%
+ \ifnum\c@tikzumlStateText=1%
+ \node[above=0] (\tikzumlState@nodeName-texttmp) at (\tikzumlState@nodeName-\tikzumlState@orig.north) {\begin{tabular}{l}\tikzumlStateText \end{tabular}};%
+ \def\tikzumlState@orig{texttmp}%
+ \fi%
+ \node[above] (\tikzumlState@nodeName-captiontmp) at (\tikzumlState@nodeName-\tikzumlState@orig.north) {\tikzumlState@caption};%
+ \ifnum\c@tikzumlStateText=1%
+ \node[rounded corners, draw=\tikzumlStateDrawColor, fill=\tikzumlStateFillColor, name=\tikzumlState@nodeName, fit=(\tikzumlState@nodeName-body) (\tikzumlState@nodeName-texttmp) (\tikzumlState@nodeName-captiontmp)] {};%
+ \else%
+ \node[rounded corners, draw=\tikzumlStateDrawColor, fill=\tikzumlStateFillColor, name=\tikzumlState@nodeName, fit=(\tikzumlState@nodeName-body) (\tikzumlState@nodeName-captiontmp)] {};%
+ \fi%
+ \ifnum\c@tikzumlStateText=1%
+ \node (\tikzumlState@nodeName-text) at (\tikzumlState@nodeName-texttmp) {\begin{tabular}{l}\tikzumlStateText \end{tabular}};%
+ \fi%
+ \node (\tikzumlState@nodeName-caption) at (\tikzumlState@nodeName-captiontmp) {\tikzumlState@caption};%
+ \draw (\tikzumlState@nodeName-caption.south -| \tikzumlState@nodeName.north west) -- (\tikzumlState@nodeName-caption.south -| \tikzumlState@nodeName.north east);%
+ \end{pgfonlayer}%
+ \end{scope}%
+}%
+%
+% shortcut for empty state
+\newcommand{\umlbasicstate}[2][]{\begin{umlstate}[#1]{#2}\end{umlstate}}%
+%
+% command to add text in a state, to be used inside umlstate environment
+\newcommand{\umlstatetext}[1]{%
+ \def\tikzumlStateText{#1}%
+ \setcounter{tikzumlStateText}{1}%
+}%
+%
+% shortcuts for state transitions macros
+\newcommand{\umltrans}[3][]{%
+ \ifthenelse{\equal{#2}{#3}}{%
+ \umlrelation[style={tikzuml transition style}, recursive mode=transition, #1]{#2}{#3}%
+ }{%
+ \umlrelation[style={tikzuml transition style}, #1]{#2}{#3}%
+ }%
+}%
+\newcommand{\umlHVtrans}[3][]{\umlHVrelation[style={tikzuml transition style}, #1]{#2}{#3}}%
+\newcommand{\umlVHtrans}[3][]{\umlVHrelation[style={tikzuml transition style}, #1]{#2}{#3}}%
+\newcommand{\umlVHVtrans}[3][]{\umlVHVrelation[style={tikzuml transition style}, #1]{#2}{#3}}%
+\newcommand{\umlHVHtrans}[3][]{\umlHVHrelation[style={tikzuml transition style}, #1]{#2}{#3}}%
+\newcommand{\umlCNtrans}[4][]{\umlCNrelation[style={tikzuml transition style}, #1]{#2}{#3}{#4}}%
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% sequence diagrams %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+\tikzstyle{tikzuml synchron-msg style}=[color=\tikzumlDefaultDrawColor, -triangle 45]%
+\tikzstyle{tikzuml asynchron-msg style}=[color=\tikzumlDefaultDrawColor, -angle 45]%
+\tikzstyle{tikzuml return-msg style}=[color=\tikzumlDefaultDrawColor, dashed, -angle 45]%
+\tikzstyle{tikzuml call return style}=[color=\tikzumlDefaultDrawColor, dashed, -angle 45]%
+\tikzstyle{tikzuml activity style}=[inner xsep=1ex, inner ysep=1ex]%
+%
+\newcounter{tikzumlObjectNum}%
+\newcounter{tikzumlCallLevel}%
+\newcounter{tikzumlCallNum}%
+\newcounter{tikzumlFragmentLevel}%
+\newcounter{tikzumlFragmentLevelNum}%
+\newcounter{tikzumlFragmentNum}%
+\newcounter{tikzumlFragmentPartNum}%
+\newcounter{tikzumlCallStartFragmentNum}%
+\newcounter{tikzumlCallEndFragmentNum}%
+%
+\newif\iftikzumlobjectNoDDots%
+\newif\iftikzumlcreatecallNoDDots%
+%
+% define a sequence diagram
+%
+\newenvironment{umlseqdiag}{%
+ \gdef\tikzumlInCreateCall{0}%
+ \setcounter{tikzumlObjectNum}{0}%
+ \setcounter{tikzumlCallLevel}{0}%
+ \setcounter{tikzumlCallNum}{0}%
+ \setcounter{tikzumlFragmentLevel}{0}%
+ \setcounter{tikzumlFragmentLevelNum}{0}%
+ \setcounter{tikzumlFragmentNum}{0}%
+ \setcounter{tikzumlFragmentPartNum}{0}%
+ \setcounter{tikzumlCallStartFragmentNum}{0}%
+ \setcounter{tikzumlCallEndFragmentNum}{0}%
+ %
+ \ifx \@umlactor \@empty
+ \newcommand{\umlactor}[2][]{%
+ \pgfkeys{/tikzuml/actorobj/.cd, .unknown/.code={%
+ \let\keyname=\pgfkeyscurrentname%
+ \let\keyvalue=\pgfkeyscurrentvalue%
+ \ifthenelse{\equal{\keyname}{stereo}}{%
+ \errmessage{TIKZUML ERROR : in umlactor, forbidden option stereo}%
+ }{}%
+ }%
+ }%
+ %
+ \pgfkeys{/tikzuml/actorobj/.cd, ##1}%
+ \umlobject[stereo=actor, ##1]{##2}%
+ }%
+ \else%
+ \renewcommand{\umlactor}[2][]{%
+ \pgfkeys{/tikzuml/actorobj/.cd, .unknown/.code={%
+ \let\keyname=\pgfkeyscurrentname%
+ \let\keyvalue=\pgfkeyscurrentvalue%
+ \ifthenelse{\equal{\keyname}{stereo}}{%
+ \errmessage{TIKZUML ERROR : in umlactor, forbidden option stereo}%
+ }{}%
+ }%
+ }%
+ %
+ \pgfkeys{/tikzuml/actorobj/.cd, ##1}%
+ \umlobject[stereo=actor, ##1]{##2}%
+ }%
+ \fi%
+ \begin{scope}[font=\tikzumlDefaultFont]%
+}{%
+ % draw lifelines of each object
+ \begin{pgfonlayer}{lifelines}%
+ \foreach \id in \tikzumlIdList {%
+ \draw (\csname tikzumlLastChild@\id \endcsname)+(0,-2.5ex) node[inner sep=0, name=end-\id] {};%
+ \draw[dotted] (\id) -- (end-\id);%
+ }%
+ \end{pgfonlayer}%
+ \end{scope}%
+}%
+%
+% define the database symbol
+% optional : global tikzpicture styles
+\newcommand{\pictureddatabase}[1]{%
+ \pgfkeys{/tikzuml/database/.cd, scale/.initial=1, .unknown/.code={}}%
+ \pgfkeys{/tikzuml/database/.cd,#1}%
+ \pgfkeys{/tikzuml/database/.cd, scale/.get=\tikzumlDatabaseScale}%
+ %
+ \begin{tikzpicture}[#1]%
+ \node[fill, draw, ellipse, minimum width=\tikzumlDatabaseScale*4ex, minimum height=\tikzumlDatabaseScale*2ex, inner sep=0] (bottom) at (0,-2ex) {};%
+ \node[fill, draw, ellipse, minimum width=\tikzumlDatabaseScale*4ex, minimum height=\tikzumlDatabaseScale*2ex, inner sep=0] (top) at (0,4ex) {};%
+ \fill (bottom.west) rectangle (top.east);%
+ \begin{scope}%
+ \clip (-3.5ex,-0.5ex) rectangle (3.5ex,2.5ex);%
+ \node[draw, dashed, ellipse, minimum width=\tikzumlDatabaseScale*4ex, minimum height=\tikzumlDatabaseScale*2ex, inner sep=0] (bottom2) at (0,-2ex) {};%
+ \end{scope}%
+ \node[draw, ellipse, minimum width=\tikzumlDatabaseScale*4ex, minimum height=\tikzumlDatabaseScale*2ex, inner sep=0] (top2) at (0,4ex) {};%
+ \draw (bottom.west) -- (top.west) (bottom.east) -- (top.east);%
+ \end{tikzpicture}%
+}%
+%
+% define the entity symbol
+% optional : global tikzpicture styles
+\newcommand{\picturedentity}[1]{%
+ \pgfkeys{/tikzuml/entity/.cd, scale/.initial=1, .unknown/.code={}}%
+ \pgfkeys{/tikzuml/entity/.cd,#1}%
+ \pgfkeys{/tikzuml/entity/.cd, scale/.get=\tikzumlEntityScale}%
+ %
+ \begin{tikzpicture}[#1]%
+ \node[fill, draw, circle, inner sep=0, minimum size=\tikzumlEntityScale*5ex] (center) at (0,0) {};%
+ \draw (center.south) node[coordinate, name=bottom] {};%
+ \draw (bottom)+(-2ex,0) node[coordinate, name=bottom-left] {};%
+ \draw (bottom)+(2ex,0) node[coordinate, name=bottom-right] {};%
+ \draw (center) -- (bottom);%
+ \draw (bottom-left) -- (bottom-right);%
+ \end{tikzpicture}%
+}%
+%
+% define the boundary symbol
+% optional : global tikzpicture styles
+\newcommand{\picturedboundary}[1]{%
+ \pgfkeys{/tikzuml/boundary/.cd, scale/.initial=1, .unknown/.code={}}%
+ \pgfkeys{/tikzuml/boundary/.cd,#1}%
+ \pgfkeys{/tikzuml/boundary/.cd, scale/.get=\tikzumlBoundaryScale}%
+ %
+ \begin{tikzpicture}[#1]
+ \node[fill, draw, circle, inner sep=0, minimum size=\tikzumlBoundaryScale*5ex] (center) at (0,0) {};
+ \draw (center.west)+(-0.8ex,0) node[coordinate, name=left] {};
+ \draw (left)+(0,0.2ex) node[coordinate, name=left-top] {};
+ \draw (left)+(0,-0.2ex) node[coordinate, name=left-bottom] {};
+ \draw (center) -- (left);
+ \draw (left-top) -- (left-bottom);
+ \end{tikzpicture}
+}%
+%
+% define the control symbol
+% optional : global tikzpicture styles
+\newcommand{\picturedcontrol}[1]{%
+ \pgfkeys{/tikzuml/control/.cd, scale/.initial=1, .unknown/.code={}}%
+ \pgfkeys{/tikzuml/control/.cd,#1}%
+ \pgfkeys{/tikzuml/control/.cd, scale/.get=\tikzumlControlScale}%
+ %
+ \begin{tikzpicture}[#1, decoration={markings, mark=at position 0.25 with {\arrow{>}}}]
+ \node[fill, draw, circle, inner sep=0, minimum size=\tikzumlControlScale*5ex, postaction={decorate}] (center) at (0,0) {};
+ \end{tikzpicture}
+}%
+%
+% define a uml object for a sequence diagram
+% args : name of the object
+% optional : x, y: coordinates of the object
+% stereo: stereotype of the object (object, actor, database, boundary, control, entity, multiobject)
+% class: class of the object
+% scale: scale factor of the object symbol
+% draw, fill, text; colors
+% no ddots: when used, disable printing of double dots
+\newcommand{\umlobject}[2][]{
+ \stepcounter{tikzumlObjectNum}%
+ %
+ \edef\tikzumlobject@ddot{:}%
+ \pgfkeys{/tikzuml/obj/.cd, x/.initial=tikzumlEmpty, y/.initial=\tikzumlDefaultX, stereo/.initial=\tikzumlObjectDefaultStereo,%
+ class/.initial={}, scale/.initial=1,%
+ draw/.initial=\tikzumlDefaultDrawColor, fill/.initial=\tikzumlObjectDefaultFillColor,%
+ text/.initial=\tikzumlDefaultTextColor,%
+ no ddots/.is if=tikzumlobjectNoDDots,%
+ no ddots=false,%
+ .unknown/.code={%
+ \let\keyname=\pgfkeyscurrentname%
+ \let\keyvalue=\pgfkeyscurrentvalue%
+ \errmessage{TIKZUML ERROR : in umlobject, invalid option \keyname}%
+ }%
+ }%
+ \pgfkeys{/tikzuml/obj/.cd, #1}%
+ \pgfkeys{/tikzuml/obj/.cd, x/.get=\tikzumlObjectX, y/.get=\tikzumlObjectY,%
+ stereo/.get=\tikzumlObjectStereo, class/.get=\tikzumlObjectClass,%
+ scale/.get=\tikzumlObjectScale,%
+ draw/.get=\tikzumlObjectDrawColor, fill/.get=\tikzumlObjectFillColor,%
+ text/.get=\tikzumlObjectTextColor%
+ }%
+ %
+ \iftikzumlobjectNoDDots%
+ \edef\tikzumlobject@ddot{}%
+ \fi%
+ %
+ \ifthenelse{\equal{\tikzumlObjectX}{tikzumlEmpty}}{%
+ \pgfmathsetmacro{\tikzumlObjectX}{4*(\thetikzumlObjectNum-1)}%
+ }{}%
+ %
+ \def\tikzumlObjectName{#2}%
+ \expandafter\xdef\csname tikzumlLastChild@\tikzumlObjectName \endcsname{\tikzumlObjectName}%
+ %
+ \ifnum\thetikzumlObjectNum=1%
+ \xdef\tikzumlIdList{\tikzumlObjectName}%
+ \else%
+ \let\tikzumlIdListOld\tikzumlIdList%
+ \expandafter\xdef\expandafter\tikzumlIdList\expandafter{\tikzumlIdListOld,\tikzumlObjectName}%
+ \fi%
+ %
+ \tikzstyle{tikzuml object box style}=[rectangle, text=\tikzumlObjectTextColor, font=\tikzumlDefaultFont]%
+ %
+ \ifthenelse{\equal{\tikzumlObjectStereo}{object}}{%
+ \tikzstyle{tikzuml object box style}+=[draw=\tikzumlObjectDrawColor, fill=\tikzumlObjectFillColor]%
+ }{%
+ \ifthenelse{\equal{\tikzumlObjectStereo}{multi}}{%
+ \tikzstyle{tikzuml object box style}+=[fill=\tikzumlObjectFillColor]%
+ }{}%
+ }%
+ %
+ \ifnum\tikzumlInCreateCall=1%
+ \draw (\tikzumlCreateCallObjectSrc -| \tikzumlObjectX,0) node[tikzuml object box style] (\tikzumlObjectName) {\tikzumlObjectName\tikzumlobject@ddot\tikzumlObjectClass};%
+ \else%
+ \node[tikzuml object box style] (\tikzumlObjectName) at (\tikzumlObjectX,\tikzumlObjectY) {\tikzumlObjectName\tikzumlobject@ddot\tikzumlObjectClass};%
+ \fi%
+ %
+ \ifthenelse{\equal{\tikzumlObjectStereo}{multi}}{%
+ \draw (\tikzumlObjectName.north east)+(0.4ex,0.4ex) node[name=\tikzumlObjectName-tr, coordinate] {};
+ \draw (\tikzumlObjectName.north west)+(0.4ex,0.4ex) node[name=\tikzumlObjectName-tl, coordinate] {};
+ \draw (\tikzumlObjectName.south east)+(0.4ex,0.4ex) node[name=\tikzumlObjectName-br, coordinate] {};
+ \draw (\tikzumlObjectName-tr)+(0.4ex,0.4ex) node[name=\tikzumlObjectName-ttr, coordinate] {};
+ \draw (\tikzumlObjectName-tl)+(0.4ex,0.4ex) node[name=\tikzumlObjectName-ttl, coordinate] {};
+ \draw (\tikzumlObjectName-br)+(0.4ex,0.4ex) node[name=\tikzumlObjectName-tbr, coordinate] {};
+ \fill[fill=\tikzumlObjectFillColor] (\tikzumlObjectName-ttl |- \tikzumlObjectName.north) -- (\tikzumlObjectName-ttl) -- (\tikzumlObjectName-ttr) -- (\tikzumlObjectName-tbr) -- (\tikzumlObjectName-tbr -| \tikzumlObjectName.east) -- (\tikzumlObjectName.north east) -- (\tikzumlObjectName-ttl |- \tikzumlObjectName.north);
+ \draw[draw=\tikzumlObjectDrawColor] (\tikzumlObjectName-ttl |- \tikzumlObjectName.north) -- (\tikzumlObjectName-ttl) -- (\tikzumlObjectName-ttr) -- (\tikzumlObjectName-tbr) -- (\tikzumlObjectName-tbr -| \tikzumlObjectName.east);
+ \fill[fill=\tikzumlObjectFillColor] (\tikzumlObjectName-tl |- \tikzumlObjectName.north) -- (\tikzumlObjectName-tl) -- (\tikzumlObjectName-tr) -- (\tikzumlObjectName-br) -- (\tikzumlObjectName-br -| \tikzumlObjectName.east) -- (\tikzumlObjectName.north east) -- (\tikzumlObjectName-tl |- \tikzumlObjectName.north);
+ \draw[draw=\tikzumlObjectDrawColor] (\tikzumlObjectName-tl |- \tikzumlObjectName.north) -- (\tikzumlObjectName-tl) -- (\tikzumlObjectName-tr) -- (\tikzumlObjectName-br) -- (\tikzumlObjectName-br -| \tikzumlObjectName.east);
+ \draw[draw=\tikzumlObjectDrawColor] (\tikzumlObjectName.north west) rectangle (\tikzumlObjectName.south east);
+ }{%
+ \ifthenelse{\equal{\tikzumlObjectStereo}{object}}{}{%
+ \node[above=1ex, name=\tikzumlObjectName-picture] at (\tikzumlObjectName) {\csname pictured\tikzumlObjectStereo \endcsname{draw=\tikzumlObjectDrawColor, fill=\tikzumlObjectFillColor, scale=\tikzumlObjectScale}};
+ }%
+ }%
+}%
+%
+% shortcuts for objects
+\newcommand{\umlbasicobject}[2][]{%
+ \pgfkeys{/tikzuml/basicobj/.cd, .unknown/.code={%
+ \let\keyname=\pgfkeyscurrentname%
+ \let\keyvalue=\pgfkeyscurrentvalue%
+ \ifthenelse{\equal{\keyname}{no ddots}}{%
+ \errmessage{TIKZUML ERROR : in umlbasicobject, forbidden option no ddots}%
+ }{}%
+ }%
+ }%
+ \pgfkeys{/tikzuml/basicobj/.cd, #1}%
+ \umlobject[no ddots, #1]{#2}%
+}%
+%
+\newcommand{\umldatabase}[2][]{%
+ \pgfkeys{/tikzuml/databaseobj/.cd, .unknown/.code={%
+ \let\keyname=\pgfkeyscurrentname%
+ \let\keyvalue=\pgfkeyscurrentvalue%
+ \ifthenelse{\equal{\keyname}{stereo}}{%
+ \errmessage{TIKZUML ERROR : in umldatabase, forbidden option stereo}%
+ }{}%
+ }%
+ }%
+ \pgfkeys{/tikzuml/databaseobj/.cd, #1}%
+ \umlobject[stereo=database, #1]{#2}%
+}%
+\newcommand{\umlentity}[2][]{%
+ \pgfkeys{/tikzuml/entityobj/.cd, .unknown/.code={%
+ \let\keyname=\pgfkeyscurrentname%
+ \let\keyvalue=\pgfkeyscurrentvalue%
+ \ifthenelse{\equal{\keyname}{stereo}}{%
+ \errmessage{TIKZUML ERROR : in umlentity, forbidden option stereo}%
+ }{}%
+ }%
+ }%
+ \pgfkeys{/tikzuml/entityobj/.cd, #1}%
+ \umlobject[stereo=entity, #1]{#2}%
+}%
+\newcommand{\umlcontrol}[2][]{%
+ \pgfkeys{/tikzuml/controlobj/.cd, .unknown/.code={%
+ \let\keyname=\pgfkeyscurrentname%
+ \let\keyvalue=\pgfkeyscurrentvalue%
+ \ifthenelse{\equal{\keyname}{stereo}}{%
+ \errmessage{TIKZUML ERROR : in umlcontrol, forbidden option stereo}%
+ }{}%
+ }%
+ }%
+ \pgfkeys{/tikzuml/controlobj/.cd, #1}%
+ \umlobject[stereo=control, #1]{#2}%
+}%
+\newcommand{\umlboundary}[2][]{%
+ \pgfkeys{/tikzuml/boundaryobj/.cd, .unknown/.code={%
+ \let\keyname=\pgfkeyscurrentname%
+ \let\keyvalue=\pgfkeyscurrentvalue%
+ \ifthenelse{\equal{\keyname}{stereo}}{%
+ \errmessage{TIKZUML ERROR : in umlboundary, forbidden option stereo}%
+ }{}%
+ }%
+ }%
+ \pgfkeys{/tikzuml/boundaryobj/.cd, #1}%
+ \umlobject[stereo=boundary, #1]{#2}%
+}%
+\newcommand{\umlmulti}[2][]{%
+ \pgfkeys{/tikzuml/multiobj/.cd, .unknown/.code={%
+ \let\keyname=\pgfkeyscurrentname%
+ \let\keyvalue=\pgfkeyscurrentvalue%
+ \ifthenelse{\equal{\keyname}{stereo}}{%
+ \errmessage{TIKZUML ERROR : in umlmulti, forbidden option stereo}%
+ }{}%
+ }%
+ }%
+ \pgfkeys{/tikzuml/multiobj/.cd, #1}%
+ \umlobject[stereo=multi, #1]{#2}%
+}%
+%
+\newcounter{tikzumlSDNodeNum}%
+%
+% define a hidden node to lengthen lifeline of a object
+% args : object node
+% optional : dt: distance between the sdnode and the last call defined on the lifeline of the object
+% name: name of the sdnode
+\newcommand{\umlsdnode}[2][]{%
+ \pgfkeys{/tikzuml/sdnode/.cd, dt/.initial=0, name/.initial=tikzumlEmpty}%
+ \pgfkeys{/tikzuml/sdnode/.cd, #1}%
+ \pgfkeys{/tikzuml/sdnode/.cd, dt/.get=\tikzumlSDNodeDT, name/.get=\tikzumlSDNodeName}%
+ %
+ \ifthenelse{\equal{\tikzumlSDNodeName}{tikzumlEmpty}}{%
+ \expandafter\def\expandafter\tikzumlSDNode@nodeName{sdnode-\thetikzumlSDNodeNum}%
+ }{%
+ \expandafter\def\expandafter\tikzumlSDNode@nodeName{\tikzumlSDNodeName}%
+ }%
+ %
+ \stepcounter{tikzumlSDNodeNum}%
+ %
+ \begingroup%
+ \def\_{_}\edef\x{\endgroup%
+ \def\noexpand\tikzumlSDNode@objnodeName{#2}}\x%
+ %
+ \draw (\expandafter\csname tikzumlLastChild@\tikzumlSDNode@objnodeName \endcsname)+(0,-\tikzumlSDNodeDT ex) node[name=\tikzumlSDNode@nodeName,coordinate] {};%
+ %
+ % update last node drawn on sender lifeline
+ \expandafter\xdef\csname tikzumlLastChild@\tikzumlSDNode@objnodeName \endcsname{\tikzumlSDNode@nodeName}%
+}%
+%
+\newlength{\tikzumlCall@xa}%
+\newlength{\tikzumlCall@xb}%
+%
+% define a uml operation call for sequence diagrams
+% args : call sender
+% call receiver
+% optional : dt: time delay from precedent event end
+% name: name of the call
+% op: operation name and input args
+% return: return value
+% type: type of the call (synchron, asynchron)
+% draw, fill, text: colors
+% padding: time padding from call start and to call end
+\newenvironment{umlcall}[3][]{%
+ \stepcounter{tikzumlCallNum}%
+ \def\tikzumlCallWithReturn{tikzumlFalse}%
+ \edef\tikzumlCall@lastchildNum{\thetikzumlCallNum}% for testing presence of sub-calls
+ \gdef\tikzumlCallBottom{0}%
+ %
+ \pgfkeys{/tikzuml/call/.cd, dt/.initial=\tikzumlCallDefaultDT, name/.initial={call-\thetikzumlCallNum},%
+ op/.initial={}, return/.initial={}, type/.initial=\tikzumlCallDefaultType,%
+ draw/.initial=\tikzumlDefaultDrawColor, fill/.initial=\tikzumlCallDefaultFillColor,%
+ text/.initial=\tikzumlDefaultTextColor,%
+ padding/.initial=\tikzumlCallDefaultPadding,%
+ .unknown/.code={%
+ \let\keyname=\pgfkeyscurrentname%
+ \let\keyvalue=\pgfkeyscurrentvalue%
+ \ifthenelse{\equal{\keyname}{with return}}{%
+ \def\tikzumlCallWithReturn{tikzumlTrue}%
+ }{%
+ \errmessage{TIKZUML ERROR : in umlcall, invalid option \keyname}%
+ }%
+ }%
+ }%
+ \pgfkeys{/tikzuml/call/.cd, #1}%
+ \pgfkeys{/tikzuml/call/.cd, dt/.get=\tikzumlCallDT, name/.get=\tikzumlCallName, op/.get=\tikzumlCallOp,%
+ return/.get=\tikzumlCallReturn, type/.get=\tikzumlCallType,%
+ padding/.get=\tikzumlCallPadding,%
+ draw/.get=\tikzumlCallDrawColor, fill/.get=\tikzumlCallFillColor,%
+ text/.get=\tikzumlCallTextColor%
+ }%
+ %
+ \edef\tikzumlfillcall{\tikzumlCallFillColor}%
+ \edef\tikzumldrawcall{\tikzumlCallDrawColor}%
+ \edef\tikzumltextcall{\tikzumlCallTextColor}%
+ \edef\tikzumltypecall{\tikzumlCallType}%
+ %
+ \ifthenelse{\equal{\tikzumlCallDT}{tikzumlEmpty}}{%
+ \ifnum\thetikzumlCallNum=1%
+ \def\tikzumlCallDT{2}%
+ \def\tikzumlcallSrc{2}%
+ \else%
+ \def\tikzumlCallDT{2}%
+ \def\tikzumlcallSrc{1}%
+ \fi%
+ }{%
+ \def\tikzumlcallSrc{0}%
+ }%
+ %
+ \let\tikzumlCallStartNodeNameold\tikzumlCallStartNodeName%
+ \def\tikzumlCallStartNodeName{#2}%
+ \let\tikzumlCallEndNodeNameold\tikzumlCallEndNodeName%
+ \def\tikzumlCallEndNodeName{#3}%
+ \def\tikzumlcallheight{\tikzumlCallPadding}%
+ %
+ % managing time delays from previous/parent fragments
+ \ifnum\thetikzumlCallStartFragmentNum>0%
+ \let\tikzumlCallDTold\tikzumlCallDT%
+ \pgfmathparse{0.5*\tikzumlFragment@paddingy+\tikzumlCallDTold}%
+ \edef\tikzumlCallDT{\pgfmathresult}%
+ \addtocounter{tikzumlCallStartFragmentNum}{-1}
+ \fi%
+ \ifnum\thetikzumlCallEndFragmentNum>0%
+ \let\tikzumlCallDTold\tikzumlCallDT%
+ \pgfmathparse{0.5*\tikzumlFragment@paddingy+\tikzumlCallDTold}%
+ \edef\tikzumlCallDT{\pgfmathresult}%
+ \addtocounter{tikzumlCallEndFragmentNum}{-1}
+ \fi%
+ \ifnum\thetikzumlFragmentPartNum>0%
+ \let\tikzumlCallDTold\tikzumlCallDT%
+ \pgfmathparse{0.5*\tikzumlFragment@paddingy+\tikzumlCallDTold}%
+ \edef\tikzumlCallDT{\pgfmathresult}%
+ \fi%
+ %
+ % managing parent-child structure
+ \ifnum\thetikzumlCallLevel>0%
+ \let\tikzumlCall@nameold\tikzumlCall@name%
+ \edef\tikzumlCall@name{\tikzumlCallName}%
+ \let\tikzumlCall@parentold\tikzumlCall@parent%
+ \edef\tikzumlCall@parent{\tikzumlCall@parentold @@\tikzumlCall@nameold}%
+ \else%
+ \edef\tikzumlCall@parent{}%
+ \edef\tikzumlCall@parentold{}%
+ \edef\tikzumlCall@nameold{}
+ \edef\tikzumlCall@name{\tikzumlCallName}%
+ \fi%
+ %
+ \begingroup%
+ \def\_{_}\edef\x{\endgroup%
+ \def\noexpand\tikzumlCall@nodeName{\tikzumlCall@name}}\x%
+ %
+ \let\tikzumlCall@nodeNameold\tikzumlCall@nodeName%
+ %
+ \def\tikzumlcallstyle{tikzuml \tikzumlCallType-msg style}%
+ %
+ % top node of activity period of call sender
+ \begin{pgfonlayer}{connections}%
+ \pgfmathparse{\tikzumlCallDT+\tikzumlcallSrc}%
+ \draw (\csname tikzumlLastChild@\tikzumlCallStartNodeName \endcsname)+(0,-\pgfmathresult ex) node[coordinate, name=tikzumlTmpNode] {};%
+ \node[tikzuml activity style] (st-\tikzumlCall@nodeName) at (\tikzumlCallStartNodeName |- tikzumlTmpNode) {};%
+ %
+ % update last node drawn on sender lifeline
+ \expandafter\xdef\csname tikzumlLastChild@\tikzumlCallStartNodeName \endcsname{st-\tikzumlCall@nodeName}%
+ %
+ % top node of activity period of call receiver
+ \ifstrequal{\tikzumlCallStartNodeName}{\tikzumlCallEndNodeName}{%
+ \draw (st-\tikzumlCall@nodeName)+(0,-0.75*\tikzumlCallPadding ex) node[coordinate, name=tikzumlTmpNode] {};%
+ \node[tikzuml activity style] (et-\tikzumlCall@nodeName) at (\tikzumlCallStartNodeName |- tikzumlTmpNode) {};%
+ }{%
+ \node[tikzuml activity style] (et-\tikzumlCall@nodeName) at (\tikzumlCallEndNodeName |- st-\tikzumlCall@nodeName) {};%
+ }%
+ %
+ % update last node drawn on receiver lifeline
+ \expandafter\xdef\csname tikzumlLastChild@\tikzumlCallEndNodeName \endcsname{et-\tikzumlCall@nodeName}%
+ \xdef\tikzumlCallBottomSrc{et-\tikzumlCall@nodeName}%
+ \end{pgfonlayer}%
+ %
+ \stepcounter{tikzumlCallLevel}%
+}{%
+ \addtocounter{tikzumlCallLevel}{-1}%
+ %
+ % bottom nodes of activity periods of call sender and receiver
+ \begin{pgfonlayer}{connections}%
+ \ifnum\tikzumlCall@lastchildNum=\thetikzumlCallNum%
+ %
+ % this test occurs a bug with latex package preview
+ \ifstrequal{\tikzumlCallStartNodeName}{\tikzumlCallEndNodeName}{%
+ \draw (\tikzumlCallBottomSrc)+(0,-\tikzumlCallPadding ex) node[coordinate, name=tikzumlTmpNode] {};%
+ \node[tikzuml activity style] (eb-\tikzumlCall@nodeName) at (\tikzumlCallEndNodeName |- tikzumlTmpNode) {};%
+ \draw (eb-\tikzumlCall@nodeName)+(0,-0.75*\tikzumlCallPadding ex) node[coordinate, name=tikzumlTmpNode] {};%
+ \node[tikzuml activity style] (sb-\tikzumlCall@nodeName) at (\tikzumlCallStartNodeName |- tikzumlTmpNode) {};%
+ }{%
+ \ifthenelse{\equal{\tikzumlCallReturn}{tikzumlEmpty}}{%
+ \pgfmathsetmacro{\tikzumlCallPaddingd}{0.5*\tikzumlCallPadding}%
+ }{%
+ \pgfmathsetmacro{\tikzumlCallPaddingd}{1.2*\tikzumlCallPadding}%
+ }%
+ \draw (\tikzumlCallBottomSrc)+(0,-\tikzumlCallPaddingd ex) node[coordinate, name=tikzumlTmpNode] {};%
+ \node[tikzuml activity style] (eb-\tikzumlCall@nodeName) at (\tikzumlCallEndNodeName |- tikzumlTmpNode) {};%
+ \node[tikzuml activity style] (sb-\tikzumlCall@nodeName) at (\tikzumlCallStartNodeName |- eb-\tikzumlCall@nodeName) {};%
+ }%
+ \xdef\tikzumlCallBottomSrc{sb-\tikzumlCall@nodeName}%
+ \else%
+ %
+ % managing time delays from previous/parent fragments
+ \ifnum\thetikzumlCallStartFragmentNum>0%
+ \let\tikzumlcallheightold\tikzumlCallPadding%
+ \pgfmathparse{\tikzumlcallheightold+0.5*\tikzumlFragment@paddingy}%
+ \edef\tikzumlcallheight{\pgfmathresult}%
+ \addtocounter{tikzumlCallStartFragmentNum}{-1}%
+ \fi%
+ \ifnum\thetikzumlCallEndFragmentNum>0%
+ \let\tikzumlcallheightold\tikzumlCallPadding%
+ \pgfmathparse{\tikzumlcallheightold+0.5*\tikzumlFragment@paddingy}%
+ \edef\tikzumlcallheight{\pgfmathresult}%
+ \addtocounter{tikzumlCallEndFragmentNum}{-1}%
+ \fi%
+ %
+ \ifstrequal{\tikzumlCallStartNodeName}{\tikzumlCallEndNodeName}{%
+ \draw (\tikzumlCallBottomSrc)+(0,-\tikzumlcallheight ex) node[coordinate, name=tikzumlTmpNode] {};%
+ \node[tikzuml activity style] (eb-\tikzumlCall@nodeName) at (\tikzumlCallEndNodeName |- tikzumlTmpNode) {};%
+ \draw (eb-\tikzumlCall@nodeName)+(0,-0.75*\tikzumlCallPadding ex) node[coordinate, name=tikzumlTmpNode] {};%
+ \node[tikzuml activity style] (sb-\tikzumlCall@nodeName) at (\tikzumlCallStartNodeName |- tikzumlTmpNode) {};%
+ }{%
+ \draw (\tikzumlCallBottomSrc)+(0,-\tikzumlcallheight ex) node[coordinate, name=tikzumlTmpNode] {};%
+ \node[tikzuml activity style] (eb-\tikzumlCall@nodeName) at (\tikzumlCallEndNodeName |- tikzumlTmpNode) {};%
+ \node[tikzuml activity style] (sb-\tikzumlCall@nodeName) at (\tikzumlCallStartNodeName |- eb-\tikzumlCall@nodeName) {};%
+ }%
+ %
+ \xdef\tikzumlCallBottomSrc{sb-\tikzumlCall@nodeName}%
+ \fi%
+ \end{pgfonlayer}%
+ %
+ % draw activity periods
+ \begin{pgfonlayer}{activity}%
+ \ifstrequal{\tikzumlCallStartNodeName}{\tikzumlCallEndNodeName}{%
+ % draw root activity period only
+ \ifnum\thetikzumlCallLevel=0%
+ \draw[draw=\tikzumldrawcall, fill=\tikzumlfillcall] (st-\tikzumlCall@nodeName.north west) rectangle (sb-\tikzumlCall@nodeName.south east);%
+ \else%
+ % draw root activity from inner call
+ \ifthenelse{\equal{\tikzumlCallStartNodeName}{\tikzumlCallEndNodeNameold}}{}{%
+ \draw[draw=\tikzumldrawcall, fill=\tikzumlfillcall] (st-\tikzumlCall@nodeName.north west) rectangle (sb-\tikzumlCall@nodeName.south east);%
+ }%
+ \fi%
+ }{%
+ % draw root activity period
+ \ifnum\thetikzumlCallLevel=0%
+ \draw[draw=\tikzumldrawcall, fill=\tikzumlfillcall] (st-\tikzumlCall@nodeName.north west) rectangle (sb-\tikzumlCall@nodeName.south east);%
+ \else%
+ % draw root activity from inner call
+ \ifthenelse{\equal{\tikzumlCallStartNodeName}{\tikzumlCallEndNodeNameold}}{}{%
+ \draw[draw=\tikzumldrawcall, fill=\tikzumlfillcall] (st-\tikzumlCall@nodeName.north west) rectangle (sb-\tikzumlCall@nodeName.south east);%
+ }%
+ \fi%
+ % draw receiver activity period
+ \draw[draw=\tikzumldrawcall, fill=\tikzumlfillcall] (et-\tikzumlCall@nodeName.north west) rectangle (eb-\tikzumlCall@nodeName.south east);%
+ }%
+ \end{pgfonlayer}%
+ \ifthenelse{\equal{\tikzumlCallDefaultFillColor}{\tikzumlCallFillColor}}{}{%
+ \fill[\tikzumlfillcall] (st-\tikzumlCall@nodeName.north west) rectangle (sb-\tikzumlCall@nodeName.south east);%
+ \draw[\tikzumldrawcall] (st-\tikzumlCall@nodeName.north west) rectangle (sb-\tikzumlCall@nodeName.south west) (st-\tikzumlCall@nodeName.north east) rectangle (sb-\tikzumlCall@nodeName.south east);%
+ }%
+ %
+ % update last nodes drawn on sender and receiver lifelines
+ \expandafter\xdef\csname tikzumlLastChild@\tikzumlCallEndNodeName \endcsname{eb-\tikzumlCall@nodeName}%
+ \expandafter\xdef\csname tikzumlLastChild@\tikzumlCallStartNodeName \endcsname{sb-\tikzumlCall@nodeName}%
+ %
+ % draw call arrows
+ \begin{pgfonlayer}{connections}%
+ \ifstrequal{\tikzumlCallStartNodeName}{\tikzumlCallEndNodeName}{%
+ \draw[\tikzumlcallstyle, \tikzumldrawcall] (st-\tikzumlCall@nodeName.east) -- ++(2.5*\tikzumlCallPadding ex,0) %
+ -- ++(0,-0.75*\tikzumlCallPadding ex) %
+ node[font=\tikzumlDefaultFont, text=\tikzumltextcall, midway, right, name=\tikzumlCall@nodeName-op] {\tikzumlCallOp} %
+ -- (et-\tikzumlCall@nodeName.east);%
+ %
+ % draw return arrow and update fit for parent fragment
+ \ifthenelse{\equal{\tikzumltypecall}{synchron}}{%
+ \ifthenelse{\NOT\equal{\tikzumlCallReturn}{}\OR\equal{\tikzumlCallWithReturn}{tikzumlTrue}}{%
+ \ifnum\c@tikzumlFragmentLevel>0%
+ \edef\tikzumlFragmentFitOld{\csname tikzumlFragmentFit\tikzumlFragment@name \endcsname}%
+ \expandafter\xdef\csname tikzumlFragmentFit\tikzumlFragment@name \endcsname{\tikzumlFragmentFitOld (st-\tikzumlCall@nodeName) (et-\tikzumlCall@nodeName) (eb-\tikzumlCall@nodeName) (sb-\tikzumlCall@nodeName) (\tikzumlCall@nodeName-op) (\tikzumlCall@nodeName-return)}%
+ \fi%
+ %
+ \draw[tikzuml call return style, \tikzumldrawcall] (eb-\tikzumlCall@nodeName.east) -- ++(2.5*\tikzumlCallPadding ex,0)
+ -- ++(0,-0.75*\tikzumlCallPadding ex) %
+ node[font=\tikzumlDefaultFont, text=\tikzumltextcall, midway, right, name=\tikzumlCall@nodeName-return] {\tikzumlCallReturn} %
+ -- (sb-\tikzumlCall@nodeName.east);%
+ }{%
+ \ifnum\c@tikzumlFragmentLevel>0%
+ \edef\tikzumlFragmentFitOld{\csname tikzumlFragmentFit\tikzumlFragment@name \endcsname}%
+ \expandafter\xdef\csname tikzumlFragmentFit\tikzumlFragment@name \endcsname{\tikzumlFragmentFitOld (st-\tikzumlCall@nodeName) (et-\tikzumlCall@nodeName) (eb-\tikzumlCall@nodeName) (sb-\tikzumlCall@nodeName) (\tikzumlCall@nodeName-op)}%
+ \fi%
+ }%
+ }{%
+ \ifnum\c@tikzumlFragmentLevel>0%
+ \edef\tikzumlFragmentFitOld{\csname tikzumlFragmentFit\tikzumlFragment@name \endcsname}%
+ \expandafter\xdef\csname tikzumlFragmentFit\tikzumlFragment@name \endcsname{\tikzumlFragmentFitOld (st-\tikzumlCall@nodeName) (et-\tikzumlCall@nodeName) (eb-\tikzumlCall@nodeName) (sb-\tikzumlCall@nodeName) (\tikzumlCall@nodeName-op)}%
+ \fi%
+ }%
+ }{%
+ % draw call arrows
+ \pgfextractx{\tikzumlCall@xa}{\pgfpointanchor{\tikzumlCallStartNodeName}{center}}%
+ \pgfextractx{\tikzumlCall@xb}{\pgfpointanchor{\tikzumlCallEndNodeName}{center}}%
+ %
+ \ifthenelse{\tikzumlCall@xb>\tikzumlCall@xa}{%
+ \draw[\tikzumlcallstyle, \tikzumldrawcall] (st-\tikzumlCall@nodeName.east) -- (et-\tikzumlCall@nodeName.west) %
+ node[font=\tikzumlDefaultFont, text=\tikzumltextcall, midway, above=-0.4ex, name=\tikzumlCall@nodeName-op] {\tikzumlCallOp};%
+ }{%
+ \draw[\tikzumlcallstyle, \tikzumldrawcall] (st-\tikzumlCall@nodeName.west) -- (et-\tikzumlCall@nodeName.east) %
+ node[font=\tikzumlDefaultFont, text=\tikzumltextcall, midway, above=-0.4ex, name=\tikzumlCall@nodeName-op] {\tikzumlCallOp};%
+ }%
+ %
+ % draw return arrow and update fit for parent fragment
+ \ifthenelse{\equal{\tikzumltypecall}{synchron}}{%
+ \ifthenelse{\NOT\equal{\tikzumlCallReturn}{}\OR\equal{\tikzumlCallWithReturn}{tikzumlTrue}}{%
+ \ifnum\c@tikzumlFragmentLevel>0%
+ \edef\tikzumlFragmentFitOld{\csname tikzumlFragmentFit\tikzumlFragment@name \endcsname}%
+ \expandafter\xdef\csname tikzumlFragmentFit\tikzumlFragment@name \endcsname{\tikzumlFragmentFitOld (st-\tikzumlCall@nodeName) (et-\tikzumlCall@nodeName) (eb-\tikzumlCall@nodeName) (sb-\tikzumlCall@nodeName) (\tikzumlCall@nodeName-op) (\tikzumlCall@nodeName-return)}%
+ \fi%
+ %
+ \ifthenelse{\tikzumlCall@xb>\tikzumlCall@xa}{%
+ \draw[tikzuml call return style, \tikzumldrawcall] (eb-\tikzumlCall@nodeName.west) -- (sb-\tikzumlCall@nodeName.east) %
+ node[font=\tikzumlDefaultFont, text=\tikzumltextcall, midway, above=-0.4ex, name=\tikzumlCall@nodeName-return] {\tikzumlCallReturn};%
+ }{%
+ \draw[tikzuml call return style, \tikzumldrawcall] (eb-\tikzumlCall@nodeName.east) -- (sb-\tikzumlCall@nodeName.west) %
+ node[font=\tikzumlDefaultFont, text=\tikzumltextcall, midway, above=-0.4ex, name=\tikzumlCall@nodeName-return] {\tikzumlCallReturn};%
+ }%
+ }{%
+ \ifnum\c@tikzumlFragmentLevel>0%
+ \edef\tikzumlFragmentFitOld{\csname tikzumlFragmentFit\tikzumlFragment@name \endcsname}%
+ \expandafter\xdef\csname tikzumlFragmentFit\tikzumlFragment@name \endcsname{\tikzumlFragmentFitOld (st-\tikzumlCall@nodeName) (et-\tikzumlCall@nodeName) (eb-\tikzumlCall@nodeName) (sb-\tikzumlCall@nodeName) (\tikzumlCall@nodeName-op)}%
+ \fi%
+ }%
+ }{%
+ \ifnum\c@tikzumlFragmentLevel>0%
+ \edef\tikzumlFragmentFitOld{\csname tikzumlFragmentFit\tikzumlFragment@name \endcsname}%
+ \expandafter\xdef\csname tikzumlFragmentFit\tikzumlFragment@name \endcsname{\tikzumlFragmentFitOld (st-\tikzumlCall@nodeName) (et-\tikzumlCall@nodeName) (eb-\tikzumlCall@nodeName) (sb-\tikzumlCall@nodeName) (\tikzumlCall@nodeName-op)}%
+ \fi%
+ }%
+ }%
+ \end{pgfonlayer}%
+}%
+%
+% alias for function self call
+\newenvironment{umlcallself}[2][]{\begin{umlcall}[#1]{#2}{#2} }{\end{umlcall}}%
+%
+% define a combined fragment
+% optional : name: name of fragment
+% type: type of fragment (opt, alt, break, loop, par, critical, ignore, consider, assert, neg, weak, strict, ref)
+% label: label of fragment (ex : condition for opt, iterator for loop, ...)
+% inner xsep, inner ysep: padding of the fragment box
+% draw, fill, text: colors
+\newenvironment{umlfragment}[1][]{%
+ % define a fragment separator
+ % optional : label of the fragment part (ex : else for alt)
+ \providecommand{\umlfpart}[1][]{%
+ \stepcounter{tikzumlFragmentPartNum}%
+ %
+ \node[outer sep=0, inner xsep=\tikzumlFragmentXSep ex, inner ysep=\tikzumlFragmentYSep ex, fit=\csname tikzumlFragmentFit\tikzumlFragment@name \endcsname, name=\tikzumlFragment@name-Part-tmp] {};%
+ \node[anchor=east, name=\tikzumlFragment@name-PartType-\thetikzumlFragmentPartNum] at (\tikzumlFragment@name-Part-tmp.north west |- \tikzumlCallBottomSrc) {\phantom{\tikzumlFragmentType}};%
+ \draw (\tikzumlFragment@name-PartType-\thetikzumlFragmentPartNum.north west |- \tikzumlCallBottomSrc)+(0,-0.4*\tikzumlFragment@paddingy ex) node[name=\tikzumlFragment@name-PartWest-\thetikzumlFragmentPartNum] {};%
+ \draw (\tikzumlFragment@name-Part-tmp.north east |- \tikzumlCallBottomSrc)+(0,-0.4*\tikzumlFragment@paddingy ex) node[name=\tikzumlFragment@name-PartEast-\thetikzumlFragmentPartNum] {};%
+ \draw[dashed] (\tikzumlFragment@name-PartWest-\thetikzumlFragmentPartNum) -- (\tikzumlFragment@name-PartEast-\thetikzumlFragmentPartNum);
+ \draw (\tikzumlFragment@name-PartType-\thetikzumlFragmentPartNum)+(0,-0.4*\tikzumlFragment@paddingy ex) node[name=tikzumlTmpNode] {\phantom{\tikzumlFragmentType}};%
+ \node[anchor=north west] at (tikzumlTmpNode.south west) {[##1]};%
+ }%
+ %
+ \stepcounter{tikzumlFragmentNum}%
+ %
+ \pgfkeys{/tikzuml/fragment/.cd, name/.initial=fragment@\alph{tikzumlFragmentNum}, type/.initial=\tikzumlFragmentDefaultType,%
+ label/.initial=tikzumlEmpty,%
+ inner xsep/.initial=\tikzumlFragmentDefaultXSep, inner ysep/.initial=\tikzumlFragmentDefaultYSep,%
+ draw/.initial=\tikzumlDefaultDrawColor, fill/.initial=\tikzumlFragmentDefaultFillColor,%
+ text/.initial=\tikzumlDefaultTextColor,%
+ .unknown/.code={%
+ \let\keyname=\pgfkeyscurrentname%
+ \let\keyvalue=\pgfkeyscurrentvalue%
+ \errmessage{TIKZUML ERROR : in umlfragment, invalid option \keyname}%
+ }%
+ }%
+ \pgfkeys{/tikzuml/fragment/.cd, #1}%
+ \pgfkeys{/tikzuml/fragment/.cd, name/.get=\tikzumlFragmentName, type/.get=\tikzumlFragmentType,%
+ label/.get=\tikzumlFragmentLabel,%
+ inner xsep/.get=\tikzumlFragmentXSep, inner ysep/.get=\tikzumlFragmentYSep,%
+ draw/.get=\tikzumlFragmentDrawColor, fill/.get=\tikzumlFragmentFillColor,%
+ text/.get=\tikzumlFragmentTextColor%
+ }%
+ %
+ \ifthenelse{\equal{\tikzumlFragmentLabel}{tikzumlEmpty}}{%
+ \def\tikzumlFragmentLabel{}%
+ }{%
+ \let\tikzumlFragmentLabelold\tikzumlFragmentLabel%
+ \def\tikzumlFragmentLabel{[\tikzumlFragmentLabelold]}%
+ }%
+ %
+ \ifnum\thetikzumlFragmentLevel>0%
+ \let\tikzumlFragment@parentold\tikzumlFragment@parent%
+ \let\tikzumlFragment@nameold\tikzumlFragment@name%
+ \edef\tikzumlFragment@parent{\tikzumlFragment@nameold}%
+ \else%
+ \setcounter{tikzumlFragmentPartNum}{0}%
+ \edef\tikzumlFragment@parent{}%
+ \edef\tikzumlFragment@parentold{}%
+ \edef\tikzumlFragment@nameold{}%
+ \fi%
+ %
+ \edef\tikzumlFragment@name{\tikzumlFragmentName}%
+ \expandafter\gdef\csname tikzumlFragmentFit\tikzumlFragment@name \endcsname{}%
+ %
+ \stepcounter{tikzumlFragmentLevel}%
+ %
+ \ifnum\thetikzumlCallLevel>0%
+ \stepcounter{tikzumlCallStartFragmentNum}%
+ \fi%
+ %
+ \pgfmathparse{6*\tikzumlFragmentYSep}%
+ \xdef\tikzumlFragment@paddingy{\pgfmathresult}%
+ \if\c@tikzumlFragmentLevelNum=0%
+ \setcounter{tikzumlFragmentLevelNum}{\thetikzumlFragmentLevel}%
+ \fi%
+ %
+ % time delay adjustment for two consecutive fragments
+ \ifnum\thetikzumlCallEndFragmentNum>0%
+ \addtocounter{tikzumlCallEndFragmentNum}{-1}
+ \fi%
+}{%
+ %
+ \addtocounter{tikzumlFragmentLevel}{-1}%
+ %
+ \ifnum\thetikzumlFragmentLevel>0%
+ \edef\tikzumlFragmentFitOld{\csname tikzumlFragmentFit\tikzumlFragment@parent \endcsname}%
+ \expandafter\xdef\csname tikzumlFragmentFit\tikzumlFragment@parent \endcsname{\tikzumlFragmentFitOld (\tikzumlFragment@name)}%
+ \fi%
+ %
+ % draw working fragment box
+ \begin{pgfonlayer}{fragment\thetikzumlFragmentLevel}%
+ \node[outer sep=0, inner xsep=\tikzumlFragmentXSep ex, inner ysep=\tikzumlFragmentYSep ex, fit=\csname tikzumlFragmentFit\tikzumlFragment@name \endcsname, name=\tikzumlFragment@name-back] {};%
+ \end{pgfonlayer}%
+ %
+ % draw type and label
+ \node[text=\tikzumlFragmentTextColor, font=\tikzumlDefaultFont, anchor=north east, name=\tikzumlFragment@name-type] %
+ at (\tikzumlFragment@name-back.north west) {\tikzumlFragmentType};%
+ \node[text=\tikzumlFragmentTextColor, font=\tikzumlDefaultFont, anchor=north west, name=\tikzumlFragment@name-label] %
+ at (\tikzumlFragment@name-type.south west) {\tikzumlFragmentLabel};%
+ %
+ % draw final fragment box
+ \begin{pgfonlayer}{fragment\thetikzumlFragmentLevel}%
+ \node[draw=\tikzumlFragmentDrawColor, fill=\tikzumlFragmentFillColor, outer sep=0, inner sep=0, font=\tikzumlDefaultFont, fit=(\tikzumlFragment@name-back) (\tikzumlFragment@name-type) (\tikzumlFragment@name-label), name=\tikzumlFragment@name] {};%
+ \end{pgfonlayer}%
+ %
+ \draw[draw=\tikzumlFragmentDrawColor] (\tikzumlFragment@name.north west) rectangle (\tikzumlFragment@name.south east);%
+ \draw (\tikzumlFragment@name-type.south east)+(0,1ex) node[name=\tikzumlFragment@name-typetop, inner sep=0] {};%
+ \draw (\tikzumlFragment@name-type.south east)+(-1ex,0) node[name=\tikzumlFragment@name-typeleft, inner sep=0] {};%
+ \draw (\tikzumlFragment@name.north west) -| (\tikzumlFragment@name-typetop.center) -- (\tikzumlFragment@name-typeleft.center) -| (\tikzumlFragment@name.north west);%
+ %
+ \ifnum\thetikzumlCallLevel>0%
+ \stepcounter{tikzumlCallEndFragmentNum}%
+ \fi%
+}%
+%
+% define a constructor call
+% arg : call sender
+% name of constructed object
+% optional : x: coordinate of the new object
+% stereo: stereotype of the new object
+% class: class type of the new object
+% dt: time delay from last event
+% name: name of the call
+% draw, fill, text: colors
+% no ddots: when used, disable printing of double dots
+\newcommand{\umlcreatecall}[3][]{%
+ \stepcounter{tikzumlCallNum}%
+ \edef\tikzumlCall@lastchildNum{\thetikzumlCallNum}% for testing presence of sub-calls
+ \gdef\tikzumlInCreateCall{1}%
+ \pgfkeys{/tikzuml/createcall/.cd, x/.initial=tikzumlEmpty, stereo/.initial=\tikzumlObjectDefaultStereo, class/.initial={},%
+ dt/.initial=\tikzumlCreateCallDefaultDT, name/.initial=call-\thetikzumlCallNum,%
+ draw/.initial=\tikzumlDefaultDrawColor, fill/.initial=\tikzumlCallDefaultFillColor,%
+ text/.initial=\tikzumlDefaultTextColor,%
+ draw obj/.initial=\tikzumlDefaultDrawColor, fill obj/.initial=\tikzumlObjectDefaultFillColor,%
+ text obj/.initial=\tikzumlDefaultTextColor,%
+ no ddots/.is if=tikzumlcreatecallNoDDots,%
+ no ddots=false,%
+ .unknown/.code={%
+ \let\keyname=\pgfkeyscurrentname%
+ \let\keyvalue=\pgfkeyscurrentvalue%
+ \errmessage{TIKZUML ERROR : in umlcreatecall, invalid option \keyname}%
+ }%
+ }%
+ \pgfkeys{/tikzuml/createcall/.cd, #1}%
+ \pgfkeys{/tikzuml/createcall/.cd, x/.get=\tikzumlCreateCallX, stereo/.get=\tikzumlCreateCallStereo,%
+ class/.get=\tikzumlCreateCallClass,%
+ dt/.get=\tikzumlCreateCallDT, name/.get=\tikzumlCreateCallName,%
+ draw/.get=\tikzumlCreateCallDrawColor, fill/.get=\tikzumlCreateCallFillColor,%
+ text/.get=\tikzumlCreateCallTextColor,%
+ draw obj/.get=\tikzumlCreateCallObjectDrawColor, fill obj/.get=\tikzumlCreateCallObjectFillColor,%
+ text obj/.get=\tikzumlCreateCallObjectTextColor%
+ }%
+ %
+ \def\tikzumlCreateCallSrc@name{#2}%
+ %
+ \begingroup%
+ \def\_{_}\edef\x{\endgroup%
+ \def\noexpand\tikzumlCreateCallSrc@nodeName{\tikzumlCreateCallSrc@name}}\x%
+ %
+ % managing time delays from previous/parent fragments
+ \ifnum\thetikzumlCallStartFragmentNum>0%
+ \let\tikzumlCreateCallDTold\tikzumlCreateCallDT%
+ \pgfmathparse{0.5*\tikzumlFragment@paddingy+\tikzumlCreateCallDTold}%
+ \edef\tikzumlCreateCallDT{\pgfmathresult}%
+ \addtocounter{tikzumlCallStartFragmentNum}{-1}
+ \fi%
+ \ifnum\thetikzumlCallEndFragmentNum>0%
+ \let\tikzumlCreateCallDTold\tikzumlCreateCallDT%
+ \pgfmathparse{0.5*\tikzumlFragment@paddingy+\tikzumlCreateCallDTold}%
+ \edef\tikzumlCreateCallDT{\pgfmathresult}%
+ \addtocounter{tikzumlCallEndFragmentNum}{-1}
+ \fi%
+ \ifnum\thetikzumlFragmentPartNum>0%
+ \let\tikzumlCreateCallDTold\tikzumlCreateCallDT%
+ \pgfmathparse{0.5*\tikzumlFragment@paddingy+\tikzumlCreateCallDTold}%
+ \edef\tikzumlCreateCallDT{\pgfmathresult}%
+ \fi%
+ %
+ % managing parent-child structure
+ \ifnum\thetikzumlCallLevel>0%
+ \let\tikzumlCall@nameold\tikzumlCall@name%
+ \def\tikzumlCall@name{\tikzumlCreateCallName}%
+ \let\tikzumlCall@parentold\tikzumlCall@parent%
+ \edef\tikzumlCall@parent{\tikzumlCall@parentold @@\tikzumlCall@nameold}%
+ \else%
+ \edef\tikzumlCall@parent{}%
+ \edef\tikzumlCall@parentold{}%
+ \edef\tikzumlCall@nameold{}
+ \edef\tikzumlCall@name{\tikzumlCreateCallName}%
+ \fi%
+ %
+ \begingroup%
+ \def\_{_}\edef\x{\endgroup%
+ \def\noexpand\tikzumlCreateCall@nodeName{\tikzumlCall@name}}\x%
+ %
+ \draw (\csname tikzumlLastChild@\tikzumlCreateCallSrc@nodeName \endcsname)+(0,-\tikzumlCreateCallDT ex) node[name=st-\tikzumlCreateCall@nodeName, tikzuml activity style] {};%
+ %
+ \xdef\tikzumlCreateCallObjectSrc{st-\tikzumlCreateCall@nodeName}%
+ %
+ \iftikzumlcreatecallNoDDots%
+ \umlobject[x=\tikzumlCreateCallX, stereo=\tikzumlCreateCallStereo, class=\tikzumlCreateCallClass, draw=\tikzumlCreateCallObjectDrawColor, fill=\tikzumlCreateCallObjectFillColor, text=\tikzumlCreateCallObjectTextColor, no ddots]{#3}%
+ \else
+ \umlobject[x=\tikzumlCreateCallX, stereo=\tikzumlCreateCallStereo, class=\tikzumlCreateCallClass, draw=\tikzumlCreateCallObjectDrawColor, fill=\tikzumlCreateCallObjectFillColor, text=\tikzumlCreateCallObjectTextColor]{#3}%
+ \fi
+ %
+ \draw (\csname tikzumlLastChild@\tikzumlCreateCallSrc@nodeName \endcsname |- #3)+(0,-0.5*\tikzumlCreateCallDT ex) node[name=sb-\tikzumlCreateCall@nodeName, tikzuml activity style] {};%
+ %
+ \expandafter\xdef\csname tikzumlLastChild@\tikzumlCreateCallSrc@nodeName \endcsname{sb-\tikzumlCreateCall@nodeName}%
+ \xdef\tikzumlCallBottomSrc{sb-\tikzumlCreateCall@nodeName}%
+ %
+ \begin{pgfonlayer}{connections}%
+ \draw[tikzuml synchron-msg style, \tikzumlCreateCallDrawColor] (st-\tikzumlCreateCall@nodeName) -- (#3) node[midway, above, font=\tikzumlDefaultFont, text=\tikzumlCreateCallTextColor, name=\tikzumlCreateCall@nodeName-op] {create};%
+ \end{pgfonlayer}%
+ %
+ \ifnum\thetikzumlCallLevel=0%
+ \begin{pgfonlayer}{activity}%
+ \draw[draw=\tikzumlCreateCallDrawColor, fill=\tikzumlCreateCallFillColor] (st-\tikzumlCreateCall@nodeName.north west) rectangle (sb-\tikzumlCreateCall@nodeName.south east);%
+ \end{pgfonlayer}%
+ \fi%
+ % add to fit fragment
+ \ifnum\c@tikzumlFragmentLevel>0%
+ \edef\tikzumlFragmentFitOld{\csname tikzumlFragmentFit\tikzumlFragment@name \endcsname}%
+ \expandafter\xdef\csname tikzumlFragmentFit\tikzumlFragment@name \endcsname{\tikzumlFragmentFitOld (st-\tikzumlCreateCall@nodeName) (sb-\tikzumlCreateCall@nodeName) (\tikzumlCreateCall@nodeName-op) (#3) }%
+ \fi%
+}
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% component diagrams %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+\tikzstyle{tikzuml connector style}=[color=\tikzumlDefaultDrawColor, -]%
+%
+\newcounter{tikzumlComponentLevel}%
+\newcounter{tikzumlComponentSubComponentNum}%
+\newcounter{tikzumlConnectorNum}%
+\setcounter{tikzumlConnectorNum}{1}%
+%
+\newif\iftikzumlcomponentWithoutCoords%
+%
+\newcommand{\picturedcomponent}[1]{%
+ \pgfkeys{/tikzuml/component/picture/.cd, scale/.initial=1, .unknown/.code={}}%
+ \pgfkeys{/tikzuml/component/picture/.cd,#1}%
+ \pgfkeys{/tikzuml/component/picture/.cd, scale/.get=\tikzumlComponentScale}%
+ \begin{tikzpicture}[#1]%
+ \filldraw (0,0) rectangle (1ex,1.5ex);%
+ \filldraw (-0.2ex,0.4ex) rectangle (0.2ex,0.6ex);%
+ \filldraw (-0.2ex,0.9ex) rectangle (0.2ex,1.1ex);%
+ \end{tikzpicture}%
+}%
+%
+% define a uml component
+% args : name of the component
+% content of the component
+% optional args : x,y coordinates of the component
+% width of the component node
+\newenvironment{umlcomponent}[2][]{%
+ \ifnum\thetikzumlComponentLevel>0%
+ \let\tikzumlComponent@nameold\tikzumlComponent@fitname%
+ \let\tikzumlComponent@parentold\tikzumlComponent@parent%
+ \edef\tikzumlComponent@parent{\tikzumlComponent@parentold @@\tikzumlComponent@nameold}%
+ \else%
+ \def\tikzumlComponent@parent{}%
+ \fi%
+ %
+ \stepcounter{tikzumlComponentLevel}%
+ %
+ \pgfkeys{/tikzuml/component/.cd, x/.initial=\tikzumlDefaultX, y/.initial=\tikzumlDefaultX, width/.initial=\tikzumlComponentDefaultWidth, name/.initial={},%
+ draw/.initial=\tikzumlDefaultDrawColor, fill/.initial=\tikzumlComponentDefaultFillColor,%
+ text/.initial=\tikzumlDefaultTextColor, style/.style={},%
+ no coords/.is if=tikzumlcomponentWithoutCoords,%
+ no coords=false,%
+ .unknown/.code={%
+ \let\keyname=\pgfkeyscurrentname%
+ \let\keyvalue=\pgfkeyscurrentvalue%
+ \ifthenelse{\equal{\keyname}{above}\OR%
+ \equal{\keyname}{left}\OR%
+ \equal{\keyname}{below}\OR%
+ \equal{\keyname}{right}\OR%
+ \equal{\keyname}{above left}\OR%
+ \equal{\keyname}{above right}\OR%
+ \equal{\keyname}{below left}\OR%
+ \equal{\keyname}{below right}}{%
+ \IfSubStr{\keyvalue}{ of }{%
+ \pgfkeys{/tikzuml/component/.cd, no coords}%
+ }{}%
+ }{}%
+ \ifx\keyvalue\pgfkeysnovalue%
+ \pgfkeys{/tikzuml/component/.cd, style/.append style/.expand once={\keyname}}%
+ \else%
+ \pgfkeys{/tikzuml/component/.cd, style/.append style/.expand twice={\expandafter\keyname\expandafter=\keyvalue}}%
+ \fi%
+ %\errmessage{TIKZUML ERROR : in umlcomponent, invalid option \keyname}%
+ }%
+ }%
+ \pgfkeys{/tikzuml/component/.cd, #1}%
+ \pgfkeys{/tikzuml/component/.cd, x/.get=\tikzumlComponentXShift, y/.get=\tikzumlComponentYShift,%
+ width/.get=\tikzumlComponentMinimumWidth, name/.get=\tikzumlComponentName,%
+ draw/.get=\tikzumlComponentDrawColor, fill/.get=\tikzumlComponentFillColor,%
+ text/.get=\tikzumlComponentTextColor%
+ }%
+ %
+ \ifthenelse{\equal{\tikzumlComponentName}{}}{%
+ \edef\tikzumlComponent@name{#2}%
+ }{%
+ \edef\tikzumlComponent@name{\tikzumlComponentName}%
+ }%
+ %
+ \begingroup%
+ \def\_{@}\edef\x{\endgroup%
+ \def\noexpand\tikzumlComponent@fitname{\tikzumlComponent@name}}\x%
+ %
+ \let\tikzumlComponent@nodeNameold\tikzumlComponent@nodeName%
+ \def\tikzumlComponent@caption{#2}%
+ %
+ \begingroup%
+ \def\_{_}\edef\x{\endgroup%
+ \def\noexpand\tikzumlComponent@nodeName{\tikzumlComponent@name}}\x%
+ %
+ \expandafter\gdef\csname tikzumlComponentFit\tikzumlComponent@parent @@\tikzumlComponent@fitname\endcsname{}%
+ %
+ \setcounter{tikzumlComponentSubComponentNum}{0}%
+ %
+ \begin{scope}[xshift=\tikzumlComponentXShift cm, yshift=\tikzumlComponentYShift cm]%
+}{%
+ \addtocounter{tikzumlComponentLevel}{-1}%
+ \begin{pgfonlayer}{component\thetikzumlComponentLevel}%
+ %
+ % if contains nothing, one define a fictive node to enable the fit option
+ \ifnum\c@tikzumlComponentSubComponentNum=0%
+ \iftikzumlcomponentWithoutCoords%
+ \node[inner ysep=0.5ex, minimum width=\tikzumlComponentMinimumWidth, font=\tikzumlDefaultFont, /tikzuml/component/style] (\tikzumlComponent@nodeName-root) {\phantom{\tikzumlComponent@nodeName}};%
+ \else%
+ \node[inner ysep=0.5ex, minimum width=\tikzumlComponentMinimumWidth, font=\tikzumlDefaultFont, /tikzuml/component/style] (\tikzumlComponent@nodeName-root) at (0,0) {\phantom{\tikzumlComponent@nodeName}};%
+ \fi%
+ \expandafter\xdef\csname tikzumlComponentFit\tikzumlComponent@parent @@\tikzumlComponent@fitname\endcsname{(\tikzumlComponent@nodeName-root)}%
+ \fi%
+ %
+ \ifnum\c@tikzumlComponentLevel>0%
+ \def\tikzumlComponentFitTmp{\csname tikzumlComponentFit\tikzumlComponent@parent\endcsname}%
+ \expandafter\xdef\csname tikzumlComponentFit\tikzumlComponent@parent\endcsname{\tikzumlComponentFitTmp (\tikzumlComponent@nodeName-body) (\tikzumlComponent@nodeName-caption)}%
+ \stepcounter{tikzumlComponentSubComponentNum}%
+ \fi%
+ %
+ \node[inner sep=2ex, font=\tikzumlDefaultFont, fit = \csname tikzumlComponentFit\tikzumlComponent@parent @@\tikzumlComponent@fitname\endcsname] (\tikzumlComponent@nodeName-body) {};%
+ \node[above, font=\tikzumlDefaultFont] (\tikzumlComponent@nodeName-captiontmp) at (\tikzumlComponent@nodeName-body.north) {\tikzumlComponent@caption};%
+ \node (\tikzumlComponent@nodeName-logotmp) at (\tikzumlComponent@nodeName-captiontmp.north -| \tikzumlComponent@nodeName-body.east) {\picturedcomponent{draw=\tikzumlComponentDrawColor, fill=\tikzumlComponentFillColor, font=\tikzumlDefaultFont} };%
+ \node[draw=\tikzumlComponentDrawColor, fill=\tikzumlComponentFillColor, name=\tikzumlComponent@nodeName, /tikzuml/component/style, fit=(\tikzumlComponent@nodeName-body) (\tikzumlComponent@nodeName-captiontmp)] {};%
+ \node[font=\tikzumlDefaultFont] (\tikzumlComponent@nodeName-caption) at (\tikzumlComponent@nodeName-captiontmp) {\tikzumlComponent@caption};%
+ \draw (\tikzumlComponent@nodeName-caption.north -| \tikzumlComponent@nodeName.east) node[font=\tikzumlDefaultFont, xshift=-1ex, below=-1ex, name=\tikzumlComponent@nodeName-logo] {\picturedcomponent{draw=\tikzumlComponentDrawColor, fill=\tikzumlComponentFillColor, font=\tikzumlDefaultFont} };%
+ \draw (\tikzumlComponent@nodeName-caption.south -| \tikzumlComponent@nodeName.north west) -- (\tikzumlComponent@nodeName-caption.south -| \tikzumlComponent@nodeName.north east);%
+ \coordinate (\tikzumlComponent@nodeName-west-port) at (\tikzumlComponent@nodeName.west);
+ \coordinate (\tikzumlComponent@nodeName-east-port) at (\tikzumlComponent@nodeName.east);
+ \coordinate (\tikzumlComponent@nodeName-south-port) at (\tikzumlComponent@nodeName.south);
+ \coordinate (\tikzumlComponent@nodeName-north-port) at (\tikzumlComponent@nodeName.north);
+ \end{pgfonlayer}%
+ \end{scope}%
+ %
+ % add to fit
+ \ifnum\c@tikzumlPackageLevel>0%
+ \edef\tikzumlPackageFitOld{\csname tikzumlPackageFit\tikzumlPackage@parent @@\tikzumlPackage@fitname\endcsname}%
+ \expandafter\xdef\csname tikzumlPackageFit\tikzumlPackage@parent @@\tikzumlPackage@fitname\endcsname{\tikzumlPackageFitOld (\tikzumlComponent@nodeName)}%
+ \stepcounter{tikzumlPackageClassNum}%
+ \fi%
+}%
+%
+% shortcut for empty component
+\newcommand{\umlbasiccomponent}[2][]{\begin{umlcomponent}[#1]{#2} \end{umlcomponent}}%
+%
+\newcommand{\umlrequiredinterface}[2][]{%
+ \def\tikzumlInterfaceWithPort{tikzumlFalse}%
+ \pgfkeys{/tikzuml/requiredinterfacerelation/.cd, interface/.initial={}, distance/.initial=\tikzumlRequiredInterfaceDefaultDistance,%
+ name/.initial=tikzumlEmpty, width/.initial=\tikzumlRequiredInterfaceDefaultWidth,%
+ padding/.initial=\tikzumlRequiredInterfaceDefaultPadding,%
+ draw/.initial=\tikzumlDefaultDrawColor, fill/.initial=\tikzumlComponentDefaultFillColor,%
+ .unknown/.code={%
+ \let\keyname=\pgfkeyscurrentname%
+ \let\keyvalue=\pgfkeyscurrentvalue%
+ \ifthenelse{\equal{\keyname}{with port}}{%
+ \def\tikzumlInterfaceWithPort{tikzumlTrue}%
+ }{}%
+ }%
+ }%
+ \pgfkeys{/tikzuml/requiredinterfacerelation/.cd, #1}%
+ \pgfkeys{/tikzuml/requiredinterfacerelation/.cd, interface/.get=\tikzumlRequiredInterfaceLabel,%
+ distance/.get=\tikzumlRequiredInterfaceDistance,%
+ name/.get=\tikzumlRequiredInterfaceName,%
+ width/.get=\tikzumlRequiredInterfaceWidth,%
+ padding/.get=\tikzumlRequiredInterfacePadding,%
+ draw/.get=\tikzumlRequiredInterfaceDrawColor,%
+ fill/.get=\tikzumlRequiredInterfaceFillColor%
+ }%
+ %
+ \ifthenelse{\equal{\tikzumlRequiredInterfaceName}{tikzumlEmpty}}{%
+ \edef\tikzumlRequiredInterface@interfacename{#2-east-interface}%
+ \edef\tikzumlRequiredInterface@portname{#2-east-port}%
+ \edef\tikzumlRequiredInterface@paddingname{#2-east-padding}%
+ }{%
+ \edef\tikzumlRequiredInterface@interfacename{\tikzumlRequiredInterfaceName}%
+ \edef\tikzumlRequiredInterface@portname{\tikzumlRequiredInterfaceName-port}%
+ \edef\tikzumlRequiredInterface@paddingname{\tikzumlRequiredInterfaceName-padding}%
+ }%
+ %
+ \edef\tikzumlRequiredInterface@name{#2}%
+ %
+ \begingroup%
+ \def\_{_}\edef\x{\endgroup%
+ \def\noexpand\tikzumlRequiredInterface@nodeName{\tikzumlRequiredInterface@name}}\x%
+ %
+ \begingroup%
+ \def\_{_}\edef\x{\endgroup%
+ \def\noexpand\tikzumlRequiredInterface@interfacenodeName{\tikzumlRequiredInterface@interfacename}}\x%
+ %
+ \begingroup%
+ \def\_{_}\edef\x{\endgroup%
+ \def\noexpand\tikzumlRequiredInterface@portnodeName{\tikzumlRequiredInterface@portname}}\x%
+ %
+ \begingroup%
+ \def\_{_}\edef\x{\endgroup%
+ \def\noexpand\tikzumlRequiredInterface@paddingnodeName{\tikzumlRequiredInterface@paddingname}}\x%
+ %
+ \ifthenelse{\equal{\tikzumlInterfaceWithPort}{tikzumlTrue}}{%
+ \node[inner sep=0.5*\tikzumlRequiredInterfaceWidth, rectangle, draw=\tikzumlRequiredInterfaceDrawColor, fill=\tikzumlRequiredInterfaceFillColor] (\tikzumlRequiredInterface@portnodeName) at (\tikzumlRequiredInterface@nodeName.east) {};%
+ }{%
+ \node[inner sep=0] (\tikzumlRequiredInterface@nodeName-east-port) at (\tikzumlRequiredInterface@nodeName.east) {};%
+ }%
+ \begin{scope}%
+ \draw (\tikzumlRequiredInterface@nodeName)+(\tikzumlRequiredInterfaceDistance,0) node[inner sep=0, text width=\tikzumlRequiredInterfaceWidth, circle, name=\tikzumlRequiredInterface@interfacenodeName-tmp] {};%
+ \clip (\tikzumlRequiredInterface@interfacenodeName-tmp.north) rectangle (\tikzumlRequiredInterface@interfacenodeName-tmp.south -| \tikzumlRequiredInterface@interfacenodeName-tmp.west);%
+ \node[inner sep=0, text width=\tikzumlRequiredInterfaceWidth, circle, draw=\tikzumlRequiredInterfaceDrawColor] (\tikzumlRequiredInterface@interfacenodeName) at (\tikzumlRequiredInterface@interfacenodeName-tmp) {};%
+ \end{scope}%
+ \node[above] at (\tikzumlRequiredInterface@interfacenodeName.north) {\tikzumlRequiredInterfaceLabel};%
+ %
+ \umlrelation[style={tikzuml connector style}, #1]{\tikzumlRequiredInterface@portnodeName}{\tikzumlRequiredInterface@interfacenodeName}%
+ %
+ \draw (\tikzumlRequiredInterface@interfacenodeName)+(\tikzumlRequiredInterfacePadding,0) node[name=\tikzumlRequiredInterface@paddingnodeName] {};%
+ %
+ % add to fit
+ \ifnum\c@tikzumlComponentLevel>0%
+ \def\tikzumlComponentFitTmp{\csname tikzumlComponentFit\tikzumlComponent@parent @@\tikzumlComponent@fitname\endcsname}%
+ \expandafter\xdef\csname tikzumlComponentFit\tikzumlComponent@parent @@\tikzumlComponent@fitname\endcsname{\tikzumlComponentFitTmp (\tikzumlRequiredInterface@paddingnodeName) (\tikzumlRequiredInterface@portnodeName) }%
+ \fi%
+}%
+%
+\newcommand{\umlprovidedinterface}[2][]{%
+ \def\tikzumlInterfaceWithPort{tikzumlFalse}%
+ \pgfkeys{/tikzuml/providedinterfacerelation/.cd, interface/.initial={}, distance/.initial=\tikzumlProvidedInterfaceDefaultDistance,%
+ name/.initial=tikzumlEmpty, width/.initial=\tikzumlProvidedInterfaceDefaultWidth,%
+ padding/.initial=\tikzumlProvidedInterfaceDefaultPadding,%
+ draw/.initial=\tikzumlDefaultDrawColor, fill/.initial=\tikzumlComponentDefaultFillColor,%
+ .unknown/.code={%
+ \let\keyname=\pgfkeyscurrentname%
+ \let\keyvalue=\pgfkeyscurrentvalue%
+ \ifthenelse{\equal{\keyname}{with port}}{%
+ \def\tikzumlInterfaceWithPort{tikzumlTrue}%
+ }{}%
+ }%
+ }%
+ \pgfkeys{/tikzuml/providedinterfacerelation/.cd, #1}%
+ \pgfkeys{/tikzuml/providedinterfacerelation/.cd, interface/.get=\tikzumlProvidedInterfaceLabel,%
+ distance/.get=\tikzumlProvidedInterfaceDistance,%
+ name/.get=\tikzumlProvidedInterfaceName,%
+ width/.get=\tikzumlProvidedInterfaceWidth,%
+ padding/.get=\tikzumlProvidedInterfacePadding,%
+ draw/.get=\tikzumlProvidedInterfaceDrawColor,%
+ fill/.get=\tikzumlProvidedInterfaceFillColor%
+ }%
+ %
+ \ifthenelse{\equal{\tikzumlProvidedInterfaceName}{tikzumlEmpty}}{%
+ \edef\tikzumlProvidedInterface@interfacename{#2-west-interface}%
+ \edef\tikzumlProvidedInterface@portname{#2-west-port}%
+ \edef\tikzumlProvidedInterface@paddingname{#2-west-padding}%
+ }{%
+ \edef\tikzumlProvidedInterface@interfacename{\tikzumlProvidedInterfaceName}%
+ \edef\tikzumlProvidedInterface@portname{\tikzumlProvidedInterfaceName-port}%
+ \edef\tikzumlProvidedInterface@paddingname{\tikzumlProvidedInterfaceName-padding}%
+ }%
+ %
+ \edef\tikzumlProvidedInterface@name{#2}%
+ %
+ \begingroup%
+ \def\_{_}\edef\x{\endgroup%
+ \def\noexpand\tikzumlProvidedInterface@nodeName{\tikzumlProvidedInterface@name}}\x%
+ %
+ \begingroup%
+ \def\_{_}\edef\x{\endgroup%
+ \def\noexpand\tikzumlProvidedInterface@interfacenodeName{\tikzumlProvidedInterface@interfacename}}\x%
+ %
+ \begingroup%
+ \def\_{_}\edef\x{\endgroup%
+ \def\noexpand\tikzumlProvidedInterface@portnodeName{\tikzumlProvidedInterface@portname}}\x%
+ %
+ \begingroup%
+ \def\_{_}\edef\x{\endgroup%
+ \def\noexpand\tikzumlProvidedInterface@paddingnodeName{\tikzumlProvidedInterface@paddingname}}\x%
+ %
+ \ifthenelse{\equal{\tikzumlInterfaceWithPort}{tikzumlTrue}}{%
+ \node[inner sep=0.5*\tikzumlProvidedInterfaceWidth, rectangle, draw=\tikzumlProvidedInterfaceDrawColor, fill=\tikzumlProvidedInterfaceFillColor] (\tikzumlProvidedInterface@portnodeName) at (\tikzumlProvidedInterface@nodeName.west) {};%
+ }{%
+ \node[inner sep=0] (\tikzumlProvidedInterface@portnodeName) at (\tikzumlProvidedInterface@nodeName.west) {};%
+ }%
+ \draw (\tikzumlProvidedInterface@nodeName)+(-\tikzumlProvidedInterfaceDistance,0) node[inner sep=0, text width=\tikzumlProvidedInterfaceWidth, circle, draw=\tikzumlProvidedInterfaceDrawColor, fill=\tikzumlProvidedInterfaceFillColor, name=\tikzumlProvidedInterface@interfacenodeName] {};%
+ \node[above] at (\tikzumlProvidedInterface@interfacenodeName.north)
+ {\tikzumlProvidedInterfaceLabel};%
+ %
+ \umlrelation[style={tikzuml connector style}, #1]{\tikzumlProvidedInterface@portnodeName}{\tikzumlProvidedInterface@interfacenodeName}%
+ %
+ \draw (\tikzumlProvidedInterface@interfacenodeName)+(-\tikzumlProvidedInterfacePadding,0) node[name=\tikzumlProvidedInterface@paddingnodeName] {};%
+ %
+ % add to fit
+ \ifnum\thetikzumlComponentLevel>0%
+ \def\tikzumlComponentFitTmp{\csname tikzumlComponentFit\tikzumlComponent@parent @@\tikzumlComponent@fitname\endcsname}%
+ \expandafter\xdef\csname tikzumlComponentFit\tikzumlComponent@parent @@\tikzumlComponent@fitname\endcsname{\tikzumlComponentFitTmp (\tikzumlProvidedInterface@paddingnodeName) (\tikzumlProvidedInterface@portnodeName) }%
+ \fi%
+}%
+%
+\newlength{\tikzuml@AC@xa}%
+\newlength{\tikzuml@AC@ya}%
+\newlength{\tikzuml@AC@xb}%
+\newlength{\tikzuml@AC@yb}%
+\newlength{\tikzuml@AC@xi}%
+\newlength{\tikzuml@AC@yi}%
+\newlength{\tikzuml@AC@xic}%
+\newlength{\tikzuml@AC@yic}%
+\newlength{\tikzuml@AC@xio}%
+\newlength{\tikzuml@AC@yio}%
+\newlength{\tikzuml@AC@AB}%
+\newlength{\tikzuml@AC@lambda}%
+\newlength{\tikzuml@AC@xtrc}%
+\newlength{\tikzuml@AC@ytrc}%
+\newlength{\tikzuml@AC@xtlc}%
+\newlength{\tikzuml@AC@ytlc}%
+\newlength{\tikzuml@AC@xblc}%
+\newlength{\tikzuml@AC@yblc}%
+\newlength{\tikzuml@AC@xbrc}%
+\newlength{\tikzuml@AC@ybrc}%
+\newlength{\tikzuml@AC@middleArm}%
+%
+\newcommand{\umlassemblyconnectorsymbol}[2]{%
+ \ifthenelse{\NOT\equal{\tikzumlAssemblyConnectorLabel}{}}{%
+ \edef\tikzuml@ACStart@name{#1}%
+ \edef\tikzuml@ACEnd@name{#2}%
+ \edef\tikzuml@AC@width{\tikzumlAssemblyConnectorWidth}%
+ %
+ \begingroup%
+ \def\_{_}\edef\x{\endgroup%
+ \def\noexpand\tikzuml@ACStart@nodeName{\tikzuml@ACStart@name}}\x%
+ %
+ \begingroup%
+ \def\_{_}\edef\x{\endgroup%
+ \def\noexpand\tikzuml@ACEnd@nodeName{\tikzuml@ACEnd@name}}\x%
+ %
+ \begingroup%
+ \def\_{_}\edef\x{\endgroup%
+ \def\noexpand\tikzuml@ACInterface@nodeName{\tikzumlAssemblyConnectorSymbolName}}\x%
+ %
+ \pgfextractx{\tikzuml@AC@xa}{\pgfpointanchor{\tikzuml@ACStart@nodeName}{\tikzumlAssemblyConnectorStartAnchor}}%
+ \pgfextracty{\tikzuml@AC@ya}{\pgfpointanchor{\tikzuml@ACStart@nodeName}{\tikzumlAssemblyConnectorStartAnchor}}%
+ \pgfextractx{\tikzuml@AC@xb}{\pgfpointanchor{\tikzuml@ACEnd@nodeName}{\tikzumlAssemblyConnectorEndAnchor}}%
+ \pgfextracty{\tikzuml@AC@yb}{\pgfpointanchor{\tikzuml@ACEnd@nodeName}{\tikzumlAssemblyConnectorEndAnchor}}%
+ \pgfmathsetlength{\tikzuml@AC@xi}{0.5*\tikzuml@AC@xa+0.5*\tikzuml@AC@xb}%
+ \pgfmathsetlength{\tikzuml@AC@yi}{0.5*\tikzuml@AC@ya+0.5*\tikzuml@AC@yb}%
+ \pgfmathsetlength{\tikzuml@AC@AB}{veclen(\tikzuml@AC@xa-\tikzuml@AC@xb,\tikzuml@AC@ya-\tikzuml@AC@yb)}%
+ \pgfmathsetlength{\tikzuml@AC@lambda}{0.25*\tikzuml@AC@width/\tikzuml@AC@AB}%
+ \pgfmathsetlength{\tikzuml@AC@xic}{\tikzuml@AC@xi-\tikzuml@AC@lambda*(\tikzuml@AC@xb-\tikzuml@AC@xa)}%
+ \pgfmathsetlength{\tikzuml@AC@yic}{\tikzuml@AC@yi-\tikzuml@AC@lambda*(\tikzuml@AC@yb-\tikzuml@AC@ya)}%
+ \pgfmathsetlength{\tikzuml@AC@xio}{\tikzuml@AC@xi+\tikzuml@AC@lambda*(\tikzuml@AC@xb-\tikzuml@AC@xa)}%
+ \pgfmathsetlength{\tikzuml@AC@yio}{\tikzuml@AC@yi+\tikzuml@AC@lambda*(\tikzuml@AC@yb-\tikzuml@AC@ya)}%
+ \node[inner sep=0.5*\tikzuml@AC@width] (\tikzuml@ACInterface@nodeName-interface) at (\tikzuml@AC@xi,\tikzuml@AC@yi) {};%
+ \node[inner sep=0, text width=\tikzuml@AC@width, circle, draw=\tikzumlAssemblyConnectorDrawColor, fill=\tikzumlAssemblyConnectorFillColor] (\tikzuml@ACInterface@nodeName-io) at (\tikzuml@AC@xio,\tikzuml@AC@yio) {};%
+ \begin{scope}%
+ \pgfmathsetlength{\tikzuml@AC@xtrc}{\tikzuml@AC@xic-2*\tikzuml@AC@lambda*(\tikzuml@AC@yb-\tikzuml@AC@ya)}%
+ \pgfmathsetlength{\tikzuml@AC@ytrc}{\tikzuml@AC@yic+2*\tikzuml@AC@lambda*(\tikzuml@AC@xb-\tikzuml@AC@xa)}%
+ \pgfmathsetlength{\tikzuml@AC@xbrc}{\tikzuml@AC@xic+2*\tikzuml@AC@lambda*(\tikzuml@AC@yb-\tikzuml@AC@ya)}%
+ \pgfmathsetlength{\tikzuml@AC@ybrc}{\tikzuml@AC@yic-2*\tikzuml@AC@lambda*(\tikzuml@AC@xb-\tikzuml@AC@xa)}%
+ \pgfmathsetlength{\tikzuml@AC@xtlc}{\tikzuml@AC@xic-3*\tikzuml@AC@lambda*(\tikzuml@AC@yb-\tikzuml@AC@ya+\tikzuml@AC@xb-\tikzuml@AC@xa)}%
+ \pgfmathsetlength{\tikzuml@AC@ytlc}{\tikzuml@AC@yic+3*\tikzuml@AC@lambda*(\tikzuml@AC@xb-\tikzuml@AC@xa+\tikzuml@AC@ya-\tikzuml@AC@yb)}%
+ \pgfmathsetlength{\tikzuml@AC@xblc}{\tikzuml@AC@xic+3*\tikzuml@AC@lambda*(\tikzuml@AC@yb-\tikzuml@AC@ya+\tikzuml@AC@xa-\tikzuml@AC@xb)}%
+ \pgfmathsetlength{\tikzuml@AC@yblc}{\tikzuml@AC@yic-3*\tikzuml@AC@lambda*(\tikzuml@AC@xb-\tikzuml@AC@xa+\tikzuml@AC@yb-\tikzuml@AC@ya)}%
+ \coordinate (\tikzuml@ACInterface@nodeName-trc) at (\tikzuml@AC@xtrc,\tikzuml@AC@ytrc);%
+ \coordinate (\tikzuml@ACInterface@nodeName-brc) at (\tikzuml@AC@xbrc,\tikzuml@AC@ybrc);%
+ \coordinate (\tikzuml@ACInterface@nodeName-tlc) at (\tikzuml@AC@xtlc,\tikzuml@AC@ytlc);%
+ \coordinate (\tikzuml@ACInterface@nodeName-blc) at (\tikzuml@AC@xblc,\tikzuml@AC@yblc);%
+ \clip (\tikzuml@ACInterface@nodeName-trc) -- (\tikzuml@ACInterface@nodeName-tlc) -- (\tikzuml@ACInterface@nodeName-blc) -- (\tikzuml@ACInterface@nodeName-brc) -- cycle;%
+ \node[inner sep=0, text width=\tikzuml@AC@width, circle, draw=\tikzumlAssemblyConnectorDrawColor, fill=\tikzumlAssemblyConnectorFillColor] (\tikzuml@ACInterface@nodeName-ic) at (\tikzuml@AC@xic,\tikzuml@AC@yic) {};%
+ \end{scope}%
+ \node[above, font=\tikzumlDefaultFont] at (\tikzuml@ACInterface@nodeName-interface.north)
+ {\tikzumlAssemblyConnectorLabel};%
+ }{}%
+}%
+%
+\newcommand{\umlassemblyconnector}[3][]{%
+ \def\tikzumlAssemblyConnectorWithPort{tikzumlFalse}%
+ \def\tikzumlAssemblyConnectorFirstArm{tikzumlFalse}%
+ \def\tikzumlAssemblyConnectorSecondArm{tikzumlFalse}%
+ \def\tikzumlAssemblyConnectorMiddleArm{tikzumlFalse}%
+ \def\tikzumlAssemblyConnectorLastArm{tikzumlFalse}%
+ \pgfkeys{/tikzuml/assemblyconnectorrelation/.cd, geometry/.initial=--, interface/.initial={},%
+ arm1/.initial={auto}, arm2/.initial={auto},%
+ name/.initial=connector-\thetikzumlConnectorNum, width/.initial=1em,%
+ anchor1/.initial={}, anchor2/.initial={},%
+ draw/.initial=\tikzumlDefaultDrawColor,%
+ fill assembly connector/.initial=\tikzumlAssemblyConnectorDefaultFillColor,%
+ fill port/.initial=\tikzumlPortDefaultFillColor,%
+ .unknown/.code={%
+ \let\keyname=\pgfkeyscurrentname%
+ \let\keyvalue=\pgfkeyscurrentvalue%
+ \ifthenelse{\equal{\keyname}{with port}}{%
+ \def\tikzumlAssemblyConnectorWithPort{tikzumlTrue}%
+ }{%
+ \ifthenelse{\equal{\keyname}{first arm}}{%
+ \def\tikzumlAssemblyConnectorFirstArm{tikzumlTrue}%
+ }{%
+ \ifthenelse{\equal{\keyname}{second arm}}{%
+ \def\tikzumlAssemblyConnectorSecondArm{tikzumlTrue}%
+ }{%
+ \ifthenelse{\equal{\keyname}{middle arm}}{%
+ \def\tikzumlAssemblyConnectorMiddleArm{tikzumlTrue}%
+ }{%
+ \ifthenelse{\equal{\keyname}{last arm}}{%
+ \def\tikzumlAssemblyConnectorLastArm{tikzumlTrue}%
+ }{%
+ }%
+ }%
+ }%
+ }%
+ }%
+ }%
+ }%
+ \pgfkeys{/tikzuml/assemblyconnectorrelation/.cd, #1}%
+ \pgfkeys{/tikzuml/assemblyconnectorrelation/.cd, geometry/.get=\tikzumlAssemblyConnectorGeometry,%
+ name/.get=\tikzumlAssemblyConnectorName,%
+ interface/.get=\tikzumlAssemblyConnectorLabel,%
+ width/.get=\tikzumlAssemblyConnectorWidth,%
+ arm1/.get=\tikzumlAssemblyConnectorStartArm,%
+ arm2/.get=\tikzumlAssemblyConnectorEndArm,%
+ anchor1/.get=\tikzumlAssemblyConnectorStartAnchorTmp,%
+ anchor2/.get=\tikzumlAssemblyConnectorEndAnchorTmp,%
+ draw/.get=\tikzumlAssemblyConnectorDrawColor,%
+ fill assembly connector/.get=\tikzumlAssemblyConnectorFillColor,%
+ fill port/.get=\tikzumlAssemblyConnectorPortFillColor%
+ }%
+ %
+ \edef\tikzumlAssemblyConnectorStart@name{#2}%
+ \edef\tikzumlAssemblyConnectorEnd@name{#3}%
+ %
+ \begingroup%
+ \def\_{_}\edef\x{\endgroup%
+ \def\noexpand\tikzumlAssemblyConnectorStart@nodeName{\tikzumlAssemblyConnectorStart@name}}\x%
+ %
+ \begingroup%
+ \def\_{_}\edef\x{\endgroup%
+ \def\noexpand\tikzumlAssemblyConnectorEnd@nodeName{\tikzumlAssemblyConnectorEnd@name}}\x%
+ %
+ \begingroup%
+ \def\_{_}\edef\x{\endgroup%
+ \def\noexpand\tikzumlAssemblyConnectorLabel@nodeName{\tikzumlAssemblyConnectorLabel}}\x%
+ %
+ \pgfextractx{\tikzuml@AC@xa}{\pgfpointanchor{\tikzumlAssemblyConnectorStart@nodeName}{center}}%
+ \pgfextracty{\tikzuml@AC@ya}{\pgfpointanchor{\tikzumlAssemblyConnectorStart@nodeName}{center}}%
+ \pgfextractx{\tikzuml@AC@xb}{\pgfpointanchor{\tikzumlAssemblyConnectorEnd@nodeName}{center}}%
+ \pgfextracty{\tikzuml@AC@yb}{\pgfpointanchor{\tikzumlAssemblyConnectorEnd@nodeName}{center}}%
+ %
+ \ifthenelse{\equal{\tikzumlAssemblyConnectorGeometry}{--}}{%
+ \ifthenelse{\tikzuml@AC@xb>\tikzuml@AC@xa}{%
+ \def\tikzumlAssemblyConnectorStartAnchor{east}%
+ \def\tikzumlAssemblyConnectorEndAnchor{west}%
+ }{%
+ \def\tikzumlAssemblyConnectorStartAnchor{west}%
+ \def\tikzumlAssemblyConnectorEndAnchor{east}%
+ }
+ }{}%
+ %
+ \ifthenelse{\equal{\tikzumlAssemblyConnectorGeometry}{-|}}{%
+ \ifthenelse{\tikzuml@AC@xb>\tikzuml@AC@xa}{%
+ \def\tikzumlAssemblyConnectorStartAnchor{east}%
+ }{%
+ \def\tikzumlAssemblyConnectorStartAnchor{west}%
+ }
+ \ifthenelse{\tikzuml@AC@yb>\tikzuml@AC@ya}{%
+ \def\tikzumlAssemblyConnectorEndAnchor{south}%
+ }{%
+ \def\tikzumlAssemblyConnectorEndAnchor{north}%
+ }
+ }{}%
+ %
+ \ifthenelse{\equal{\tikzumlAssemblyConnectorGeometry}{|-}}{%
+ \ifthenelse{\tikzuml@AC@xb>\tikzuml@AC@xa}{%
+ \def\tikzumlAssemblyConnectorEndAnchor{west}%
+ }{%
+ \def\tikzumlAssemblyConnectorEndAnchor{east}%
+ }
+ \ifthenelse{\tikzuml@AC@yb>\tikzuml@AC@ya}{%
+ \def\tikzumlAssemblyConnectorStartAnchor{north}%
+ }{%
+ \def\tikzumlAssemblyConnectorStartAnchor{south}%
+ }
+ }{}%
+ %
+ \ifthenelse{\equal{\tikzumlAssemblyConnectorGeometry}{-|-}}{%
+ \ifthenelse{\equal{\tikzumlAssemblyConnectorStartArm}{auto}}{%
+ \ifthenelse{\equal{\tikzumlAssemblyConnectorEndArm}{auto}}{%
+ \pgfmathsetlength{\tikzuml@AC@middleArm}{0.5 * \tikzuml@AC@xa + 0.5 * \tikzuml@AC@xb}%
+ }{%
+ \pgfmathsetlength{\tikzuml@AC@middleArm}{\tikzuml@AC@xb+\tikzumlAssemblyConnectorEndArm}%
+ }%
+ }{%
+ \pgfmathsetlength{\tikzuml@AC@middleArm}{\tikzuml@AC@xa+\tikzumlAssemblyConnectorStartArm}%
+ }%
+ \pgfmathparse{\tikzuml@AC@middleArm>\tikzuml@AC@xa}
+ \pgfmathparse{\tikzuml@AC@middleArm>\tikzuml@AC@xb}
+ \ifthenelse{\lengthtest{\tikzuml@AC@middleArm>\tikzuml@AC@xa}}{%
+ \def\tikzumlAssemblyConnectorStartAnchor{east}%
+ }{%
+ \def\tikzumlAssemblyConnectorStartAnchor{west}%
+ }
+ \ifthenelse{\lengthtest{\tikzuml@AC@middleArm>\tikzuml@AC@xb}}{%
+ \def\tikzumlAssemblyConnectorEndAnchor{east}%
+ }{%
+ \def\tikzumlAssemblyConnectorEndAnchor{west}%
+ }
+ }{}%
+ %
+ \ifthenelse{\equal{\tikzumlAssemblyConnectorGeometry}{|-|}}{%
+ \ifthenelse{\equal{\tikzumlAssemblyConnectorStartArm}{auto}}{%
+ \ifthenelse{\equal{\tikzumlAssemblyConnectorEndArm}{auto}}{%
+ \pgfmathsetlength{\tikzuml@AC@middleArm}{0.5 * \tikzuml@AC@ya + 0.5 * \tikzuml@AC@yb}%
+ }{%
+ \pgfmathsetlength{\tikzuml@AC@middleArm}{\tikzuml@AC@yb+\tikzumlAssemblyConnectorEndArm}%
+ }%
+ }{%
+ \pgfmathsetlength{\tikzuml@AC@middleArm}{\tikzuml@AC@ya+\tikzumlAssemblyConnectorStartArm}%
+ }%
+ \ifthenelse{\tikzuml@AC@middleArm>\tikzuml@AC@ya}{%
+ \def\tikzumlAssemblyConnectorStartAnchor{north}%
+ }{%
+ \def\tikzumlAssemblyConnectorStartAnchor{south}%
+ }
+ \ifthenelse{\tikzuml@AC@middleArm>\tikzuml@AC@yb}{%
+ \def\tikzumlAssemblyConnectorEndAnchor{north}%
+ }{%
+ \def\tikzumlAssemblyConnectorEndAnchor{south}%
+ }
+ }{}%
+ %
+ \ifthenelse{\equal{\tikzumlAssemblyConnectorStartAnchorTmp}{}}{%
+ }{%
+ \def\tikzumlAssemblyConnectorStartAnchor{\tikzumlAssemblyConnectorStartAnchorTmp}%
+ }%
+ \ifthenelse{\equal{\tikzumlAssemblyConnectorEndAnchorTmp}{}}{%
+ }{%
+ \def\tikzumlAssemblyConnectorEndAnchor{\tikzumlAssemblyConnectorEndAnchorTmp}%
+ }%
+ %
+ \node[inner sep=0] (\tikzumlAssemblyConnectorStart@nodeName-\tikzumlAssemblyConnectorLabel@nodeName-port-tmp) at (\tikzumlAssemblyConnectorStart@nodeName.\tikzumlAssemblyConnectorStartAnchor) {};%
+ \node[inner sep=0] (\tikzumlAssemblyConnectorEnd@nodeName-\tikzumlAssemblyConnectorLabel@nodeName-port-tmp) at (\tikzumlAssemblyConnectorEnd@nodeName.\tikzumlAssemblyConnectorEndAnchor) {};%
+ %
+ \umlrelation[style={tikzuml connector style}, #1]{\tikzumlAssemblyConnectorStart@nodeName-\tikzumlAssemblyConnectorLabel@nodeName-port-tmp}{\tikzumlAssemblyConnectorEnd@nodeName-\tikzumlAssemblyConnectorLabel@nodeName-port-tmp}%
+ %
+ \ifthenelse{\equal{\tikzumlAssemblyConnectorWithPort}{tikzumlTrue}}{%
+ \node[inner sep=0.5*\tikzumlAssemblyConnectorWidth, rectangle, draw=\tikzumlAssemblyConnectorDrawColor, fill=\tikzumlAssemblyConnectorPortFillColor] (\tikzumlAssemblyConnectorStart@nodeName-\tikzumlAssemblyConnectorLabel@nodeName-port) at (\tikzumlAssemblyConnectorStart@nodeName-\tikzumlAssemblyConnectorLabel@nodeName-port-tmp) {};%
+ \node[inner sep=0.5*\tikzumlAssemblyConnectorWidth, rectangle, draw=\tikzumlAssemblyConnectorDrawColor, fill=\tikzumlAssemblyConnectorPortFillColor] (\tikzumlAssemblyConnectorEnd@nodeName-\tikzumlAssemblyConnectorLabel@nodeName-port) at (\tikzumlAssemblyConnectorEnd@nodeName-\tikzumlAssemblyConnectorLabel@nodeName-port-tmp) {};%
+ }{%
+ \node[inner sep=0] (\tikzumlAssemblyConnectorStart@nodeName-\tikzumlAssemblyConnectorLabel@nodeName-port) at (\tikzumlAssemblyConnectorStart@nodeName.\tikzumlAssemblyConnectorStartAnchor) {};%
+ \node[inner sep=0] (\tikzumlAssemblyConnectorEnd@nodeName-\tikzumlAssemblyConnectorLabel@nodeName-port) at (\tikzumlAssemblyConnectorEnd@nodeName.\tikzumlAssemblyConnectorEndAnchor) {};%
+ }%
+ %
+ \addtocounter{tikzumlRelationNum}{-1}%
+ \ifthenelse{\equal{\tikzumlAssemblyConnectorName}{connector-\thetikzumlConnectorNum}}{%
+ \edef\tikzumlAssemblyConnectorName{relation-\thetikzumlRelationNum}%
+ \edef\tikzumlAssemblyConnectorSymbolName{\tikzumlAssemblyConnectorLabel@nodeName}%
+ }{%
+ \edef\tikzumlAssemblyConnectorSymbolName{\tikzumlAssemblyConnectorName}%
+ }%
+ %
+ \stepcounter{tikzumlRelationNum}%
+ %
+ \ifthenelse{\equal{\tikzumlAssemblyConnectorGeometry}{--}}{%
+ \umlassemblyconnectorsymbol{\tikzumlAssemblyConnectorStart@nodeName}{\tikzumlAssemblyConnectorEnd@nodeName}%
+ }{%
+ \ifthenelse{\equal{\tikzumlAssemblyConnectorGeometry}{-|}}{%
+ \ifthenelse{\equal{\tikzumlAssemblyConnectorFirstArm}{tikzumlTrue}}{%
+ \umlassemblyconnectorsymbol{\tikzumlAssemblyConnectorStart@nodeName}{\tikzumlAssemblyConnectorName-2}%
+ }{%
+ \umlassemblyconnectorsymbol{\tikzumlAssemblyConnectorName-2}{\tikzumlAssemblyConnectorEnd@nodeName}%
+ }%
+ }{%
+ \ifthenelse{\equal{\tikzumlAssemblyConnectorGeometry}{|-}}{%
+ \ifthenelse{\equal{\tikzumlAssemblyConnectorFirstArm}{tikzumlTrue}}{%
+ \umlassemblyconnectorsymbol{\tikzumlAssemblyConnectorStart@nodeName}{\tikzumlAssemblyConnectorName-2}%
+ }{%
+ \umlassemblyconnectorsymbol{\tikzumlAssemblyConnectorName-2}{\tikzumlAssemblyConnectorEnd@nodeName}%
+ }%
+ }{%
+ \ifthenelse{\equal{\tikzumlAssemblyConnectorGeometry}{-|-}}{%
+ \ifthenelse{\equal{\tikzumlAssemblyConnectorFirstArm}{tikzumlTrue}}{%
+ \umlassemblyconnectorsymbol{\tikzumlAssemblyConnectorStart@nodeName}{\tikzumlAssemblyConnectorName-2}%
+ }{%
+ \ifthenelse{\equal{\tikzumlAssemblyConnectorLastArm}{tikzumlTrue}}{%
+ \umlassemblyconnectorsymbol{\tikzumlAssemblyConnectorName-4}{\tikzumlAssemblyConnectorEnd@nodeName}%
+ }{%
+ \umlassemblyconnectorsymbol{\tikzumlAssemblyConnectorName-2}{\tikzumlAssemblyConnectorName-4}%
+ }%
+ }%
+ }{%
+ \ifthenelse{\equal{\tikzumlAssemblyConnectorGeometry}{|-|}}{%
+ \ifthenelse{\equal{\tikzumlAssemblyConnectorFirstArm}{tikzumlTrue}}{%
+ \umlassemblyconnectorsymbol{\tikzumlAssemblyConnectorStart@nodeName}{\tikzumlAssemblyConnectorName-2}%
+ }{%
+ \ifthenelse{\equal{\tikzumlAssemblyConnectorLastArm}{tikzumlTrue}}{%
+ \umlassemblyconnectorsymbol{\tikzumlAssemblyConnectorName-4}{\tikzumlAssemblyConnectorEnd@nodeName}%
+ }{%
+ \umlassemblyconnectorsymbol{\tikzumlAssemblyConnectorName-2}{\tikzumlAssemblyConnectorName-4}%
+ }%
+ }%
+ }{}%
+ }%
+ }%
+ }%
+ }%
+ \stepcounter{tikzumlConnectorNum}%
+}%
+%
+% shortcuts of \umlassemblyconnector
+\newcommand{\umlHVassemblyconnector}[3][]{%
+ \pgfkeys{/tikzuml/HVassemblyconnector/.cd,%
+ .unknown/.code={%
+ \let\keyname=\pgfkeyscurrentname%
+ \let\keyvalue=\pgfkeyscurrentvalue%
+ \ifthenelse{\equal{\keyname}{geometry}}{%
+ \errmessage{TIKZUML ERROR : in umlHVassemblyconnector, forbidden option geometry}%
+ }{}%
+ }}%
+ \pgfkeys{/tikzuml/HVassemblyconnector/.cd, #1}%
+ \umlassemblyconnector[geometry=-|, #1]{#2}{#3}%
+}%
+%
+\newcommand{\umlVHassemblyconnector}[3][]{%
+ \pgfkeys{/tikzuml/VHassemblyconnector/.cd,%
+ .unknown/.code={%
+ \let\keyname=\pgfkeyscurrentname%
+ \let\keyvalue=\pgfkeyscurrentvalue%
+ \ifthenelse{\equal{\keyname}{geometry}}{%
+ \errmessage{TIKZUML ERROR : in umlVHassemblyconnector, forbidden option geometry}%
+ }{}%
+ }%
+ }%
+ \pgfkeys{/tikzuml/VHassemblyconnector/.cd, #1}%
+ \umlassemblyconnector[geometry=|-, #1]{#2}{#3}%
+}%
+%
+\newcommand{\umlHVHassemblyconnector}[3][]{%
+ \pgfkeys{/tikzuml/HVHassemblyconnector/.cd,%
+ .unknown/.code={%
+ \let\keyname=\pgfkeyscurrentname%
+ \let\keyvalue=\pgfkeyscurrentvalue%
+ \ifthenelse{\equal{\keyname}{geometry}}{%
+ \errmessage{TIKZUML ERROR : in umlHVHassemblyconnector, forbidden option geometry}%
+ }{}%
+ }}%
+ \pgfkeys{/tikzuml/HVHassemblyconnector/.cd, #1}%
+ \umlassemblyconnector[geometry=-|-, #1]{#2}{#3}%
+}%
+%
+\newcommand{\umlVHVassemblyconnector}[3][]{%
+ \pgfkeys{/tikzuml/VHVassemblyconnector/.cd,%
+ .unknown/.code={%
+ \let\keyname=\pgfkeyscurrentname%
+ \let\keyvalue=\pgfkeyscurrentvalue%
+ \ifthenelse{\equal{\keyname}{geometry}}{%
+ \errmessage{TIKZUML ERROR : in umlVHVassemblyconnector, forbidden option geometry}%
+ }{}%
+ }}%
+ \pgfkeys{/tikzuml/VHVassemblyconnector/.cd, #1}%
+ \umlassemblyconnector[geometry=|-|, #1]{#2}{#3}%
+}%
+%
+\newcommand{\umlport}[3][]{%
+ \pgfkeys{/tikzuml/port/.cd, draw/.initial=\tikzumlDefaultDrawColor, fill/.initial=\tikzumlPortDefaultFillColor,%
+ width/.initial=\tikzumlPortDefaultWidth,%
+ .unknown/.code={%
+ \let\keyname=\pgfkeyscurrentname%
+ \let\keyvalue=\pgfkeyscurrentvalue%
+ \errmessage{TIKZUML ERROR : in umlport forbidden option \keyname}%
+ }%
+ }%
+ \pgfkeys{/tikzuml/port/.cd, #1}%
+ \pgfkeys{/tikzuml/port/.cd, width/.get=\tikzumlPortWidth,%
+ draw/.get=\tikzumlPortDrawColor, fill/.get=\tikzumlPortFillColor}%
+ \edef\tikzumlPort@name{#2}%
+ \edef\tikzumlPort@anchor{#3}%
+ \begingroup%
+ \def\_{_}\edef\x{\endgroup%
+ \def\noexpand\tikzumlPort@nodeName{\tikzumlPort@name}}\x%
+ %
+ \node[inner sep=0.5*\tikzumlPortWidth, rectangle, draw=\tikzumlPortDrawColor, fill=\tikzumlPortFillColor] (\tikzumlPort@nodeName-\tikzumlPort@anchor-port) at (\tikzumlPort@nodeName.\tikzumlPort@anchor) {};%
+}%
+%
+\newcommand{\umldelegateconnector}[3][]{%
+ \def\tikzumlDelegateConnectorWithStartPort{tikzumlFalse}%
+ \def\tikzumlDelegateConnectorWithEndPort{tikzumlFalse}%
+ \pgfkeys{/tikzuml/delegateconnector/.cd,
+ .unknown/.code={%
+ \let\keyname=\pgfkeyscurrentname%
+ \let\keyvalue=\pgfkeyscurrentvalue%
+ \ifthenelse{\equal{\keyname}{stereo}}{%
+ \errmessage{TIKZUML ERROR : in umldelegateconnector, forbidden option stereo}%
+ }{}%
+ }}%
+ \pgfkeys{/tikzuml/delegateconnector/.cd, #1}%
+ \umlrelation[style={tikzuml connector style}, stereo=delegate, #1]{#2}{#3}%
+}%
+%
+% shortcuts of \umldelegateconnector
+\newcommand{\umlHVdelegateconnector}[3][]{%
+ \pgfkeys{/tikzuml/HVdelegateconnector/.cd,%
+ .unknown/.code={%
+ \let\keyname=\pgfkeyscurrentname%
+ \let\keyvalue=\pgfkeyscurrentvalue%
+ \ifthenelse{\equal{\keyname}{geometry}\OR\equal{\keyname}{stereo}}{%
+ \errmessage{TIKZUML ERROR : in umlHVdelegateconnector, forbidden option \keyname}%
+ }{}%
+ }}%
+ \pgfkeys{/tikzuml/HVdelegateconnector/.cd, #1}%
+ \umldelegateconnector[geometry=-|, #1]{#2}{#3}%
+}%
+%
+\newcommand{\umlVHdelegateconnector}[3][]{%
+ \pgfkeys{/tikzuml/VHdelegateconnector/.cd,%
+ .unknown/.code={%
+ \let\keyname=\pgfkeyscurrentname%
+ \let\keyvalue=\pgfkeyscurrentvalue%
+ \ifthenelse{\equal{\keyname}{geometry}\OR\equal{\keyname}{stereo}}{%
+ \errmessage{TIKZUML ERROR : in umlVHdelegateconnector, forbidden option \keyname}%
+ }{}%
+ }}%
+ \pgfkeys{/tikzuml/VHdelegateconnector/.cd, #1}%
+ \umldelegateconnector[geometry=|-, #1]{#2}{#3}%
+}%
+%
+\newcommand{\umlHVHdelegateconnector}[3][]{%
+ \pgfkeys{/tikzuml/HVHdelegateconnector/.cd,%
+ .unknown/.code={%
+ \let\keyname=\pgfkeyscurrentname%
+ \let\keyvalue=\pgfkeyscurrentvalue%
+ \ifthenelse{\equal{\keyname}{geometry}\OR\equal{\keyname}{stereo}}{%
+ \errmessage{TIKZUML ERROR : in umlHVHdelegateconnector, forbidden option \keyname}%
+ }{}%
+ }}%
+ \pgfkeys{/tikzuml/HVHdelegateconnector/.cd, #1}%
+ \umldelegateconnector[geometry=-|-, #1]{#2}{#3}%
+}%
+%
+\newcommand{\umlVHVdelegateconnector}[3][]{%
+ \pgfkeys{/tikzuml/VHVdelegateconnector/.cd,%
+ .unknown/.code={%
+ \let\keyname=\pgfkeyscurrentname%
+ \let\keyvalue=\pgfkeyscurrentvalue%
+ \ifthenelse{\equal{\keyname}{geometry}\OR\equal{\keyname}{stereo}}{%
+ \errmessage{TIKZUML ERROR : in umlVHVdelegateconnector, forbidden option \keyname}%
+ }{}%
+ }}%
+ \pgfkeys{/tikzuml/VHVdelegateconnector/.cd, #1}%
+ \umldelegateconnector[geometry=|-|, #1]{#2}{#3}%
+}%
+%%% End of tikz-uml.sty
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \ No newline at end of file