diff --git a/.c4s/C4.puml b/.c4s/C4.puml new file mode 100644 index 0000000..3d7e330 --- /dev/null +++ b/.c4s/C4.puml @@ -0,0 +1,1658 @@ +' C4-PlantUML + +' Global pre-settings +' ################################## +' ENABLE_ALL_PLANT_ELEMENTS +' If ENABLE_ALL_PLANT_ELEMENTS is set BEFORE the first C4_* file is loaded, nearly "all" PlantUML elements can be used like +' Component(StorageA, "Storage A ", $baseShape="storage") +' ENABLE_ALL_PLANT_ELEMENTS can be set via +' !ENABLE_ALL_PLANT_ELEMENTS = 1 +' or with additional command line argument -DENABLE_ALL_PLANT_ELEMENTS=1 + +'Version +' ################################## +!function C4Version() + ' 2 spaces and ' are used as unique marker, that the release scripts makes the correct version update + !$c4Version = "2.10.0beta1" + !return $c4Version +!end function + +!procedure C4VersionDetails() +rectangle C4VersionDetailsArea <> [ +| PlantUML | **%version()** | +| C4-PlantUML | **C4Version()** | +] +!end procedure + +' Colors +' ################################## +!$ELEMENT_FONT_COLOR ?= "#FFFFFF" + +!$ARROW_COLOR ?= "#666666" +!$ARROW_FONT_COLOR ?= $ARROW_COLOR + +!$BOUNDARY_COLOR ?= "#444444" +!$BOUNDARY_BG_COLOR ?= "transparent" +!$BOUNDARY_BORDER_STYLE ?= "dashed" + +!$LEGEND_TITLE_COLOR ?= "#000000" +!$LEGEND_FONT_COLOR ?= "#FFFFFF" +!$LEGEND_BG_COLOR ?= "transparent" +!$LEGEND_BORDER_COLOR ?= "transparent" +' %darken(darkkhaki,50), #khaki +!$LEGEND_DARK_COLOR ?= "#66622E" +!$LEGEND_LIGHT_COLOR ?= "#khaki" + +!$SKETCH_BG_COLOR ?= "#EEEBDC" +!$SKETCH_FONT_COLOR ?= "" +!$SKETCH_WARNING_COLOR ?= "red" +!$SKETCH_FONT_NAME ?= "Comic Sans MS" + +' Labels +' ################################## + +!$LEGEND_SHADOW_TEXT ?= "shadow" +!$LEGEND_NO_SHADOW_TEXT ?= "no shadow" +!$LEGEND_NO_FONT_BG_TEXT ?= "last text and back color" +!$LEGEND_NO_FONT_TEXT ?= "last text color" +!$LEGEND_NO_BG_TEXT ?= "last back color" +!$LEGEND_NO_LINE_TEXT ?= "last line color" +!$LEGEND_ROUNDED_BOX ?= "rounded box" +!$LEGEND_EIGHT_SIDED ?= "eight sided" +!$LEGEND_DOTTED_LINE ?= "dotted" +!$LEGEND_DASHED_LINE ?= "dashed" +!$LEGEND_BOLD_LINE ?= "bold" +!$LEGEND_SOLID_LINE ?= "solid" + +!$LEGEND_BOUNDARY ?= "boundary" +' ignore (boundary) transparent atm, that the legend is smaller +' !$LEGEND_BOUNDARY_TRANSPARENT_INCL_COMA ?= "transparent, " +!$LEGEND_BOUNDARY_TRANSPARENT_INCL_COMA ?= "" +' (boundary) dashed should not be ignored atm +!$LEGEND_BOUNDARY_DASHED_INCL_COMA ?= "dashed, " +' !$LEGEND_BOUNDARY_DASHED_INCL_COMA ?= "" + +!$LEGEND_THICKNESS ?= "thickness" + +!$SKETCH_FOOTER_WARNING ?= "Warning:" +!$SKETCH_FOOTER_TEXT ?= "Created for discussion, needs to be validated" + +' Styling +' ################################## + +!$STEREOTYPE_FONT_SIZE ?= 12 +!global $TRANSPARENT_STEREOTYPE_FONT_SIZE = $STEREOTYPE_FONT_SIZE/2 +!$TECHN_FONT_SIZE ?= 12 + +!$ARROW_FONT_SIZE ?= 12 + +!$LEGEND_DETAILS_SMALL_SIZE ?= 10 +!$LEGEND_DETAILS_NORMAL_SIZE ?= 14 +!global $LEGEND_DETAILS_SIZE = $LEGEND_DETAILS_SMALL_SIZE + +' element symbols typically 4 times too big in legend +!$LEGEND_IMAGE_SIZE_FACTOR ?= 0.25 + +!$ROUNDED_BOX_SIZE ?= 25 +!$EIGHT_SIDED_SIZE ?= 18 + +' Default element wrap width (of an element) +!$DEFAULT_WRAP_WIDTH ?= 200 +' Maximum size in pixels, of a message (in a sequence diagram?) +!$MAX_MESSAGE_SIZE ?= 150 +' PlantUML supports no DETERMINISTIC/automatic line breaks of "PlantUML line" (C4 Relationships) +' therefore Rel...() implements an automatic line break based on spaces (like in all other objects). +' If a $type contains \n then these are used (and no automatic space based line breaks are done) +' $REL_TECHN_MAX_CHAR_WIDTH defines the automatic line break position +!$REL_TECHN_MAX_CHAR_WIDTH ?= 35 +!$REL_DESCR_MAX_CHAR_WIDTH ?= 32 + +' internal +' ################################## + +!global $ROUNDED_BOX = "roundedBox" +!global $EIGHT_SIDED = "eightSided" + +!global $DOTTED_LINE = "dotted" +!global $DASHED_LINE = "dashed" +!global $BOLD_LINE = "bold" +' solid is not defined in plantUML, but works as reset of all other styles too +!global $SOLID_LINE = "solid" + +!global $LEGEND_DETAILS_NONE = "none" +!global $LEGEND_DETAILS_NORMAL = "normal" +!global $LEGEND_DETAILS_SMALL = "small" + +skinparam defaultTextAlignment center + +skinparam wrapWidth $DEFAULT_WRAP_WIDTH +skinparam maxMessageSize $MAX_MESSAGE_SIZE + +skinparam LegendFontColor $LEGEND_FONT_COLOR +skinparam LegendBackgroundColor $LEGEND_BG_COLOR +skinparam LegendBorderColor $LEGEND_BORDER_COLOR + +skinparam rectangle<> { + backgroundcolor $LEGEND_BG_COLOR + bordercolor $LEGEND_BORDER_COLOR +} + +skinparam rectangle { + StereotypeFontSize $STEREOTYPE_FONT_SIZE +} + +skinparam database { + StereotypeFontSize $STEREOTYPE_FONT_SIZE +} + +skinparam queue { + StereotypeFontSize $STEREOTYPE_FONT_SIZE +} + +skinparam participant { + StereotypeFontSize $STEREOTYPE_FONT_SIZE +} + +skinparam arrow { + Color $ARROW_COLOR + FontColor $ARROW_FONT_COLOR + FontSize $ARROW_FONT_SIZE +} + +skinparam person { + StereotypeFontSize $STEREOTYPE_FONT_SIZE +} + +skinparam actor { + StereotypeFontSize $STEREOTYPE_FONT_SIZE + style awesome +} + +!if %variable_exists("ENABLE_ALL_PLANT_ELEMENTS") +skinparam agent { + StereotypeFontSize $STEREOTYPE_FONT_SIZE +} +skinparam artifact { + StereotypeFontSize $STEREOTYPE_FONT_SIZE +} +skinparam boundary { + StereotypeFontSize $STEREOTYPE_FONT_SIZE +} +skinparam card { + StereotypeFontSize $STEREOTYPE_FONT_SIZE +} +skinparam circle { + StereotypeFontSize $STEREOTYPE_FONT_SIZE +} +skinparam cloud { + StereotypeFontSize $STEREOTYPE_FONT_SIZE +} +skinparam collections { + StereotypeFontSize $STEREOTYPE_FONT_SIZE +} +skinparam control { + StereotypeFontSize $STEREOTYPE_FONT_SIZE +} +skinparam entity { + StereotypeFontSize $STEREOTYPE_FONT_SIZE +} +skinparam file { + StereotypeFontSize $STEREOTYPE_FONT_SIZE +} +skinparam folder { + StereotypeFontSize $STEREOTYPE_FONT_SIZE +} +skinparam frame { + StereotypeFontSize $STEREOTYPE_FONT_SIZE +} +skinparam hexagon { + StereotypeFontSize $STEREOTYPE_FONT_SIZE +} +skinparam interface { + StereotypeFontSize $STEREOTYPE_FONT_SIZE +} +skinparam label { + StereotypeFontSize $STEREOTYPE_FONT_SIZE +} +skinparam stack { + StereotypeFontSize $STEREOTYPE_FONT_SIZE +} +skinparam storage { + StereotypeFontSize $STEREOTYPE_FONT_SIZE +} +skinparam usecase { + StereotypeFontSize $STEREOTYPE_FONT_SIZE +} +skinparam person { + StereotypeFontSize $STEREOTYPE_FONT_SIZE +} +!endif + +' Some boundary skinparams have to be set as package skinparams too (PlantUML uses internal packages) +' UpdateBoundaryStyle() called in boundary section below +skinparam rectangle<> { + StereotypeFontSize $TRANSPARENT_STEREOTYPE_FONT_SIZE + StereotypeFontColor $BOUNDARY_BG_COLOR + BorderStyle $BOUNDARY_BORDER_STYLE +} + +skinparam package { + StereotypeFontSize $TRANSPARENT_STEREOTYPE_FONT_SIZE + StereotypeFontColor $BOUNDARY_BG_COLOR + FontStyle plain + BackgroundColor $BOUNDARY_BG_COLOR +} + +' Legend and Tags +' ################################## +!global $tagDefaultLegend = "" +!global $tagCustomLegend = "" + +' rel specific +!unquoted function $toStereos($tags) + !if (%strlen($tags) == 0) + !return '' + !endif + !$stereos = '' + !$brPos = %strpos($tags, "+") + !while ($brPos >= 0) + !$tag = %substr($tags, 0, $brPos) + !$stereos = $stereos + '<<' + $tag + '>>' +%set_variable_value("$" + $tag + "_LineLegend", %true()) + !$tags = %substr($tags, $brPos+1) + !$brPos = %strpos($tags, "+") + !endwhile + !if (%strlen($tags) > 0) + !$stereos = $stereos + '<<' + $tags + '>>' +%set_variable_value("$" + $tags + "_LineLegend", %true()) + !endif + !return $stereos +!endfunction + +' if $sprite/$techn is an empty argument, try to calculate it via the defined $tag +!unquoted function $toRelArg($arg, $tags, $varPostfix) + !if ($arg > "") + !return $arg + !endif + + !if (%strlen($tags) == 0) + !return $arg + !endif + !$brPos = %strpos($tags, "+") + !while ($brPos >= 0) + !$tag = %substr($tags, 0, $brPos) + !$newArg = %get_variable_value("$" + $tag + $varPostfix) + !if ($newArg > "") + !return $newArg + !endif + !$tags = %substr($tags, $brPos+1) + !$brPos = %strpos($tags, "+") + !endwhile + !if (%strlen($tags) > 0) + !$newArg = %get_variable_value("$" + $tags + $varPostfix) + !if ($newArg > "") + !return $newArg + !endif + !endif + !return $arg +!endfunction + +' element specific (unused are hidden based on mask) +!unquoted function $toStereos($elementType, $tags) + !if (%strlen($tags) == 0) + !$stereos = '<<' + $elementType + '>>' +%set_variable_value("$" + $elementType + "Legend", %true()) + !return $stereos + !endif + !$stereos = '' + !$mask = $resetMask() + !$brPos = %strpos($tags, "+") + !while ($brPos >= 0) + !$tag = %substr($tags, 0, $brPos) + !$stereos = $stereos + '<<' + $tag + '>>' + !$mergedMask = $combineMaskWithTag($mask, $tag) + !if ($mergedMask != $mask) +%set_variable_value("$" + $tag + "Legend", %true()) + !$mask = $mergedMask + !endif + !$tags = %substr($tags, $brPos+1) + !$brPos = %strpos($tags, "+") + !endwhile + !if (%strlen($tags) > 0) + !$stereos = $stereos + '<<' + $tags + '>>' + !$mergedMask = $combineMaskWithTag($mask, $tags) + !if ($mergedMask != $mask) +%set_variable_value("$" + $tags + "Legend", %true()) + !$mask = $mergedMask + !endif + !endif + ' has to be last, otherwise PlantUML overwrites all tag specific skinparams + !$stereos = $stereos + '<<' + $elementType + '>>' + !$mergedMask = $combineMaskWithTag($mask, $elementType) + !if ($mergedMask != $mask) +%set_variable_value("$" + $elementType + "Legend", %true()) + !$mask = $mergedMask + !endif + !return $stereos +!endfunction + +' if $sprite/$techn is an empty argument, try to calculate it via the defined $tag +!unquoted function $toElementArg($arg, $tags, $varPostfix, $elementType) + !if ($arg > "") + !return $arg + !endif + + !if (%strlen($tags) == 0) + !$newArg = %get_variable_value("$" + $elementType + $varPostfix) + !if ($newArg > "") + !return $newArg + !else + !return $arg + !endif + !endif + !$brPos = %strpos($tags, "+") + !while ($brPos >= 0) + !$tag = %substr($tags, 0, $brPos) + !$newArg = %get_variable_value("$" + $tag + $varPostfix) + !if ($newArg > "") + !return $newArg + !endif + !$tags = %substr($tags, $brPos+1) + !$brPos = %strpos($tags, "+") + !endwhile + !if (%strlen($tags) > 0) + !$newArg = %get_variable_value("$" + $tags + $varPostfix) + !if ($newArg > "") + !return $newArg + !endif + !$newArg = %get_variable_value("$" + $elementType + $varPostfix) + !if ($newArg > "") + !return $newArg + !endif + !endif + !return $arg +!endfunction + +' if $value is empty try to load it via variable, optional can it store the calculated value +!function $restoreEmpty($elementType, $property, $value, $store) + !$var = "$" + $elementType + "Restore" + $property + !if ($value == "") + !$value = %get_variable_value($var) + !elseif ($store) + %set_variable_value($var, $value) + !endif + !return $value +!endfunction + +' clear the restore property +!function $clearRestore($elementType, $property) + !$var = "$" + $elementType + "Restore" + $property + %set_variable_value($var, "") + !return "" +!endfunction + +!function $elementTagSkinparams($element, $tagStereo, $bgColor, $fontColor, $borderColor, $shadowing, $shape, $borderStyle, $borderThickness) + !$elementSkin = "skinparam " + $element + "<<" + $tagStereo + ">> {" + %newline() + !if ($fontColor != "") + !if (%strpos($tagStereo, "boundary") < 0) + !$elementSkin = $elementSkin + " StereotypeFontColor " + $fontColor + %newline() + !endif + !$elementSkin = $elementSkin + " FontColor " + $fontColor + %newline() + !endif + !if ($bgColor != "") + !$elementSkin = $elementSkin + " BackgroundColor " + $bgColor + %newline() + !endif + !if ($borderColor != "") + !$elementSkin = $elementSkin + " BorderColor " + $borderColor+ %newline() + !endif + !if ($shadowing == "true") + !$elementSkin = $elementSkin + " Shadowing<<" + $tagStereo + ">> " + "true" + %newline() + !endif + !if ($shadowing == "false") + !$elementSkin = $elementSkin + " Shadowing<<" + $tagStereo + ">> " + "false" + %newline() + !endif + ' only rectangle supports shape(d corners), define both skinparam that overlays are working + !if ($shape != "" && $element == "rectangle") + !if ($shape == $ROUNDED_BOX) + !$elementSkin = $elementSkin + " RoundCorner " + $ROUNDED_BOX_SIZE+ %newline() + !$elementSkin = $elementSkin + " DiagonalCorner " + "0" + %newline() + !elseif ($shape == $EIGHT_SIDED) + !$elementSkin = $elementSkin + " RoundCorner " + "0" + %newline() + !$elementSkin = $elementSkin + " DiagonalCorner " + $EIGHT_SIDED_SIZE+ %newline() + !endif + !endif + !if ($borderStyle != "") + !$elementSkin = $elementSkin + " BorderStyle " + $borderStyle + %newline() + !endif + !if ($borderThickness != "") + !$elementSkin = $elementSkin + " BorderThickness " + $borderThickness + %newline() + !endif + !$elementSkin = $elementSkin + "}" + %newline() + !return $elementSkin +!endfunction + +!unquoted procedure $defineSkinparams($tagStereo, $bgColor, $fontColor, $borderColor, $shadowing, $shape, $borderStyle, $borderThickness) + ' only rectangle supports shape(d corners) + !$tagSkin = $elementTagSkinparams("rectangle", $tagStereo, $bgColor, $fontColor, $borderColor, $shadowing, $shape, $borderStyle, $borderThickness) + !$tagSkin = $tagSkin + $elementTagSkinparams("database", $tagStereo, $bgColor, $fontColor, $borderColor, $shadowing, "", $borderStyle, $borderThickness) + !$tagSkin = $tagSkin + $elementTagSkinparams("queue", $tagStereo, $bgColor, $fontColor, $borderColor, $shadowing, "", $borderStyle, $borderThickness) + ' plantuml.jar bug - actor have to be after person + !$tagSkin = $tagSkin + $elementTagSkinparams("person", $tagStereo, $bgColor, $fontColor, $borderColor, $shadowing, "", $borderStyle, $borderThickness) + ' actor has style awesome, therefore $fontColor is ignored and text uses $bgColor too + !$tagSkin = $tagSkin + $elementTagSkinparams("actor", $tagStereo, $bgColor, $bgColor, $borderColor, $shadowing, "", $borderStyle, $borderThickness) + ' sequence requires participant + !$tagSkin = $tagSkin + $elementTagSkinparams("participant", $tagStereo, $bgColor, $fontColor, $borderColor, $shadowing, "", $borderStyle, $borderThickness) + !$tagSkin = $tagSkin + $elementTagSkinparams("sequencebox", $tagStereo, $bgColor, $fontColor, $borderColor, $shadowing, "", $borderStyle, $borderThickness) + !if (%strpos($tagStereo, "boundary") >= 0 && $bgColor != "") + !$tagSkin = $tagSkin + "skinparam package<<" + $tagStereo + ">>StereotypeFontColor " + $bgColor + %newline() + !$tagSkin = $tagSkin + "skinparam rectangle<<" + $tagStereo + ">>StereotypeFontColor " + $bgColor + %newline() + !endif + !if %variable_exists("ENABLE_ALL_PLANT_ELEMENTS") + !$tagSkin = $tagSkin + $elementTagSkinparams("agent", $tagStereo, $bgColor, $fontColor, $borderColor, $shadowing, "", $borderStyle, $borderThickness) + !$tagSkin = $tagSkin + $elementTagSkinparams("artifact", $tagStereo, $bgColor, $fontColor, $borderColor, $shadowing, "", $borderStyle, $borderThickness) + !$tagSkin = $tagSkin + $elementTagSkinparams("card", $tagStereo, $bgColor, $fontColor, $borderColor, $shadowing, "", $borderStyle, $borderThickness) + !$tagSkin = $tagSkin + $elementTagSkinparams("cloud", $tagStereo, $bgColor, $fontColor, $borderColor, $shadowing, "", $borderStyle, $borderThickness) + !$tagSkin = $tagSkin + $elementTagSkinparams("collections", $tagStereo, $bgColor, $fontColor, $borderColor, $shadowing, "", $borderStyle, $borderThickness) + !$tagSkin = $tagSkin + $elementTagSkinparams("file", $tagStereo, $bgColor, $fontColor, $borderColor, $shadowing, "", $borderStyle, $borderThickness) + !$tagSkin = $tagSkin + $elementTagSkinparams("folder", $tagStereo, $bgColor, $fontColor, $borderColor, $shadowing, "", $borderStyle, $borderThickness) + !$tagSkin = $tagSkin + $elementTagSkinparams("frame", $tagStereo, $bgColor, $fontColor, $borderColor, $shadowing, "", $borderStyle, $borderThickness) + !$tagSkin = $tagSkin + $elementTagSkinparams("hexagon", $tagStereo, $bgColor, $fontColor, $borderColor, $shadowing, "", $borderStyle, $borderThickness) + !$tagSkin = $tagSkin + $elementTagSkinparams("package", $tagStereo, $bgColor, $fontColor, $borderColor, $shadowing, "", $borderStyle, $borderThickness) + !$tagSkin = $tagSkin + $elementTagSkinparams("stack", $tagStereo, $bgColor, $fontColor, $borderColor, $shadowing, "", $borderStyle, $borderThickness) + !$tagSkin = $tagSkin + $elementTagSkinparams("storage", $tagStereo, $bgColor, $fontColor, $borderColor, $shadowing, "", $borderStyle, $borderThickness) + !$tagSkin = $tagSkin + $elementTagSkinparams("usecase", $tagStereo, $bgColor, $fontColor, $borderColor, $shadowing, "", $borderStyle, $borderThickness) + ' elements without background: font uses $bgColor + !$tagSkin = $tagSkin + $elementTagSkinparams("boundary", $tagStereo, $bgColor, $bgColor, $borderColor, $shadowing, "", $borderStyle, $borderThickness) + !$tagSkin = $tagSkin + $elementTagSkinparams("circle", $tagStereo, $bgColor, $bgColor, $borderColor, $shadowing, "", $borderStyle, $borderThickness) + !$tagSkin = $tagSkin + $elementTagSkinparams("control", $tagStereo, $bgColor, $bgColor, $borderColor, $shadowing, "", $borderStyle, $borderThickness) + !$tagSkin = $tagSkin + $elementTagSkinparams("entity", $tagStereo, $bgColor, $bgColor, $borderColor, $shadowing, "", $borderStyle, $borderThickness) + !$tagSkin = $tagSkin + $elementTagSkinparams("interface", $tagStereo, $bgColor, $bgColor, $borderColor, $shadowing, "", $borderStyle, $borderThickness) + ' label uses wrong font color? (should be $bgColor too) + !$tagSkin = $tagSkin + $elementTagSkinparams("label", $tagStereo, $bgColor, $bgColor, $borderColor, $shadowing, "", $borderStyle, $borderThickness) + !endif +$tagSkin +!endprocedure + +' arrow colors cannot start with # (legend background has to start with #) +!function $colorWithoutHash($c) + !if (%substr($c, 0, 1) == "#") + !$c = %substr($c,1) + !endif + !return $c +!endfunction + +!unquoted procedure $defineRelSkinparams($tagStereo, $textColor, $lineColor, $lineStyle, $lineThickness) + !$elementSkin = "skinparam arrow<<" + $tagStereo + ">> {" + %newline() + !if ($lineColor != "") || ($textColor != "") || ($lineStyle != "") + !$elementSkin = $elementSkin + " Color " + !if ($lineColor != "") + !$elementSkin = $elementSkin + $colorWithoutHash($lineColor) + !endif + !if ($textColor != "") + !$elementSkin = $elementSkin + ";text:" + $colorWithoutHash($textColor) + !endif + !if ($lineStyle != "") + !$elementSkin = $elementSkin + ";line." + $lineStyle + !endif + !$elementSkin = $elementSkin + %newline() + !endif + !if ($lineThickness != "") + !$elementSkin = $elementSkin + " thickness " + $lineThickness + %newline() + !endif + !$elementSkin = $elementSkin + "}" + %newline() +$elementSkin +!endprocedure + +' %is_dark() requires PlantUML version >= 1.2021.6 +!if (%function_exists("%is_dark")) + !$PlantUMLSupportsDynamicLegendColor = %true() +!else + !$PlantUMLSupportsDynamicLegendColor = %false() + !log "dynamic undefined legend colors" requires PlantUML version >= 1.2021.6, therefore only static assigned colors are used +!endif + +!unquoted function $contrastLegend($color) + !if (%is_dark($color)) + !$value = $LEGEND_LIGHT_COLOR + !else + !$value = $LEGEND_DARK_COLOR + !endif + !return $value +!endfunction + +!unquoted function $flatLegend($color) + !if (%is_dark($color)) + !$value = $LEGEND_DARK_COLOR + !else + !$value = $LEGEND_LIGHT_COLOR + !endif + !return $value +!endfunction + +' legend background has to start with # +!function $colorWithHash($c) + !if (%substr($c, 0, 1) != "#") + !$c = "#" + $c + !endif + !return $c +!endfunction + +!function $addMaskFlag($mask, $attr) + !if ($attr == "") + !$mask = $mask + "0" + !else + !$mask = $mask + "1" + !endif + !return $mask +!endfunction + +!function $orFlags($flag1, $flag2) + !if ($flag1 == "0" && $flag2 == "0") + !return "0" + !endif + !return "1" +!endfunction + +!function $tagLegendMask($bgColor, $fontColor, $borderColor, $shadowing, $shape, $sprite, $borderStyle, $borderThickness) + !$mask = "" + !$mask = $addMaskFlag($mask, $bgColor) + !$mask = $addMaskFlag($mask, $fontColor) + !$mask = $addMaskFlag($mask, $borderColor) + !$mask = $addMaskFlag($mask, $shadowing) + !$mask = $addMaskFlag($mask, $shape) + !$mask = $addMaskFlag($mask, $sprite) + !$mask = $addMaskFlag($mask, $borderStyle) + !$mask = $addMaskFlag($mask, $borderThickness) + !return $mask +!endfunction + +!function $resetMask() + !return "00000000" +!endfunction + +!function $combineMasks($mask1, $mask2) + !$mask = "" + !$mask = $mask + $orFlags(%substr($mask1, 0, 1), %substr($mask2, 0, 1)) + !$mask = $mask + $orFlags(%substr($mask1, 1, 1), %substr($mask2, 1, 1)) + !$mask = $mask + $orFlags(%substr($mask1, 2, 1), %substr($mask2, 2, 1)) + !$mask = $mask + $orFlags(%substr($mask1, 3, 1), %substr($mask2, 3, 1)) + !$mask = $mask + $orFlags(%substr($mask1, 4, 1), %substr($mask2, 4, 1)) + !$mask = $mask + $orFlags(%substr($mask1, 5, 1), %substr($mask2, 5, 1)) + !$mask = $mask + $orFlags(%substr($mask1, 6, 1), %substr($mask2, 6, 1)) + !$mask = $mask + $orFlags(%substr($mask1, 7, 1), %substr($mask2, 7, 1)) + !return $mask +!endfunction + +!function $combineMaskWithTag($mask1, $tag) + !$mask2 = %get_variable_value("$" + $tag+ "LegendMask") + !if ($mask2 == "") + ' !log combineMaskWithTag $mask1, $tag, ... only $mask1 + !return $mask1 + !endif + + ' !log combineMaskWithTag $mask1, $tag, $mask2 ... $combineMasks($mask1, $mask2) + !return $combineMasks($mask1, $mask2) +!endfunction + +' element symbols typically 4 times too big in legend +!function $smallVersionSprite($sprite) + ' ,scale= ... has to be first (...,color=black,scale=0.25... is invalid too) + !if (%strpos($sprite, "=") < 0) + !if (%substr($sprite, 0, 4) == "img:") + !$smallSprite = $sprite + "{scale=" + $LEGEND_IMAGE_SIZE_FACTOR + "}" + !else + !$smallSprite = $sprite + ",scale=" + $LEGEND_IMAGE_SIZE_FACTOR + !endif + !else + !$smallSprite = $sprite + !endif + !return $smallSprite +!endfunction + +' format sprite that it can be used in diagram +!function $getSprite($sprite) + ' if it starts with & it's a OpenIconic, details see https://useiconic.com/open/ + ' if it starts with img: it's an image, details see https://plantuml.com/creole + !if (%substr($sprite, 0, 1) != "&" && %substr($sprite, 0, 4) != "img:") + !$formatted = "<$" + $sprite + ">" + !else + !$formatted = "<" + $sprite + ">" + !endif + !return $formatted +!endfunction + +!function $setTagLegendVariables($tagStereo, $bgColor, $fontColor, $borderColor, $shadowing, $shape, $legendText, $legendSprite, $borderStyle, $borderThickness) + !$bg = $bgColor + !$fo = $fontColor + !$bo = $borderColor + + !if ($fo == "") + !if ($bg != "") +!if ($PlantUMLSupportsDynamicLegendColor) + !$fo = $contrastLegend($bg) +!else + !$fo = $LEGEND_DARK_COLOR +!endif + !else + !if ($bo == "") + !$fo = $LEGEND_DARK_COLOR + !$bg = $LEGEND_LIGHT_COLOR + !else +!if ($PlantUMLSupportsDynamicLegendColor) + !$fo = $flatLegend($bo) + !$bg = $contrastLegend($bo) +!else + !$fo = $LEGEND_DARK_COLOR + !$bg = $LEGEND_LIGHT_COLOR +!endif + !endif + !endif + !else + !if ($bg == "") +!if ($PlantUMLSupportsDynamicLegendColor) + !$bg = $contrastLegend($fo) +!else + !$bg = $LEGEND_LIGHT_COLOR +!endif + !endif + !endif + + !if ($bo == "") + !$bo = $bg + !endif + + !$tagEntry = "|" + !$tagDetails = "(" + !$tagEntry = $tagEntry + "<" + $colorWithHash($bg) +">" + ' ..white rectangle + !$tagEntry = $tagEntry + " " + !$tagEntry = $tagEntry + "" + !if ($legendSprite != "") + !$tagEntry = $tagEntry + $getSprite($legendSprite) + " " + !endif + + !$isBoundary = 0 + !if ($legendText == "") + !if (%strpos($tagStereo, "boundary") >= 0) + !if ($tagStereo == "boundary") + !$isBoundary = 1 + !$tagEntry = $tagEntry + " " + $LEGEND_BOUNDARY + " " + !else + ' if contains/ends with _boundary remove _boundary and add "boundary (dashed)" + !$pos = %strpos($tagStereo, "_boundary") + !if ($pos > 0) + !$isBoundary = 1 + !$tagEntry = $tagEntry + " " + %substr($tagStereo, 0 ,$pos) + " " +$LEGEND_BOUNDARY + " " + !endif + !endif + !endif + !if ($isBoundary == 0) + !$tagEntry = $tagEntry + " " + $tagStereo + " " + !endif + + !if ($isBoundary == 1 && ($bgColor == "#00000000" || %lower($bgColor) == "transparent")) + !$tagDetails = $tagDetails + $LEGEND_BOUNDARY_TRANSPARENT_INCL_COMA + !endif + !if ($shadowing == "true") + !$tagDetails = $tagDetails + $LEGEND_SHADOW_TEXT + ", " + !endif + !if ($shadowing == "false") + !$tagDetails = $tagDetails + $LEGEND_NO_SHADOW_TEXT + ", " + !endif + !if ($shape == $ROUNDED_BOX) + !$tagDetails = $tagDetails + $LEGEND_ROUNDED_BOX + ", " + !endif + !if ($shape == $EIGHT_SIDED) + !$tagDetails = $tagDetails + $LEGEND_EIGHT_SIDED + ", " + !endif + !if ($fontColor == "" && $bgColor == "") + !$tagDetails = $tagDetails + $LEGEND_NO_FONT_BG_TEXT + ", " + !else + !if ($fontColor == "") + !$tagDetails = $tagDetails + $LEGEND_NO_FONT_TEXT + ", " + !endif + !if ($bgColor == "") + !$tagDetails = $tagDetails + $LEGEND_NO_BG_TEXT + ", " + !endif + !endif + !if ($borderStyle != "") + !if ($borderStyle == $DOTTED_LINE) + !$tagDetails = $tagDetails + $LEGEND_DOTTED_LINE + ", " + !elseif ($borderStyle == $DASHED_LINE) + !if ($isBoundary == 1) + !$tagDetails = $tagDetails + $LEGEND_BOUNDARY_DASHED_INCL_COMA + !else + !$tagDetails = $tagDetails + $LEGEND_DASHED_LINE + ", " + !endif + !elseif ($borderStyle == $BOLD_LINE) + !$tagDetails = $tagDetails + $LEGEND_BOLD_LINE + ", " + !elseif ($borderStyle == $SOLID_LINE) + !$tagDetails = $tagDetails + $LEGEND_SOLID_LINE + ", " + !else + !$tagDetails = $tagDetails + $lineStyle + ", " + !endif + !endif + !if ($borderThickness != "") + !$tagDetails = $tagDetails + $LEGEND_THICKNESS + " " + $borderThickness + ", " + !endif + !if ($tagDetails=="(" || $tagDetails=="(, ") + !$tagDetails = "" + !else + !$tagDetails = %substr($tagDetails, 0, %strlen($tagDetails)-2) + !$tagDetails = $tagDetails + ")" + !endif + !else + !$brPos = %strpos($legendText, "\n") + !if ($brPos > 0) + !$tagEntry = $tagEntry + %substr($legendText, 0, $brPos) + " " + !$details = %substr($legendText, $brPos + 2) + !if ($details=="") + !$tagDetails = "" + !else + !$tagDetails = $tagDetails + $details + ")" + !endif + !else + !$tagEntry = $tagEntry + " " + $legendText + " " + !$tagDetails = "" + !endif + !endif + + !$tagDetails = $tagDetails + " " + !$tagDetails = $tagDetails + "|" +%set_variable_value("$" + $tagStereo + "LegendEntry", $tagEntry) +%set_variable_value("$" + $tagStereo + "LegendDetails", $tagDetails) + !return $tagEntry +!endfunction + +!function $setTagRelLegendVariables($tagStereo, $textColor, $lineColor, $lineStyle, $legendText, $legendSprite, $lineThickness) + !$tc = $textColor + !$lc = $lineColor + + !if ($tc == "") + !if ($PlantUMLSupportsDynamicLegendColor) + !$tc = $flatLegend($ARROW_FONT_COLOR) + !else + !$tc = $LEGEND_DARK_COLOR + !endif + !endif + !if ($lc == "") + !if ($PlantUMLSupportsDynamicLegendColor) + !$lc = $flatLegend($ARROW_COLOR) + !else + !$lc = $LEGEND_DARK_COLOR + !endif + !endif + + !$tagEntry = "|" + !$tagDetails = "(" + ' ..white line + !$tagEntry = $tagEntry + " " + !$tagEntry = $tagEntry + "" + !if ($legendSprite != "") + !$tagEntry = $tagEntry + $getSprite($legendSprite) + " " + !endif + !if ($legendText == "") + !$tagEntry = $tagEntry + " " + $tagStereo + " " + !if ($textColor == "") + !$tagDetails = $tagDetails + $LEGEND_NO_FONT_TEXT + ", " + !endif + !if ($lineColor == "") + !$tagDetails = $tagDetails + $LEGEND_NO_LINE_TEXT + ", " + !endif + !if ($lineStyle != "") + !if ($lineStyle == $DOTTED_LINE) + !$tagDetails = $tagDetails + $LEGEND_DOTTED_LINE + ", " + !elseif ($lineStyle == $DASHED_LINE) + !$tagDetails = $tagDetails + $LEGEND_DASHED_LINE + ", " + !elseif ($lineStyle == $BOLD_LINE) + !$tagDetails = $tagDetails + $LEGEND_BOLD_LINE + ", " + !else + !$tagDetails = $tagDetails + $lineStyle + ", " + !endif + !endif + !if ($lineThickness != "") + !$tagDetails = $tagDetails + $LEGEND_THICKNESS + " " + $lineThickness + ", " + !endif + !if ($tagDetails=="(") + !$tagDetails = "" + !else + !$tagDetails = %substr($tagDetails, 0, %strlen($tagDetails)-2) + !$tagDetails = $tagDetails + ")" + !endif + !else + !$brPos = %strpos($legendText, "\n") + !if ($brPos > 0) + !$tagEntry = $tagEntry + " " + %substr($legendText, 0, $brPos) + " " + !$details = %substr($legendText, $brPos + 2) + !if ($details=="") + !$tagDetails = "" + !else + !$tagDetails = $tagDetails + $details + ")" + !endif + !else + !$tagEntry = $tagEntry + " " + $legendText + " " + !$tagDetails = "" + !endif + !endif + + !$tagDetails = $tagDetails + " " + !$tagDetails = $tagDetails + "|" +%set_variable_value("$" + $tagStereo + "_LineLegendEntry", $tagEntry) +%set_variable_value("$" + $tagStereo + "_LineLegendDetails", $tagDetails) + !return $tagEntry +!endfunction + +!unquoted procedure $addTagToLegend($tagStereo, $bgColor="", $fontColor="", $borderColor="", $shadowing="", $shape="", $legendText="", $legendSprite="", $borderStyle="", $borderThickness="") +'' if a combined element tag is defined (e.g. "v1.0&v1.1") then it is typically a merged color, +'' like a new $fontColor="#fdae61" therefore it should be added to the legend +'' and the & combined tags will be not removed +' !if (%strpos($tagStereo, "&") < 0) + !$dummyAlreadyVariables = $setTagLegendVariables($tagStereo, $bgColor, $fontColor, $borderColor, $shadowing, $shape, $legendText, $legendSprite, $borderStyle, $borderThickness) + !$tagCustomLegend = $tagCustomLegend + $tagStereo + "\n" + !$tagMask = $tagLegendMask( $bgColor, $fontColor, $borderColor, $shadowing, $shape, $sprite, $borderStyle, $borderThickness) +%set_variable_value("$" + $tagStereo + "LegendMask", $tagMask) +' !endif +!endprocedure + +!unquoted procedure $addRelTagToLegend($tagStereo, $textColor="", $lineColor="", $lineStyle="", $legendText="", $legendSprite="", $lineThickness="") +'' Arrows have a bug with stereotype/skinparams and cannot combine text colors of one stereotype +'' and the line color of another stereotype. Therefore the text color of one tag and the line color +'' of another tag have to be combined via a "workaround" tag ("v1.0&v1.1"). +'' This workaround tag could be theoretically removed in the legend but after that there would +'' be an inconsistency between the element tags and the rel tags and therefore +'' & combined workaround tags are not removed too (and in unlikely cases the color itself could be changed) +' !if (%strpos($tagStereo, "&") < 0) + !$dummyAlreadyVariables = $setTagRelLegendVariables($tagStereo, $textColor, $lineColor, $lineStyle, $legendText, $legendSprite, $lineThickness) + !$tagCustomLegend = $tagCustomLegend + $tagStereo + "_Line\n" +' !endif +!endprocedure + +!procedure $showActiveLegendEntries($allDefined) + !$brPos = %strpos($allDefined, "\n") + !while ($brPos >= 0) + !$tagStereo = %substr($allDefined, 0, $brPos) + !$allDefined = %substr($allDefined, $brPos+2) + !$brPos = %strpos($allDefined, "\n") + !if (%variable_exists("$" + $tagStereo + "Legend")) + ' is part of legendDetails + !$part1 = %get_variable_value("$" + $tagStereo + "LegendEntry") + !$partSize = "" + !$part2 = %get_variable_value("$" + $tagStereo + "LegendDetails") + !$line = $part1 + $partSize + $part2 +$line + !endif + !endwhile + !if (%strlen($allDefined) > 0) + !$tagStereo = $allDefined + !if (%variable_exists("$" + $tagStereo + "Legend")) + ' is part of legendDetails + !$part1 = %get_variable_value("$" + $tagStereo + "LegendEntry") + !$partSize = "" + !$part2 = %get_variable_value("$" + $tagStereo + "LegendDetails") + !$line = $part1 + $partSize + $part2 +$line + !endif + !endif +!endprocedure + +!function RoundedBoxShape() +!return $ROUNDED_BOX +!endfunction + +!function EightSidedShape() +!return $EIGHT_SIDED +!endfunction + +!function DottedLine() +!return $DOTTED_LINE +!endfunction + +!function DashedLine() +!return $DASHED_LINE +!endfunction + +!function BoldLine() +!return $BOLD_LINE +!endfunction + +!function SolidLine() +!return $SOLID_LINE +!endfunction + +' used by new defined tags +!unquoted procedure AddElementTag($tagStereo, $bgColor="", $fontColor="", $borderColor="", $shadowing="", $shape="", $sprite="", $techn="", $legendText="", $legendSprite="", $borderStyle="", $borderThickness="") +$defineSkinparams($tagStereo, $bgColor, $fontColor, $borderColor, $shadowing, $shape, $borderStyle, $borderThickness) + !if ($sprite!="") +%set_variable_value("$" + $tagStereo + "ElementTagSprite", $sprite) + !if ($legendSprite == "") + !$legendSprite = $smallVersionSprite($sprite) + !endif + !endif + !if ($techn != "") +%set_variable_value("$" + $tagStereo + "ElementTagTechn", $techn) + !endif +$addTagToLegend($tagStereo, $bgColor, $fontColor, $borderColor, $shadowing, $shape, $legendText, $legendSprite, $borderStyle, $borderThickness) +!endprocedure + +!unquoted procedure $addElementTagInclReuse($elementName, $tagStereo, $bgColor="", $fontColor="", $borderColor="", $shadowing="", $shape="", $sprite="", $techn="", $legendText="", $legendSprite="", $borderStyle="", $borderThickness="") + !$bgColor=$restoreEmpty($elementName, "bgColor", $bgColor, %false()) + !$fontColor=$restoreEmpty($elementName, "fontColor", $fontColor, %false()) + !$borderColor=$restoreEmpty($elementName, "borderColor", $borderColor, %false()) + !$shadowing=$restoreEmpty($elementName, "shadowing", $shadowing, %false()) + !$shape=$restoreEmpty($elementName, "shape", $shape, %false()) + !$sprite=$restoreEmpty($elementName, "sprite", $sprite, %false()) + !$techn=$restoreEmpty($elementName, "techn", $techn, %false()) + ' new style should has its own legend text + ' !$legendText=$restoreEmpty($elementName, "legendText", $legendText, %false()) + !$legendSprite=$restoreEmpty($elementName, "legendSprite", $legendSprite, %false()) + !$borderStyle=$restoreEmpty($elementName, "borderStyle", $borderStyle, %false()) + !$borderThickness=$restoreEmpty($elementName, "borderThickness", $borderThickness, %false()) + + AddElementTag($tagStereo, $bgColor, $fontColor, $borderColor, $shadowing, $shape, $sprite, $techn, $legendText, $legendSprite, $borderStyle, $borderThickness) +!endprocedure + +' used by new defined rel tags +!unquoted procedure AddRelTag($tagStereo, $textColor="", $lineColor="", $lineStyle="", $sprite="", $techn="", $legendText="", $legendSprite="", $lineThickness="") +$defineRelSkinparams($tagStereo, $textColor, $lineColor, $lineStyle, $lineThickness) + !if ($sprite != "") +%set_variable_value("$" + $tagStereo + "RelTagSprite", $sprite) + !if ($legendSprite == "") + ' relation symbols typically 1:1 no additional scale required + !$legendSprite = $sprite + !endif + !endif + !if ($techn != "") +%set_variable_value("$" + $tagStereo + "RelTagTechn", $techn) + !endif +$addRelTagToLegend($tagStereo, $textColor, $lineColor, $lineStyle, $legendText, $legendSprite, $lineThickness) +!endprocedure + +' update the style of existing elements like person, ... +!unquoted procedure UpdateElementStyle($elementName, $bgColor="", $fontColor="", $borderColor="", $shadowing="", $shape="", $sprite="", $techn="", $legendText="", $legendSprite="", $borderStyle="", $borderThickness="") +!$bgColor=$restoreEmpty($elementName, "bgColor", $bgColor, %true()) +!$fontColor=$restoreEmpty($elementName, "fontColor", $fontColor, %true()) +!$borderColor=$restoreEmpty($elementName, "borderColor", $borderColor, %true()) +!$shadowing=$restoreEmpty($elementName, "shadowing", $shadowing, %true()) +!$shape=$restoreEmpty($elementName, "shape", $shape, %true()) +!$sprite=$restoreEmpty($elementName, "sprite", $sprite, %true()) +!$techn=$restoreEmpty($elementName, "techn", $techn, %true()) +!$legendText=$restoreEmpty($elementName, "legendText", $legendText, %true()) +!$legendSprite=$restoreEmpty($elementName, "legendSprite", $legendSprite, %true()) +!$borderStyle=$restoreEmpty($elementName, "borderStyle", $borderStyle, %true()) +!$borderThickness=$restoreEmpty($elementName, "borderThickness", $borderThickness, %true()) + +$defineSkinparams($elementName, $bgColor, $fontColor, $borderColor, $shadowing, $shape, $borderStyle, $borderThickness) + !if ($sprite != "") +%set_variable_value("$" + $elementName + "ElementTagSprite", $sprite) + !if ($legendSprite == "") + !$legendSprite = $smallVersionSprite($sprite) + !endif + !endif + !if ($techn != "") +%set_variable_value("$" + $elementName + "ElementTagTechn", $techn) + !endif + !$dummyAlreadyVariables = $setTagLegendVariables($elementName, $bgColor, $fontColor, $borderColor, $shadowing, $shape, $legendText, $legendSprite, $borderStyle, $borderThickness) + ' default tags sets at least bgColor and fontColor + !$tagMask = $tagLegendMask("CHANGED", "CHANGED", $borderColor, $shadowing, $shape, $sprite, $borderStyle, $borderThickness) +%set_variable_value("$" + $elementName + "LegendMask", $tagMask) +!endprocedure + +/' @deprecated in favor of UpdateElementStyle '/ +!unquoted procedure UpdateSkinparamsAndLegendEntry($elementName, $bgColor="", $fontColor="", $borderColor="", $shadowing="") +UpdateElementStyle($elementName, $bgColor, $fontColor, $borderColor, $shadowing) +!endprocedure + +' update the style of default relation, it has to set both properties (combined statement not working) +!unquoted procedure UpdateRelStyle($textColor, $lineColor) + !$elementSkin = "skinparam arrow {" + %newline() + !$elementSkin = $elementSkin + " Color " + $lineColor + %newline() + !$elementSkin = $elementSkin + " FontColor " + $textColor + %newline() + !$elementSkin = $elementSkin + "}" + %newline() +$elementSkin +!endprocedure + +' tags/stereotypes have to be delimited with \n +!unquoted procedure SetDefaultLegendEntries($tagStereoEntries) + !$tagDefaultLegend = $tagStereoEntries +!endprocedure + +' Links +' ################################## + +!function $getLink($link) + !if ($link != "") + !return "[[" + $link + "]]" + !else + !return "" + !endif +!endfunction + +' Line breaks +' ################################## + +!unquoted function $breakText($text, $usedNewLine, $widthStr="-1") +!$width = %intval($widthStr) +!$multiLine = "" +!if (%strpos($text, "\n") >= 0) + !while (%strpos($text, "\n") >= 0) + !$brPos = %strpos($text, "\n") + !if ($brPos > 0) + !$multiLine = $multiLine + %substr($text, 0, $brPos) + $usedNewLine + !else + ' non breaking change that newLine breaks with formats can be used with \n\n + !$multiLine = $multiLine + "" + $usedNewLine + !endif + !$text = %substr($text, $brPos+2) + !if (%strlen($text) == 0) + !$text = "" + !endif + !endwhile +!else + !while ($width>0 && %strlen($text) > $width) + !$brPos = $width + !while ($brPos > 0 && %substr($text, $brPos, 1) != ' ') + !$brPos = $brPos - 1 + !endwhile + + !if ($brPos < 1) + !$brPos = %strpos($text, " ") + !else + !endif + + !if ($brPos > 0) + !$multiLine = $multiLine + %substr($text, 0, $brPos) + $usedNewLine + !$text = %substr($text, $brPos + 1) + !else + !$multiLine = $multiLine+ $text + !$text = "" + !endif + !endwhile +!endif +!if (%strlen($text) > 0) + !$multiLine = $multiLine + $text +!endif +!return $multiLine +!endfunction + +!unquoted function $breakLabel($text) +!$usedNewLine = "\n== " +!$multiLine = $breakText($text, $usedNewLine) +!return $multiLine +!endfunction + +!unquoted function $breakDescr($text, $widthStr) + !$usedNewLine = "\n" + !return $breakText($text, $usedNewLine, $widthStr) +!endfunction + +' $breakTechn() supports //...//; $breakNode() in C4_Deployment supports no //....// +!unquoted function $breakTechn($text, $widthStr) + !$usedNewLine = '//\n//' + !return $breakText($text, $usedNewLine, $widthStr) +!endfunction + +' Element base layout +' ################################## + +!function $getElementBase($label, $techn, $descr, $sprite) + !$element = "" + !if ($sprite != "") + !$element = $element + $getSprite($sprite) + !if ($label != "") + !$element = $element + '\n' + !endif + !endif + !if ($label != "") + !$element = $element + '== ' + $breakLabel($label) + !else + !$element = $element + '.' + !endif + !if ($techn != "") + !$element = $element + '\n//[' + $breakTechn($techn, '-1') + ']//' + !endif + !if ($descr != "") + !$element = $element + '\n\n' + $descr + !endif + !return $element +!endfunction + +!function $getElementLine($umlShape, $elementType, $alias, $label, $techn, $descr, $sprite, $tags, $link) + !$sprite=$toElementArg($sprite, $tags, "ElementTagSprite", $elementType) + !$techn=$toElementArg($techn, $tags, "ElementTagTechn", $elementType) + !$baseProp = $getElementBase($label, $techn, $descr, $sprite) + $getProps() + !$stereo = $toStereos($elementType,$tags) + !$calcLink = $getLink($link) + + !$line = $umlShape + " " + %chr(34) + $baseProp + %chr(34) +" " + $stereo + " as " + $alias + $calcLink + !return $line +!endfunction + +' Element properties +' ################################## + +' collect all defined properties as table rows +!global $propTable = "" +!global $propTableCaption = "" +!global $propColCaption = "=" + +!unquoted function SetPropertyHeader($col1Name, $col2Name, $col3Name = "", $col4Name = "") + !$propColCaption = "" + !$propTableCaption = "|= " + $col1Name + " |= " + $col2Name + " |" + !if ($col3Name != "") + !$propTableCaption = $propTableCaption + "= " + $col3Name + " |" + !endif + !if ($col4Name != "") + !$propTableCaption = $propTableCaption + "= " + $col4Name + " |" + !endif + !return "" +!endfunction + +!unquoted function WithoutPropertyHeader() + !$propTableCaption = "" + !$propColCaption = "=" + !return "" +!endfunction + +!unquoted function AddProperty($col1, $col2, $col3 = "", $col4 = "") + !if ($propTable == "") + !if ($propTableCaption != "") + !$propTable = $propTableCaption + "\n" + !endif + !else + !$propTable = $propTable + "\n" + !endif + !$propTable = $propTable + "| " + $col1 + " |" + $propColCaption + " " + $col2 + " |" + !if ($col3 != "") + !$propTable = $propTable + " " + $col3 + " |" + !endif + !if ($col4 != "") + !$propTable = $propTable + " " + $col4 + " |" + !endif + !return "" +!endfunction + +!unquoted function $getProps($alignedNL = "\n") + !if ($propTable != "") + !$retTable = $alignedNL + $propTable + !$propTable = "" + !return $retTable + !endif + !return "" +!endfunction + +!unquoted function $getProps_L() + !return $getProps("\l") +!endfunction + +!unquoted function $getProps_R() + !return $getProps("\r") +!endfunction + +SetPropertyHeader("Property","Value") + +' Layout +' ################################## + +!function $getLegendDetailsSize($detailsFormat) + !if $detailsFormat == $LEGEND_DETAILS_NONE + !$size = 0 + !elseif $detailsFormat == $LEGEND_DETAILS_SMALL + !$size = $LEGEND_DETAILS_SMALL_SIZE + !else + !$size = $LEGEND_DETAILS_NORMAL_SIZE + !endif + !return $size +!endfunction + +!procedure $getHideStereotype($hideStereotype) +!if ($hideStereotype == "true") +hide stereotype +!endif +!endprocedure + +!procedure $getLegendTable($detailsFormat) +!global $LEGEND_DETAILS_SIZE = $getLegendDetailsSize($detailsFormat) +<$colorWithHash(transparent),$colorWithHash(transparent)>|**Legend** | +$showActiveLegendEntries($tagDefaultLegend) +$showActiveLegendEntries($tagCustomLegend) +!endprocedure + +!procedure $getLegendArea($areaAlias, $hideStereotype, $details) +$getHideStereotype($hideStereotype) +rectangle $areaAlias<> [ +$getLegendTable($details) +] +!endprocedure + +!procedure HIDE_STEREOTYPE() +hide stereotype +!endprocedure + +!unquoted procedure SET_SKETCH_STYLE($bgColor="_dont_change_", $fontColor="_dont_change_", $warningColor="_dont_change_", $fontName="_dont_change_", $footerWarning="_dont_change_", $footerText="_dont_change_") +!if $bgColor != "_dont_change_" + !global $SKETCH_BG_COLOR = $bgColor +!endif +!if $fontColor != "_dont_change_" + !global $SKETCH_FONT_COLOR = $fontColor +!endif +!if $warningColor != "_dont_change_" + !global $SKETCH_WARNING_COLOR = $warningColor +!endif +!if $fontName != "_dont_change_" + !global $SKETCH_FONT_NAME = $fontName +!endif +!if $footerWarning != "_dont_change_" + !global $SKETCH_FOOTER_WARNING = $footerWarning +!endif +!if $footerText != "_dont_change_" + !global $SKETCH_FOOTER_TEXT = $footerText +!endif +!endprocedure + +!procedure LAYOUT_AS_SKETCH() + skinparam handwritten true +!if $SKETCH_BG_COLOR > "" + skinparam backgroundColor $SKETCH_BG_COLOR +!endif +!if $SKETCH_FONT_COLOR > "" + skinparam footer { + FontColor $SKETCH_FONT_COLOR + } + !if $ARROW_COLOR == "#666666" + !global $ARROW_COLOR = $SKETCH_FONT_COLOR + !global $ARROW_FONT_COLOR = $SKETCH_FONT_COLOR + skinparam arrow { + Color $ARROW_COLOR + FontColor $ARROW_FONT_COLOR + } + !endif + !if $BOUNDARY_COLOR == "#444444" + !global $BOUNDARY_COLOR = $SKETCH_FONT_COLOR + skinparam rectangle<> { + FontColor $BOUNDARY_COLOR + BorderColor $BOUNDARY_COLOR + } + !endif +!endif +!if $SKETCH_FONT_NAMES > "" + skinparam defaultFontName $SKETCH_FONT_NAME +!endif +!if $SKETCH_FOOTER_WARNING > "" || $SKETCH_FOOTER_TEXT > "" + !$line = "footer "+ $SKETCH_FOOTER_WARNING + " " + $SKETCH_FOOTER_TEXT + $line +!endif +!endprocedure + +!global $fix_direction=%false() + +!function $down($start,$end) +!if ($fix_direction) +!return $start+"RIGHT"+$end +!else +!return $start+"DOWN"+$end +!endif +!endfunction + +!function $up($start,$end) +!if ($fix_direction) +!return $start+"LEFT"+$end +!else +!return $start+"UP"+$end +!endif +!endfunction + +!function $left($start,$end) +!if ($fix_direction) +!return $start+"UP"+$end +!else +!return $start+"LEFT"+$end +!endif +!endfunction + +!function $right($start,$end) +!if ($fix_direction) +!return $start+"DOWN"+$end +!else +!return $start+"RIGHT"+$end +!endif +!endfunction + +!procedure LAYOUT_TOP_DOWN() +!global $fix_direction=%false() +top to bottom direction +!endprocedure + +!procedure LAYOUT_LEFT_RIGHT() +!global $fix_direction = %false() +left to right direction +!endprocedure + +!procedure LAYOUT_LANDSCAPE() +!global $fix_direction = %true() +left to right direction +!endprocedure + +' legend details can displayed as Normal(), Small(), None() +!function None() +!return $LEGEND_DETAILS_NONE +!endfunction + +!function Normal() +!return $LEGEND_DETAILS_NORMAL +!endfunction + +!function Small() +!return $LEGEND_DETAILS_SMALL +!endfunction + +' has to be last call in diagram +!unquoted procedure SHOW_LEGEND($hideStereotype="true", $details=Small()) +$getHideStereotype($hideStereotype) +legend right +$getLegendTable($details) +endlegend +!endprocedure + +/' @deprecated in favor of SHOW_LEGEND '/ +!unquoted procedure SHOW_DYNAMIC_LEGEND($hideStereotype="true") +SHOW_LEGEND($hideStereotype) +!endprocedure + +' legend is reserved and cannot be uses as alias of SHOW_FLOATING_LEGEND() therefore +' LEGEND() is introduced. It returns the default name of the floating alias "floating_legend_alias" +' and can be used in the Lay_Distance() calls +!function LEGEND() +!return "floating_legend_alias" +!endfunction + +' enables that legend can be located in drawing area of the diagram. It has to be last call in diagram followed by Lay_Distance() +!unquoted procedure SHOW_FLOATING_LEGEND($alias=LEGEND(), $hideStereotype="true", $details=Small()) +$getLegendArea($alias, $hideStereotype, $details) +!endprocedure + +' Boundaries +' ################################## + +!unquoted procedure UpdateBoundaryStyle($elementName="", $bgColor="", $fontColor="", $borderColor="", $shadowing="", $shape="", $type="", $legendText="", $borderStyle="", $borderThickness="") + !if ($elementName != "") + !$elementBoundary = $elementName + '_boundary' + UpdateElementStyle($elementBoundary, $bgColor, $fontColor, $borderColor, $shadowing, $shape, "", $type, $legendText, "", $borderStyle, $borderThickness) + !else + UpdateElementStyle("boundary", $bgColor, $fontColor, $borderColor, $shadowing, $shape, "", $type, $legendText, "", $borderStyle, $borderThickness) + ' simulate color inheritance + UpdateBoundaryStyle("enterprise", $bgColor, $fontColor, $borderColor, $shadowing, $shape, "Enterprise", "", $borderStyle, $borderThickness) + UpdateBoundaryStyle("system", $bgColor, $fontColor, $borderColor, $shadowing, $shape, "System", "", $borderStyle, $borderThickness) + UpdateBoundaryStyle("container", $bgColor, $fontColor, $borderColor, $shadowing, $shape, "Container", "", $borderStyle, $borderThickness) + !endif +!endprocedure + +!unquoted procedure AddBoundaryTag($tagStereo, $bgColor="", $fontColor="", $borderColor="", $shadowing="", $shape="", $type="", $legendText="", $borderStyle="", $borderThickness="") + !$tagBoundary = $tagStereo + '_boundary' + AddElementTag($tagBoundary, $bgColor, $fontColor, $borderColor, $shadowing, $shape, "", $type, $legendText, "", $borderStyle, $borderThickness) +!endprocedure + +' add _boundary to all tags that short tag version can be used +!unquoted function $addBoundaryPostfix($tags) + !if (%strlen($tags) == 0) + !return '' + !endif + !$boundaryTags = '' + !$brPos = %strpos($tags, "+") + !while ($brPos >= 0) + !$tag = %substr($tags, 0, $brPos) + !$boundaryTags = $boundaryTags + $tag + '_boundary+' + !$tags = %substr($tags, $brPos+1) + !$brPos = %strpos($tags, "+") + !endwhile + !if (%strlen($tags) > 0) + !$boundaryTags = $boundaryTags + $tags + '_boundary' + !endif + !return $boundaryTags +!endfunction + +!function $getBoundary($label, $type) + !if ($type == "") + !return '== ' + $breakLabel($label) + !endif + !if (type != "") + !return '== ' + $breakLabel($label) + '\n[' + $type + ']' + !endif +!endfunction + +!unquoted procedure Boundary($alias, $label, $type="", $tags="", $link="") +!$boundaryTags = $addBoundaryPostfix($tags) +' nodes $type reuses $techn definition of $boundaryTags +!$type=$toElementArg($type, $boundaryTags, "ElementTagTechn", "boundary") +rectangle "$getBoundary($label, $type)" $toStereos("boundary", $boundaryTags) as $alias $getLink($link) +!endprocedure + +' Boundary Styling +UpdateBoundaryStyle("", $bgColor=$BOUNDARY_BG_COLOR, $fontColor=$BOUNDARY_COLOR, $borderColor=$BOUNDARY_COLOR, $borderStyle=DashedLine()) + +' Index +' ################################## + +' Dynamic/Sequence diagram supports (automatically) numbered interactions: +' preferred function calls +' (Uppercase) LastIndex(): return the last used index (function which can be used as argument) +' (Uppercase) Index($offset=1): returns current index and calculates next index (function which can be used as argument) +' (Uppercase) SetIndex($new_index): returns new set index and calculates next index (function which can be used as argument) + +' old procedures calls +' (lowercase) increment($offset=1): increase current index (procedure which has no direct output) +' (lowercase) setIndex($new_index): set the new index (procedure which has no direct output) + +!$lastIndex = 0 +!$index = 1 + +!procedure increment($offset=1) + !$lastIndex = $index + !$index = $index + $offset +!endprocedure + +!procedure setIndex($new_index) + !$lastIndex = $index + !$index = $new_index +!endprocedure + +!function Index($offset=1) + !$lastIndex = $index + !$index = $lastIndex + $offset + !return $lastIndex +!endfunction + +!function LastIndex() + !return $lastIndex +!endfunction + +!function SetIndex($new_index, $offset=1) + !$lastIndex = $new_index + !$index = $new_index + $offset + !return $lastIndex +!endfunction + +!unquoted function $getPrefix($index) + !if ($index == "") + !$pre = Index() + ": " + !else + !$pre = $index + ": " + !endif + !return $pre +!endfunction + +' Relationship +' ################################## + +!function $getRel($direction, $alias1, $alias2, $label, $techn, $descr, $sprite, $tags, $link) + !$sprite = $toRelArg($sprite, $tags, "RelTagSprite") + !$techn = $toRelArg($techn, $tags, "RelTagTechn") + !$rel = $alias1 + ' ' + $direction + ' ' + $alias2 + !if ($tags != "") + !$rel = $rel + ' ' + $toStereos($tags) + !endif + !$rel = $rel + ' : ' + !if ($link != "") + !$rel = $rel + '**[[' + $link + ' ' + !endif + !if ($sprite != "") + !$rel = $rel + $getSprite($sprite) + !if ($label != "") + !$rel = $rel + ' ' + !endif + !endif + !if ($link != "") + !$usedNewLine = ']]**\n**[[' + $link + ' ' + ' if sprite and label is empty than the link url is shown (otherwise link cannot be activated at all) + !$rel = $rel + $breakText($label, $usedNewLine) + ']]**' + !else + !if ($label != "") + !$usedNewLine = '**\n**' + !$rel = $rel + '**' + $breakText($label, $usedNewLine) + '**' + !else + !$rel = $rel + '.' + !endif + !endif + !if ($techn != "") + ' line break is not deterministic, calculate it + !$rel = $rel + '\n//[' + $breakTechn($techn, $REL_TECHN_MAX_CHAR_WIDTH) + ']//' + !endif + !if ($descr != "") + ' line break is not deterministic, calculate it + !$rel = $rel + '\n\n' + $breakDescr($descr, $REL_DESCR_MAX_CHAR_WIDTH) + !endif + !$prop = $getProps() + !if ($prop != "") + ' reuse table + !$rel = $rel + $prop + !endif + !return $rel +!endfunction + +!unquoted procedure Rel_($alias1, $alias2, $label, $direction) +$getRel($direction, $alias1, $alias2, $label, "", "", "", "", "") +!endprocedure +!unquoted procedure Rel_($alias1, $alias2, $label, $techn, $direction) +$getRel($direction, $alias1, $alias2, $label, $techn, "", "", "", "") +!endprocedure + +!unquoted procedure Rel($from, $to, $label, $techn="", $descr="", $sprite="", $tags="", $link="") +$getRel("-->>", $from, $to, $label, $techn, $descr, $sprite, $tags, $link) +!endprocedure + +!unquoted procedure BiRel($from, $to, $label, $techn="", $descr="", $sprite="", $tags="", $link="") +$getRel("<<-->>", $from, $to, $label, $techn, $descr, $sprite, $tags, $link) +!endprocedure + +!unquoted procedure Rel_Back($from, $to, $label, $techn="", $descr="", $sprite="", $tags="", $link="") +$getRel("<<--", $from, $to, $label, $techn, $descr, $sprite, $tags, $link) +!endprocedure + +!unquoted procedure Rel_Neighbor($from, $to, $label, $techn="", $descr="", $sprite="", $tags="", $link="") +$getRel("->>", $from, $to, $label, $techn, $descr, $sprite, $tags, $link) +!endprocedure + +!unquoted procedure BiRel_Neighbor($from, $to, $label, $techn="", $descr="", $sprite="", $tags="", $link="") +$getRel("<<->>", $from, $to, $label, $techn, $descr, $sprite, $tags, $link) +!endprocedure + +!unquoted procedure Rel_Back_Neighbor($from, $to, $label, $techn="", $descr="", $sprite="", $tags="", $link="") +$getRel("<<-", $from, $to, $label, $techn, $descr, $sprite, $tags, $link) +!endprocedure + +!unquoted procedure Rel_D($from, $to, $label, $techn="", $descr="", $sprite="", $tags="", $link="") +$getRel($down("-","->>"), $from, $to, $label, $techn, $descr, $sprite, $tags, $link) +!endprocedure +!unquoted procedure Rel_Down($from, $to, $label, $techn="", $descr="", $sprite="", $tags="", $link="") +$getRel($down("-","->>"), $from, $to, $label, $techn, $descr, $sprite, $tags, $link) +!endprocedure + +!unquoted procedure BiRel_D($from, $to, $label, $techn="", $descr="", $sprite="", $tags="", $link="") +$getRel($down("<<-","->>"), $from, $to, $label, $techn, $descr, $sprite, $tags, $link) +!endprocedure +!unquoted procedure BiRel_Down($from, $to, $label, $techn="", $descr="", $sprite="", $tags="", $link="") +$getRel($down("<<-","->>"), $from, $to, $label, $techn, $descr, $sprite, $tags, $link) +!endprocedure + +!unquoted procedure Rel_U($from, $to, $label, $techn="", $descr="", $sprite="", $tags="", $link="") +$getRel($up("-","->>"), $from, $to, $label, $techn, $descr, $sprite, $tags, $link) +!endprocedure +!unquoted procedure Rel_Up($from, $to, $label, $techn="", $descr="", $sprite="", $tags="", $link="") +$getRel($up("-","->>"), $from, $to, $label, $techn, $descr, $sprite, $tags, $link) +!endprocedure + +!unquoted procedure BiRel_U($from, $to, $label, $techn="", $descr="", $sprite="", $tags="", $link="") +$getRel($up("<<-","->>"), $from, $to, $label, $techn, $descr, $sprite, $tags, $link) +!endprocedure +!unquoted procedure BiRel_Up($from, $to, $label, $techn="", $descr="", $sprite="", $tags="", $link="") +$getRel($up("<<-","->>"), $from, $to, $label, $techn, $descr, $sprite, $tags, $link) +!endprocedure + +!unquoted procedure Rel_L($from, $to, $label, $techn="", $descr="", $sprite="", $tags="", $link="") +$getRel($left("-","->>"), $from, $to, $label, $techn, $descr, $sprite, $tags, $link) +!endprocedure +!unquoted procedure Rel_Left($from, $to, $label, $techn="", $descr="", $sprite="", $tags="", $link="") +$getRel($left("-","->>"), $from, $to, $label, $techn, $descr, $sprite, $tags, $link) +!endprocedure + +!unquoted procedure BiRel_L($from, $to, $label, $techn="", $descr="", $sprite="", $tags="", $link="") +$getRel($left("<<-","->>"), $from, $to, $label, $techn, $descr, $sprite, $tags, $link) +!endprocedure +!unquoted procedure BiRel_Left($from, $to, $label, $techn="", $descr="", $sprite="", $tags="", $link="") +$getRel($left("<<-","->>"), $from, $to, $label, $techn, $descr, $sprite, $tags, $link) +!endprocedure + +!unquoted procedure Rel_R($from, $to, $label, $techn="", $descr="", $sprite="", $tags="", $link="") +$getRel($right("-","->>"), $from, $to, $label, $techn, $descr, $sprite, $tags, $link) +!endprocedure +!unquoted procedure Rel_Right($from, $to, $label, $techn="", $descr="", $sprite="", $tags="", $link="") +$getRel($right("-","->>"), $from, $to, $label, $techn, $descr, $sprite, $tags, $link) +!endprocedure + +!unquoted procedure BiRel_R($from, $to, $label, $techn="", $descr="", $sprite="", $tags="", $link="") +$getRel($right("<<-","->>"), $from, $to, $label, $techn, $descr, $sprite, $tags, $link) +!endprocedure +!unquoted procedure BiRel_Right($from, $to, $label, $techn="", $descr="", $sprite="", $tags="", $link="") +$getRel($right("<<-","->>"), $from, $to, $label, $techn, $descr, $sprite, $tags, $link) +!endprocedure + +' Layout Helpers +' ################################## + +!function $getHiddenLine($distance) + !return '-[hidden]' + %substr('------------', 0, %intval($distance) + 1) +!endfunction + +!unquoted procedure Lay_D($from, $to) +$from -[hidden]D- $to +!endprocedure +!unquoted procedure Lay_Down($from, $to) +$from -[hidden]D- $to +!endprocedure + +!unquoted procedure Lay_U($from, $to) +$from -[hidden]U- $to +!endprocedure +!unquoted procedure Lay_Up($from, $to) +$from -[hidden]U- $to +!endprocedure + +!unquoted procedure Lay_R($from, $to) +$from -[hidden]R- $to +!endprocedure +!unquoted procedure Lay_Right($from, $to) +$from -[hidden]R- $to +!endprocedure + +!unquoted procedure Lay_L($from, $to) +$from -[hidden]L- $to +!endprocedure +!unquoted procedure Lay_Left($from, $to) +$from -[hidden]L- $to +!endprocedure + +' PlantUML bug: lines which does "not match" with the orientation/direction of the diagram +' use the same length therefore the method offers no direction at all. +' If a direction is required the Lay_...() methods can be used +!unquoted procedure Lay_Distance($from, $to, $distance="0") +$from $getHiddenLine($distance) $to +!endprocedure diff --git a/.c4s/C4_Component.puml b/.c4s/C4_Component.puml new file mode 100644 index 0000000..a4137d6 --- /dev/null +++ b/.c4s/C4_Component.puml @@ -0,0 +1,83 @@ +' convert it with additional command line argument -DRELATIVE_INCLUDE="relative/absolute" to use locally +!if %variable_exists("RELATIVE_INCLUDE") + !include ./C4_Container.puml +!else + !include https://raw.githubusercontent.com/plantuml-stdlib/C4-PlantUML/master/C4_Container.puml +!endif + +' Scope: A single container. +' Primary elements: Components within the container in scope. +' Supporting elements: Containers (within the software system in scope) plus people and software systems directly connected to the components. +' Intended audience: Software architects and developers. + +' Colors +' ################################## + +!$COMPONENT_FONT_COLOR ?= "#000000" +!$COMPONENT_BG_COLOR ?= "#85BBF0" +!$COMPONENT_BORDER_COLOR ?= "#78A8D8" + +!$EXTERNAL_COMPONENT_FONT_COLOR ?= $COMPONENT_FONT_COLOR +!$EXTERNAL_COMPONENT_BG_COLOR ?= "#CCCCCC" +!$EXTERNAL_COMPONENT_BORDER_COLOR ?= "#BFBFBF" + +' Styling +' ################################## + +UpdateElementStyle("component", $COMPONENT_BG_COLOR, $COMPONENT_FONT_COLOR, $COMPONENT_BORDER_COLOR, false) +UpdateElementStyle("external_component", $EXTERNAL_COMPONENT_BG_COLOR, $EXTERNAL_COMPONENT_FONT_COLOR, $EXTERNAL_COMPONENT_BORDER_COLOR, false) + +' shortcuts with default colors +!unquoted procedure AddComponentTag($tagStereo, $bgColor="", $fontColor="", $borderColor="", $shadowing="", $shape="", $sprite="", $techn="", $legendText="", $legendSprite="", $borderStyle="", $borderThickness="") + $addElementTagInclReuse("component", $tagStereo, $bgColor, $fontColor, $borderColor, $shadowing, $shape, $sprite, $techn, $legendText, $legendSprite, $borderStyle, $borderThickness) +!endprocedure +!unquoted procedure AddExternalComponentTag($tagStereo, $bgColor="", $fontColor="", $borderColor="", $shadowing="", $shape="", $sprite="", $techn="", $legendText="", $legendSprite="", $borderStyle="", $borderThickness="") + $addElementTagInclReuse("external_component", $tagStereo, $bgColor, $fontColor, $borderColor, $shadowing, $shape, $sprite, $techn, $legendText, $legendSprite, $borderStyle, $borderThickness) +!endprocedure + +' Layout +' ################################## + +SetDefaultLegendEntries("person\nsystem\ncontainer\ncomponent\nexternal_person\nexternal_system\nexternal_container\nexternal_component\nenterprise_boundary\nsystem_boundary\ncontainer_boundary\nboundary") + +!procedure LAYOUT_WITH_LEGEND() +hide stereotype +legend right +|**Legend** | +|<$PERSON_BG_COLOR> person | +|<$SYSTEM_BG_COLOR> system | +|<$CONTAINER_BG_COLOR> container | +|<$COMPONENT_BG_COLOR> component | +|<$EXTERNAL_PERSON_BG_COLOR> external person | +|<$EXTERNAL_SYSTEM_BG_COLOR> external system | +|<$EXTERNAL_CONTAINER_BG_COLOR> external container | +|<$EXTERNAL_COMPONENT_BG_COLOR> external component | +endlegend +!endprocedure + +' Elements +' ################################## + +!unquoted procedure Component($alias, $label, $techn="", $descr="", $sprite="", $tags="", $link="", $baseShape="rectangle") + $getElementLine($baseShape, "component", $alias, $label, $techn, $descr, $sprite, $tags, $link) +!endprocedure + +!unquoted procedure ComponentDb($alias, $label, $techn="", $descr="", $sprite="", $tags="", $link="") + $getElementLine("database", "component", $alias, $label, $techn, $descr, $sprite, $tags, $link) +!endprocedure + +!unquoted procedure ComponentQueue($alias, $label, $techn="", $descr="", $sprite="", $tags="", $link="") + $getElementLine("queue", "component", $alias, $label, $techn, $descr, $sprite, $tags, $link) +!endprocedure + +!unquoted procedure Component_Ext($alias, $label, $techn="", $descr="", $sprite="", $tags="", $link="", $baseShape="rectangle") + $getElementLine($baseShape, "external_component", $alias, $label, $techn, $descr, $sprite, $tags, $link) +!endprocedure + +!unquoted procedure ComponentDb_Ext($alias, $label, $techn="", $descr="", $sprite="", $tags="", $link="") + $getElementLine("database", "external_component", $alias, $label, $techn, $descr, $sprite, $tags, $link) +!endprocedure + +!unquoted procedure ComponentQueue_Ext($alias, $label, $techn="", $descr="", $sprite="", $tags="", $link="") + $getElementLine("queue", "external_component", $alias, $label, $techn, $descr, $sprite, $tags, $link) +!endprocedure diff --git a/.c4s/C4_Container.puml b/.c4s/C4_Container.puml new file mode 100644 index 0000000..bccd6fd --- /dev/null +++ b/.c4s/C4_Container.puml @@ -0,0 +1,103 @@ +' convert it with additional command line argument -DRELATIVE_INCLUDE="relative/absolute" to use locally +!if %variable_exists("RELATIVE_INCLUDE") + !include ./C4_Context.puml +!else + !include https://raw.githubusercontent.com/plantuml-stdlib/C4-PlantUML/master/C4_Context.puml +!endif + +' Scope: A single software system. +' Primary elements: Containers within the software system in scope. +' Supporting elements: People and software systems directly connected to the containers. +' Intended audience: Technical people inside and outside of the software development team; including software architects, developers and operations/support staff. + +' Colors +' ################################## + +!$CONTAINER_FONT_COLOR ?= $ELEMENT_FONT_COLOR +!$CONTAINER_BG_COLOR ?= "#438DD5" +!$CONTAINER_BORDER_COLOR ?= "#3C7FC0" + +!$CONTAINER_BOUNDARY_COLOR ?= $BOUNDARY_COLOR +!$CONTAINER_BOUNDARY_BG_COLOR ?= $BOUNDARY_BG_COLOR +!$CONTAINER_BOUNDARY_BORDER_STYLE ?= $BOUNDARY_BORDER_STYLE + +!$EXTERNAL_CONTAINER_FONT_COLOR ?= $ELEMENT_FONT_COLOR +!$EXTERNAL_CONTAINER_BG_COLOR ?= "#B3B3B3" +!$EXTERNAL_CONTAINER_BORDER_COLOR ?= "#A6A6A6" + +' Styling +' ################################## +UpdateElementStyle("container", $CONTAINER_BG_COLOR, $CONTAINER_FONT_COLOR, $CONTAINER_BORDER_COLOR, false) +UpdateElementStyle("external_container", $EXTERNAL_CONTAINER_BG_COLOR, $EXTERNAL_CONTAINER_FONT_COLOR, $EXTERNAL_CONTAINER_BORDER_COLOR, false) + +UpdateBoundaryStyle("container", $bgColor=$CONTAINER_BOUNDARY_BG_COLOR, $fontColor=$CONTAINER_BOUNDARY_COLOR, $borderColor=$CONTAINER_BOUNDARY_COLOR, $type="Container", $shadowing="false") + +' shortcuts with default colors +!unquoted procedure AddContainerTag($tagStereo, $bgColor="", $fontColor="", $borderColor="", $shadowing="", $shape="", $sprite="", $techn="", $legendText="", $legendSprite="", $borderStyle="", $borderThickness="") + $addElementTagInclReuse("container", $tagStereo, $bgColor, $fontColor, $borderColor, $shadowing, $shape, $sprite, $techn, $legendText, $legendSprite, $borderStyle, $borderThickness) +!endprocedure +!unquoted procedure AddExternalContainerTag($tagStereo, $bgColor="", $fontColor="", $borderColor="", $shadowing="", $shape="", $sprite="", $techn="", $legendText="", $legendSprite="", $borderStyle="", $borderThickness="") + $addElementTagInclReuse("external_container", $tagStereo, $bgColor, $fontColor, $borderColor, $shadowing, $shape, $sprite, $techn, $legendText, $legendSprite, $borderStyle, $borderThickness) +!endprocedure + +!unquoted procedure UpdateContainerBoundaryStyle($bgColor=$CONTAINER_BOUNDARY_BG_COLOR, $fontColor=$CONTAINER_BOUNDARY_COLOR, $borderColor=$CONTAINER_BOUNDARY_COLOR, $shadowing="", $shape="", $type="Container", $legendText="", $borderStyle="", $borderThickness="") + UpdateBoundaryStyle("container", $bgColor, $fontColor, $borderColor, $shadowing, $shape, $type, $legendText, $borderStyle, $borderThickness) +!endprocedure + +' Layout +' ################################## + +SetDefaultLegendEntries("person\nsystem\ncontainer\nexternal_person\nexternal_system\nexternal_container\nenterprise_boundary\nsystem_boundary\ncontainer_boundary\nboundary") + +!procedure LAYOUT_WITH_LEGEND() +hide stereotype +legend right +|**Legend** | +|<$PERSON_BG_COLOR> person | +|<$SYSTEM_BG_COLOR> system | +|<$CONTAINER_BG_COLOR> container | +|<$EXTERNAL_PERSON_BG_COLOR> external person | +|<$EXTERNAL_SYSTEM_BG_COLOR> external system | +|<$EXTERNAL_CONTAINER_BG_COLOR> external container | +endlegend +!endprocedure + +' Elements +' ################################## + +!unquoted procedure Container($alias, $label, $techn="", $descr="", $sprite="", $tags="", $link="", $baseShape="rectangle") + $getElementLine($baseShape , "container", $alias, $label, $techn, $descr, $sprite, $tags, $link) +!endprocedure + +!unquoted procedure ContainerDb($alias, $label, $techn="", $descr="", $sprite="", $tags="", $link="") + $getElementLine("database", "container", $alias, $label, $techn, $descr, $sprite, $tags, $link) +!endprocedure + +!unquoted procedure ContainerQueue($alias, $label, $techn="", $descr="", $sprite="", $tags="", $link="") + $getElementLine("queue", "container", $alias, $label, $techn, $descr, $sprite, $tags, $link) +!endprocedure + +!unquoted procedure Container_Ext($alias, $label, $techn="", $descr="", $sprite="", $tags="", $link="", $baseShape="rectangle") + $getElementLine($baseShape , "external_container", $alias, $label, $techn, $descr, $sprite, $tags, $link) +!endprocedure + +!unquoted procedure ContainerDb_Ext($alias, $label, $techn="", $descr="", $sprite="", $tags="", $link="") + $getElementLine("database", "external_container", $alias, $label, $techn, $descr, $sprite, $tags, $link) +!endprocedure + +!unquoted procedure ContainerQueue_Ext($alias, $label, $techn="", $descr="", $sprite="", $tags="", $link="") + $getElementLine("queue", "external_container", $alias, $label, $techn, $descr, $sprite, $tags, $link) +!endprocedure + +' Boundaries +' ################################## + +!unquoted procedure Container_Boundary($alias, $label, $tags="", $link="") + !if ($tags != "") + !$allTags = $tags + '+container' + !else + !$allTags = 'container' + !endif + ' $type defined via $tag style + Boundary($alias, $label, "", $allTags, $link) +!endprocedure diff --git a/.c4s/C4_Context.puml b/.c4s/C4_Context.puml new file mode 100644 index 0000000..71b2574 --- /dev/null +++ b/.c4s/C4_Context.puml @@ -0,0 +1,434 @@ +' convert it with additional command line argument -DRELATIVE_INCLUDE="relative/absolute" to use locally +!if %variable_exists("RELATIVE_INCLUDE") + !include ./C4.puml +!else + !include https://raw.githubusercontent.com/plantuml-stdlib/C4-PlantUML/master/C4.puml +!endif + +' Scope: A single software system. +' Primary elements: The software system in scope. +' Supporting elements: People and software systems directly connected to the software system in scope. +' Intended audience: Everybody, both technical and non-technical people, inside and outside of the software development team. + +' Colors +' ################################## + +!$PERSON_FONT_COLOR ?= $ELEMENT_FONT_COLOR +!$PERSON_BG_COLOR ?= "#08427B" +!$PERSON_BORDER_COLOR ?= "#073B6F" + +!$EXTERNAL_PERSON_FONT_COLOR ?= $ELEMENT_FONT_COLOR +!$EXTERNAL_PERSON_BG_COLOR ?= "#686868" +!$EXTERNAL_PERSON_BORDER_COLOR ?= "#8A8A8A" + +!$SYSTEM_FONT_COLOR ?= $ELEMENT_FONT_COLOR +!$SYSTEM_BG_COLOR ?= "#1168BD" +!$SYSTEM_BORDER_COLOR ?= "#3C7FC0" + +!$SYSTEM_BOUNDARY_COLOR ?= $BOUNDARY_COLOR +!$SYSTEM_BOUNDARY_BG_COLOR ?= $BOUNDARY_BG_COLOR +!$SYSTEM_BOUNDARY_BORDER_STYLE ?= $BOUNDARY_BORDER_STYLE + +!$EXTERNAL_SYSTEM_FONT_COLOR ?= $ELEMENT_FONT_COLOR +!$EXTERNAL_SYSTEM_BG_COLOR ?= "#999999" +!$EXTERNAL_SYSTEM_BORDER_COLOR ?= "#8A8A8A" + +!$ENTERPRISE_BOUNDARY_COLOR ?= $BOUNDARY_COLOR +!$ENTERPRISE_BOUNDARY_BG_COLOR ?= $BOUNDARY_BG_COLOR +!$ENTERPRISE_BOUNDARY_BORDER_STYLE ?= $BOUNDARY_BORDER_STYLE + +' Styling +' ################################## + +UpdateElementStyle("person", $PERSON_BG_COLOR, $PERSON_FONT_COLOR, $PERSON_BORDER_COLOR, false) +UpdateElementStyle("external_person", $EXTERNAL_PERSON_BG_COLOR, $EXTERNAL_PERSON_FONT_COLOR, $EXTERNAL_PERSON_BORDER_COLOR, false) +UpdateElementStyle("system", $SYSTEM_BG_COLOR, $SYSTEM_FONT_COLOR, $SYSTEM_BORDER_COLOR, false) +UpdateElementStyle("external_system", $EXTERNAL_SYSTEM_BG_COLOR, $EXTERNAL_SYSTEM_FONT_COLOR, $EXTERNAL_SYSTEM_BORDER_COLOR, false) + +UpdateBoundaryStyle("system", $bgColor=$SYSTEM_BOUNDARY_BG_COLOR, $fontColor=$SYSTEM_BOUNDARY_COLOR, $borderColor=$SYSTEM_BOUNDARY_COLOR, $type="System", $shadowing="false") +UpdateBoundaryStyle("enterprise", $bgColor=$ENTERPRISE_BOUNDARY_BG_COLOR, $fontColor=$ENTERPRISE_BOUNDARY_COLOR, $borderColor=$ENTERPRISE_BOUNDARY_COLOR, $type="Enterprise", $shadowing="false") + +' shortcuts with default colors +!unquoted procedure AddPersonTag($tagStereo, $bgColor="", $fontColor="", $borderColor="", $shadowing="", $shape="", $sprite="", $legendText="", $legendSprite="", $type="", $borderStyle="", $borderThickness="") + $addElementTagInclReuse("person", $tagStereo, $bgColor, $fontColor, $borderColor, $shadowing, $shape, $sprite, $type, $legendText, $legendSprite, $borderStyle, $borderThickness) +!endprocedure +!unquoted procedure AddExternalPersonTag($tagStereo, $bgColor="", $fontColor="", $borderColor="", $shadowing="", $shape="", $sprite="", $legendText="", $legendSprite="", $type="", $borderStyle="", $borderThickness="") + $addElementTagInclReuse("external_person", $tagStereo, $bgColor, $fontColor, $borderColor, $shadowing, $shape, $sprite, $type, $legendText, $legendSprite, $borderStyle, $borderThickness) +!endprocedure +!unquoted procedure AddSystemTag($tagStereo, $bgColor="", $fontColor="", $borderColor="", $shadowing="", $shape="", $sprite="", $legendText="", $legendSprite="", $type="", $borderStyle="", $borderThickness="") + $addElementTagInclReuse("system", $tagStereo, $bgColor, $fontColor, $borderColor, $shadowing, $shape, $sprite, $type, $legendText, $legendSprite, $borderStyle, $borderThickness) +!endprocedure +!unquoted procedure AddExternalSystemTag($tagStereo, $bgColor="", $fontColor="", $borderColor="", $shadowing="", $shape="", $sprite="", $legendText="", $legendSprite="", $type="", $borderStyle="", $borderThickness="") + $addElementTagInclReuse("external_system", $tagStereo, $bgColor, $fontColor, $borderColor, $shadowing, $shape, $sprite, $type, $legendText, $legendSprite, $borderStyle, $borderThickness) +!endprocedure + +!unquoted procedure UpdateEnterpriseBoundaryStyle($bgColor=$ENTERPRISE_BOUNDARY_BG_COLOR, $fontColor=$ENTERPRISE_BOUNDARY_COLOR, $borderColor=$ENTERPRISE_BOUNDARY_COLOR, $shadowing="", $shape="", $type="Enterprise", $legendText="", $borderStyle="", $borderThickness="") + UpdateBoundaryStyle("enterprise", $bgColor, $fontColor, $borderColor, $shadowing, $shape, $type, $legendText, $borderStyle, $borderThickness) +!endprocedure +!unquoted procedure UpdateSystemBoundaryStyle($bgColor=$SYSTEM_BOUNDARY_BG_COLOR, $fontColor=$SYSTEM_BOUNDARY_COLOR, $borderColor=$SYSTEM_BOUNDARY_COLOR, $shadowing="", $shape="", $type="System", $legendText="", $borderStyle="", $borderThickness="") + UpdateBoundaryStyle("system", $bgColor, $fontColor, $borderColor, $shadowing, $shape, $type, $legendText, $borderStyle, $borderThickness) +!endprocedure + +' Sprites +' ################################## + +sprite $person [48x48/16] { +000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000 +0000000000000000000049BCCA7200000000000000000000 +0000000000000000006EFFFFFFFFB3000000000000000000 +00000000000000001CFFFFFFFFFFFF700000000000000000 +0000000000000001EFFFFFFFFFFFFFF80000000000000000 +000000000000000CFFFFFFFFFFFFFFFF6000000000000000 +000000000000007FFFFFFFFFFFFFFFFFF100000000000000 +00000000000001FFFFFFFFFFFFFFFFFFF900000000000000 +00000000000006FFFFFFFFFFFFFFFFFFFF00000000000000 +0000000000000BFFFFFFFFFFFFFFFFFFFF40000000000000 +0000000000000EFFFFFFFFFFFFFFFFFFFF70000000000000 +0000000000000FFFFFFFFFFFFFFFFFFFFF80000000000000 +0000000000000FFFFFFFFFFFFFFFFFFFFF80000000000000 +0000000000000DFFFFFFFFFFFFFFFFFFFF60000000000000 +0000000000000AFFFFFFFFFFFFFFFFFFFF40000000000000 +00000000000006FFFFFFFFFFFFFFFFFFFE00000000000000 +00000000000000EFFFFFFFFFFFFFFFFFF800000000000000 +000000000000007FFFFFFFFFFFFFFFFFF100000000000000 +000000000000000BFFFFFFFFFFFFFFFF5000000000000000 +0000000000000001DFFFFFFFFFFFFFF70000000000000000 +00000000000000000BFFFFFFFFFFFF500000000000000000 +0000000000000000005DFFFFFFFFA1000000000000000000 +0000000000000000000037ABB96100000000000000000000 +000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000 +000000000000025788300000000005886410000000000000 +000000000007DFFFFFFD9643347BFFFFFFFB400000000000 +0000000004EFFFFFFFFFFFFFFFFFFFFFFFFFFB1000000000 +000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFD200000000 +00000006FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE10000000 +0000003FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB0000000 +000000BFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5000000 +000003FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD000000 +000009FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF200000 +00000DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF600000 +00000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF800000 +00001FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA00000 +00001FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB00000 +00001FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB00000 +00001FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB00000 +00001FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA00000 +00000EFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF700000 +000006FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE100000 +0000008FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD3000000 +000000014555555555555555555555555555555300000000 +000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000 +} + +sprite $person2 [48x48/16] { +0000000000000000000049BCCA7200000000000000000000 +0000000000000000006EFFFFFFFFB3000000000000000000 +00000000000000001CFFFFFFFFFFFF700000000000000000 +0000000000000001EFFFFFFFFFFFFFF80000000000000000 +000000000000000CFFFFFFFFFFFFFFFF6000000000000000 +000000000000007FFFFFFFFFFFFFFFFFF100000000000000 +00000000000001FFFFFFFFFFFFFFFFFFF900000000000000 +00000000000006FFFFFFFFFFFFFFFFFFFF00000000000000 +0000000000000BFFFFFFFFFFFFFFFFFFFF40000000000000 +0000000000000EFFFFFFFFFFFFFFFFFFFF70000000000000 +0000000000000FFFFFFFFFFFFFFFFFFFFF80000000000000 +0000000000000FFFFFFFFFFFFFFFFFFFFF80000000000000 +0000000000000DFFFFFFFFFFFFFFFFFFFF60000000000000 +0000000000000AFFFFFFFFFFFFFFFFFFFF40000000000000 +00000000000006FFFFFFFFFFFFFFFFFFFE00000000000000 +00000000000000EFFFFFFFFFFFFFFFFFF800000000000000 +000000000000007FFFFFFFFFFFFFFFFFF100000000000000 +000000000000000BFFFFFFFFFFFFFFFF5000000000000000 +0000000000000001DFFFFFFFFFFFFFF70000000000000000 +00000000000000000BFFFFFFFFFFFF500000000000000000 +0000000000000000005DFFFFFFFFA1000000000000000000 +0000000000000000000037ABB96100000000000000000000 +000000000002578888300000000005888864100000000000 +0000000007DFFFFFFFFD9643347BFFFFFFFFFB4000000000 +00000004EFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB10000000 +0000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD2000000 +000006FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE100000 +00003FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB00000 +0000BFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF50000 +0003FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD0000 +0009FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2000 +000DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6000 +000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8000 +001FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB000 +001FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB000 +001FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB000 +001FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA000 +000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8000 +000DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6000 +0009FFFFFFFF8FFFFFFFFFFFFFFFFFFFFFF8FFFFFFFF2000 +0003FFFFFFFF8FFFFFFFFFFFFFFFFFFFFFF8FFFFFFFD0000 +0000BFFFFFFF8FFFFFFFFFFFFFFFFFFFFFF8FFFFFFF50000 +00003FFFFFFF8FFFFFFFFFFFFFFFFFFFFFF8FFFFFFB00000 +000006FFFFFF8FFFFFFFFFFFFFFFFFFFFFF8FFFFFE100000 +0000007FFFFF8FFFFFFFFFFFFFFFFFFFFFF8FFFFD2000000 +00000004EFFF8FFFFFFFFFFFFFFFFFFFFFF8FFFB10000000 +0000000007DF8FFFFFFFFFFFFFFFFFFFFFF8FB4000000000 +000000000002578888888888888888888864100000000000 +} + +sprite $robot [48x48/16] { +000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000 +000000000005BFFFFFFFFFFFFFFFFFFFFFE9100000000000 +0000000000AFFFFFFFFFFFFFFFFFFFFFFFFFE30000000000 +0000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFE1000000000 +000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFF8000000000 +000000004FFFFFFFFFFFFFFFFFFFFFFFFFFFFFC000000000 +000000005FFFFFFFFFFFFFFFFFFFFFFFFFFFFFD000000000 +000000005FFFFFFFFFFFFFFFFFFFFFFFFFFFFFE000000000 +000000005FFFFFFFFFFFFFFFFFFFFFFFFFFFFFE000000000 +000699405FFFFFFC427FFFFFFFFFC427FFFFFFE009982000 +008FFF705FFFFFE10006FFFFFFFE00007FFFFFE00FFFF100 +00CFFF705FFFFFA00001FFFFFFF900002FFFFFE00FFFF500 +00DFFF705FFFFFB00002FFFFFFFA00003FFFFFE00FFFF500 +00DFFF705FFFFFF4000AFFFFFFFF3000BFFFFFE00FFFF500 +00DFFF705FFFFFFFA8DFFFFFFFFFFA8DFFFFFFE00FFFF500 +00DFFF705FFFFFFFFFFFFFFFFFFFFFFFFFFFFFE00FFFF500 +00DFFF705FFFFFFFFFFFFFFFFFFFFFFFFFFFFFE00FFFF500 +00DFFF705FFFFFFFFFFFFFFFFFFFFFFFFFFFFFE00FFFF500 +00DFFF705FFFFFFFFFFFFFFFFFFFFFFFFFFFFFE00FFFF500 +00DFFF705FFFFFFFFFFFFFFFFFFFFFFFFFFFFFE00FFFF500 +00CFFF705FFFFFF87777777777777777CFFFFFE00FFFF500 +008FFF705FFFFFF100000000000000009FFFFFE00FFFF100 +000699405FFFFFF76666666666666666CFFFFFE009982000 +000000005FFFFFFFFFFFFFFFFFFFFFFFFFFFFFE000000000 +000000005FFFFFFFFFFFFFFFFFFFFFFFFFFFFFE000000000 +000000004FFFFFFFFFFFFFFFFFFFFFFFFFFFFFC000000000 +000000000EFFFFFFFFFFFFFFFFFFFFFFFFFFFF7000000000 +0000000005FFFFFFFFFFFFFFFFFFFFFFFFFFFD0000000000 +00000000004CFFFFFFFFFFFFFFFFFFFFFFFF910000000000 +000000000000011111111111111111111110000000000000 +000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000 +} + +sprite $robot2 [48x48/16] { +000000000000000088888888888888880000000000000000 +000000000000000AFFFFFFFFFFFFFFFFA000000000000000 +00000000000000CFFFFFFFFFFFFFFFFFFC00000000000000 +00000000000004EFFFFFFFFFFFFFFFFFFE40000000000000 +0000000000000AFFFFFFFFFFFFFFFFFFFFA0000000000000 +00000000000008FFFFFFFFFFFFFFFFFFFF80000000000000 +00000000000008FFFFFFFFFFFFFFFFFFFF80000000000000 +00000000000008FFFFFFFFFFFFFFFFFFFF80000000000000 +00000000000888FFFFFFFFFFFFFFFFFFFF88800000000000 +00000000008FF8FFFFFFFFFFFFFFFFFFFF8FF80000000000 +00000000008FF8FFFFFFFFFFFFFFFFFFFF8FF80000000000 +00000000008FF8FFFFFFFFFFFFFFFFFFFF8FF80000000000 +00000000008FF8FFFFFFFFFFFFFFFFFFFF8FF80000000000 +00000000008FF8FFFFFFFFFFFFFFFFFFFF8FF80000000000 +00000000008FF8FFFFFFFFFFFFFFFFFFFF8FF80000000000 +00000000000888FFFFFFFFFFFFFFFFFFFF88800000000000 +00000000000008FFFFFFFFFFFFFFFFFFFF80000000000000 +00000000000008FFFFFFFFFFFFFFFFFFFF80000000000000 +00000000000008FFFFFFFFFFFFFFFFFFFF80000000000000 +00000000000008FFFFFFFFFFFFFFFFFFFF80000000000000 +00000000000008FFFFFFFFFFFFFFFFFFFF80000000000000 +00000000000004CFFFFFFFFFFFFFFFFFFC40000000000000 +000000488888848CFFFFFFFFFFFFFFFFC848888884000000 +00000CFFFFFFFFC888888888888888888CFFFFFFFFC00000 +00008FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000 +0000CFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC0000 +0008FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8000 +0008FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8000 +0008FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8000 +0008FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8000 +0008FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8000 +0008FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8000 +0008FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8000 +0008FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8000 +0008FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8000 +0008FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8000 +0008FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8000 +0008FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8000 +0008FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8000 +0008FFFFFFFF8FFFFFFFFFFFFFFFFFFFFFF8FFFFFFFF8000 +0008FFFFFFFF8FFFFFFFFFFFFFFFFFFFFFF8FFFFFFFF8000 +0008FFFFFFFF8FFFFFFFFFFFFFFFFFFFFFF8FFFFFFFF8000 +0008FFFFFFFF8FFFFFFFFFFFFFFFFFFFFFF8FFFFFFFF8000 +0000CFFFFFFF8FFFFFFFFFFFFFFFFFFFFFF8FFFFFFFC0000 +00008FFFFFFF8FFFFFFFFFFFFFFFFFFFFFF8FFFFFFF80000 +00000CFFFFFF8FFFFFFFFFFFFFFFFFFFFFF8FFFFFFC00000 +000000488887578888888888888888888864688884000000 +000000000000000000000000000000000000000000000000 +} + +' Layout +' ################################## + +SetDefaultLegendEntries("person\nsystem\nexternal_person\nexternal_system\nenterprise_boundary\nsystem_boundary\nboundary") + +!procedure LAYOUT_WITH_LEGEND() +hide stereotype +legend right +|**Legend** | +|<$PERSON_BG_COLOR> person | +|<$SYSTEM_BG_COLOR> system| +|<$EXTERNAL_PERSON_BG_COLOR> external person | +|<$EXTERNAL_SYSTEM_BG_COLOR> external system | +endlegend +!endprocedure + +!global $defaultPersonSprite = "person" +!$dummy = $restoreEmpty("person", "sprite", $defaultPersonSprite, %true()) +UpdateElementStyle("person") +' workaround of plantuml.jar bug - person overwrites external_person setting +!$dummy = $restoreEmpty("external_person", "sprite", $defaultPersonSprite, %true()) +UpdateElementStyle("external_person") +!global $portraitPerson = "false" + +!procedure $clearPersonRestore() + !$dummy = $clearRestore("person", "sprite") + !$dummy = $clearRestore("person", "legendSprite") + %set_variable_value("$" + "person" + "ElementTagSprite", "") + UpdateElementStyle("person") + ' workaround of plantuml.jar bug - person overwrites external_person setting + !$dummy = $clearRestore("external_person", "sprite") + !$dummy = $clearRestore("external_person", "legendSprite") + %set_variable_value("$" + "external_person" + "ElementTagSprite", "") + UpdateElementStyle("external_person") +!endprocedure + +!procedure HIDE_PERSON_SPRITE() + !$defaultPersonSprite = "" + !$portraitPerson = "false" + $clearPersonRestore() +!endprocedure + +!unquoted procedure SHOW_PERSON_SPRITE($sprite="") + !if ($sprite == "") + !$defaultPersonSprite = "person" + !else + !$defaultPersonSprite = $sprite + !endif + !$dummy = $restoreEmpty("person", "sprite", $defaultPersonSprite, %true()) + UpdateElementStyle("person") + ' workaround of plantuml.jar bug - person overwrites external_person setting + !$dummy = $restoreEmpty("external_person", "sprite", $defaultPersonSprite, %true()) + UpdateElementStyle("external_person") + !$portraitPerson = "false" +!endprocedure + +!unquoted procedure SHOW_PERSON_PORTRAIT() + !$defaultPersonSprite = "" + !$portraitPerson = "portrait" + $clearPersonRestore() +!endprocedure + +!unquoted procedure SHOW_PERSON_OUTLINE() + !$defaultPersonSprite = "" + !$portraitPerson = "outline" + $clearPersonRestore() +!endprocedure + +' Elements +' ################################## + +!function $getPerson($label, $type, $descr, $sprite) + !if ($sprite == "") && ($defaultPersonSprite != "") + !$sprite = $defaultPersonSprite + !endif + !return $getElementBase($label, $type, $descr, $sprite) +!endfunction + +!unquoted procedure Person($alias, $label, $descr="", $sprite="", $tags="", $link="", $type="") +!$sprite=$toElementArg($sprite, $tags, "ElementTagSprite", "person") +' $type reuses $techn definition of $tags +!$type=$toElementArg($type, $tags, "ElementTagTechn", "person") +!if ($portraitPerson == "portrait") && ($sprite == "") +actor "$getPerson($label, $type, $descr, $sprite)$getProps()" $toStereos("person", $tags) as $alias $getLink($link) +!elseif ($portraitPerson == "outline") && ($sprite == "") +person "$getPerson($label, $type, $descr, $sprite)$getProps()" $toStereos("person", $tags) as $alias $getLink($link) +!else +rectangle "$getPerson($label, $type, $descr, $sprite)$getProps()" $toStereos("person", $tags) as $alias $getLink($link) +!endif +!endprocedure + +!unquoted procedure Person_Ext($alias, $label, $descr="", $sprite="", $tags="", $link="", $type="") +!$sprite=$toElementArg($sprite, $tags, "ElementTagSprite", "external_person") +' $type reuses $techn definition of $tags +!$type=$toElementArg($type, $tags, "ElementTagTechn", "external_person") +!if ($portraitPerson == "portrait") && ($sprite == "") +actor "$getPerson($label, $type, $descr, $sprite)$getProps()" $toStereos("external_person", $tags) as $alias $getLink($link) +!elseif ($portraitPerson == "outline") && ($sprite == "") +person "$getPerson($label, $type, $descr, $sprite)$getProps()" $toStereos("external_person", $tags) as $alias $getLink($link) +!else +rectangle "$getPerson($label, $type, $descr, $sprite)$getProps()" $toStereos("external_person", $tags) as $alias $getLink($link) +!endif +!endprocedure + +!unquoted procedure System($alias, $label, $descr="", $sprite="", $tags="", $link="", $type="", $baseShape="rectangle") + ' $type reuses $techn definition of $tags + $getElementLine($baseShape, "system", $alias, $label, $type, $descr, $sprite, $tags, $link) +!endprocedure + +!unquoted procedure SystemDb($alias, $label, $descr="", $sprite="", $tags="", $link="", $type="") + ' $type reuses $techn definition of $tags + $getElementLine("database", "system", $alias, $label, $type, $descr, $sprite, $tags, $link) +!endprocedure + +!unquoted procedure SystemQueue($alias, $label, $descr="", $sprite="", $tags="", $link="", $type="") + ' $type reuses $techn definition of $tags + $getElementLine("queue", "system", $alias, $label, $type, $descr, $sprite, $tags, $link) +!endprocedure + +!unquoted procedure System_Ext($alias, $label, $descr="", $sprite="", $tags="", $link="", $type="", $baseShape="rectangle") + ' $type reuses $techn definition of $tags + $getElementLine($baseShape , "external_system", $alias, $label, $type, $descr, $sprite, $tags, $link) +!endprocedure + +!unquoted procedure SystemDb_Ext($alias, $label, $descr="", $sprite="", $tags="", $link="", $type="") + ' $type reuses $techn definition of $tags + $getElementLine("database", "external_system", $alias, $label, $type, $descr, $sprite, $tags, $link) +!endprocedure + +!unquoted procedure SystemQueue_Ext($alias, $label, $descr="", $sprite="", $tags="", $link="", $type="") + ' $type reuses $techn definition of $tags + $getElementLine("queue", "external_system", $alias, $label, $type, $descr, $sprite, $tags, $link) +!endprocedure + +' Boundaries +' ################################## + +!unquoted procedure Enterprise_Boundary($alias, $label, $tags="", $link="") + !if ($tags != "") + !$allTags = $tags + '+enterprise' + !else + !$allTags = 'enterprise' + !endif + ' $type defined via $tag style + Boundary($alias, $label, "", $allTags, $link) +!endprocedure + +!unquoted procedure System_Boundary($alias, $label, $tags="", $link="") + !if ($tags != "") + !$allTags = $tags + '+system' + !else + !$allTags = 'system' + !endif + ' $type defined via $tag style + Boundary($alias, $label, "", $allTags, $link) +!endprocedure diff --git a/.c4s/C4_Deployment.puml b/.c4s/C4_Deployment.puml new file mode 100644 index 0000000..afc9945 --- /dev/null +++ b/.c4s/C4_Deployment.puml @@ -0,0 +1,140 @@ +' convert it with additional command line argument -DRELATIVE_INCLUDE="relative/absolute" to use locally +!if %variable_exists("RELATIVE_INCLUDE") + !include ./C4_Container.puml +!else + !include https://raw.githubusercontent.com/plantuml-stdlib/C4-PlantUML/master/C4_Container.puml +!endif + +' Colors +' ################################## + +!$NODE_FONT_COLOR ?= "#000000" +!$NODE_BG_COLOR ?= "#FFFFFF" +!$NODE_BORDER_COLOR ?= "#A2A2A2" + +' Styling +' ################################## + +' PlantUML supports no automatic line breaks of "PlantUML containers" (C4 Deployment_Node is a "PlantUML container") +' therefore (Deployment_)Node() implements an automatic line break based on spaces (like in all other objects). +' If a $type contains \n then these are used (and no automatic space based line breaks are done) +' $NODE_TYPE_MAX_CHAR_WIDTH defines the automatic line break position +!$NODE_TYPE_MAX_CHAR_WIDTH ?= 35 +!$NODE_DESCR_MAX_CHAR_WIDTH ?= 32 + +UpdateElementStyle("node", $bgColor=$NODE_BG_COLOR, $fontColor=$NODE_FONT_COLOR, $borderColor=$NODE_BORDER_COLOR, false) +skinparam rectangle<> { + FontStyle normal +} + +' shortcuts with default colors +' node specific: $techn is only used in old scripts, new scripts uses $type ($techn has to remain, it could be called via named argument) +!unquoted procedure AddNodeTag($tagStereo, $bgColor="", $fontColor="", $borderColor="", $shadowing="", $shape="", $sprite="", $type="", $legendText="", $legendSprite="", $techn="", $borderStyle="", $borderThickness="") + !$type=$type+$techn + $addElementTagInclReuse("node", $tagStereo, $bgColor, $fontColor, $borderColor, $shadowing, $shape, $sprite, $type, $legendText, $legendSprite, $borderStyle, $borderThickness) +!endprocedure + +' Layout +' ################################## + +' comment if node should not be added to legend. No calculated legend extension required +SetDefaultLegendEntries("person\nsystem\ncontainer\nexternal_person\nexternal_system\nexternal_container\nnode\nenterprise_boundary\nsystem_boundary\ncontainer_boundary\nboundary") + +' Line breaks +' ################################## + +' $breakTechn() in C4 supports //...//; $breakNode() in C4_Deployment supports no //....// +!unquoted function $breakNode($text, $widthStr) + !$usedNewLine = '\n' + !return $breakText($text, $usedNewLine, $widthStr) +!endfunction + +' Elements +' ################################## + +!function $getNode($label, $type, $descr, $sprite) + !$nodeText = "" + !if ($sprite != "") + !$nodeText = $nodeText + $getSprite($sprite) + '\n' + !endif + !$nodeText = $nodeText + '== ' + $breakText($label, "\n== ") + !if ($type != "") + !$nodeText = $nodeText + '\n[' + $breakNode($type, $NODE_TYPE_MAX_CHAR_WIDTH) + ']' + !endif + !if ($descr != "") + !$nodeText = $nodeText + '\n\n' + $breakDescr($descr, $NODE_DESCR_MAX_CHAR_WIDTH) + !endif + !return $nodeText +!endfunction + +!function $getNode_L($label, $type, $descr, $sprite) + !$nodeText = "" + !if ($sprite != "") + !$nodeText = $nodeText + $getSprite($sprite) + '\l' + !endif + !$nodeText = $nodeText + '== ' + $breakText($label, "\l== ") + !if ($type != "") + !$nodeText = $nodeText + '\l[' + $breakNode($type, $NODE_TYPE_MAX_CHAR_WIDTH) + ']' + !endif + !if ($descr != "") + !$nodeText = $nodeText + '\l\l' + $breakDescr($descr, $NODE_DESCR_MAX_CHAR_WIDTH) + !endif + !return $nodeText +!endfunction + +!function $getNode_R($label, $type, $descr, $sprite) + !$nodeText = "" + !if ($sprite != "") + !$nodeText = $nodeText + $getSprite($sprite) + '\r' + !endif + !$nodeText = $nodeText + '== ' + $breakText($label, "\r== ") + !if ($type != "") + !$nodeText = $nodeText + '\r[' + $breakNode($type, $NODE_TYPE_MAX_CHAR_WIDTH) + ']' + !endif + !if ($descr != "") + !$nodeText = $nodeText + '\r\r' + $breakDescr($descr, $NODE_DESCR_MAX_CHAR_WIDTH) + !endif + !return $nodeText +!endfunction + +!unquoted procedure Deployment_Node($alias, $label, $type="", $descr="", $sprite="", $tags="", $link="") +!$sprite=$toElementArg($sprite, $tags, "ElementTagSprite", "node") +' nodes $type reuses $techn definition of $tags +!$type=$toElementArg($type, $tags, "ElementTagTechn", "node") +rectangle "$getNode($label, $type, $descr, $sprite)$getProps()" $toStereos("node",$tags) as $alias $getLink($link) +!endprocedure + +!unquoted procedure Deployment_Node_L($alias, $label, $type="", $descr="", $sprite="", $tags="", $link="") +!$sprite=$toElementArg($sprite, $tags, "ElementTagSprite", "node") +' nodes $type reuses $techn definition of $tags +!$type=$toElementArg($type, $tags, "ElementTagTechn", "node") +rectangle "$getNode_L($label, $type, $descr, $sprite)$getProps_L()" $toStereos("node",$tags) as $alias $getLink($link) +!endprocedure + +!unquoted procedure Deployment_Node_R($alias, $label, $type="", $descr="", $sprite="", $tags="", $link="") +!$sprite=$toElementArg($sprite, $tags, "ElementTagSprite", "node") +' nodes $type reuses $techn definition of $tags +!$type=$toElementArg($type, $tags, "ElementTagTechn", "node") +rectangle "$getNode_R($label, $type, $descr, $sprite)$getProps_R()" $toStereos("node",$tags) as $alias $getLink($link) +!endprocedure + +!unquoted procedure Node($alias, $label, $type="", $descr="", $sprite="", $tags="", $link="") +!$sprite=$toElementArg($sprite, $tags, "ElementTagSprite", "node") +' nodes $type reuses $techn definition of $tags +!$type=$toElementArg($type, $tags, "ElementTagTechn", "node") +rectangle "$getNode($label, $type, $descr, $sprite)$getProps()" $toStereos("node",$tags) as $alias $getLink($link) +!endprocedure + +!unquoted procedure Node_L($alias, $label, $type="", $descr="", $sprite="", $tags="", $link="") +!$sprite=$toElementArg($sprite, $tags, "ElementTagSprite", "node") +' nodes $type reuses $techn definition of $tags +!$type=$toElementArg($type, $tags, "ElementTagTechn", "node") +rectangle "$getNode_L($label, $type, $descr, $sprite)$getProps_L()" $toStereos("node",$tags) as $alias $getLink($link) +!endprocedure + +!unquoted procedure Node_R($alias, $label, $type="", $descr="", $sprite="", $tags="", $link="") +!$sprite=$toElementArg($sprite, $tags, "ElementTagSprite", "node") +' nodes $type reuses $techn definition of $tags +!$type=$toElementArg($type, $tags, "ElementTagTechn", "node") +rectangle "$getNode_R($label, $type, $descr, $sprite)$getProps_R()" $toStereos("node",$tags) as $alias $getLink($link) +!endprocedure diff --git a/.c4s/C4_Sequence.puml b/.c4s/C4_Sequence.puml new file mode 100644 index 0000000..ee40694 --- /dev/null +++ b/.c4s/C4_Sequence.puml @@ -0,0 +1,398 @@ +' convert it with additional command line argument -DRELATIVE_INCLUDE="relative/absolute" to use locally +!if %variable_exists("RELATIVE_INCLUDE") + !include ./C4_Component.puml +!else + !include https://raw.githubusercontent.com/plantuml-stdlib/C4-PlantUML/master/C4_Component.puml +!endif + +' Scope: Interactions in an enterprise, software system or container. +' Primary and supporting elements: Depends on the diagram scope - +' enterprise - people and software systems Related to the enterprise in scope +' software system - see system context or container diagrams, +' container - see component diagram. +' Intended audience: Technical and non-technical people, inside and outside of the software development team. + +' Sequence diagram introduces (automatically) numbered interactions: +' (lowercase) increment($offset=1): increase current index (procedure which has no direct output) +' (lowercase) setIndex($new_index): set the new index (procedure which has no direct output) +' +' (Uppercase) LastIndex(): return the last used index (function which can be used as argument) +' (Uppercase) Index($offset=1): returns current index and calculates next index (function which can be used as argument) +' (Uppercase) SetIndex($new_index): returns new set index and calculates next index (function which can be used as argument) + +' enables multi-level boxes +!pragma teoz true + + +' Legend redefintion +' ################################## +' sequence has no dashed boxes +!if ($LEGEND_DASHED_BOUNDARY == "dashed") + !$LEGEND_DASHED_BOUNDARY = "" +!endif +!if ($LEGEND_DASHED_TRANSPARENT_BOUNDARY == "dashed") + !$LEGEND_DASHED_TRANSPARENT_BOUNDARY = "" +!endif +UpdateBoundaryStyle("", $bgColor=$BOUNDARY_BG_COLOR, $fontColor=$BOUNDARY_COLOR, $borderColor=$BOUNDARY_COLOR) +UpdateBoundaryStyle("enterprise", $bgColor=$ENTERPRISE_BOUNDARY_BG_COLOR, $fontColor=$ENTERPRISE_BOUNDARY_COLOR, $borderColor=$ENTERPRISE_BOUNDARY_COLOR, $type="Enterprise") +UpdateBoundaryStyle("system", $bgColor=$SYSTEM_BOUNDARY_BG_COLOR, $fontColor=$SYSTEM_BOUNDARY_COLOR, $borderColor=$SYSTEM_BOUNDARY_COLOR, $type="System") +UpdateBoundaryStyle("container", $bgColor=$CONTAINER_BOUNDARY_BG_COLOR, $fontColor=$CONTAINER_BOUNDARY_COLOR, $borderColor=$CONTAINER_BOUNDARY_COLOR, $type="Container") + +' Styling and Layout +' ################################## + +!global $display_element_description = %false() + +' typically the element/participant descriptions are not displayed in a sequence diagram, but it can be activated with this call +!unquoted procedure SHOW_ELEMENT_DESCRIPTIONS($show="true") +!if ($show == "true") + !global $display_element_description = %true() +!else + !global $display_element_description = %false() +!endif +!endprocedure + +' typically the foot boxes descriptions are not displayed in a sequence diagram, but it can be activated with this call +!unquoted procedure SHOW_FOOT_BOXES($show="true") +!if ($show == "true") + show footbox +!else + hide footbox +!endif +!endprocedure + +!global $show_index = %false() +' All relation specific (default) ordinary index numbers can be shown with this call +!unquoted procedure SHOW_INDEX($show="true") +!if ($show == "true") + !global $show_index = %true() +!else + !global $show_index = %false() +!endif +!endprocedure + +' ======= if no theme is defined hide foot box and activate C4_blue styles +!if (%variable_exists("$THEME")) +!else +' $BOUNDARY_BG_COLOR... have to be defined in theme itself that it can be used in styles,... +' (no default values which are defined in C4.puml) +' If skinparams and styles are defined with concrete values no variables are required +!$BOUNDARY_BG_COLOR ?= "transparent" +!$BOUNDARY_COLOR ?= "#444444" +!$ARROW_COLOR ?= "#666666" + +' replace transparent with concrete background that it can be used as font color too +!if ($BOUNDARY_BG_COLOR == "transparent") + !$SEQUENCE_BG_COLOR = white +!else + !$SEQUENCE_BG_COLOR = $BOUNDARY_BG_COLOR +!endif + +' "C4 styled" default is no foot boxes +hide footbox +' "C4 styled" default is that lifeline is arrow color +skinparam SequenceLifelineBorderColor $ARROW_COLOR + +skinparam SequenceGroupBodyBackgroundColor $SEQUENCE_BG_COLOR +skinparam SequenceGroupFontColor $BOUNDARY_COLOR +skinparam SequenceGroupBackgroundColor $BOUNDARY_COLOR +skinparam SequenceGroupHeaderFontColor $SEQUENCE_BG_COLOR +skinparam SequenceGroupBorderColor $BOUNDARY_COLOR + +skinparam SequenceReferenceBackgroundColor $SEQUENCE_BG_COLOR +skinparam SequenceReferenceFontColor $BOUNDARY_COLOR +skinparam SequenceReferenceHeaderBackgroundColor $BOUNDARY_COLOR +' VIA STYLE +' skinparam SequenceReferenceHeaderFontColor $SEQUENCE_BG_COLOR + +skinparam SequenceReferenceBorderColor $BOUNDARY_COLOR + +skinparam SequenceDividerBackgroundColor $SEQUENCE_BG_COLOR +skinparam SequenceDividerFontColor $BOUNDARY_COLOR +skinparam SequenceDividerBorderColor $BOUNDARY_COLOR + +' VIA STYLE +' skinparam SequenceDelayFontColor green + +!endif +' ======= if no theme is defined hide foot box and activate C4_blue styles + +' Elements redefinition +' ################################## + +' all elements have to be displayed as participant +' participants requires ` %newline()` instead of `\n` + +!unquoted function $breakWithNewline($text, $lineEnd, $lineStart, $widthStr="-1") +!$width = %intval($widthStr) +!$multiLine = "" +!if (%strpos($text, "\n") >= 0) + !while (%strpos($text, "\n") >= 0) + !$brPos = %strpos($text, "\n") + !if ($brPos > 0) + !$multiLine = $multiLine + %substr($text, 0, $brPos) + $lineEnd + %newline() + $lineStart + !else + ' non breaking change that newLine breaks with formats can be used with \n\n + !$multiLine = $multiLine + "" + $lineEnd + %newline() + $lineStart + !endif + !$text = %substr($text, $brPos+2) + !if (%strlen($text) == 0) + !$text = "" + !endif + !endwhile +!else + !while ($width>0 && %strlen($text) > $width) + !$brPos = $width + !while ($brPos > 0 && %substr($text, $brPos, 1) != ' ') + !$brPos = $brPos - 1 + !endwhile + + !if ($brPos < 1) + !$brPos = %strpos($text, " ") + !else + !endif + + !if ($brPos > 0) + !$multiLine = $multiLine + %substr($text, 0, $brPos) + $lineEnd + %newline() + $lineStart + !$text = %substr($text, $brPos + 1) + !else + !$multiLine = $multiLine+ $text + !$text = "" + !endif + !endwhile +!endif +!if (%strlen($text) > 0) + !$multiLine = $multiLine + $text +!endif +!return $multiLine +!endfunction + +!unquoted function $breakNewLineLabel($text) +!$multiLine = $breakWithNewline($text, "", "==") +!return $multiLine +!endfunction + +!unquoted function $breakNewLineDescr($text) + !return $breakWithNewline($text, "", "", $REL_DESCR_MAX_CHAR_WIDTH) +!endfunction + +!unquoted function $breakNewLineTechn($text) + !$lineStart = "//" + !$lineEnd = '//' + !return $breakWithNewline($text, $lineStart, $lineEnd, $REL_TECHN_MAX_CHAR_WIDTH) +!endfunction + +' description is not displayed (size too big, line breaks not supported) +' properties are not displayed in sequence diagram (size would be too big) +' $breakLabel() not required by participant +!procedure $getParticipant($elementType, $alias, $label, $techn, $descr, $sprite, $tags, $link) + !$sprite=$toElementArg($sprite, $tags, "ElementTagSprite", $elementType) + !$techn=$toElementArg($techn, $tags, "ElementTagTechn", $elementType) + !$stereo = $toStereos($elementType,$tags) + !$calcLabel = "== " + $breakNewLineLabel($label) + !$calcTech = "//[" + $breakNewLineTechn($techn) + "]//" + !$calcDescr = $breakNewLineDescr($descr) + !$calcLink = $getLink($link) + +participant $alias $stereo $calcLink [ +!if ($sprite != "") +$getSprite($sprite) +!endif +!if ($label != "") +$calcLabel +!endif +!if ($techn != "") +$calcTech +!endif +!if ($display_element_description == %true() && $descr != "") + +$calcDescr +!endif +] +!endprocedure + + +!unquoted procedure Person($alias, $label, $descr="", $sprite="", $tags="", $link="", $type="") + ' $type reuses $techn definition of $tags + $getParticipant("person", $alias, $label, $type, $descr, $sprite, $tags, $link) +!endprocedure + +!unquoted procedure Person_Ext($alias, $label, $descr="", $sprite="", $tags="", $link="", $type="") + ' $type reuses $techn definition of $tags + $getParticipant("external_person", $alias, $label, $type, $descr, $sprite, $tags, $link) +!endprocedure + +!unquoted procedure System($alias, $label, $descr="", $sprite="", $tags="", $link="", $type="", $baseShape="rectangle") + ' $type reuses $techn definition of $tags + $getParticipant("system", $alias, $label, $type, $descr, $sprite, $tags, $link) +!endprocedure + +!unquoted procedure SystemDb($alias, $label, $descr="", $sprite="", $tags="", $link="", $type="") + ' $type reuses $techn definition of $tags + $getParticipant("system", $alias, $label, $type, $descr, $sprite, $tags, $link) +!endprocedure + +!unquoted procedure SystemQueue($alias, $label, $descr="", $sprite="", $tags="", $link="", $type="") + ' $type reuses $techn definition of $tags + $getParticipant("system", $alias, $label, $type, $descr, $sprite, $tags, $link) +!endprocedure + +!unquoted procedure System_Ext($alias, $label, $descr="", $sprite="", $tags="", $link="", $type="", $baseShape="rectangle") + ' $type reuses $techn definition of $tags + $getParticipant("external_system", $alias, $label, $type, $descr, $sprite, $tags, $link) +!endprocedure + +!unquoted procedure SystemDb_Ext($alias, $label, $descr="", $sprite="", $tags="", $link="", $type="") + ' $type reuses $techn definition of $tags + $getParticipant("external_system", $alias, $label, $type, $descr, $sprite, $tags, $link) +!endprocedure + +!unquoted procedure SystemQueue_Ext($alias, $label, $descr="", $sprite="", $tags="", $link="", $type="") + ' $type reuses $techn definition of $tags + $getParticipant("external_system", $alias, $label, $type, $descr, $sprite, $tags, $link) +!endprocedure + + + +!unquoted procedure Container($alias, $label, $techn="", $descr="", $sprite="", $tags="", $link="", $baseShape="rectangle") + $getParticipant("container", $alias, $label, $techn, $descr, $sprite, $tags, $link) +!endprocedure + +!unquoted procedure ContainerDb($alias, $label, $techn="", $descr="", $sprite="", $tags="", $link="") + $getParticipant("container", $alias, $label, $techn, $descr, $sprite, $tags, $link) +!endprocedure + +!unquoted procedure ContainerQueue($alias, $label, $techn="", $descr="", $sprite="", $tags="", $link="") + $getParticipant("container", $alias, $label, $techn, $descr, $sprite, $tags, $link) +!endprocedure + +!unquoted procedure Container_Ext($alias, $label, $techn="", $descr="", $sprite="", $tags="", $link="", $baseShape="rectangle") + $getParticipant("external_container", $alias, $label, $techn, $descr, $sprite, $tags, $link) +!endprocedure + +!unquoted procedure ContainerDb_Ext($alias, $label, $techn="", $descr="", $sprite="", $tags="", $link="") + $getParticipant("external_container", $alias, $label, $techn, $descr, $sprite, $tags, $link) +!endprocedure + +!unquoted procedure ContainerQueue_Ext($alias, $label, $techn="", $descr="", $sprite="", $tags="", $link="") + $getParticipant("external_container", $alias, $label, $techn, $descr, $sprite, $tags, $link) +!endprocedure + + + +!unquoted procedure Component($alias, $label, $techn="", $descr="", $sprite="", $tags="", $link="", $baseShape="rectangle") + $getParticipant("component", $alias, $label, $techn, $descr, $sprite, $tags, $link) +!endprocedure + +!unquoted procedure ComponentDb($alias, $label, $techn="", $descr="", $sprite="", $tags="", $link="") + $getParticipant("component", $alias, $label, $techn, $descr, $sprite, $tags, $link) +!endprocedure + +!unquoted procedure ComponentQueue($alias, $label, $techn="", $descr="", $sprite="", $tags="", $link="") + $getParticipant("component", $alias, $label, $techn, $descr, $sprite, $tags, $link) +!endprocedure + +!unquoted procedure Component_Ext($alias, $label, $techn="", $descr="", $sprite="", $tags="", $link="", $baseShape="rectangle") + $getParticipant("external_component", $alias, $label, $techn, $descr, $sprite, $tags, $link) +!endprocedure + +!unquoted procedure ComponentDb_Ext($alias, $label, $techn="", $descr="", $sprite="", $tags="", $link="") + $getParticipant("external_component", $alias, $label, $techn, $descr, $sprite, $tags, $link) +!endprocedure + +!unquoted procedure ComponentQueue_Ext($alias, $label, $techn="", $descr="", $sprite="", $tags="", $link="") + $getParticipant("external_component", $alias, $label, $techn, $descr, $sprite, $tags, $link) +!endprocedure + + +' Boundary redefinition +' ################################## + +' all boundaries have to be displayed as box and +' !!! important changes: without { at the end; and boundary ends with Boundary_End() instead of } + +' alias ignored +' $breakLabel() not required by participant + +!unquoted procedure Boundary($alias, $label, $type="", $tags="", $link="") +!$boundaryTags = $addBoundaryPostfix($tags) +' nodes $type reuses $techn definition of $boundaryTags +!$type=$toElementArg($type, $boundaryTags, "ElementTagTechn", "boundary") +!if ($link != "") + !$usedNewLine = ']]\n== [[' + $link + ' ' + !$labelType = '== [[' + $link + ' ' + $breakText($label, $usedNewLine) + ']]' +!else + !$usedNewLine = '\n== ' + !$labelType = $breakText($label, $usedNewLine) +!endif +!if (type != "") + !$labelType = $labelType + '\n[' + $type + ']' +!endif +box "$labelType" $toStereos("boundary", $boundaryTags) +!endprocedure + +!procedure Boundary_End() +end box +!endprocedure + +!unquoted procedure Enterprise_Boundary($alias, $label, $tags="", $link="") + !if ($tags != "") + !$allTags = $tags + '+enterprise' + !else + !$allTags = 'enterprise' + !endif + ' $type defined via $tag style + Boundary($alias, $label, "", $allTags, $link) +!endprocedure + +!unquoted procedure System_Boundary($alias, $label, $tags="", $link="") + !if ($tags != "") + !$allTags = $tags + '+system' + !else + !$allTags = 'system' + !endif + ' $type defined via $tag style + Boundary($alias, $label, "", $allTags, $link) +!endprocedure + +!unquoted procedure Container_Boundary($alias, $label, $tags="", $link="") + !if ($tags != "") + !$allTags = $tags + '+container' + !else + !$allTags = 'container' + !endif + ' $type defined via $tag style + Boundary($alias, $label, "", $allTags, $link) +!endprocedure + +' Relationship (redefinition) +' ################################## + +' only Rel is supported in sequence diagram + +' first Rel() supports the $index and $rel argument too; second Rel() overwrites C4.puml definition +' don't add empty lines in procedure otherwise & calls are not working anymore '& a -> b: call' are not working anymore +!unquoted procedure Rel($from, $to, $label, $techn="", $descr="", $sprite="", $tags="", $link="", $index="", $rel="") + !if ($show_index == %true()) + !$pre = $getPrefix($index) + !else + !$pre = "" + !endif + !if ($rel == "") + !$rel = "->" + !endif +$getRel($rel, $from, $to, $pre + $label, $techn, $descr, $sprite, $tags, $link) +!endprocedure +!unquoted procedure Rel($from, $to, $label, $techn="", $descr="", $sprite="", $tags="", $link="") +Rel($from, $to, $label, $techn, $descr, $sprite, $tags, $link, "", "") +!endprocedure \ No newline at end of file diff --git a/C4Sharp.sln b/C4Sharp.sln index 8487151..c521537 100644 --- a/C4Sharp.sln +++ b/C4Sharp.sln @@ -10,28 +10,89 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "C4Sharp.Tools", "src\C4Shar EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ModelDiagrams", "samples\ModelDiagrams\ModelDiagrams.csproj", "{A6E8E401-D8DE-4640-A6FA-2242A07F2481}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "C4Sharp.Generator", "src\C4Sharp.Generator\C4Sharp.Generator.csproj", "{608F2323-04CF-460F-8D98-D65472570FD5}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "C4Sharp.Diagrams", "src\C4Sharp.Diagrams\C4Sharp.Diagrams.csproj", "{4AA29DB8-221B-422F-852C-1CA6043763AC}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 Release|Any CPU = Release|Any CPU + Release|x64 = Release|x64 + Release|x86 = Release|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {B3850A7A-EBB2-4C33-827B-98B88901A638}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {B3850A7A-EBB2-4C33-827B-98B88901A638}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B3850A7A-EBB2-4C33-827B-98B88901A638}.Debug|x64.ActiveCfg = Debug|Any CPU + {B3850A7A-EBB2-4C33-827B-98B88901A638}.Debug|x64.Build.0 = Debug|Any CPU + {B3850A7A-EBB2-4C33-827B-98B88901A638}.Debug|x86.ActiveCfg = Debug|Any CPU + {B3850A7A-EBB2-4C33-827B-98B88901A638}.Debug|x86.Build.0 = Debug|Any CPU {B3850A7A-EBB2-4C33-827B-98B88901A638}.Release|Any CPU.ActiveCfg = Release|Any CPU {B3850A7A-EBB2-4C33-827B-98B88901A638}.Release|Any CPU.Build.0 = Release|Any CPU + {B3850A7A-EBB2-4C33-827B-98B88901A638}.Release|x64.ActiveCfg = Release|Any CPU + {B3850A7A-EBB2-4C33-827B-98B88901A638}.Release|x64.Build.0 = Release|Any CPU + {B3850A7A-EBB2-4C33-827B-98B88901A638}.Release|x86.ActiveCfg = Release|Any CPU + {B3850A7A-EBB2-4C33-827B-98B88901A638}.Release|x86.Build.0 = Release|Any CPU {AEF17681-C9AB-4C49-8B06-06E5AF8C4237}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {AEF17681-C9AB-4C49-8B06-06E5AF8C4237}.Debug|Any CPU.Build.0 = Debug|Any CPU + {AEF17681-C9AB-4C49-8B06-06E5AF8C4237}.Debug|x64.ActiveCfg = Debug|Any CPU + {AEF17681-C9AB-4C49-8B06-06E5AF8C4237}.Debug|x64.Build.0 = Debug|Any CPU + {AEF17681-C9AB-4C49-8B06-06E5AF8C4237}.Debug|x86.ActiveCfg = Debug|Any CPU + {AEF17681-C9AB-4C49-8B06-06E5AF8C4237}.Debug|x86.Build.0 = Debug|Any CPU {AEF17681-C9AB-4C49-8B06-06E5AF8C4237}.Release|Any CPU.ActiveCfg = Release|Any CPU {AEF17681-C9AB-4C49-8B06-06E5AF8C4237}.Release|Any CPU.Build.0 = Release|Any CPU + {AEF17681-C9AB-4C49-8B06-06E5AF8C4237}.Release|x64.ActiveCfg = Release|Any CPU + {AEF17681-C9AB-4C49-8B06-06E5AF8C4237}.Release|x64.Build.0 = Release|Any CPU + {AEF17681-C9AB-4C49-8B06-06E5AF8C4237}.Release|x86.ActiveCfg = Release|Any CPU + {AEF17681-C9AB-4C49-8B06-06E5AF8C4237}.Release|x86.Build.0 = Release|Any CPU {A6E8E401-D8DE-4640-A6FA-2242A07F2481}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {A6E8E401-D8DE-4640-A6FA-2242A07F2481}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A6E8E401-D8DE-4640-A6FA-2242A07F2481}.Debug|x64.ActiveCfg = Debug|Any CPU + {A6E8E401-D8DE-4640-A6FA-2242A07F2481}.Debug|x64.Build.0 = Debug|Any CPU + {A6E8E401-D8DE-4640-A6FA-2242A07F2481}.Debug|x86.ActiveCfg = Debug|Any CPU + {A6E8E401-D8DE-4640-A6FA-2242A07F2481}.Debug|x86.Build.0 = Debug|Any CPU {A6E8E401-D8DE-4640-A6FA-2242A07F2481}.Release|Any CPU.ActiveCfg = Release|Any CPU {A6E8E401-D8DE-4640-A6FA-2242A07F2481}.Release|Any CPU.Build.0 = Release|Any CPU + {A6E8E401-D8DE-4640-A6FA-2242A07F2481}.Release|x64.ActiveCfg = Release|Any CPU + {A6E8E401-D8DE-4640-A6FA-2242A07F2481}.Release|x64.Build.0 = Release|Any CPU + {A6E8E401-D8DE-4640-A6FA-2242A07F2481}.Release|x86.ActiveCfg = Release|Any CPU + {A6E8E401-D8DE-4640-A6FA-2242A07F2481}.Release|x86.Build.0 = Release|Any CPU + {608F2323-04CF-460F-8D98-D65472570FD5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {608F2323-04CF-460F-8D98-D65472570FD5}.Debug|Any CPU.Build.0 = Debug|Any CPU + {608F2323-04CF-460F-8D98-D65472570FD5}.Debug|x64.ActiveCfg = Debug|Any CPU + {608F2323-04CF-460F-8D98-D65472570FD5}.Debug|x64.Build.0 = Debug|Any CPU + {608F2323-04CF-460F-8D98-D65472570FD5}.Debug|x86.ActiveCfg = Debug|Any CPU + {608F2323-04CF-460F-8D98-D65472570FD5}.Debug|x86.Build.0 = Debug|Any CPU + {608F2323-04CF-460F-8D98-D65472570FD5}.Release|Any CPU.ActiveCfg = Release|Any CPU + {608F2323-04CF-460F-8D98-D65472570FD5}.Release|Any CPU.Build.0 = Release|Any CPU + {608F2323-04CF-460F-8D98-D65472570FD5}.Release|x64.ActiveCfg = Release|Any CPU + {608F2323-04CF-460F-8D98-D65472570FD5}.Release|x64.Build.0 = Release|Any CPU + {608F2323-04CF-460F-8D98-D65472570FD5}.Release|x86.ActiveCfg = Release|Any CPU + {608F2323-04CF-460F-8D98-D65472570FD5}.Release|x86.Build.0 = Release|Any CPU + {4AA29DB8-221B-422F-852C-1CA6043763AC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4AA29DB8-221B-422F-852C-1CA6043763AC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4AA29DB8-221B-422F-852C-1CA6043763AC}.Debug|x64.ActiveCfg = Debug|Any CPU + {4AA29DB8-221B-422F-852C-1CA6043763AC}.Debug|x64.Build.0 = Debug|Any CPU + {4AA29DB8-221B-422F-852C-1CA6043763AC}.Debug|x86.ActiveCfg = Debug|Any CPU + {4AA29DB8-221B-422F-852C-1CA6043763AC}.Debug|x86.Build.0 = Debug|Any CPU + {4AA29DB8-221B-422F-852C-1CA6043763AC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4AA29DB8-221B-422F-852C-1CA6043763AC}.Release|Any CPU.Build.0 = Release|Any CPU + {4AA29DB8-221B-422F-852C-1CA6043763AC}.Release|x64.ActiveCfg = Release|Any CPU + {4AA29DB8-221B-422F-852C-1CA6043763AC}.Release|x64.Build.0 = Release|Any CPU + {4AA29DB8-221B-422F-852C-1CA6043763AC}.Release|x86.ActiveCfg = Release|Any CPU + {4AA29DB8-221B-422F-852C-1CA6043763AC}.Release|x86.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE EndGlobalSection GlobalSection(NestedProjects) = preSolution {B3850A7A-EBB2-4C33-827B-98B88901A638} = {758DA496-3186-4129-B0FA-5C3205B52763} {AEF17681-C9AB-4C49-8B06-06E5AF8C4237} = {758DA496-3186-4129-B0FA-5C3205B52763} {A6E8E401-D8DE-4640-A6FA-2242A07F2481} = {53454ACB-CE39-4F53-AB32-C28C15720537} + {608F2323-04CF-460F-8D98-D65472570FD5} = {758DA496-3186-4129-B0FA-5C3205B52763} + {4AA29DB8-221B-422F-852C-1CA6043763AC} = {758DA496-3186-4129-B0FA-5C3205B52763} EndGlobalSection EndGlobal diff --git a/PD.C4.code-workspace b/PD.C4.code-workspace new file mode 100644 index 0000000..876a149 --- /dev/null +++ b/PD.C4.code-workspace @@ -0,0 +1,8 @@ +{ + "folders": [ + { + "path": "." + } + ], + "settings": {} +} \ No newline at end of file diff --git a/diagrams/Healthcare/SolutionArchitecture/config.json b/diagrams/Healthcare/SolutionArchitecture/config.json new file mode 100644 index 0000000..a3f4711 --- /dev/null +++ b/diagrams/Healthcare/SolutionArchitecture/config.json @@ -0,0 +1,145 @@ +{ + "title": "Healthcare Solution Architecture", + "slug": "healthcare-solution-architecture", + "structures": [ + { + "alias": "member_portal", + "label": "Member Portal", + "description": "Cloud-native frontend for member interaction. Benefits: Personalized engagement, scalable access, secure communication. Tools: React/Angular/Vue.js, Azure App Service/AWS Amplify/GCP Firebase Hosting, OAuth2/OpenID Connect, Azure AD B2C/AWS Cognito.", + "type": "SoftwareSystem" + }, + { + "alias": "integration_layer", + "label": "Integration Layer", + "description": "Connects cloud portal to on-prem systems ABC and XYZ. Benefits: Real-time data sync, secure API access, ETL capabilities. Tools: Azure API Management/AWS API Gateway, Apache NiFi/Azure Data Factory/Talend, Kafka/Azure Event Grid/AWS EventBridge, MuleSoft/Boomi/WSO2.", + "type": "SoftwareSystem" + }, + { + "alias": "service_orchestration", + "label": "Service Orchestration Layer", + "description": "Coordinates internal microservices and workflows. Benefits: Efficient service communication, modularity, fault isolation. Tools: Kubernetes/Docker Swarm, Istio/Linkerd, Camunda/Temporal/Apache Airflow.", + "type": "SoftwareSystem" + }, + { + "alias": "ai_decision_engine", + "label": "AI Decision Support Engine", + "description": "Provides predictive insights and care recommendations. Benefits: Improved targeting, proactive outreach, personalized care. Tools: Azure Machine Learning/AWS SageMaker/Google Vertex AI, Python (scikit-learn, TensorFlow, PyTorch), MLflow/DVC.", + "type": "SoftwareSystem" + }, + { + "alias": "care_coordination", + "label": "Care Coordination Workflow Engine", + "description": "Automates case management and alerts. Benefits: Reduced manual effort, faster response, better resource allocation. Tools: Salesforce Health Cloud/Microsoft Dynamics 365/ServiceNow Health IT, Custom microservices with workflow logic, BPMN engines like Camunda or Zeebe.", + "type": "SoftwareSystem" + }, + { + "alias": "data_lake", + "label": "Data Lake & Analytics", + "description": "Centralized data storage and reporting. Benefits: Historical analysis, model training, compliance reporting. Tools: Azure Data Lake/AWS S3/Google Cloud Storage, Snowflake/BigQuery/Redshift, Power BI/Tableau/Looker.", + "type": "SoftwareSystem" + }, + { + "alias": "security_compliance", + "label": "Security & Compliance Layer", + "description": "Ensures secure data flow and regulatory alignment. Benefits: POPIA/GDPR compliance, encryption, access control. Tools: Azure Key Vault/AWS KMS/HashiCorp Vault, TLS 1.2+/1.3 AES-256 encryption, SIEM tools like Splunk Sentinel, Compliance frameworks POPIA GDPR HIPAA.", + "type": "SoftwareSystem" + }, + { + "alias": "monitoring_scalability", + "label": "Monitoring & Scalability", + "description": "Tracks system health and performance. Benefits: Autoscaling, uptime assurance, proactive issue detection. Tools: Prometheus + Grafana/Azure Monitor/CloudWatch, Elastic Stack (ELK)/Fluentd, Auto-scaling groups/Kubernetes HPA.", + "type": "SoftwareSystem" + }, + { + "alias": "change_management", + "label": "Change Management", + "description": "Supports adoption and stakeholder alignment. Benefits: Training, feedback loops, smoother transition to digital workflows. Tools: Prosci ADKAR/Kotter's 8-Step Model, Confluence/SharePoint/LMS platforms, Feedback tools Microsoft Forms SurveyMonkey.", + "type": "SoftwareSystem" + }, + { + "alias": "healthcare_member", + "label": "Healthcare Member", + "description": "End user accessing healthcare services through the member portal. Receives personalized care recommendations and manages health information.", + "type": "Person" + }, + { + "alias": "care_manager", + "label": "Care Manager", + "description": "Healthcare professional managing member care coordination. Uses AI insights and workflow automation for proactive care management.", + "type": "Person" + }, + { + "alias": "system_admin", + "label": "System Administrator", + "description": "Technical administrator responsible for system monitoring, security compliance, and change management processes.", + "type": "Person" + } + ], + "relationships": [ + { + "from": "healthcare_member", + "to": "member_portal", + "label": "Accesses healthcare services" + }, + { + "from": "care_manager", + "to": "care_coordination", + "label": "Manages care workflows" + }, + { + "from": "system_admin", + "to": "monitoring_scalability", + "label": "Monitors system health" + }, + { + "from": "member_portal", + "to": "integration_layer", + "label": "Requests member data" + }, + { + "from": "integration_layer", + "to": "service_orchestration", + "label": "Routes to microservices" + }, + { + "from": "service_orchestration", + "to": "ai_decision_engine", + "label": "Requests AI insights" + }, + { + "from": "service_orchestration", + "to": "care_coordination", + "label": "Triggers care workflows" + }, + { + "from": "ai_decision_engine", + "to": "data_lake", + "label": "Accesses training data" + }, + { + "from": "care_coordination", + "to": "data_lake", + "label": "Stores workflow metrics" + }, + { + "from": "security_compliance", + "to": "member_portal", + "label": "Enforces security policies" + }, + { + "from": "security_compliance", + "to": "integration_layer", + "label": "Secures API access" + }, + { + "from": "monitoring_scalability", + "to": "service_orchestration", + "label": "Tracks microservice health" + }, + { + "from": "change_management", + "to": "healthcare_member", + "label": "Provides training support" + } + ] +} diff --git a/generated-diagrams/.c4s/C4.puml b/generated-diagrams/.c4s/C4.puml new file mode 100644 index 0000000..3d7e330 --- /dev/null +++ b/generated-diagrams/.c4s/C4.puml @@ -0,0 +1,1658 @@ +' C4-PlantUML + +' Global pre-settings +' ################################## +' ENABLE_ALL_PLANT_ELEMENTS +' If ENABLE_ALL_PLANT_ELEMENTS is set BEFORE the first C4_* file is loaded, nearly "all" PlantUML elements can be used like +' Component(StorageA, "Storage A ", $baseShape="storage") +' ENABLE_ALL_PLANT_ELEMENTS can be set via +' !ENABLE_ALL_PLANT_ELEMENTS = 1 +' or with additional command line argument -DENABLE_ALL_PLANT_ELEMENTS=1 + +'Version +' ################################## +!function C4Version() + ' 2 spaces and ' are used as unique marker, that the release scripts makes the correct version update + !$c4Version = "2.10.0beta1" + !return $c4Version +!end function + +!procedure C4VersionDetails() +rectangle C4VersionDetailsArea <> [ +| PlantUML | **%version()** | +| C4-PlantUML | **C4Version()** | +] +!end procedure + +' Colors +' ################################## +!$ELEMENT_FONT_COLOR ?= "#FFFFFF" + +!$ARROW_COLOR ?= "#666666" +!$ARROW_FONT_COLOR ?= $ARROW_COLOR + +!$BOUNDARY_COLOR ?= "#444444" +!$BOUNDARY_BG_COLOR ?= "transparent" +!$BOUNDARY_BORDER_STYLE ?= "dashed" + +!$LEGEND_TITLE_COLOR ?= "#000000" +!$LEGEND_FONT_COLOR ?= "#FFFFFF" +!$LEGEND_BG_COLOR ?= "transparent" +!$LEGEND_BORDER_COLOR ?= "transparent" +' %darken(darkkhaki,50), #khaki +!$LEGEND_DARK_COLOR ?= "#66622E" +!$LEGEND_LIGHT_COLOR ?= "#khaki" + +!$SKETCH_BG_COLOR ?= "#EEEBDC" +!$SKETCH_FONT_COLOR ?= "" +!$SKETCH_WARNING_COLOR ?= "red" +!$SKETCH_FONT_NAME ?= "Comic Sans MS" + +' Labels +' ################################## + +!$LEGEND_SHADOW_TEXT ?= "shadow" +!$LEGEND_NO_SHADOW_TEXT ?= "no shadow" +!$LEGEND_NO_FONT_BG_TEXT ?= "last text and back color" +!$LEGEND_NO_FONT_TEXT ?= "last text color" +!$LEGEND_NO_BG_TEXT ?= "last back color" +!$LEGEND_NO_LINE_TEXT ?= "last line color" +!$LEGEND_ROUNDED_BOX ?= "rounded box" +!$LEGEND_EIGHT_SIDED ?= "eight sided" +!$LEGEND_DOTTED_LINE ?= "dotted" +!$LEGEND_DASHED_LINE ?= "dashed" +!$LEGEND_BOLD_LINE ?= "bold" +!$LEGEND_SOLID_LINE ?= "solid" + +!$LEGEND_BOUNDARY ?= "boundary" +' ignore (boundary) transparent atm, that the legend is smaller +' !$LEGEND_BOUNDARY_TRANSPARENT_INCL_COMA ?= "transparent, " +!$LEGEND_BOUNDARY_TRANSPARENT_INCL_COMA ?= "" +' (boundary) dashed should not be ignored atm +!$LEGEND_BOUNDARY_DASHED_INCL_COMA ?= "dashed, " +' !$LEGEND_BOUNDARY_DASHED_INCL_COMA ?= "" + +!$LEGEND_THICKNESS ?= "thickness" + +!$SKETCH_FOOTER_WARNING ?= "Warning:" +!$SKETCH_FOOTER_TEXT ?= "Created for discussion, needs to be validated" + +' Styling +' ################################## + +!$STEREOTYPE_FONT_SIZE ?= 12 +!global $TRANSPARENT_STEREOTYPE_FONT_SIZE = $STEREOTYPE_FONT_SIZE/2 +!$TECHN_FONT_SIZE ?= 12 + +!$ARROW_FONT_SIZE ?= 12 + +!$LEGEND_DETAILS_SMALL_SIZE ?= 10 +!$LEGEND_DETAILS_NORMAL_SIZE ?= 14 +!global $LEGEND_DETAILS_SIZE = $LEGEND_DETAILS_SMALL_SIZE + +' element symbols typically 4 times too big in legend +!$LEGEND_IMAGE_SIZE_FACTOR ?= 0.25 + +!$ROUNDED_BOX_SIZE ?= 25 +!$EIGHT_SIDED_SIZE ?= 18 + +' Default element wrap width (of an element) +!$DEFAULT_WRAP_WIDTH ?= 200 +' Maximum size in pixels, of a message (in a sequence diagram?) +!$MAX_MESSAGE_SIZE ?= 150 +' PlantUML supports no DETERMINISTIC/automatic line breaks of "PlantUML line" (C4 Relationships) +' therefore Rel...() implements an automatic line break based on spaces (like in all other objects). +' If a $type contains \n then these are used (and no automatic space based line breaks are done) +' $REL_TECHN_MAX_CHAR_WIDTH defines the automatic line break position +!$REL_TECHN_MAX_CHAR_WIDTH ?= 35 +!$REL_DESCR_MAX_CHAR_WIDTH ?= 32 + +' internal +' ################################## + +!global $ROUNDED_BOX = "roundedBox" +!global $EIGHT_SIDED = "eightSided" + +!global $DOTTED_LINE = "dotted" +!global $DASHED_LINE = "dashed" +!global $BOLD_LINE = "bold" +' solid is not defined in plantUML, but works as reset of all other styles too +!global $SOLID_LINE = "solid" + +!global $LEGEND_DETAILS_NONE = "none" +!global $LEGEND_DETAILS_NORMAL = "normal" +!global $LEGEND_DETAILS_SMALL = "small" + +skinparam defaultTextAlignment center + +skinparam wrapWidth $DEFAULT_WRAP_WIDTH +skinparam maxMessageSize $MAX_MESSAGE_SIZE + +skinparam LegendFontColor $LEGEND_FONT_COLOR +skinparam LegendBackgroundColor $LEGEND_BG_COLOR +skinparam LegendBorderColor $LEGEND_BORDER_COLOR + +skinparam rectangle<> { + backgroundcolor $LEGEND_BG_COLOR + bordercolor $LEGEND_BORDER_COLOR +} + +skinparam rectangle { + StereotypeFontSize $STEREOTYPE_FONT_SIZE +} + +skinparam database { + StereotypeFontSize $STEREOTYPE_FONT_SIZE +} + +skinparam queue { + StereotypeFontSize $STEREOTYPE_FONT_SIZE +} + +skinparam participant { + StereotypeFontSize $STEREOTYPE_FONT_SIZE +} + +skinparam arrow { + Color $ARROW_COLOR + FontColor $ARROW_FONT_COLOR + FontSize $ARROW_FONT_SIZE +} + +skinparam person { + StereotypeFontSize $STEREOTYPE_FONT_SIZE +} + +skinparam actor { + StereotypeFontSize $STEREOTYPE_FONT_SIZE + style awesome +} + +!if %variable_exists("ENABLE_ALL_PLANT_ELEMENTS") +skinparam agent { + StereotypeFontSize $STEREOTYPE_FONT_SIZE +} +skinparam artifact { + StereotypeFontSize $STEREOTYPE_FONT_SIZE +} +skinparam boundary { + StereotypeFontSize $STEREOTYPE_FONT_SIZE +} +skinparam card { + StereotypeFontSize $STEREOTYPE_FONT_SIZE +} +skinparam circle { + StereotypeFontSize $STEREOTYPE_FONT_SIZE +} +skinparam cloud { + StereotypeFontSize $STEREOTYPE_FONT_SIZE +} +skinparam collections { + StereotypeFontSize $STEREOTYPE_FONT_SIZE +} +skinparam control { + StereotypeFontSize $STEREOTYPE_FONT_SIZE +} +skinparam entity { + StereotypeFontSize $STEREOTYPE_FONT_SIZE +} +skinparam file { + StereotypeFontSize $STEREOTYPE_FONT_SIZE +} +skinparam folder { + StereotypeFontSize $STEREOTYPE_FONT_SIZE +} +skinparam frame { + StereotypeFontSize $STEREOTYPE_FONT_SIZE +} +skinparam hexagon { + StereotypeFontSize $STEREOTYPE_FONT_SIZE +} +skinparam interface { + StereotypeFontSize $STEREOTYPE_FONT_SIZE +} +skinparam label { + StereotypeFontSize $STEREOTYPE_FONT_SIZE +} +skinparam stack { + StereotypeFontSize $STEREOTYPE_FONT_SIZE +} +skinparam storage { + StereotypeFontSize $STEREOTYPE_FONT_SIZE +} +skinparam usecase { + StereotypeFontSize $STEREOTYPE_FONT_SIZE +} +skinparam person { + StereotypeFontSize $STEREOTYPE_FONT_SIZE +} +!endif + +' Some boundary skinparams have to be set as package skinparams too (PlantUML uses internal packages) +' UpdateBoundaryStyle() called in boundary section below +skinparam rectangle<> { + StereotypeFontSize $TRANSPARENT_STEREOTYPE_FONT_SIZE + StereotypeFontColor $BOUNDARY_BG_COLOR + BorderStyle $BOUNDARY_BORDER_STYLE +} + +skinparam package { + StereotypeFontSize $TRANSPARENT_STEREOTYPE_FONT_SIZE + StereotypeFontColor $BOUNDARY_BG_COLOR + FontStyle plain + BackgroundColor $BOUNDARY_BG_COLOR +} + +' Legend and Tags +' ################################## +!global $tagDefaultLegend = "" +!global $tagCustomLegend = "" + +' rel specific +!unquoted function $toStereos($tags) + !if (%strlen($tags) == 0) + !return '' + !endif + !$stereos = '' + !$brPos = %strpos($tags, "+") + !while ($brPos >= 0) + !$tag = %substr($tags, 0, $brPos) + !$stereos = $stereos + '<<' + $tag + '>>' +%set_variable_value("$" + $tag + "_LineLegend", %true()) + !$tags = %substr($tags, $brPos+1) + !$brPos = %strpos($tags, "+") + !endwhile + !if (%strlen($tags) > 0) + !$stereos = $stereos + '<<' + $tags + '>>' +%set_variable_value("$" + $tags + "_LineLegend", %true()) + !endif + !return $stereos +!endfunction + +' if $sprite/$techn is an empty argument, try to calculate it via the defined $tag +!unquoted function $toRelArg($arg, $tags, $varPostfix) + !if ($arg > "") + !return $arg + !endif + + !if (%strlen($tags) == 0) + !return $arg + !endif + !$brPos = %strpos($tags, "+") + !while ($brPos >= 0) + !$tag = %substr($tags, 0, $brPos) + !$newArg = %get_variable_value("$" + $tag + $varPostfix) + !if ($newArg > "") + !return $newArg + !endif + !$tags = %substr($tags, $brPos+1) + !$brPos = %strpos($tags, "+") + !endwhile + !if (%strlen($tags) > 0) + !$newArg = %get_variable_value("$" + $tags + $varPostfix) + !if ($newArg > "") + !return $newArg + !endif + !endif + !return $arg +!endfunction + +' element specific (unused are hidden based on mask) +!unquoted function $toStereos($elementType, $tags) + !if (%strlen($tags) == 0) + !$stereos = '<<' + $elementType + '>>' +%set_variable_value("$" + $elementType + "Legend", %true()) + !return $stereos + !endif + !$stereos = '' + !$mask = $resetMask() + !$brPos = %strpos($tags, "+") + !while ($brPos >= 0) + !$tag = %substr($tags, 0, $brPos) + !$stereos = $stereos + '<<' + $tag + '>>' + !$mergedMask = $combineMaskWithTag($mask, $tag) + !if ($mergedMask != $mask) +%set_variable_value("$" + $tag + "Legend", %true()) + !$mask = $mergedMask + !endif + !$tags = %substr($tags, $brPos+1) + !$brPos = %strpos($tags, "+") + !endwhile + !if (%strlen($tags) > 0) + !$stereos = $stereos + '<<' + $tags + '>>' + !$mergedMask = $combineMaskWithTag($mask, $tags) + !if ($mergedMask != $mask) +%set_variable_value("$" + $tags + "Legend", %true()) + !$mask = $mergedMask + !endif + !endif + ' has to be last, otherwise PlantUML overwrites all tag specific skinparams + !$stereos = $stereos + '<<' + $elementType + '>>' + !$mergedMask = $combineMaskWithTag($mask, $elementType) + !if ($mergedMask != $mask) +%set_variable_value("$" + $elementType + "Legend", %true()) + !$mask = $mergedMask + !endif + !return $stereos +!endfunction + +' if $sprite/$techn is an empty argument, try to calculate it via the defined $tag +!unquoted function $toElementArg($arg, $tags, $varPostfix, $elementType) + !if ($arg > "") + !return $arg + !endif + + !if (%strlen($tags) == 0) + !$newArg = %get_variable_value("$" + $elementType + $varPostfix) + !if ($newArg > "") + !return $newArg + !else + !return $arg + !endif + !endif + !$brPos = %strpos($tags, "+") + !while ($brPos >= 0) + !$tag = %substr($tags, 0, $brPos) + !$newArg = %get_variable_value("$" + $tag + $varPostfix) + !if ($newArg > "") + !return $newArg + !endif + !$tags = %substr($tags, $brPos+1) + !$brPos = %strpos($tags, "+") + !endwhile + !if (%strlen($tags) > 0) + !$newArg = %get_variable_value("$" + $tags + $varPostfix) + !if ($newArg > "") + !return $newArg + !endif + !$newArg = %get_variable_value("$" + $elementType + $varPostfix) + !if ($newArg > "") + !return $newArg + !endif + !endif + !return $arg +!endfunction + +' if $value is empty try to load it via variable, optional can it store the calculated value +!function $restoreEmpty($elementType, $property, $value, $store) + !$var = "$" + $elementType + "Restore" + $property + !if ($value == "") + !$value = %get_variable_value($var) + !elseif ($store) + %set_variable_value($var, $value) + !endif + !return $value +!endfunction + +' clear the restore property +!function $clearRestore($elementType, $property) + !$var = "$" + $elementType + "Restore" + $property + %set_variable_value($var, "") + !return "" +!endfunction + +!function $elementTagSkinparams($element, $tagStereo, $bgColor, $fontColor, $borderColor, $shadowing, $shape, $borderStyle, $borderThickness) + !$elementSkin = "skinparam " + $element + "<<" + $tagStereo + ">> {" + %newline() + !if ($fontColor != "") + !if (%strpos($tagStereo, "boundary") < 0) + !$elementSkin = $elementSkin + " StereotypeFontColor " + $fontColor + %newline() + !endif + !$elementSkin = $elementSkin + " FontColor " + $fontColor + %newline() + !endif + !if ($bgColor != "") + !$elementSkin = $elementSkin + " BackgroundColor " + $bgColor + %newline() + !endif + !if ($borderColor != "") + !$elementSkin = $elementSkin + " BorderColor " + $borderColor+ %newline() + !endif + !if ($shadowing == "true") + !$elementSkin = $elementSkin + " Shadowing<<" + $tagStereo + ">> " + "true" + %newline() + !endif + !if ($shadowing == "false") + !$elementSkin = $elementSkin + " Shadowing<<" + $tagStereo + ">> " + "false" + %newline() + !endif + ' only rectangle supports shape(d corners), define both skinparam that overlays are working + !if ($shape != "" && $element == "rectangle") + !if ($shape == $ROUNDED_BOX) + !$elementSkin = $elementSkin + " RoundCorner " + $ROUNDED_BOX_SIZE+ %newline() + !$elementSkin = $elementSkin + " DiagonalCorner " + "0" + %newline() + !elseif ($shape == $EIGHT_SIDED) + !$elementSkin = $elementSkin + " RoundCorner " + "0" + %newline() + !$elementSkin = $elementSkin + " DiagonalCorner " + $EIGHT_SIDED_SIZE+ %newline() + !endif + !endif + !if ($borderStyle != "") + !$elementSkin = $elementSkin + " BorderStyle " + $borderStyle + %newline() + !endif + !if ($borderThickness != "") + !$elementSkin = $elementSkin + " BorderThickness " + $borderThickness + %newline() + !endif + !$elementSkin = $elementSkin + "}" + %newline() + !return $elementSkin +!endfunction + +!unquoted procedure $defineSkinparams($tagStereo, $bgColor, $fontColor, $borderColor, $shadowing, $shape, $borderStyle, $borderThickness) + ' only rectangle supports shape(d corners) + !$tagSkin = $elementTagSkinparams("rectangle", $tagStereo, $bgColor, $fontColor, $borderColor, $shadowing, $shape, $borderStyle, $borderThickness) + !$tagSkin = $tagSkin + $elementTagSkinparams("database", $tagStereo, $bgColor, $fontColor, $borderColor, $shadowing, "", $borderStyle, $borderThickness) + !$tagSkin = $tagSkin + $elementTagSkinparams("queue", $tagStereo, $bgColor, $fontColor, $borderColor, $shadowing, "", $borderStyle, $borderThickness) + ' plantuml.jar bug - actor have to be after person + !$tagSkin = $tagSkin + $elementTagSkinparams("person", $tagStereo, $bgColor, $fontColor, $borderColor, $shadowing, "", $borderStyle, $borderThickness) + ' actor has style awesome, therefore $fontColor is ignored and text uses $bgColor too + !$tagSkin = $tagSkin + $elementTagSkinparams("actor", $tagStereo, $bgColor, $bgColor, $borderColor, $shadowing, "", $borderStyle, $borderThickness) + ' sequence requires participant + !$tagSkin = $tagSkin + $elementTagSkinparams("participant", $tagStereo, $bgColor, $fontColor, $borderColor, $shadowing, "", $borderStyle, $borderThickness) + !$tagSkin = $tagSkin + $elementTagSkinparams("sequencebox", $tagStereo, $bgColor, $fontColor, $borderColor, $shadowing, "", $borderStyle, $borderThickness) + !if (%strpos($tagStereo, "boundary") >= 0 && $bgColor != "") + !$tagSkin = $tagSkin + "skinparam package<<" + $tagStereo + ">>StereotypeFontColor " + $bgColor + %newline() + !$tagSkin = $tagSkin + "skinparam rectangle<<" + $tagStereo + ">>StereotypeFontColor " + $bgColor + %newline() + !endif + !if %variable_exists("ENABLE_ALL_PLANT_ELEMENTS") + !$tagSkin = $tagSkin + $elementTagSkinparams("agent", $tagStereo, $bgColor, $fontColor, $borderColor, $shadowing, "", $borderStyle, $borderThickness) + !$tagSkin = $tagSkin + $elementTagSkinparams("artifact", $tagStereo, $bgColor, $fontColor, $borderColor, $shadowing, "", $borderStyle, $borderThickness) + !$tagSkin = $tagSkin + $elementTagSkinparams("card", $tagStereo, $bgColor, $fontColor, $borderColor, $shadowing, "", $borderStyle, $borderThickness) + !$tagSkin = $tagSkin + $elementTagSkinparams("cloud", $tagStereo, $bgColor, $fontColor, $borderColor, $shadowing, "", $borderStyle, $borderThickness) + !$tagSkin = $tagSkin + $elementTagSkinparams("collections", $tagStereo, $bgColor, $fontColor, $borderColor, $shadowing, "", $borderStyle, $borderThickness) + !$tagSkin = $tagSkin + $elementTagSkinparams("file", $tagStereo, $bgColor, $fontColor, $borderColor, $shadowing, "", $borderStyle, $borderThickness) + !$tagSkin = $tagSkin + $elementTagSkinparams("folder", $tagStereo, $bgColor, $fontColor, $borderColor, $shadowing, "", $borderStyle, $borderThickness) + !$tagSkin = $tagSkin + $elementTagSkinparams("frame", $tagStereo, $bgColor, $fontColor, $borderColor, $shadowing, "", $borderStyle, $borderThickness) + !$tagSkin = $tagSkin + $elementTagSkinparams("hexagon", $tagStereo, $bgColor, $fontColor, $borderColor, $shadowing, "", $borderStyle, $borderThickness) + !$tagSkin = $tagSkin + $elementTagSkinparams("package", $tagStereo, $bgColor, $fontColor, $borderColor, $shadowing, "", $borderStyle, $borderThickness) + !$tagSkin = $tagSkin + $elementTagSkinparams("stack", $tagStereo, $bgColor, $fontColor, $borderColor, $shadowing, "", $borderStyle, $borderThickness) + !$tagSkin = $tagSkin + $elementTagSkinparams("storage", $tagStereo, $bgColor, $fontColor, $borderColor, $shadowing, "", $borderStyle, $borderThickness) + !$tagSkin = $tagSkin + $elementTagSkinparams("usecase", $tagStereo, $bgColor, $fontColor, $borderColor, $shadowing, "", $borderStyle, $borderThickness) + ' elements without background: font uses $bgColor + !$tagSkin = $tagSkin + $elementTagSkinparams("boundary", $tagStereo, $bgColor, $bgColor, $borderColor, $shadowing, "", $borderStyle, $borderThickness) + !$tagSkin = $tagSkin + $elementTagSkinparams("circle", $tagStereo, $bgColor, $bgColor, $borderColor, $shadowing, "", $borderStyle, $borderThickness) + !$tagSkin = $tagSkin + $elementTagSkinparams("control", $tagStereo, $bgColor, $bgColor, $borderColor, $shadowing, "", $borderStyle, $borderThickness) + !$tagSkin = $tagSkin + $elementTagSkinparams("entity", $tagStereo, $bgColor, $bgColor, $borderColor, $shadowing, "", $borderStyle, $borderThickness) + !$tagSkin = $tagSkin + $elementTagSkinparams("interface", $tagStereo, $bgColor, $bgColor, $borderColor, $shadowing, "", $borderStyle, $borderThickness) + ' label uses wrong font color? (should be $bgColor too) + !$tagSkin = $tagSkin + $elementTagSkinparams("label", $tagStereo, $bgColor, $bgColor, $borderColor, $shadowing, "", $borderStyle, $borderThickness) + !endif +$tagSkin +!endprocedure + +' arrow colors cannot start with # (legend background has to start with #) +!function $colorWithoutHash($c) + !if (%substr($c, 0, 1) == "#") + !$c = %substr($c,1) + !endif + !return $c +!endfunction + +!unquoted procedure $defineRelSkinparams($tagStereo, $textColor, $lineColor, $lineStyle, $lineThickness) + !$elementSkin = "skinparam arrow<<" + $tagStereo + ">> {" + %newline() + !if ($lineColor != "") || ($textColor != "") || ($lineStyle != "") + !$elementSkin = $elementSkin + " Color " + !if ($lineColor != "") + !$elementSkin = $elementSkin + $colorWithoutHash($lineColor) + !endif + !if ($textColor != "") + !$elementSkin = $elementSkin + ";text:" + $colorWithoutHash($textColor) + !endif + !if ($lineStyle != "") + !$elementSkin = $elementSkin + ";line." + $lineStyle + !endif + !$elementSkin = $elementSkin + %newline() + !endif + !if ($lineThickness != "") + !$elementSkin = $elementSkin + " thickness " + $lineThickness + %newline() + !endif + !$elementSkin = $elementSkin + "}" + %newline() +$elementSkin +!endprocedure + +' %is_dark() requires PlantUML version >= 1.2021.6 +!if (%function_exists("%is_dark")) + !$PlantUMLSupportsDynamicLegendColor = %true() +!else + !$PlantUMLSupportsDynamicLegendColor = %false() + !log "dynamic undefined legend colors" requires PlantUML version >= 1.2021.6, therefore only static assigned colors are used +!endif + +!unquoted function $contrastLegend($color) + !if (%is_dark($color)) + !$value = $LEGEND_LIGHT_COLOR + !else + !$value = $LEGEND_DARK_COLOR + !endif + !return $value +!endfunction + +!unquoted function $flatLegend($color) + !if (%is_dark($color)) + !$value = $LEGEND_DARK_COLOR + !else + !$value = $LEGEND_LIGHT_COLOR + !endif + !return $value +!endfunction + +' legend background has to start with # +!function $colorWithHash($c) + !if (%substr($c, 0, 1) != "#") + !$c = "#" + $c + !endif + !return $c +!endfunction + +!function $addMaskFlag($mask, $attr) + !if ($attr == "") + !$mask = $mask + "0" + !else + !$mask = $mask + "1" + !endif + !return $mask +!endfunction + +!function $orFlags($flag1, $flag2) + !if ($flag1 == "0" && $flag2 == "0") + !return "0" + !endif + !return "1" +!endfunction + +!function $tagLegendMask($bgColor, $fontColor, $borderColor, $shadowing, $shape, $sprite, $borderStyle, $borderThickness) + !$mask = "" + !$mask = $addMaskFlag($mask, $bgColor) + !$mask = $addMaskFlag($mask, $fontColor) + !$mask = $addMaskFlag($mask, $borderColor) + !$mask = $addMaskFlag($mask, $shadowing) + !$mask = $addMaskFlag($mask, $shape) + !$mask = $addMaskFlag($mask, $sprite) + !$mask = $addMaskFlag($mask, $borderStyle) + !$mask = $addMaskFlag($mask, $borderThickness) + !return $mask +!endfunction + +!function $resetMask() + !return "00000000" +!endfunction + +!function $combineMasks($mask1, $mask2) + !$mask = "" + !$mask = $mask + $orFlags(%substr($mask1, 0, 1), %substr($mask2, 0, 1)) + !$mask = $mask + $orFlags(%substr($mask1, 1, 1), %substr($mask2, 1, 1)) + !$mask = $mask + $orFlags(%substr($mask1, 2, 1), %substr($mask2, 2, 1)) + !$mask = $mask + $orFlags(%substr($mask1, 3, 1), %substr($mask2, 3, 1)) + !$mask = $mask + $orFlags(%substr($mask1, 4, 1), %substr($mask2, 4, 1)) + !$mask = $mask + $orFlags(%substr($mask1, 5, 1), %substr($mask2, 5, 1)) + !$mask = $mask + $orFlags(%substr($mask1, 6, 1), %substr($mask2, 6, 1)) + !$mask = $mask + $orFlags(%substr($mask1, 7, 1), %substr($mask2, 7, 1)) + !return $mask +!endfunction + +!function $combineMaskWithTag($mask1, $tag) + !$mask2 = %get_variable_value("$" + $tag+ "LegendMask") + !if ($mask2 == "") + ' !log combineMaskWithTag $mask1, $tag, ... only $mask1 + !return $mask1 + !endif + + ' !log combineMaskWithTag $mask1, $tag, $mask2 ... $combineMasks($mask1, $mask2) + !return $combineMasks($mask1, $mask2) +!endfunction + +' element symbols typically 4 times too big in legend +!function $smallVersionSprite($sprite) + ' ,scale= ... has to be first (...,color=black,scale=0.25... is invalid too) + !if (%strpos($sprite, "=") < 0) + !if (%substr($sprite, 0, 4) == "img:") + !$smallSprite = $sprite + "{scale=" + $LEGEND_IMAGE_SIZE_FACTOR + "}" + !else + !$smallSprite = $sprite + ",scale=" + $LEGEND_IMAGE_SIZE_FACTOR + !endif + !else + !$smallSprite = $sprite + !endif + !return $smallSprite +!endfunction + +' format sprite that it can be used in diagram +!function $getSprite($sprite) + ' if it starts with & it's a OpenIconic, details see https://useiconic.com/open/ + ' if it starts with img: it's an image, details see https://plantuml.com/creole + !if (%substr($sprite, 0, 1) != "&" && %substr($sprite, 0, 4) != "img:") + !$formatted = "<$" + $sprite + ">" + !else + !$formatted = "<" + $sprite + ">" + !endif + !return $formatted +!endfunction + +!function $setTagLegendVariables($tagStereo, $bgColor, $fontColor, $borderColor, $shadowing, $shape, $legendText, $legendSprite, $borderStyle, $borderThickness) + !$bg = $bgColor + !$fo = $fontColor + !$bo = $borderColor + + !if ($fo == "") + !if ($bg != "") +!if ($PlantUMLSupportsDynamicLegendColor) + !$fo = $contrastLegend($bg) +!else + !$fo = $LEGEND_DARK_COLOR +!endif + !else + !if ($bo == "") + !$fo = $LEGEND_DARK_COLOR + !$bg = $LEGEND_LIGHT_COLOR + !else +!if ($PlantUMLSupportsDynamicLegendColor) + !$fo = $flatLegend($bo) + !$bg = $contrastLegend($bo) +!else + !$fo = $LEGEND_DARK_COLOR + !$bg = $LEGEND_LIGHT_COLOR +!endif + !endif + !endif + !else + !if ($bg == "") +!if ($PlantUMLSupportsDynamicLegendColor) + !$bg = $contrastLegend($fo) +!else + !$bg = $LEGEND_LIGHT_COLOR +!endif + !endif + !endif + + !if ($bo == "") + !$bo = $bg + !endif + + !$tagEntry = "|" + !$tagDetails = "(" + !$tagEntry = $tagEntry + "<" + $colorWithHash($bg) +">" + ' ..white rectangle + !$tagEntry = $tagEntry + " " + !$tagEntry = $tagEntry + "" + !if ($legendSprite != "") + !$tagEntry = $tagEntry + $getSprite($legendSprite) + " " + !endif + + !$isBoundary = 0 + !if ($legendText == "") + !if (%strpos($tagStereo, "boundary") >= 0) + !if ($tagStereo == "boundary") + !$isBoundary = 1 + !$tagEntry = $tagEntry + " " + $LEGEND_BOUNDARY + " " + !else + ' if contains/ends with _boundary remove _boundary and add "boundary (dashed)" + !$pos = %strpos($tagStereo, "_boundary") + !if ($pos > 0) + !$isBoundary = 1 + !$tagEntry = $tagEntry + " " + %substr($tagStereo, 0 ,$pos) + " " +$LEGEND_BOUNDARY + " " + !endif + !endif + !endif + !if ($isBoundary == 0) + !$tagEntry = $tagEntry + " " + $tagStereo + " " + !endif + + !if ($isBoundary == 1 && ($bgColor == "#00000000" || %lower($bgColor) == "transparent")) + !$tagDetails = $tagDetails + $LEGEND_BOUNDARY_TRANSPARENT_INCL_COMA + !endif + !if ($shadowing == "true") + !$tagDetails = $tagDetails + $LEGEND_SHADOW_TEXT + ", " + !endif + !if ($shadowing == "false") + !$tagDetails = $tagDetails + $LEGEND_NO_SHADOW_TEXT + ", " + !endif + !if ($shape == $ROUNDED_BOX) + !$tagDetails = $tagDetails + $LEGEND_ROUNDED_BOX + ", " + !endif + !if ($shape == $EIGHT_SIDED) + !$tagDetails = $tagDetails + $LEGEND_EIGHT_SIDED + ", " + !endif + !if ($fontColor == "" && $bgColor == "") + !$tagDetails = $tagDetails + $LEGEND_NO_FONT_BG_TEXT + ", " + !else + !if ($fontColor == "") + !$tagDetails = $tagDetails + $LEGEND_NO_FONT_TEXT + ", " + !endif + !if ($bgColor == "") + !$tagDetails = $tagDetails + $LEGEND_NO_BG_TEXT + ", " + !endif + !endif + !if ($borderStyle != "") + !if ($borderStyle == $DOTTED_LINE) + !$tagDetails = $tagDetails + $LEGEND_DOTTED_LINE + ", " + !elseif ($borderStyle == $DASHED_LINE) + !if ($isBoundary == 1) + !$tagDetails = $tagDetails + $LEGEND_BOUNDARY_DASHED_INCL_COMA + !else + !$tagDetails = $tagDetails + $LEGEND_DASHED_LINE + ", " + !endif + !elseif ($borderStyle == $BOLD_LINE) + !$tagDetails = $tagDetails + $LEGEND_BOLD_LINE + ", " + !elseif ($borderStyle == $SOLID_LINE) + !$tagDetails = $tagDetails + $LEGEND_SOLID_LINE + ", " + !else + !$tagDetails = $tagDetails + $lineStyle + ", " + !endif + !endif + !if ($borderThickness != "") + !$tagDetails = $tagDetails + $LEGEND_THICKNESS + " " + $borderThickness + ", " + !endif + !if ($tagDetails=="(" || $tagDetails=="(, ") + !$tagDetails = "" + !else + !$tagDetails = %substr($tagDetails, 0, %strlen($tagDetails)-2) + !$tagDetails = $tagDetails + ")" + !endif + !else + !$brPos = %strpos($legendText, "\n") + !if ($brPos > 0) + !$tagEntry = $tagEntry + %substr($legendText, 0, $brPos) + " " + !$details = %substr($legendText, $brPos + 2) + !if ($details=="") + !$tagDetails = "" + !else + !$tagDetails = $tagDetails + $details + ")" + !endif + !else + !$tagEntry = $tagEntry + " " + $legendText + " " + !$tagDetails = "" + !endif + !endif + + !$tagDetails = $tagDetails + " " + !$tagDetails = $tagDetails + "|" +%set_variable_value("$" + $tagStereo + "LegendEntry", $tagEntry) +%set_variable_value("$" + $tagStereo + "LegendDetails", $tagDetails) + !return $tagEntry +!endfunction + +!function $setTagRelLegendVariables($tagStereo, $textColor, $lineColor, $lineStyle, $legendText, $legendSprite, $lineThickness) + !$tc = $textColor + !$lc = $lineColor + + !if ($tc == "") + !if ($PlantUMLSupportsDynamicLegendColor) + !$tc = $flatLegend($ARROW_FONT_COLOR) + !else + !$tc = $LEGEND_DARK_COLOR + !endif + !endif + !if ($lc == "") + !if ($PlantUMLSupportsDynamicLegendColor) + !$lc = $flatLegend($ARROW_COLOR) + !else + !$lc = $LEGEND_DARK_COLOR + !endif + !endif + + !$tagEntry = "|" + !$tagDetails = "(" + ' ..white line + !$tagEntry = $tagEntry + " " + !$tagEntry = $tagEntry + "" + !if ($legendSprite != "") + !$tagEntry = $tagEntry + $getSprite($legendSprite) + " " + !endif + !if ($legendText == "") + !$tagEntry = $tagEntry + " " + $tagStereo + " " + !if ($textColor == "") + !$tagDetails = $tagDetails + $LEGEND_NO_FONT_TEXT + ", " + !endif + !if ($lineColor == "") + !$tagDetails = $tagDetails + $LEGEND_NO_LINE_TEXT + ", " + !endif + !if ($lineStyle != "") + !if ($lineStyle == $DOTTED_LINE) + !$tagDetails = $tagDetails + $LEGEND_DOTTED_LINE + ", " + !elseif ($lineStyle == $DASHED_LINE) + !$tagDetails = $tagDetails + $LEGEND_DASHED_LINE + ", " + !elseif ($lineStyle == $BOLD_LINE) + !$tagDetails = $tagDetails + $LEGEND_BOLD_LINE + ", " + !else + !$tagDetails = $tagDetails + $lineStyle + ", " + !endif + !endif + !if ($lineThickness != "") + !$tagDetails = $tagDetails + $LEGEND_THICKNESS + " " + $lineThickness + ", " + !endif + !if ($tagDetails=="(") + !$tagDetails = "" + !else + !$tagDetails = %substr($tagDetails, 0, %strlen($tagDetails)-2) + !$tagDetails = $tagDetails + ")" + !endif + !else + !$brPos = %strpos($legendText, "\n") + !if ($brPos > 0) + !$tagEntry = $tagEntry + " " + %substr($legendText, 0, $brPos) + " " + !$details = %substr($legendText, $brPos + 2) + !if ($details=="") + !$tagDetails = "" + !else + !$tagDetails = $tagDetails + $details + ")" + !endif + !else + !$tagEntry = $tagEntry + " " + $legendText + " " + !$tagDetails = "" + !endif + !endif + + !$tagDetails = $tagDetails + " " + !$tagDetails = $tagDetails + "|" +%set_variable_value("$" + $tagStereo + "_LineLegendEntry", $tagEntry) +%set_variable_value("$" + $tagStereo + "_LineLegendDetails", $tagDetails) + !return $tagEntry +!endfunction + +!unquoted procedure $addTagToLegend($tagStereo, $bgColor="", $fontColor="", $borderColor="", $shadowing="", $shape="", $legendText="", $legendSprite="", $borderStyle="", $borderThickness="") +'' if a combined element tag is defined (e.g. "v1.0&v1.1") then it is typically a merged color, +'' like a new $fontColor="#fdae61" therefore it should be added to the legend +'' and the & combined tags will be not removed +' !if (%strpos($tagStereo, "&") < 0) + !$dummyAlreadyVariables = $setTagLegendVariables($tagStereo, $bgColor, $fontColor, $borderColor, $shadowing, $shape, $legendText, $legendSprite, $borderStyle, $borderThickness) + !$tagCustomLegend = $tagCustomLegend + $tagStereo + "\n" + !$tagMask = $tagLegendMask( $bgColor, $fontColor, $borderColor, $shadowing, $shape, $sprite, $borderStyle, $borderThickness) +%set_variable_value("$" + $tagStereo + "LegendMask", $tagMask) +' !endif +!endprocedure + +!unquoted procedure $addRelTagToLegend($tagStereo, $textColor="", $lineColor="", $lineStyle="", $legendText="", $legendSprite="", $lineThickness="") +'' Arrows have a bug with stereotype/skinparams and cannot combine text colors of one stereotype +'' and the line color of another stereotype. Therefore the text color of one tag and the line color +'' of another tag have to be combined via a "workaround" tag ("v1.0&v1.1"). +'' This workaround tag could be theoretically removed in the legend but after that there would +'' be an inconsistency between the element tags and the rel tags and therefore +'' & combined workaround tags are not removed too (and in unlikely cases the color itself could be changed) +' !if (%strpos($tagStereo, "&") < 0) + !$dummyAlreadyVariables = $setTagRelLegendVariables($tagStereo, $textColor, $lineColor, $lineStyle, $legendText, $legendSprite, $lineThickness) + !$tagCustomLegend = $tagCustomLegend + $tagStereo + "_Line\n" +' !endif +!endprocedure + +!procedure $showActiveLegendEntries($allDefined) + !$brPos = %strpos($allDefined, "\n") + !while ($brPos >= 0) + !$tagStereo = %substr($allDefined, 0, $brPos) + !$allDefined = %substr($allDefined, $brPos+2) + !$brPos = %strpos($allDefined, "\n") + !if (%variable_exists("$" + $tagStereo + "Legend")) + ' is part of legendDetails + !$part1 = %get_variable_value("$" + $tagStereo + "LegendEntry") + !$partSize = "" + !$part2 = %get_variable_value("$" + $tagStereo + "LegendDetails") + !$line = $part1 + $partSize + $part2 +$line + !endif + !endwhile + !if (%strlen($allDefined) > 0) + !$tagStereo = $allDefined + !if (%variable_exists("$" + $tagStereo + "Legend")) + ' is part of legendDetails + !$part1 = %get_variable_value("$" + $tagStereo + "LegendEntry") + !$partSize = "" + !$part2 = %get_variable_value("$" + $tagStereo + "LegendDetails") + !$line = $part1 + $partSize + $part2 +$line + !endif + !endif +!endprocedure + +!function RoundedBoxShape() +!return $ROUNDED_BOX +!endfunction + +!function EightSidedShape() +!return $EIGHT_SIDED +!endfunction + +!function DottedLine() +!return $DOTTED_LINE +!endfunction + +!function DashedLine() +!return $DASHED_LINE +!endfunction + +!function BoldLine() +!return $BOLD_LINE +!endfunction + +!function SolidLine() +!return $SOLID_LINE +!endfunction + +' used by new defined tags +!unquoted procedure AddElementTag($tagStereo, $bgColor="", $fontColor="", $borderColor="", $shadowing="", $shape="", $sprite="", $techn="", $legendText="", $legendSprite="", $borderStyle="", $borderThickness="") +$defineSkinparams($tagStereo, $bgColor, $fontColor, $borderColor, $shadowing, $shape, $borderStyle, $borderThickness) + !if ($sprite!="") +%set_variable_value("$" + $tagStereo + "ElementTagSprite", $sprite) + !if ($legendSprite == "") + !$legendSprite = $smallVersionSprite($sprite) + !endif + !endif + !if ($techn != "") +%set_variable_value("$" + $tagStereo + "ElementTagTechn", $techn) + !endif +$addTagToLegend($tagStereo, $bgColor, $fontColor, $borderColor, $shadowing, $shape, $legendText, $legendSprite, $borderStyle, $borderThickness) +!endprocedure + +!unquoted procedure $addElementTagInclReuse($elementName, $tagStereo, $bgColor="", $fontColor="", $borderColor="", $shadowing="", $shape="", $sprite="", $techn="", $legendText="", $legendSprite="", $borderStyle="", $borderThickness="") + !$bgColor=$restoreEmpty($elementName, "bgColor", $bgColor, %false()) + !$fontColor=$restoreEmpty($elementName, "fontColor", $fontColor, %false()) + !$borderColor=$restoreEmpty($elementName, "borderColor", $borderColor, %false()) + !$shadowing=$restoreEmpty($elementName, "shadowing", $shadowing, %false()) + !$shape=$restoreEmpty($elementName, "shape", $shape, %false()) + !$sprite=$restoreEmpty($elementName, "sprite", $sprite, %false()) + !$techn=$restoreEmpty($elementName, "techn", $techn, %false()) + ' new style should has its own legend text + ' !$legendText=$restoreEmpty($elementName, "legendText", $legendText, %false()) + !$legendSprite=$restoreEmpty($elementName, "legendSprite", $legendSprite, %false()) + !$borderStyle=$restoreEmpty($elementName, "borderStyle", $borderStyle, %false()) + !$borderThickness=$restoreEmpty($elementName, "borderThickness", $borderThickness, %false()) + + AddElementTag($tagStereo, $bgColor, $fontColor, $borderColor, $shadowing, $shape, $sprite, $techn, $legendText, $legendSprite, $borderStyle, $borderThickness) +!endprocedure + +' used by new defined rel tags +!unquoted procedure AddRelTag($tagStereo, $textColor="", $lineColor="", $lineStyle="", $sprite="", $techn="", $legendText="", $legendSprite="", $lineThickness="") +$defineRelSkinparams($tagStereo, $textColor, $lineColor, $lineStyle, $lineThickness) + !if ($sprite != "") +%set_variable_value("$" + $tagStereo + "RelTagSprite", $sprite) + !if ($legendSprite == "") + ' relation symbols typically 1:1 no additional scale required + !$legendSprite = $sprite + !endif + !endif + !if ($techn != "") +%set_variable_value("$" + $tagStereo + "RelTagTechn", $techn) + !endif +$addRelTagToLegend($tagStereo, $textColor, $lineColor, $lineStyle, $legendText, $legendSprite, $lineThickness) +!endprocedure + +' update the style of existing elements like person, ... +!unquoted procedure UpdateElementStyle($elementName, $bgColor="", $fontColor="", $borderColor="", $shadowing="", $shape="", $sprite="", $techn="", $legendText="", $legendSprite="", $borderStyle="", $borderThickness="") +!$bgColor=$restoreEmpty($elementName, "bgColor", $bgColor, %true()) +!$fontColor=$restoreEmpty($elementName, "fontColor", $fontColor, %true()) +!$borderColor=$restoreEmpty($elementName, "borderColor", $borderColor, %true()) +!$shadowing=$restoreEmpty($elementName, "shadowing", $shadowing, %true()) +!$shape=$restoreEmpty($elementName, "shape", $shape, %true()) +!$sprite=$restoreEmpty($elementName, "sprite", $sprite, %true()) +!$techn=$restoreEmpty($elementName, "techn", $techn, %true()) +!$legendText=$restoreEmpty($elementName, "legendText", $legendText, %true()) +!$legendSprite=$restoreEmpty($elementName, "legendSprite", $legendSprite, %true()) +!$borderStyle=$restoreEmpty($elementName, "borderStyle", $borderStyle, %true()) +!$borderThickness=$restoreEmpty($elementName, "borderThickness", $borderThickness, %true()) + +$defineSkinparams($elementName, $bgColor, $fontColor, $borderColor, $shadowing, $shape, $borderStyle, $borderThickness) + !if ($sprite != "") +%set_variable_value("$" + $elementName + "ElementTagSprite", $sprite) + !if ($legendSprite == "") + !$legendSprite = $smallVersionSprite($sprite) + !endif + !endif + !if ($techn != "") +%set_variable_value("$" + $elementName + "ElementTagTechn", $techn) + !endif + !$dummyAlreadyVariables = $setTagLegendVariables($elementName, $bgColor, $fontColor, $borderColor, $shadowing, $shape, $legendText, $legendSprite, $borderStyle, $borderThickness) + ' default tags sets at least bgColor and fontColor + !$tagMask = $tagLegendMask("CHANGED", "CHANGED", $borderColor, $shadowing, $shape, $sprite, $borderStyle, $borderThickness) +%set_variable_value("$" + $elementName + "LegendMask", $tagMask) +!endprocedure + +/' @deprecated in favor of UpdateElementStyle '/ +!unquoted procedure UpdateSkinparamsAndLegendEntry($elementName, $bgColor="", $fontColor="", $borderColor="", $shadowing="") +UpdateElementStyle($elementName, $bgColor, $fontColor, $borderColor, $shadowing) +!endprocedure + +' update the style of default relation, it has to set both properties (combined statement not working) +!unquoted procedure UpdateRelStyle($textColor, $lineColor) + !$elementSkin = "skinparam arrow {" + %newline() + !$elementSkin = $elementSkin + " Color " + $lineColor + %newline() + !$elementSkin = $elementSkin + " FontColor " + $textColor + %newline() + !$elementSkin = $elementSkin + "}" + %newline() +$elementSkin +!endprocedure + +' tags/stereotypes have to be delimited with \n +!unquoted procedure SetDefaultLegendEntries($tagStereoEntries) + !$tagDefaultLegend = $tagStereoEntries +!endprocedure + +' Links +' ################################## + +!function $getLink($link) + !if ($link != "") + !return "[[" + $link + "]]" + !else + !return "" + !endif +!endfunction + +' Line breaks +' ################################## + +!unquoted function $breakText($text, $usedNewLine, $widthStr="-1") +!$width = %intval($widthStr) +!$multiLine = "" +!if (%strpos($text, "\n") >= 0) + !while (%strpos($text, "\n") >= 0) + !$brPos = %strpos($text, "\n") + !if ($brPos > 0) + !$multiLine = $multiLine + %substr($text, 0, $brPos) + $usedNewLine + !else + ' non breaking change that newLine breaks with formats can be used with \n\n + !$multiLine = $multiLine + "" + $usedNewLine + !endif + !$text = %substr($text, $brPos+2) + !if (%strlen($text) == 0) + !$text = "" + !endif + !endwhile +!else + !while ($width>0 && %strlen($text) > $width) + !$brPos = $width + !while ($brPos > 0 && %substr($text, $brPos, 1) != ' ') + !$brPos = $brPos - 1 + !endwhile + + !if ($brPos < 1) + !$brPos = %strpos($text, " ") + !else + !endif + + !if ($brPos > 0) + !$multiLine = $multiLine + %substr($text, 0, $brPos) + $usedNewLine + !$text = %substr($text, $brPos + 1) + !else + !$multiLine = $multiLine+ $text + !$text = "" + !endif + !endwhile +!endif +!if (%strlen($text) > 0) + !$multiLine = $multiLine + $text +!endif +!return $multiLine +!endfunction + +!unquoted function $breakLabel($text) +!$usedNewLine = "\n== " +!$multiLine = $breakText($text, $usedNewLine) +!return $multiLine +!endfunction + +!unquoted function $breakDescr($text, $widthStr) + !$usedNewLine = "\n" + !return $breakText($text, $usedNewLine, $widthStr) +!endfunction + +' $breakTechn() supports //...//; $breakNode() in C4_Deployment supports no //....// +!unquoted function $breakTechn($text, $widthStr) + !$usedNewLine = '//\n//' + !return $breakText($text, $usedNewLine, $widthStr) +!endfunction + +' Element base layout +' ################################## + +!function $getElementBase($label, $techn, $descr, $sprite) + !$element = "" + !if ($sprite != "") + !$element = $element + $getSprite($sprite) + !if ($label != "") + !$element = $element + '\n' + !endif + !endif + !if ($label != "") + !$element = $element + '== ' + $breakLabel($label) + !else + !$element = $element + '.' + !endif + !if ($techn != "") + !$element = $element + '\n//[' + $breakTechn($techn, '-1') + ']//' + !endif + !if ($descr != "") + !$element = $element + '\n\n' + $descr + !endif + !return $element +!endfunction + +!function $getElementLine($umlShape, $elementType, $alias, $label, $techn, $descr, $sprite, $tags, $link) + !$sprite=$toElementArg($sprite, $tags, "ElementTagSprite", $elementType) + !$techn=$toElementArg($techn, $tags, "ElementTagTechn", $elementType) + !$baseProp = $getElementBase($label, $techn, $descr, $sprite) + $getProps() + !$stereo = $toStereos($elementType,$tags) + !$calcLink = $getLink($link) + + !$line = $umlShape + " " + %chr(34) + $baseProp + %chr(34) +" " + $stereo + " as " + $alias + $calcLink + !return $line +!endfunction + +' Element properties +' ################################## + +' collect all defined properties as table rows +!global $propTable = "" +!global $propTableCaption = "" +!global $propColCaption = "=" + +!unquoted function SetPropertyHeader($col1Name, $col2Name, $col3Name = "", $col4Name = "") + !$propColCaption = "" + !$propTableCaption = "|= " + $col1Name + " |= " + $col2Name + " |" + !if ($col3Name != "") + !$propTableCaption = $propTableCaption + "= " + $col3Name + " |" + !endif + !if ($col4Name != "") + !$propTableCaption = $propTableCaption + "= " + $col4Name + " |" + !endif + !return "" +!endfunction + +!unquoted function WithoutPropertyHeader() + !$propTableCaption = "" + !$propColCaption = "=" + !return "" +!endfunction + +!unquoted function AddProperty($col1, $col2, $col3 = "", $col4 = "") + !if ($propTable == "") + !if ($propTableCaption != "") + !$propTable = $propTableCaption + "\n" + !endif + !else + !$propTable = $propTable + "\n" + !endif + !$propTable = $propTable + "| " + $col1 + " |" + $propColCaption + " " + $col2 + " |" + !if ($col3 != "") + !$propTable = $propTable + " " + $col3 + " |" + !endif + !if ($col4 != "") + !$propTable = $propTable + " " + $col4 + " |" + !endif + !return "" +!endfunction + +!unquoted function $getProps($alignedNL = "\n") + !if ($propTable != "") + !$retTable = $alignedNL + $propTable + !$propTable = "" + !return $retTable + !endif + !return "" +!endfunction + +!unquoted function $getProps_L() + !return $getProps("\l") +!endfunction + +!unquoted function $getProps_R() + !return $getProps("\r") +!endfunction + +SetPropertyHeader("Property","Value") + +' Layout +' ################################## + +!function $getLegendDetailsSize($detailsFormat) + !if $detailsFormat == $LEGEND_DETAILS_NONE + !$size = 0 + !elseif $detailsFormat == $LEGEND_DETAILS_SMALL + !$size = $LEGEND_DETAILS_SMALL_SIZE + !else + !$size = $LEGEND_DETAILS_NORMAL_SIZE + !endif + !return $size +!endfunction + +!procedure $getHideStereotype($hideStereotype) +!if ($hideStereotype == "true") +hide stereotype +!endif +!endprocedure + +!procedure $getLegendTable($detailsFormat) +!global $LEGEND_DETAILS_SIZE = $getLegendDetailsSize($detailsFormat) +<$colorWithHash(transparent),$colorWithHash(transparent)>|**Legend** | +$showActiveLegendEntries($tagDefaultLegend) +$showActiveLegendEntries($tagCustomLegend) +!endprocedure + +!procedure $getLegendArea($areaAlias, $hideStereotype, $details) +$getHideStereotype($hideStereotype) +rectangle $areaAlias<> [ +$getLegendTable($details) +] +!endprocedure + +!procedure HIDE_STEREOTYPE() +hide stereotype +!endprocedure + +!unquoted procedure SET_SKETCH_STYLE($bgColor="_dont_change_", $fontColor="_dont_change_", $warningColor="_dont_change_", $fontName="_dont_change_", $footerWarning="_dont_change_", $footerText="_dont_change_") +!if $bgColor != "_dont_change_" + !global $SKETCH_BG_COLOR = $bgColor +!endif +!if $fontColor != "_dont_change_" + !global $SKETCH_FONT_COLOR = $fontColor +!endif +!if $warningColor != "_dont_change_" + !global $SKETCH_WARNING_COLOR = $warningColor +!endif +!if $fontName != "_dont_change_" + !global $SKETCH_FONT_NAME = $fontName +!endif +!if $footerWarning != "_dont_change_" + !global $SKETCH_FOOTER_WARNING = $footerWarning +!endif +!if $footerText != "_dont_change_" + !global $SKETCH_FOOTER_TEXT = $footerText +!endif +!endprocedure + +!procedure LAYOUT_AS_SKETCH() + skinparam handwritten true +!if $SKETCH_BG_COLOR > "" + skinparam backgroundColor $SKETCH_BG_COLOR +!endif +!if $SKETCH_FONT_COLOR > "" + skinparam footer { + FontColor $SKETCH_FONT_COLOR + } + !if $ARROW_COLOR == "#666666" + !global $ARROW_COLOR = $SKETCH_FONT_COLOR + !global $ARROW_FONT_COLOR = $SKETCH_FONT_COLOR + skinparam arrow { + Color $ARROW_COLOR + FontColor $ARROW_FONT_COLOR + } + !endif + !if $BOUNDARY_COLOR == "#444444" + !global $BOUNDARY_COLOR = $SKETCH_FONT_COLOR + skinparam rectangle<> { + FontColor $BOUNDARY_COLOR + BorderColor $BOUNDARY_COLOR + } + !endif +!endif +!if $SKETCH_FONT_NAMES > "" + skinparam defaultFontName $SKETCH_FONT_NAME +!endif +!if $SKETCH_FOOTER_WARNING > "" || $SKETCH_FOOTER_TEXT > "" + !$line = "footer "+ $SKETCH_FOOTER_WARNING + " " + $SKETCH_FOOTER_TEXT + $line +!endif +!endprocedure + +!global $fix_direction=%false() + +!function $down($start,$end) +!if ($fix_direction) +!return $start+"RIGHT"+$end +!else +!return $start+"DOWN"+$end +!endif +!endfunction + +!function $up($start,$end) +!if ($fix_direction) +!return $start+"LEFT"+$end +!else +!return $start+"UP"+$end +!endif +!endfunction + +!function $left($start,$end) +!if ($fix_direction) +!return $start+"UP"+$end +!else +!return $start+"LEFT"+$end +!endif +!endfunction + +!function $right($start,$end) +!if ($fix_direction) +!return $start+"DOWN"+$end +!else +!return $start+"RIGHT"+$end +!endif +!endfunction + +!procedure LAYOUT_TOP_DOWN() +!global $fix_direction=%false() +top to bottom direction +!endprocedure + +!procedure LAYOUT_LEFT_RIGHT() +!global $fix_direction = %false() +left to right direction +!endprocedure + +!procedure LAYOUT_LANDSCAPE() +!global $fix_direction = %true() +left to right direction +!endprocedure + +' legend details can displayed as Normal(), Small(), None() +!function None() +!return $LEGEND_DETAILS_NONE +!endfunction + +!function Normal() +!return $LEGEND_DETAILS_NORMAL +!endfunction + +!function Small() +!return $LEGEND_DETAILS_SMALL +!endfunction + +' has to be last call in diagram +!unquoted procedure SHOW_LEGEND($hideStereotype="true", $details=Small()) +$getHideStereotype($hideStereotype) +legend right +$getLegendTable($details) +endlegend +!endprocedure + +/' @deprecated in favor of SHOW_LEGEND '/ +!unquoted procedure SHOW_DYNAMIC_LEGEND($hideStereotype="true") +SHOW_LEGEND($hideStereotype) +!endprocedure + +' legend is reserved and cannot be uses as alias of SHOW_FLOATING_LEGEND() therefore +' LEGEND() is introduced. It returns the default name of the floating alias "floating_legend_alias" +' and can be used in the Lay_Distance() calls +!function LEGEND() +!return "floating_legend_alias" +!endfunction + +' enables that legend can be located in drawing area of the diagram. It has to be last call in diagram followed by Lay_Distance() +!unquoted procedure SHOW_FLOATING_LEGEND($alias=LEGEND(), $hideStereotype="true", $details=Small()) +$getLegendArea($alias, $hideStereotype, $details) +!endprocedure + +' Boundaries +' ################################## + +!unquoted procedure UpdateBoundaryStyle($elementName="", $bgColor="", $fontColor="", $borderColor="", $shadowing="", $shape="", $type="", $legendText="", $borderStyle="", $borderThickness="") + !if ($elementName != "") + !$elementBoundary = $elementName + '_boundary' + UpdateElementStyle($elementBoundary, $bgColor, $fontColor, $borderColor, $shadowing, $shape, "", $type, $legendText, "", $borderStyle, $borderThickness) + !else + UpdateElementStyle("boundary", $bgColor, $fontColor, $borderColor, $shadowing, $shape, "", $type, $legendText, "", $borderStyle, $borderThickness) + ' simulate color inheritance + UpdateBoundaryStyle("enterprise", $bgColor, $fontColor, $borderColor, $shadowing, $shape, "Enterprise", "", $borderStyle, $borderThickness) + UpdateBoundaryStyle("system", $bgColor, $fontColor, $borderColor, $shadowing, $shape, "System", "", $borderStyle, $borderThickness) + UpdateBoundaryStyle("container", $bgColor, $fontColor, $borderColor, $shadowing, $shape, "Container", "", $borderStyle, $borderThickness) + !endif +!endprocedure + +!unquoted procedure AddBoundaryTag($tagStereo, $bgColor="", $fontColor="", $borderColor="", $shadowing="", $shape="", $type="", $legendText="", $borderStyle="", $borderThickness="") + !$tagBoundary = $tagStereo + '_boundary' + AddElementTag($tagBoundary, $bgColor, $fontColor, $borderColor, $shadowing, $shape, "", $type, $legendText, "", $borderStyle, $borderThickness) +!endprocedure + +' add _boundary to all tags that short tag version can be used +!unquoted function $addBoundaryPostfix($tags) + !if (%strlen($tags) == 0) + !return '' + !endif + !$boundaryTags = '' + !$brPos = %strpos($tags, "+") + !while ($brPos >= 0) + !$tag = %substr($tags, 0, $brPos) + !$boundaryTags = $boundaryTags + $tag + '_boundary+' + !$tags = %substr($tags, $brPos+1) + !$brPos = %strpos($tags, "+") + !endwhile + !if (%strlen($tags) > 0) + !$boundaryTags = $boundaryTags + $tags + '_boundary' + !endif + !return $boundaryTags +!endfunction + +!function $getBoundary($label, $type) + !if ($type == "") + !return '== ' + $breakLabel($label) + !endif + !if (type != "") + !return '== ' + $breakLabel($label) + '\n[' + $type + ']' + !endif +!endfunction + +!unquoted procedure Boundary($alias, $label, $type="", $tags="", $link="") +!$boundaryTags = $addBoundaryPostfix($tags) +' nodes $type reuses $techn definition of $boundaryTags +!$type=$toElementArg($type, $boundaryTags, "ElementTagTechn", "boundary") +rectangle "$getBoundary($label, $type)" $toStereos("boundary", $boundaryTags) as $alias $getLink($link) +!endprocedure + +' Boundary Styling +UpdateBoundaryStyle("", $bgColor=$BOUNDARY_BG_COLOR, $fontColor=$BOUNDARY_COLOR, $borderColor=$BOUNDARY_COLOR, $borderStyle=DashedLine()) + +' Index +' ################################## + +' Dynamic/Sequence diagram supports (automatically) numbered interactions: +' preferred function calls +' (Uppercase) LastIndex(): return the last used index (function which can be used as argument) +' (Uppercase) Index($offset=1): returns current index and calculates next index (function which can be used as argument) +' (Uppercase) SetIndex($new_index): returns new set index and calculates next index (function which can be used as argument) + +' old procedures calls +' (lowercase) increment($offset=1): increase current index (procedure which has no direct output) +' (lowercase) setIndex($new_index): set the new index (procedure which has no direct output) + +!$lastIndex = 0 +!$index = 1 + +!procedure increment($offset=1) + !$lastIndex = $index + !$index = $index + $offset +!endprocedure + +!procedure setIndex($new_index) + !$lastIndex = $index + !$index = $new_index +!endprocedure + +!function Index($offset=1) + !$lastIndex = $index + !$index = $lastIndex + $offset + !return $lastIndex +!endfunction + +!function LastIndex() + !return $lastIndex +!endfunction + +!function SetIndex($new_index, $offset=1) + !$lastIndex = $new_index + !$index = $new_index + $offset + !return $lastIndex +!endfunction + +!unquoted function $getPrefix($index) + !if ($index == "") + !$pre = Index() + ": " + !else + !$pre = $index + ": " + !endif + !return $pre +!endfunction + +' Relationship +' ################################## + +!function $getRel($direction, $alias1, $alias2, $label, $techn, $descr, $sprite, $tags, $link) + !$sprite = $toRelArg($sprite, $tags, "RelTagSprite") + !$techn = $toRelArg($techn, $tags, "RelTagTechn") + !$rel = $alias1 + ' ' + $direction + ' ' + $alias2 + !if ($tags != "") + !$rel = $rel + ' ' + $toStereos($tags) + !endif + !$rel = $rel + ' : ' + !if ($link != "") + !$rel = $rel + '**[[' + $link + ' ' + !endif + !if ($sprite != "") + !$rel = $rel + $getSprite($sprite) + !if ($label != "") + !$rel = $rel + ' ' + !endif + !endif + !if ($link != "") + !$usedNewLine = ']]**\n**[[' + $link + ' ' + ' if sprite and label is empty than the link url is shown (otherwise link cannot be activated at all) + !$rel = $rel + $breakText($label, $usedNewLine) + ']]**' + !else + !if ($label != "") + !$usedNewLine = '**\n**' + !$rel = $rel + '**' + $breakText($label, $usedNewLine) + '**' + !else + !$rel = $rel + '.' + !endif + !endif + !if ($techn != "") + ' line break is not deterministic, calculate it + !$rel = $rel + '\n//[' + $breakTechn($techn, $REL_TECHN_MAX_CHAR_WIDTH) + ']//' + !endif + !if ($descr != "") + ' line break is not deterministic, calculate it + !$rel = $rel + '\n\n' + $breakDescr($descr, $REL_DESCR_MAX_CHAR_WIDTH) + !endif + !$prop = $getProps() + !if ($prop != "") + ' reuse table + !$rel = $rel + $prop + !endif + !return $rel +!endfunction + +!unquoted procedure Rel_($alias1, $alias2, $label, $direction) +$getRel($direction, $alias1, $alias2, $label, "", "", "", "", "") +!endprocedure +!unquoted procedure Rel_($alias1, $alias2, $label, $techn, $direction) +$getRel($direction, $alias1, $alias2, $label, $techn, "", "", "", "") +!endprocedure + +!unquoted procedure Rel($from, $to, $label, $techn="", $descr="", $sprite="", $tags="", $link="") +$getRel("-->>", $from, $to, $label, $techn, $descr, $sprite, $tags, $link) +!endprocedure + +!unquoted procedure BiRel($from, $to, $label, $techn="", $descr="", $sprite="", $tags="", $link="") +$getRel("<<-->>", $from, $to, $label, $techn, $descr, $sprite, $tags, $link) +!endprocedure + +!unquoted procedure Rel_Back($from, $to, $label, $techn="", $descr="", $sprite="", $tags="", $link="") +$getRel("<<--", $from, $to, $label, $techn, $descr, $sprite, $tags, $link) +!endprocedure + +!unquoted procedure Rel_Neighbor($from, $to, $label, $techn="", $descr="", $sprite="", $tags="", $link="") +$getRel("->>", $from, $to, $label, $techn, $descr, $sprite, $tags, $link) +!endprocedure + +!unquoted procedure BiRel_Neighbor($from, $to, $label, $techn="", $descr="", $sprite="", $tags="", $link="") +$getRel("<<->>", $from, $to, $label, $techn, $descr, $sprite, $tags, $link) +!endprocedure + +!unquoted procedure Rel_Back_Neighbor($from, $to, $label, $techn="", $descr="", $sprite="", $tags="", $link="") +$getRel("<<-", $from, $to, $label, $techn, $descr, $sprite, $tags, $link) +!endprocedure + +!unquoted procedure Rel_D($from, $to, $label, $techn="", $descr="", $sprite="", $tags="", $link="") +$getRel($down("-","->>"), $from, $to, $label, $techn, $descr, $sprite, $tags, $link) +!endprocedure +!unquoted procedure Rel_Down($from, $to, $label, $techn="", $descr="", $sprite="", $tags="", $link="") +$getRel($down("-","->>"), $from, $to, $label, $techn, $descr, $sprite, $tags, $link) +!endprocedure + +!unquoted procedure BiRel_D($from, $to, $label, $techn="", $descr="", $sprite="", $tags="", $link="") +$getRel($down("<<-","->>"), $from, $to, $label, $techn, $descr, $sprite, $tags, $link) +!endprocedure +!unquoted procedure BiRel_Down($from, $to, $label, $techn="", $descr="", $sprite="", $tags="", $link="") +$getRel($down("<<-","->>"), $from, $to, $label, $techn, $descr, $sprite, $tags, $link) +!endprocedure + +!unquoted procedure Rel_U($from, $to, $label, $techn="", $descr="", $sprite="", $tags="", $link="") +$getRel($up("-","->>"), $from, $to, $label, $techn, $descr, $sprite, $tags, $link) +!endprocedure +!unquoted procedure Rel_Up($from, $to, $label, $techn="", $descr="", $sprite="", $tags="", $link="") +$getRel($up("-","->>"), $from, $to, $label, $techn, $descr, $sprite, $tags, $link) +!endprocedure + +!unquoted procedure BiRel_U($from, $to, $label, $techn="", $descr="", $sprite="", $tags="", $link="") +$getRel($up("<<-","->>"), $from, $to, $label, $techn, $descr, $sprite, $tags, $link) +!endprocedure +!unquoted procedure BiRel_Up($from, $to, $label, $techn="", $descr="", $sprite="", $tags="", $link="") +$getRel($up("<<-","->>"), $from, $to, $label, $techn, $descr, $sprite, $tags, $link) +!endprocedure + +!unquoted procedure Rel_L($from, $to, $label, $techn="", $descr="", $sprite="", $tags="", $link="") +$getRel($left("-","->>"), $from, $to, $label, $techn, $descr, $sprite, $tags, $link) +!endprocedure +!unquoted procedure Rel_Left($from, $to, $label, $techn="", $descr="", $sprite="", $tags="", $link="") +$getRel($left("-","->>"), $from, $to, $label, $techn, $descr, $sprite, $tags, $link) +!endprocedure + +!unquoted procedure BiRel_L($from, $to, $label, $techn="", $descr="", $sprite="", $tags="", $link="") +$getRel($left("<<-","->>"), $from, $to, $label, $techn, $descr, $sprite, $tags, $link) +!endprocedure +!unquoted procedure BiRel_Left($from, $to, $label, $techn="", $descr="", $sprite="", $tags="", $link="") +$getRel($left("<<-","->>"), $from, $to, $label, $techn, $descr, $sprite, $tags, $link) +!endprocedure + +!unquoted procedure Rel_R($from, $to, $label, $techn="", $descr="", $sprite="", $tags="", $link="") +$getRel($right("-","->>"), $from, $to, $label, $techn, $descr, $sprite, $tags, $link) +!endprocedure +!unquoted procedure Rel_Right($from, $to, $label, $techn="", $descr="", $sprite="", $tags="", $link="") +$getRel($right("-","->>"), $from, $to, $label, $techn, $descr, $sprite, $tags, $link) +!endprocedure + +!unquoted procedure BiRel_R($from, $to, $label, $techn="", $descr="", $sprite="", $tags="", $link="") +$getRel($right("<<-","->>"), $from, $to, $label, $techn, $descr, $sprite, $tags, $link) +!endprocedure +!unquoted procedure BiRel_Right($from, $to, $label, $techn="", $descr="", $sprite="", $tags="", $link="") +$getRel($right("<<-","->>"), $from, $to, $label, $techn, $descr, $sprite, $tags, $link) +!endprocedure + +' Layout Helpers +' ################################## + +!function $getHiddenLine($distance) + !return '-[hidden]' + %substr('------------', 0, %intval($distance) + 1) +!endfunction + +!unquoted procedure Lay_D($from, $to) +$from -[hidden]D- $to +!endprocedure +!unquoted procedure Lay_Down($from, $to) +$from -[hidden]D- $to +!endprocedure + +!unquoted procedure Lay_U($from, $to) +$from -[hidden]U- $to +!endprocedure +!unquoted procedure Lay_Up($from, $to) +$from -[hidden]U- $to +!endprocedure + +!unquoted procedure Lay_R($from, $to) +$from -[hidden]R- $to +!endprocedure +!unquoted procedure Lay_Right($from, $to) +$from -[hidden]R- $to +!endprocedure + +!unquoted procedure Lay_L($from, $to) +$from -[hidden]L- $to +!endprocedure +!unquoted procedure Lay_Left($from, $to) +$from -[hidden]L- $to +!endprocedure + +' PlantUML bug: lines which does "not match" with the orientation/direction of the diagram +' use the same length therefore the method offers no direction at all. +' If a direction is required the Lay_...() methods can be used +!unquoted procedure Lay_Distance($from, $to, $distance="0") +$from $getHiddenLine($distance) $to +!endprocedure diff --git a/generated-diagrams/.c4s/C4_Component.puml b/generated-diagrams/.c4s/C4_Component.puml new file mode 100644 index 0000000..a4137d6 --- /dev/null +++ b/generated-diagrams/.c4s/C4_Component.puml @@ -0,0 +1,83 @@ +' convert it with additional command line argument -DRELATIVE_INCLUDE="relative/absolute" to use locally +!if %variable_exists("RELATIVE_INCLUDE") + !include ./C4_Container.puml +!else + !include https://raw.githubusercontent.com/plantuml-stdlib/C4-PlantUML/master/C4_Container.puml +!endif + +' Scope: A single container. +' Primary elements: Components within the container in scope. +' Supporting elements: Containers (within the software system in scope) plus people and software systems directly connected to the components. +' Intended audience: Software architects and developers. + +' Colors +' ################################## + +!$COMPONENT_FONT_COLOR ?= "#000000" +!$COMPONENT_BG_COLOR ?= "#85BBF0" +!$COMPONENT_BORDER_COLOR ?= "#78A8D8" + +!$EXTERNAL_COMPONENT_FONT_COLOR ?= $COMPONENT_FONT_COLOR +!$EXTERNAL_COMPONENT_BG_COLOR ?= "#CCCCCC" +!$EXTERNAL_COMPONENT_BORDER_COLOR ?= "#BFBFBF" + +' Styling +' ################################## + +UpdateElementStyle("component", $COMPONENT_BG_COLOR, $COMPONENT_FONT_COLOR, $COMPONENT_BORDER_COLOR, false) +UpdateElementStyle("external_component", $EXTERNAL_COMPONENT_BG_COLOR, $EXTERNAL_COMPONENT_FONT_COLOR, $EXTERNAL_COMPONENT_BORDER_COLOR, false) + +' shortcuts with default colors +!unquoted procedure AddComponentTag($tagStereo, $bgColor="", $fontColor="", $borderColor="", $shadowing="", $shape="", $sprite="", $techn="", $legendText="", $legendSprite="", $borderStyle="", $borderThickness="") + $addElementTagInclReuse("component", $tagStereo, $bgColor, $fontColor, $borderColor, $shadowing, $shape, $sprite, $techn, $legendText, $legendSprite, $borderStyle, $borderThickness) +!endprocedure +!unquoted procedure AddExternalComponentTag($tagStereo, $bgColor="", $fontColor="", $borderColor="", $shadowing="", $shape="", $sprite="", $techn="", $legendText="", $legendSprite="", $borderStyle="", $borderThickness="") + $addElementTagInclReuse("external_component", $tagStereo, $bgColor, $fontColor, $borderColor, $shadowing, $shape, $sprite, $techn, $legendText, $legendSprite, $borderStyle, $borderThickness) +!endprocedure + +' Layout +' ################################## + +SetDefaultLegendEntries("person\nsystem\ncontainer\ncomponent\nexternal_person\nexternal_system\nexternal_container\nexternal_component\nenterprise_boundary\nsystem_boundary\ncontainer_boundary\nboundary") + +!procedure LAYOUT_WITH_LEGEND() +hide stereotype +legend right +|**Legend** | +|<$PERSON_BG_COLOR> person | +|<$SYSTEM_BG_COLOR> system | +|<$CONTAINER_BG_COLOR> container | +|<$COMPONENT_BG_COLOR> component | +|<$EXTERNAL_PERSON_BG_COLOR> external person | +|<$EXTERNAL_SYSTEM_BG_COLOR> external system | +|<$EXTERNAL_CONTAINER_BG_COLOR> external container | +|<$EXTERNAL_COMPONENT_BG_COLOR> external component | +endlegend +!endprocedure + +' Elements +' ################################## + +!unquoted procedure Component($alias, $label, $techn="", $descr="", $sprite="", $tags="", $link="", $baseShape="rectangle") + $getElementLine($baseShape, "component", $alias, $label, $techn, $descr, $sprite, $tags, $link) +!endprocedure + +!unquoted procedure ComponentDb($alias, $label, $techn="", $descr="", $sprite="", $tags="", $link="") + $getElementLine("database", "component", $alias, $label, $techn, $descr, $sprite, $tags, $link) +!endprocedure + +!unquoted procedure ComponentQueue($alias, $label, $techn="", $descr="", $sprite="", $tags="", $link="") + $getElementLine("queue", "component", $alias, $label, $techn, $descr, $sprite, $tags, $link) +!endprocedure + +!unquoted procedure Component_Ext($alias, $label, $techn="", $descr="", $sprite="", $tags="", $link="", $baseShape="rectangle") + $getElementLine($baseShape, "external_component", $alias, $label, $techn, $descr, $sprite, $tags, $link) +!endprocedure + +!unquoted procedure ComponentDb_Ext($alias, $label, $techn="", $descr="", $sprite="", $tags="", $link="") + $getElementLine("database", "external_component", $alias, $label, $techn, $descr, $sprite, $tags, $link) +!endprocedure + +!unquoted procedure ComponentQueue_Ext($alias, $label, $techn="", $descr="", $sprite="", $tags="", $link="") + $getElementLine("queue", "external_component", $alias, $label, $techn, $descr, $sprite, $tags, $link) +!endprocedure diff --git a/generated-diagrams/.c4s/C4_Container.puml b/generated-diagrams/.c4s/C4_Container.puml new file mode 100644 index 0000000..bccd6fd --- /dev/null +++ b/generated-diagrams/.c4s/C4_Container.puml @@ -0,0 +1,103 @@ +' convert it with additional command line argument -DRELATIVE_INCLUDE="relative/absolute" to use locally +!if %variable_exists("RELATIVE_INCLUDE") + !include ./C4_Context.puml +!else + !include https://raw.githubusercontent.com/plantuml-stdlib/C4-PlantUML/master/C4_Context.puml +!endif + +' Scope: A single software system. +' Primary elements: Containers within the software system in scope. +' Supporting elements: People and software systems directly connected to the containers. +' Intended audience: Technical people inside and outside of the software development team; including software architects, developers and operations/support staff. + +' Colors +' ################################## + +!$CONTAINER_FONT_COLOR ?= $ELEMENT_FONT_COLOR +!$CONTAINER_BG_COLOR ?= "#438DD5" +!$CONTAINER_BORDER_COLOR ?= "#3C7FC0" + +!$CONTAINER_BOUNDARY_COLOR ?= $BOUNDARY_COLOR +!$CONTAINER_BOUNDARY_BG_COLOR ?= $BOUNDARY_BG_COLOR +!$CONTAINER_BOUNDARY_BORDER_STYLE ?= $BOUNDARY_BORDER_STYLE + +!$EXTERNAL_CONTAINER_FONT_COLOR ?= $ELEMENT_FONT_COLOR +!$EXTERNAL_CONTAINER_BG_COLOR ?= "#B3B3B3" +!$EXTERNAL_CONTAINER_BORDER_COLOR ?= "#A6A6A6" + +' Styling +' ################################## +UpdateElementStyle("container", $CONTAINER_BG_COLOR, $CONTAINER_FONT_COLOR, $CONTAINER_BORDER_COLOR, false) +UpdateElementStyle("external_container", $EXTERNAL_CONTAINER_BG_COLOR, $EXTERNAL_CONTAINER_FONT_COLOR, $EXTERNAL_CONTAINER_BORDER_COLOR, false) + +UpdateBoundaryStyle("container", $bgColor=$CONTAINER_BOUNDARY_BG_COLOR, $fontColor=$CONTAINER_BOUNDARY_COLOR, $borderColor=$CONTAINER_BOUNDARY_COLOR, $type="Container", $shadowing="false") + +' shortcuts with default colors +!unquoted procedure AddContainerTag($tagStereo, $bgColor="", $fontColor="", $borderColor="", $shadowing="", $shape="", $sprite="", $techn="", $legendText="", $legendSprite="", $borderStyle="", $borderThickness="") + $addElementTagInclReuse("container", $tagStereo, $bgColor, $fontColor, $borderColor, $shadowing, $shape, $sprite, $techn, $legendText, $legendSprite, $borderStyle, $borderThickness) +!endprocedure +!unquoted procedure AddExternalContainerTag($tagStereo, $bgColor="", $fontColor="", $borderColor="", $shadowing="", $shape="", $sprite="", $techn="", $legendText="", $legendSprite="", $borderStyle="", $borderThickness="") + $addElementTagInclReuse("external_container", $tagStereo, $bgColor, $fontColor, $borderColor, $shadowing, $shape, $sprite, $techn, $legendText, $legendSprite, $borderStyle, $borderThickness) +!endprocedure + +!unquoted procedure UpdateContainerBoundaryStyle($bgColor=$CONTAINER_BOUNDARY_BG_COLOR, $fontColor=$CONTAINER_BOUNDARY_COLOR, $borderColor=$CONTAINER_BOUNDARY_COLOR, $shadowing="", $shape="", $type="Container", $legendText="", $borderStyle="", $borderThickness="") + UpdateBoundaryStyle("container", $bgColor, $fontColor, $borderColor, $shadowing, $shape, $type, $legendText, $borderStyle, $borderThickness) +!endprocedure + +' Layout +' ################################## + +SetDefaultLegendEntries("person\nsystem\ncontainer\nexternal_person\nexternal_system\nexternal_container\nenterprise_boundary\nsystem_boundary\ncontainer_boundary\nboundary") + +!procedure LAYOUT_WITH_LEGEND() +hide stereotype +legend right +|**Legend** | +|<$PERSON_BG_COLOR> person | +|<$SYSTEM_BG_COLOR> system | +|<$CONTAINER_BG_COLOR> container | +|<$EXTERNAL_PERSON_BG_COLOR> external person | +|<$EXTERNAL_SYSTEM_BG_COLOR> external system | +|<$EXTERNAL_CONTAINER_BG_COLOR> external container | +endlegend +!endprocedure + +' Elements +' ################################## + +!unquoted procedure Container($alias, $label, $techn="", $descr="", $sprite="", $tags="", $link="", $baseShape="rectangle") + $getElementLine($baseShape , "container", $alias, $label, $techn, $descr, $sprite, $tags, $link) +!endprocedure + +!unquoted procedure ContainerDb($alias, $label, $techn="", $descr="", $sprite="", $tags="", $link="") + $getElementLine("database", "container", $alias, $label, $techn, $descr, $sprite, $tags, $link) +!endprocedure + +!unquoted procedure ContainerQueue($alias, $label, $techn="", $descr="", $sprite="", $tags="", $link="") + $getElementLine("queue", "container", $alias, $label, $techn, $descr, $sprite, $tags, $link) +!endprocedure + +!unquoted procedure Container_Ext($alias, $label, $techn="", $descr="", $sprite="", $tags="", $link="", $baseShape="rectangle") + $getElementLine($baseShape , "external_container", $alias, $label, $techn, $descr, $sprite, $tags, $link) +!endprocedure + +!unquoted procedure ContainerDb_Ext($alias, $label, $techn="", $descr="", $sprite="", $tags="", $link="") + $getElementLine("database", "external_container", $alias, $label, $techn, $descr, $sprite, $tags, $link) +!endprocedure + +!unquoted procedure ContainerQueue_Ext($alias, $label, $techn="", $descr="", $sprite="", $tags="", $link="") + $getElementLine("queue", "external_container", $alias, $label, $techn, $descr, $sprite, $tags, $link) +!endprocedure + +' Boundaries +' ################################## + +!unquoted procedure Container_Boundary($alias, $label, $tags="", $link="") + !if ($tags != "") + !$allTags = $tags + '+container' + !else + !$allTags = 'container' + !endif + ' $type defined via $tag style + Boundary($alias, $label, "", $allTags, $link) +!endprocedure diff --git a/generated-diagrams/.c4s/C4_Context.puml b/generated-diagrams/.c4s/C4_Context.puml new file mode 100644 index 0000000..71b2574 --- /dev/null +++ b/generated-diagrams/.c4s/C4_Context.puml @@ -0,0 +1,434 @@ +' convert it with additional command line argument -DRELATIVE_INCLUDE="relative/absolute" to use locally +!if %variable_exists("RELATIVE_INCLUDE") + !include ./C4.puml +!else + !include https://raw.githubusercontent.com/plantuml-stdlib/C4-PlantUML/master/C4.puml +!endif + +' Scope: A single software system. +' Primary elements: The software system in scope. +' Supporting elements: People and software systems directly connected to the software system in scope. +' Intended audience: Everybody, both technical and non-technical people, inside and outside of the software development team. + +' Colors +' ################################## + +!$PERSON_FONT_COLOR ?= $ELEMENT_FONT_COLOR +!$PERSON_BG_COLOR ?= "#08427B" +!$PERSON_BORDER_COLOR ?= "#073B6F" + +!$EXTERNAL_PERSON_FONT_COLOR ?= $ELEMENT_FONT_COLOR +!$EXTERNAL_PERSON_BG_COLOR ?= "#686868" +!$EXTERNAL_PERSON_BORDER_COLOR ?= "#8A8A8A" + +!$SYSTEM_FONT_COLOR ?= $ELEMENT_FONT_COLOR +!$SYSTEM_BG_COLOR ?= "#1168BD" +!$SYSTEM_BORDER_COLOR ?= "#3C7FC0" + +!$SYSTEM_BOUNDARY_COLOR ?= $BOUNDARY_COLOR +!$SYSTEM_BOUNDARY_BG_COLOR ?= $BOUNDARY_BG_COLOR +!$SYSTEM_BOUNDARY_BORDER_STYLE ?= $BOUNDARY_BORDER_STYLE + +!$EXTERNAL_SYSTEM_FONT_COLOR ?= $ELEMENT_FONT_COLOR +!$EXTERNAL_SYSTEM_BG_COLOR ?= "#999999" +!$EXTERNAL_SYSTEM_BORDER_COLOR ?= "#8A8A8A" + +!$ENTERPRISE_BOUNDARY_COLOR ?= $BOUNDARY_COLOR +!$ENTERPRISE_BOUNDARY_BG_COLOR ?= $BOUNDARY_BG_COLOR +!$ENTERPRISE_BOUNDARY_BORDER_STYLE ?= $BOUNDARY_BORDER_STYLE + +' Styling +' ################################## + +UpdateElementStyle("person", $PERSON_BG_COLOR, $PERSON_FONT_COLOR, $PERSON_BORDER_COLOR, false) +UpdateElementStyle("external_person", $EXTERNAL_PERSON_BG_COLOR, $EXTERNAL_PERSON_FONT_COLOR, $EXTERNAL_PERSON_BORDER_COLOR, false) +UpdateElementStyle("system", $SYSTEM_BG_COLOR, $SYSTEM_FONT_COLOR, $SYSTEM_BORDER_COLOR, false) +UpdateElementStyle("external_system", $EXTERNAL_SYSTEM_BG_COLOR, $EXTERNAL_SYSTEM_FONT_COLOR, $EXTERNAL_SYSTEM_BORDER_COLOR, false) + +UpdateBoundaryStyle("system", $bgColor=$SYSTEM_BOUNDARY_BG_COLOR, $fontColor=$SYSTEM_BOUNDARY_COLOR, $borderColor=$SYSTEM_BOUNDARY_COLOR, $type="System", $shadowing="false") +UpdateBoundaryStyle("enterprise", $bgColor=$ENTERPRISE_BOUNDARY_BG_COLOR, $fontColor=$ENTERPRISE_BOUNDARY_COLOR, $borderColor=$ENTERPRISE_BOUNDARY_COLOR, $type="Enterprise", $shadowing="false") + +' shortcuts with default colors +!unquoted procedure AddPersonTag($tagStereo, $bgColor="", $fontColor="", $borderColor="", $shadowing="", $shape="", $sprite="", $legendText="", $legendSprite="", $type="", $borderStyle="", $borderThickness="") + $addElementTagInclReuse("person", $tagStereo, $bgColor, $fontColor, $borderColor, $shadowing, $shape, $sprite, $type, $legendText, $legendSprite, $borderStyle, $borderThickness) +!endprocedure +!unquoted procedure AddExternalPersonTag($tagStereo, $bgColor="", $fontColor="", $borderColor="", $shadowing="", $shape="", $sprite="", $legendText="", $legendSprite="", $type="", $borderStyle="", $borderThickness="") + $addElementTagInclReuse("external_person", $tagStereo, $bgColor, $fontColor, $borderColor, $shadowing, $shape, $sprite, $type, $legendText, $legendSprite, $borderStyle, $borderThickness) +!endprocedure +!unquoted procedure AddSystemTag($tagStereo, $bgColor="", $fontColor="", $borderColor="", $shadowing="", $shape="", $sprite="", $legendText="", $legendSprite="", $type="", $borderStyle="", $borderThickness="") + $addElementTagInclReuse("system", $tagStereo, $bgColor, $fontColor, $borderColor, $shadowing, $shape, $sprite, $type, $legendText, $legendSprite, $borderStyle, $borderThickness) +!endprocedure +!unquoted procedure AddExternalSystemTag($tagStereo, $bgColor="", $fontColor="", $borderColor="", $shadowing="", $shape="", $sprite="", $legendText="", $legendSprite="", $type="", $borderStyle="", $borderThickness="") + $addElementTagInclReuse("external_system", $tagStereo, $bgColor, $fontColor, $borderColor, $shadowing, $shape, $sprite, $type, $legendText, $legendSprite, $borderStyle, $borderThickness) +!endprocedure + +!unquoted procedure UpdateEnterpriseBoundaryStyle($bgColor=$ENTERPRISE_BOUNDARY_BG_COLOR, $fontColor=$ENTERPRISE_BOUNDARY_COLOR, $borderColor=$ENTERPRISE_BOUNDARY_COLOR, $shadowing="", $shape="", $type="Enterprise", $legendText="", $borderStyle="", $borderThickness="") + UpdateBoundaryStyle("enterprise", $bgColor, $fontColor, $borderColor, $shadowing, $shape, $type, $legendText, $borderStyle, $borderThickness) +!endprocedure +!unquoted procedure UpdateSystemBoundaryStyle($bgColor=$SYSTEM_BOUNDARY_BG_COLOR, $fontColor=$SYSTEM_BOUNDARY_COLOR, $borderColor=$SYSTEM_BOUNDARY_COLOR, $shadowing="", $shape="", $type="System", $legendText="", $borderStyle="", $borderThickness="") + UpdateBoundaryStyle("system", $bgColor, $fontColor, $borderColor, $shadowing, $shape, $type, $legendText, $borderStyle, $borderThickness) +!endprocedure + +' Sprites +' ################################## + +sprite $person [48x48/16] { +000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000 +0000000000000000000049BCCA7200000000000000000000 +0000000000000000006EFFFFFFFFB3000000000000000000 +00000000000000001CFFFFFFFFFFFF700000000000000000 +0000000000000001EFFFFFFFFFFFFFF80000000000000000 +000000000000000CFFFFFFFFFFFFFFFF6000000000000000 +000000000000007FFFFFFFFFFFFFFFFFF100000000000000 +00000000000001FFFFFFFFFFFFFFFFFFF900000000000000 +00000000000006FFFFFFFFFFFFFFFFFFFF00000000000000 +0000000000000BFFFFFFFFFFFFFFFFFFFF40000000000000 +0000000000000EFFFFFFFFFFFFFFFFFFFF70000000000000 +0000000000000FFFFFFFFFFFFFFFFFFFFF80000000000000 +0000000000000FFFFFFFFFFFFFFFFFFFFF80000000000000 +0000000000000DFFFFFFFFFFFFFFFFFFFF60000000000000 +0000000000000AFFFFFFFFFFFFFFFFFFFF40000000000000 +00000000000006FFFFFFFFFFFFFFFFFFFE00000000000000 +00000000000000EFFFFFFFFFFFFFFFFFF800000000000000 +000000000000007FFFFFFFFFFFFFFFFFF100000000000000 +000000000000000BFFFFFFFFFFFFFFFF5000000000000000 +0000000000000001DFFFFFFFFFFFFFF70000000000000000 +00000000000000000BFFFFFFFFFFFF500000000000000000 +0000000000000000005DFFFFFFFFA1000000000000000000 +0000000000000000000037ABB96100000000000000000000 +000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000 +000000000000025788300000000005886410000000000000 +000000000007DFFFFFFD9643347BFFFFFFFB400000000000 +0000000004EFFFFFFFFFFFFFFFFFFFFFFFFFFB1000000000 +000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFD200000000 +00000006FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE10000000 +0000003FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB0000000 +000000BFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5000000 +000003FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD000000 +000009FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF200000 +00000DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF600000 +00000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF800000 +00001FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA00000 +00001FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB00000 +00001FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB00000 +00001FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB00000 +00001FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA00000 +00000EFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF700000 +000006FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE100000 +0000008FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD3000000 +000000014555555555555555555555555555555300000000 +000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000 +} + +sprite $person2 [48x48/16] { +0000000000000000000049BCCA7200000000000000000000 +0000000000000000006EFFFFFFFFB3000000000000000000 +00000000000000001CFFFFFFFFFFFF700000000000000000 +0000000000000001EFFFFFFFFFFFFFF80000000000000000 +000000000000000CFFFFFFFFFFFFFFFF6000000000000000 +000000000000007FFFFFFFFFFFFFFFFFF100000000000000 +00000000000001FFFFFFFFFFFFFFFFFFF900000000000000 +00000000000006FFFFFFFFFFFFFFFFFFFF00000000000000 +0000000000000BFFFFFFFFFFFFFFFFFFFF40000000000000 +0000000000000EFFFFFFFFFFFFFFFFFFFF70000000000000 +0000000000000FFFFFFFFFFFFFFFFFFFFF80000000000000 +0000000000000FFFFFFFFFFFFFFFFFFFFF80000000000000 +0000000000000DFFFFFFFFFFFFFFFFFFFF60000000000000 +0000000000000AFFFFFFFFFFFFFFFFFFFF40000000000000 +00000000000006FFFFFFFFFFFFFFFFFFFE00000000000000 +00000000000000EFFFFFFFFFFFFFFFFFF800000000000000 +000000000000007FFFFFFFFFFFFFFFFFF100000000000000 +000000000000000BFFFFFFFFFFFFFFFF5000000000000000 +0000000000000001DFFFFFFFFFFFFFF70000000000000000 +00000000000000000BFFFFFFFFFFFF500000000000000000 +0000000000000000005DFFFFFFFFA1000000000000000000 +0000000000000000000037ABB96100000000000000000000 +000000000002578888300000000005888864100000000000 +0000000007DFFFFFFFFD9643347BFFFFFFFFFB4000000000 +00000004EFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB10000000 +0000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD2000000 +000006FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE100000 +00003FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB00000 +0000BFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF50000 +0003FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD0000 +0009FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2000 +000DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6000 +000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8000 +001FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB000 +001FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB000 +001FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB000 +001FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA000 +000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8000 +000DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6000 +0009FFFFFFFF8FFFFFFFFFFFFFFFFFFFFFF8FFFFFFFF2000 +0003FFFFFFFF8FFFFFFFFFFFFFFFFFFFFFF8FFFFFFFD0000 +0000BFFFFFFF8FFFFFFFFFFFFFFFFFFFFFF8FFFFFFF50000 +00003FFFFFFF8FFFFFFFFFFFFFFFFFFFFFF8FFFFFFB00000 +000006FFFFFF8FFFFFFFFFFFFFFFFFFFFFF8FFFFFE100000 +0000007FFFFF8FFFFFFFFFFFFFFFFFFFFFF8FFFFD2000000 +00000004EFFF8FFFFFFFFFFFFFFFFFFFFFF8FFFB10000000 +0000000007DF8FFFFFFFFFFFFFFFFFFFFFF8FB4000000000 +000000000002578888888888888888888864100000000000 +} + +sprite $robot [48x48/16] { +000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000 +000000000005BFFFFFFFFFFFFFFFFFFFFFE9100000000000 +0000000000AFFFFFFFFFFFFFFFFFFFFFFFFFE30000000000 +0000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFE1000000000 +000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFF8000000000 +000000004FFFFFFFFFFFFFFFFFFFFFFFFFFFFFC000000000 +000000005FFFFFFFFFFFFFFFFFFFFFFFFFFFFFD000000000 +000000005FFFFFFFFFFFFFFFFFFFFFFFFFFFFFE000000000 +000000005FFFFFFFFFFFFFFFFFFFFFFFFFFFFFE000000000 +000699405FFFFFFC427FFFFFFFFFC427FFFFFFE009982000 +008FFF705FFFFFE10006FFFFFFFE00007FFFFFE00FFFF100 +00CFFF705FFFFFA00001FFFFFFF900002FFFFFE00FFFF500 +00DFFF705FFFFFB00002FFFFFFFA00003FFFFFE00FFFF500 +00DFFF705FFFFFF4000AFFFFFFFF3000BFFFFFE00FFFF500 +00DFFF705FFFFFFFA8DFFFFFFFFFFA8DFFFFFFE00FFFF500 +00DFFF705FFFFFFFFFFFFFFFFFFFFFFFFFFFFFE00FFFF500 +00DFFF705FFFFFFFFFFFFFFFFFFFFFFFFFFFFFE00FFFF500 +00DFFF705FFFFFFFFFFFFFFFFFFFFFFFFFFFFFE00FFFF500 +00DFFF705FFFFFFFFFFFFFFFFFFFFFFFFFFFFFE00FFFF500 +00DFFF705FFFFFFFFFFFFFFFFFFFFFFFFFFFFFE00FFFF500 +00CFFF705FFFFFF87777777777777777CFFFFFE00FFFF500 +008FFF705FFFFFF100000000000000009FFFFFE00FFFF100 +000699405FFFFFF76666666666666666CFFFFFE009982000 +000000005FFFFFFFFFFFFFFFFFFFFFFFFFFFFFE000000000 +000000005FFFFFFFFFFFFFFFFFFFFFFFFFFFFFE000000000 +000000004FFFFFFFFFFFFFFFFFFFFFFFFFFFFFC000000000 +000000000EFFFFFFFFFFFFFFFFFFFFFFFFFFFF7000000000 +0000000005FFFFFFFFFFFFFFFFFFFFFFFFFFFD0000000000 +00000000004CFFFFFFFFFFFFFFFFFFFFFFFF910000000000 +000000000000011111111111111111111110000000000000 +000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000 +} + +sprite $robot2 [48x48/16] { +000000000000000088888888888888880000000000000000 +000000000000000AFFFFFFFFFFFFFFFFA000000000000000 +00000000000000CFFFFFFFFFFFFFFFFFFC00000000000000 +00000000000004EFFFFFFFFFFFFFFFFFFE40000000000000 +0000000000000AFFFFFFFFFFFFFFFFFFFFA0000000000000 +00000000000008FFFFFFFFFFFFFFFFFFFF80000000000000 +00000000000008FFFFFFFFFFFFFFFFFFFF80000000000000 +00000000000008FFFFFFFFFFFFFFFFFFFF80000000000000 +00000000000888FFFFFFFFFFFFFFFFFFFF88800000000000 +00000000008FF8FFFFFFFFFFFFFFFFFFFF8FF80000000000 +00000000008FF8FFFFFFFFFFFFFFFFFFFF8FF80000000000 +00000000008FF8FFFFFFFFFFFFFFFFFFFF8FF80000000000 +00000000008FF8FFFFFFFFFFFFFFFFFFFF8FF80000000000 +00000000008FF8FFFFFFFFFFFFFFFFFFFF8FF80000000000 +00000000008FF8FFFFFFFFFFFFFFFFFFFF8FF80000000000 +00000000000888FFFFFFFFFFFFFFFFFFFF88800000000000 +00000000000008FFFFFFFFFFFFFFFFFFFF80000000000000 +00000000000008FFFFFFFFFFFFFFFFFFFF80000000000000 +00000000000008FFFFFFFFFFFFFFFFFFFF80000000000000 +00000000000008FFFFFFFFFFFFFFFFFFFF80000000000000 +00000000000008FFFFFFFFFFFFFFFFFFFF80000000000000 +00000000000004CFFFFFFFFFFFFFFFFFFC40000000000000 +000000488888848CFFFFFFFFFFFFFFFFC848888884000000 +00000CFFFFFFFFC888888888888888888CFFFFFFFFC00000 +00008FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000 +0000CFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC0000 +0008FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8000 +0008FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8000 +0008FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8000 +0008FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8000 +0008FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8000 +0008FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8000 +0008FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8000 +0008FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8000 +0008FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8000 +0008FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8000 +0008FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8000 +0008FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8000 +0008FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8000 +0008FFFFFFFF8FFFFFFFFFFFFFFFFFFFFFF8FFFFFFFF8000 +0008FFFFFFFF8FFFFFFFFFFFFFFFFFFFFFF8FFFFFFFF8000 +0008FFFFFFFF8FFFFFFFFFFFFFFFFFFFFFF8FFFFFFFF8000 +0008FFFFFFFF8FFFFFFFFFFFFFFFFFFFFFF8FFFFFFFF8000 +0000CFFFFFFF8FFFFFFFFFFFFFFFFFFFFFF8FFFFFFFC0000 +00008FFFFFFF8FFFFFFFFFFFFFFFFFFFFFF8FFFFFFF80000 +00000CFFFFFF8FFFFFFFFFFFFFFFFFFFFFF8FFFFFFC00000 +000000488887578888888888888888888864688884000000 +000000000000000000000000000000000000000000000000 +} + +' Layout +' ################################## + +SetDefaultLegendEntries("person\nsystem\nexternal_person\nexternal_system\nenterprise_boundary\nsystem_boundary\nboundary") + +!procedure LAYOUT_WITH_LEGEND() +hide stereotype +legend right +|**Legend** | +|<$PERSON_BG_COLOR> person | +|<$SYSTEM_BG_COLOR> system| +|<$EXTERNAL_PERSON_BG_COLOR> external person | +|<$EXTERNAL_SYSTEM_BG_COLOR> external system | +endlegend +!endprocedure + +!global $defaultPersonSprite = "person" +!$dummy = $restoreEmpty("person", "sprite", $defaultPersonSprite, %true()) +UpdateElementStyle("person") +' workaround of plantuml.jar bug - person overwrites external_person setting +!$dummy = $restoreEmpty("external_person", "sprite", $defaultPersonSprite, %true()) +UpdateElementStyle("external_person") +!global $portraitPerson = "false" + +!procedure $clearPersonRestore() + !$dummy = $clearRestore("person", "sprite") + !$dummy = $clearRestore("person", "legendSprite") + %set_variable_value("$" + "person" + "ElementTagSprite", "") + UpdateElementStyle("person") + ' workaround of plantuml.jar bug - person overwrites external_person setting + !$dummy = $clearRestore("external_person", "sprite") + !$dummy = $clearRestore("external_person", "legendSprite") + %set_variable_value("$" + "external_person" + "ElementTagSprite", "") + UpdateElementStyle("external_person") +!endprocedure + +!procedure HIDE_PERSON_SPRITE() + !$defaultPersonSprite = "" + !$portraitPerson = "false" + $clearPersonRestore() +!endprocedure + +!unquoted procedure SHOW_PERSON_SPRITE($sprite="") + !if ($sprite == "") + !$defaultPersonSprite = "person" + !else + !$defaultPersonSprite = $sprite + !endif + !$dummy = $restoreEmpty("person", "sprite", $defaultPersonSprite, %true()) + UpdateElementStyle("person") + ' workaround of plantuml.jar bug - person overwrites external_person setting + !$dummy = $restoreEmpty("external_person", "sprite", $defaultPersonSprite, %true()) + UpdateElementStyle("external_person") + !$portraitPerson = "false" +!endprocedure + +!unquoted procedure SHOW_PERSON_PORTRAIT() + !$defaultPersonSprite = "" + !$portraitPerson = "portrait" + $clearPersonRestore() +!endprocedure + +!unquoted procedure SHOW_PERSON_OUTLINE() + !$defaultPersonSprite = "" + !$portraitPerson = "outline" + $clearPersonRestore() +!endprocedure + +' Elements +' ################################## + +!function $getPerson($label, $type, $descr, $sprite) + !if ($sprite == "") && ($defaultPersonSprite != "") + !$sprite = $defaultPersonSprite + !endif + !return $getElementBase($label, $type, $descr, $sprite) +!endfunction + +!unquoted procedure Person($alias, $label, $descr="", $sprite="", $tags="", $link="", $type="") +!$sprite=$toElementArg($sprite, $tags, "ElementTagSprite", "person") +' $type reuses $techn definition of $tags +!$type=$toElementArg($type, $tags, "ElementTagTechn", "person") +!if ($portraitPerson == "portrait") && ($sprite == "") +actor "$getPerson($label, $type, $descr, $sprite)$getProps()" $toStereos("person", $tags) as $alias $getLink($link) +!elseif ($portraitPerson == "outline") && ($sprite == "") +person "$getPerson($label, $type, $descr, $sprite)$getProps()" $toStereos("person", $tags) as $alias $getLink($link) +!else +rectangle "$getPerson($label, $type, $descr, $sprite)$getProps()" $toStereos("person", $tags) as $alias $getLink($link) +!endif +!endprocedure + +!unquoted procedure Person_Ext($alias, $label, $descr="", $sprite="", $tags="", $link="", $type="") +!$sprite=$toElementArg($sprite, $tags, "ElementTagSprite", "external_person") +' $type reuses $techn definition of $tags +!$type=$toElementArg($type, $tags, "ElementTagTechn", "external_person") +!if ($portraitPerson == "portrait") && ($sprite == "") +actor "$getPerson($label, $type, $descr, $sprite)$getProps()" $toStereos("external_person", $tags) as $alias $getLink($link) +!elseif ($portraitPerson == "outline") && ($sprite == "") +person "$getPerson($label, $type, $descr, $sprite)$getProps()" $toStereos("external_person", $tags) as $alias $getLink($link) +!else +rectangle "$getPerson($label, $type, $descr, $sprite)$getProps()" $toStereos("external_person", $tags) as $alias $getLink($link) +!endif +!endprocedure + +!unquoted procedure System($alias, $label, $descr="", $sprite="", $tags="", $link="", $type="", $baseShape="rectangle") + ' $type reuses $techn definition of $tags + $getElementLine($baseShape, "system", $alias, $label, $type, $descr, $sprite, $tags, $link) +!endprocedure + +!unquoted procedure SystemDb($alias, $label, $descr="", $sprite="", $tags="", $link="", $type="") + ' $type reuses $techn definition of $tags + $getElementLine("database", "system", $alias, $label, $type, $descr, $sprite, $tags, $link) +!endprocedure + +!unquoted procedure SystemQueue($alias, $label, $descr="", $sprite="", $tags="", $link="", $type="") + ' $type reuses $techn definition of $tags + $getElementLine("queue", "system", $alias, $label, $type, $descr, $sprite, $tags, $link) +!endprocedure + +!unquoted procedure System_Ext($alias, $label, $descr="", $sprite="", $tags="", $link="", $type="", $baseShape="rectangle") + ' $type reuses $techn definition of $tags + $getElementLine($baseShape , "external_system", $alias, $label, $type, $descr, $sprite, $tags, $link) +!endprocedure + +!unquoted procedure SystemDb_Ext($alias, $label, $descr="", $sprite="", $tags="", $link="", $type="") + ' $type reuses $techn definition of $tags + $getElementLine("database", "external_system", $alias, $label, $type, $descr, $sprite, $tags, $link) +!endprocedure + +!unquoted procedure SystemQueue_Ext($alias, $label, $descr="", $sprite="", $tags="", $link="", $type="") + ' $type reuses $techn definition of $tags + $getElementLine("queue", "external_system", $alias, $label, $type, $descr, $sprite, $tags, $link) +!endprocedure + +' Boundaries +' ################################## + +!unquoted procedure Enterprise_Boundary($alias, $label, $tags="", $link="") + !if ($tags != "") + !$allTags = $tags + '+enterprise' + !else + !$allTags = 'enterprise' + !endif + ' $type defined via $tag style + Boundary($alias, $label, "", $allTags, $link) +!endprocedure + +!unquoted procedure System_Boundary($alias, $label, $tags="", $link="") + !if ($tags != "") + !$allTags = $tags + '+system' + !else + !$allTags = 'system' + !endif + ' $type defined via $tag style + Boundary($alias, $label, "", $allTags, $link) +!endprocedure diff --git a/generated-diagrams/.c4s/C4_Deployment.puml b/generated-diagrams/.c4s/C4_Deployment.puml new file mode 100644 index 0000000..afc9945 --- /dev/null +++ b/generated-diagrams/.c4s/C4_Deployment.puml @@ -0,0 +1,140 @@ +' convert it with additional command line argument -DRELATIVE_INCLUDE="relative/absolute" to use locally +!if %variable_exists("RELATIVE_INCLUDE") + !include ./C4_Container.puml +!else + !include https://raw.githubusercontent.com/plantuml-stdlib/C4-PlantUML/master/C4_Container.puml +!endif + +' Colors +' ################################## + +!$NODE_FONT_COLOR ?= "#000000" +!$NODE_BG_COLOR ?= "#FFFFFF" +!$NODE_BORDER_COLOR ?= "#A2A2A2" + +' Styling +' ################################## + +' PlantUML supports no automatic line breaks of "PlantUML containers" (C4 Deployment_Node is a "PlantUML container") +' therefore (Deployment_)Node() implements an automatic line break based on spaces (like in all other objects). +' If a $type contains \n then these are used (and no automatic space based line breaks are done) +' $NODE_TYPE_MAX_CHAR_WIDTH defines the automatic line break position +!$NODE_TYPE_MAX_CHAR_WIDTH ?= 35 +!$NODE_DESCR_MAX_CHAR_WIDTH ?= 32 + +UpdateElementStyle("node", $bgColor=$NODE_BG_COLOR, $fontColor=$NODE_FONT_COLOR, $borderColor=$NODE_BORDER_COLOR, false) +skinparam rectangle<> { + FontStyle normal +} + +' shortcuts with default colors +' node specific: $techn is only used in old scripts, new scripts uses $type ($techn has to remain, it could be called via named argument) +!unquoted procedure AddNodeTag($tagStereo, $bgColor="", $fontColor="", $borderColor="", $shadowing="", $shape="", $sprite="", $type="", $legendText="", $legendSprite="", $techn="", $borderStyle="", $borderThickness="") + !$type=$type+$techn + $addElementTagInclReuse("node", $tagStereo, $bgColor, $fontColor, $borderColor, $shadowing, $shape, $sprite, $type, $legendText, $legendSprite, $borderStyle, $borderThickness) +!endprocedure + +' Layout +' ################################## + +' comment if node should not be added to legend. No calculated legend extension required +SetDefaultLegendEntries("person\nsystem\ncontainer\nexternal_person\nexternal_system\nexternal_container\nnode\nenterprise_boundary\nsystem_boundary\ncontainer_boundary\nboundary") + +' Line breaks +' ################################## + +' $breakTechn() in C4 supports //...//; $breakNode() in C4_Deployment supports no //....// +!unquoted function $breakNode($text, $widthStr) + !$usedNewLine = '\n' + !return $breakText($text, $usedNewLine, $widthStr) +!endfunction + +' Elements +' ################################## + +!function $getNode($label, $type, $descr, $sprite) + !$nodeText = "" + !if ($sprite != "") + !$nodeText = $nodeText + $getSprite($sprite) + '\n' + !endif + !$nodeText = $nodeText + '== ' + $breakText($label, "\n== ") + !if ($type != "") + !$nodeText = $nodeText + '\n[' + $breakNode($type, $NODE_TYPE_MAX_CHAR_WIDTH) + ']' + !endif + !if ($descr != "") + !$nodeText = $nodeText + '\n\n' + $breakDescr($descr, $NODE_DESCR_MAX_CHAR_WIDTH) + !endif + !return $nodeText +!endfunction + +!function $getNode_L($label, $type, $descr, $sprite) + !$nodeText = "" + !if ($sprite != "") + !$nodeText = $nodeText + $getSprite($sprite) + '\l' + !endif + !$nodeText = $nodeText + '== ' + $breakText($label, "\l== ") + !if ($type != "") + !$nodeText = $nodeText + '\l[' + $breakNode($type, $NODE_TYPE_MAX_CHAR_WIDTH) + ']' + !endif + !if ($descr != "") + !$nodeText = $nodeText + '\l\l' + $breakDescr($descr, $NODE_DESCR_MAX_CHAR_WIDTH) + !endif + !return $nodeText +!endfunction + +!function $getNode_R($label, $type, $descr, $sprite) + !$nodeText = "" + !if ($sprite != "") + !$nodeText = $nodeText + $getSprite($sprite) + '\r' + !endif + !$nodeText = $nodeText + '== ' + $breakText($label, "\r== ") + !if ($type != "") + !$nodeText = $nodeText + '\r[' + $breakNode($type, $NODE_TYPE_MAX_CHAR_WIDTH) + ']' + !endif + !if ($descr != "") + !$nodeText = $nodeText + '\r\r' + $breakDescr($descr, $NODE_DESCR_MAX_CHAR_WIDTH) + !endif + !return $nodeText +!endfunction + +!unquoted procedure Deployment_Node($alias, $label, $type="", $descr="", $sprite="", $tags="", $link="") +!$sprite=$toElementArg($sprite, $tags, "ElementTagSprite", "node") +' nodes $type reuses $techn definition of $tags +!$type=$toElementArg($type, $tags, "ElementTagTechn", "node") +rectangle "$getNode($label, $type, $descr, $sprite)$getProps()" $toStereos("node",$tags) as $alias $getLink($link) +!endprocedure + +!unquoted procedure Deployment_Node_L($alias, $label, $type="", $descr="", $sprite="", $tags="", $link="") +!$sprite=$toElementArg($sprite, $tags, "ElementTagSprite", "node") +' nodes $type reuses $techn definition of $tags +!$type=$toElementArg($type, $tags, "ElementTagTechn", "node") +rectangle "$getNode_L($label, $type, $descr, $sprite)$getProps_L()" $toStereos("node",$tags) as $alias $getLink($link) +!endprocedure + +!unquoted procedure Deployment_Node_R($alias, $label, $type="", $descr="", $sprite="", $tags="", $link="") +!$sprite=$toElementArg($sprite, $tags, "ElementTagSprite", "node") +' nodes $type reuses $techn definition of $tags +!$type=$toElementArg($type, $tags, "ElementTagTechn", "node") +rectangle "$getNode_R($label, $type, $descr, $sprite)$getProps_R()" $toStereos("node",$tags) as $alias $getLink($link) +!endprocedure + +!unquoted procedure Node($alias, $label, $type="", $descr="", $sprite="", $tags="", $link="") +!$sprite=$toElementArg($sprite, $tags, "ElementTagSprite", "node") +' nodes $type reuses $techn definition of $tags +!$type=$toElementArg($type, $tags, "ElementTagTechn", "node") +rectangle "$getNode($label, $type, $descr, $sprite)$getProps()" $toStereos("node",$tags) as $alias $getLink($link) +!endprocedure + +!unquoted procedure Node_L($alias, $label, $type="", $descr="", $sprite="", $tags="", $link="") +!$sprite=$toElementArg($sprite, $tags, "ElementTagSprite", "node") +' nodes $type reuses $techn definition of $tags +!$type=$toElementArg($type, $tags, "ElementTagTechn", "node") +rectangle "$getNode_L($label, $type, $descr, $sprite)$getProps_L()" $toStereos("node",$tags) as $alias $getLink($link) +!endprocedure + +!unquoted procedure Node_R($alias, $label, $type="", $descr="", $sprite="", $tags="", $link="") +!$sprite=$toElementArg($sprite, $tags, "ElementTagSprite", "node") +' nodes $type reuses $techn definition of $tags +!$type=$toElementArg($type, $tags, "ElementTagTechn", "node") +rectangle "$getNode_R($label, $type, $descr, $sprite)$getProps_R()" $toStereos("node",$tags) as $alias $getLink($link) +!endprocedure diff --git a/generated-diagrams/.c4s/C4_Sequence.puml b/generated-diagrams/.c4s/C4_Sequence.puml new file mode 100644 index 0000000..ee40694 --- /dev/null +++ b/generated-diagrams/.c4s/C4_Sequence.puml @@ -0,0 +1,398 @@ +' convert it with additional command line argument -DRELATIVE_INCLUDE="relative/absolute" to use locally +!if %variable_exists("RELATIVE_INCLUDE") + !include ./C4_Component.puml +!else + !include https://raw.githubusercontent.com/plantuml-stdlib/C4-PlantUML/master/C4_Component.puml +!endif + +' Scope: Interactions in an enterprise, software system or container. +' Primary and supporting elements: Depends on the diagram scope - +' enterprise - people and software systems Related to the enterprise in scope +' software system - see system context or container diagrams, +' container - see component diagram. +' Intended audience: Technical and non-technical people, inside and outside of the software development team. + +' Sequence diagram introduces (automatically) numbered interactions: +' (lowercase) increment($offset=1): increase current index (procedure which has no direct output) +' (lowercase) setIndex($new_index): set the new index (procedure which has no direct output) +' +' (Uppercase) LastIndex(): return the last used index (function which can be used as argument) +' (Uppercase) Index($offset=1): returns current index and calculates next index (function which can be used as argument) +' (Uppercase) SetIndex($new_index): returns new set index and calculates next index (function which can be used as argument) + +' enables multi-level boxes +!pragma teoz true + + +' Legend redefintion +' ################################## +' sequence has no dashed boxes +!if ($LEGEND_DASHED_BOUNDARY == "dashed") + !$LEGEND_DASHED_BOUNDARY = "" +!endif +!if ($LEGEND_DASHED_TRANSPARENT_BOUNDARY == "dashed") + !$LEGEND_DASHED_TRANSPARENT_BOUNDARY = "" +!endif +UpdateBoundaryStyle("", $bgColor=$BOUNDARY_BG_COLOR, $fontColor=$BOUNDARY_COLOR, $borderColor=$BOUNDARY_COLOR) +UpdateBoundaryStyle("enterprise", $bgColor=$ENTERPRISE_BOUNDARY_BG_COLOR, $fontColor=$ENTERPRISE_BOUNDARY_COLOR, $borderColor=$ENTERPRISE_BOUNDARY_COLOR, $type="Enterprise") +UpdateBoundaryStyle("system", $bgColor=$SYSTEM_BOUNDARY_BG_COLOR, $fontColor=$SYSTEM_BOUNDARY_COLOR, $borderColor=$SYSTEM_BOUNDARY_COLOR, $type="System") +UpdateBoundaryStyle("container", $bgColor=$CONTAINER_BOUNDARY_BG_COLOR, $fontColor=$CONTAINER_BOUNDARY_COLOR, $borderColor=$CONTAINER_BOUNDARY_COLOR, $type="Container") + +' Styling and Layout +' ################################## + +!global $display_element_description = %false() + +' typically the element/participant descriptions are not displayed in a sequence diagram, but it can be activated with this call +!unquoted procedure SHOW_ELEMENT_DESCRIPTIONS($show="true") +!if ($show == "true") + !global $display_element_description = %true() +!else + !global $display_element_description = %false() +!endif +!endprocedure + +' typically the foot boxes descriptions are not displayed in a sequence diagram, but it can be activated with this call +!unquoted procedure SHOW_FOOT_BOXES($show="true") +!if ($show == "true") + show footbox +!else + hide footbox +!endif +!endprocedure + +!global $show_index = %false() +' All relation specific (default) ordinary index numbers can be shown with this call +!unquoted procedure SHOW_INDEX($show="true") +!if ($show == "true") + !global $show_index = %true() +!else + !global $show_index = %false() +!endif +!endprocedure + +' ======= if no theme is defined hide foot box and activate C4_blue styles +!if (%variable_exists("$THEME")) +!else +' $BOUNDARY_BG_COLOR... have to be defined in theme itself that it can be used in styles,... +' (no default values which are defined in C4.puml) +' If skinparams and styles are defined with concrete values no variables are required +!$BOUNDARY_BG_COLOR ?= "transparent" +!$BOUNDARY_COLOR ?= "#444444" +!$ARROW_COLOR ?= "#666666" + +' replace transparent with concrete background that it can be used as font color too +!if ($BOUNDARY_BG_COLOR == "transparent") + !$SEQUENCE_BG_COLOR = white +!else + !$SEQUENCE_BG_COLOR = $BOUNDARY_BG_COLOR +!endif + +' "C4 styled" default is no foot boxes +hide footbox +' "C4 styled" default is that lifeline is arrow color +skinparam SequenceLifelineBorderColor $ARROW_COLOR + +skinparam SequenceGroupBodyBackgroundColor $SEQUENCE_BG_COLOR +skinparam SequenceGroupFontColor $BOUNDARY_COLOR +skinparam SequenceGroupBackgroundColor $BOUNDARY_COLOR +skinparam SequenceGroupHeaderFontColor $SEQUENCE_BG_COLOR +skinparam SequenceGroupBorderColor $BOUNDARY_COLOR + +skinparam SequenceReferenceBackgroundColor $SEQUENCE_BG_COLOR +skinparam SequenceReferenceFontColor $BOUNDARY_COLOR +skinparam SequenceReferenceHeaderBackgroundColor $BOUNDARY_COLOR +' VIA STYLE +' skinparam SequenceReferenceHeaderFontColor $SEQUENCE_BG_COLOR + +skinparam SequenceReferenceBorderColor $BOUNDARY_COLOR + +skinparam SequenceDividerBackgroundColor $SEQUENCE_BG_COLOR +skinparam SequenceDividerFontColor $BOUNDARY_COLOR +skinparam SequenceDividerBorderColor $BOUNDARY_COLOR + +' VIA STYLE +' skinparam SequenceDelayFontColor green + +!endif +' ======= if no theme is defined hide foot box and activate C4_blue styles + +' Elements redefinition +' ################################## + +' all elements have to be displayed as participant +' participants requires ` %newline()` instead of `\n` + +!unquoted function $breakWithNewline($text, $lineEnd, $lineStart, $widthStr="-1") +!$width = %intval($widthStr) +!$multiLine = "" +!if (%strpos($text, "\n") >= 0) + !while (%strpos($text, "\n") >= 0) + !$brPos = %strpos($text, "\n") + !if ($brPos > 0) + !$multiLine = $multiLine + %substr($text, 0, $brPos) + $lineEnd + %newline() + $lineStart + !else + ' non breaking change that newLine breaks with formats can be used with \n\n + !$multiLine = $multiLine + "" + $lineEnd + %newline() + $lineStart + !endif + !$text = %substr($text, $brPos+2) + !if (%strlen($text) == 0) + !$text = "" + !endif + !endwhile +!else + !while ($width>0 && %strlen($text) > $width) + !$brPos = $width + !while ($brPos > 0 && %substr($text, $brPos, 1) != ' ') + !$brPos = $brPos - 1 + !endwhile + + !if ($brPos < 1) + !$brPos = %strpos($text, " ") + !else + !endif + + !if ($brPos > 0) + !$multiLine = $multiLine + %substr($text, 0, $brPos) + $lineEnd + %newline() + $lineStart + !$text = %substr($text, $brPos + 1) + !else + !$multiLine = $multiLine+ $text + !$text = "" + !endif + !endwhile +!endif +!if (%strlen($text) > 0) + !$multiLine = $multiLine + $text +!endif +!return $multiLine +!endfunction + +!unquoted function $breakNewLineLabel($text) +!$multiLine = $breakWithNewline($text, "", "==") +!return $multiLine +!endfunction + +!unquoted function $breakNewLineDescr($text) + !return $breakWithNewline($text, "", "", $REL_DESCR_MAX_CHAR_WIDTH) +!endfunction + +!unquoted function $breakNewLineTechn($text) + !$lineStart = "//" + !$lineEnd = '//' + !return $breakWithNewline($text, $lineStart, $lineEnd, $REL_TECHN_MAX_CHAR_WIDTH) +!endfunction + +' description is not displayed (size too big, line breaks not supported) +' properties are not displayed in sequence diagram (size would be too big) +' $breakLabel() not required by participant +!procedure $getParticipant($elementType, $alias, $label, $techn, $descr, $sprite, $tags, $link) + !$sprite=$toElementArg($sprite, $tags, "ElementTagSprite", $elementType) + !$techn=$toElementArg($techn, $tags, "ElementTagTechn", $elementType) + !$stereo = $toStereos($elementType,$tags) + !$calcLabel = "== " + $breakNewLineLabel($label) + !$calcTech = "//[" + $breakNewLineTechn($techn) + "]//" + !$calcDescr = $breakNewLineDescr($descr) + !$calcLink = $getLink($link) + +participant $alias $stereo $calcLink [ +!if ($sprite != "") +$getSprite($sprite) +!endif +!if ($label != "") +$calcLabel +!endif +!if ($techn != "") +$calcTech +!endif +!if ($display_element_description == %true() && $descr != "") + +$calcDescr +!endif +] +!endprocedure + + +!unquoted procedure Person($alias, $label, $descr="", $sprite="", $tags="", $link="", $type="") + ' $type reuses $techn definition of $tags + $getParticipant("person", $alias, $label, $type, $descr, $sprite, $tags, $link) +!endprocedure + +!unquoted procedure Person_Ext($alias, $label, $descr="", $sprite="", $tags="", $link="", $type="") + ' $type reuses $techn definition of $tags + $getParticipant("external_person", $alias, $label, $type, $descr, $sprite, $tags, $link) +!endprocedure + +!unquoted procedure System($alias, $label, $descr="", $sprite="", $tags="", $link="", $type="", $baseShape="rectangle") + ' $type reuses $techn definition of $tags + $getParticipant("system", $alias, $label, $type, $descr, $sprite, $tags, $link) +!endprocedure + +!unquoted procedure SystemDb($alias, $label, $descr="", $sprite="", $tags="", $link="", $type="") + ' $type reuses $techn definition of $tags + $getParticipant("system", $alias, $label, $type, $descr, $sprite, $tags, $link) +!endprocedure + +!unquoted procedure SystemQueue($alias, $label, $descr="", $sprite="", $tags="", $link="", $type="") + ' $type reuses $techn definition of $tags + $getParticipant("system", $alias, $label, $type, $descr, $sprite, $tags, $link) +!endprocedure + +!unquoted procedure System_Ext($alias, $label, $descr="", $sprite="", $tags="", $link="", $type="", $baseShape="rectangle") + ' $type reuses $techn definition of $tags + $getParticipant("external_system", $alias, $label, $type, $descr, $sprite, $tags, $link) +!endprocedure + +!unquoted procedure SystemDb_Ext($alias, $label, $descr="", $sprite="", $tags="", $link="", $type="") + ' $type reuses $techn definition of $tags + $getParticipant("external_system", $alias, $label, $type, $descr, $sprite, $tags, $link) +!endprocedure + +!unquoted procedure SystemQueue_Ext($alias, $label, $descr="", $sprite="", $tags="", $link="", $type="") + ' $type reuses $techn definition of $tags + $getParticipant("external_system", $alias, $label, $type, $descr, $sprite, $tags, $link) +!endprocedure + + + +!unquoted procedure Container($alias, $label, $techn="", $descr="", $sprite="", $tags="", $link="", $baseShape="rectangle") + $getParticipant("container", $alias, $label, $techn, $descr, $sprite, $tags, $link) +!endprocedure + +!unquoted procedure ContainerDb($alias, $label, $techn="", $descr="", $sprite="", $tags="", $link="") + $getParticipant("container", $alias, $label, $techn, $descr, $sprite, $tags, $link) +!endprocedure + +!unquoted procedure ContainerQueue($alias, $label, $techn="", $descr="", $sprite="", $tags="", $link="") + $getParticipant("container", $alias, $label, $techn, $descr, $sprite, $tags, $link) +!endprocedure + +!unquoted procedure Container_Ext($alias, $label, $techn="", $descr="", $sprite="", $tags="", $link="", $baseShape="rectangle") + $getParticipant("external_container", $alias, $label, $techn, $descr, $sprite, $tags, $link) +!endprocedure + +!unquoted procedure ContainerDb_Ext($alias, $label, $techn="", $descr="", $sprite="", $tags="", $link="") + $getParticipant("external_container", $alias, $label, $techn, $descr, $sprite, $tags, $link) +!endprocedure + +!unquoted procedure ContainerQueue_Ext($alias, $label, $techn="", $descr="", $sprite="", $tags="", $link="") + $getParticipant("external_container", $alias, $label, $techn, $descr, $sprite, $tags, $link) +!endprocedure + + + +!unquoted procedure Component($alias, $label, $techn="", $descr="", $sprite="", $tags="", $link="", $baseShape="rectangle") + $getParticipant("component", $alias, $label, $techn, $descr, $sprite, $tags, $link) +!endprocedure + +!unquoted procedure ComponentDb($alias, $label, $techn="", $descr="", $sprite="", $tags="", $link="") + $getParticipant("component", $alias, $label, $techn, $descr, $sprite, $tags, $link) +!endprocedure + +!unquoted procedure ComponentQueue($alias, $label, $techn="", $descr="", $sprite="", $tags="", $link="") + $getParticipant("component", $alias, $label, $techn, $descr, $sprite, $tags, $link) +!endprocedure + +!unquoted procedure Component_Ext($alias, $label, $techn="", $descr="", $sprite="", $tags="", $link="", $baseShape="rectangle") + $getParticipant("external_component", $alias, $label, $techn, $descr, $sprite, $tags, $link) +!endprocedure + +!unquoted procedure ComponentDb_Ext($alias, $label, $techn="", $descr="", $sprite="", $tags="", $link="") + $getParticipant("external_component", $alias, $label, $techn, $descr, $sprite, $tags, $link) +!endprocedure + +!unquoted procedure ComponentQueue_Ext($alias, $label, $techn="", $descr="", $sprite="", $tags="", $link="") + $getParticipant("external_component", $alias, $label, $techn, $descr, $sprite, $tags, $link) +!endprocedure + + +' Boundary redefinition +' ################################## + +' all boundaries have to be displayed as box and +' !!! important changes: without { at the end; and boundary ends with Boundary_End() instead of } + +' alias ignored +' $breakLabel() not required by participant + +!unquoted procedure Boundary($alias, $label, $type="", $tags="", $link="") +!$boundaryTags = $addBoundaryPostfix($tags) +' nodes $type reuses $techn definition of $boundaryTags +!$type=$toElementArg($type, $boundaryTags, "ElementTagTechn", "boundary") +!if ($link != "") + !$usedNewLine = ']]\n== [[' + $link + ' ' + !$labelType = '== [[' + $link + ' ' + $breakText($label, $usedNewLine) + ']]' +!else + !$usedNewLine = '\n== ' + !$labelType = $breakText($label, $usedNewLine) +!endif +!if (type != "") + !$labelType = $labelType + '\n[' + $type + ']' +!endif +box "$labelType" $toStereos("boundary", $boundaryTags) +!endprocedure + +!procedure Boundary_End() +end box +!endprocedure + +!unquoted procedure Enterprise_Boundary($alias, $label, $tags="", $link="") + !if ($tags != "") + !$allTags = $tags + '+enterprise' + !else + !$allTags = 'enterprise' + !endif + ' $type defined via $tag style + Boundary($alias, $label, "", $allTags, $link) +!endprocedure + +!unquoted procedure System_Boundary($alias, $label, $tags="", $link="") + !if ($tags != "") + !$allTags = $tags + '+system' + !else + !$allTags = 'system' + !endif + ' $type defined via $tag style + Boundary($alias, $label, "", $allTags, $link) +!endprocedure + +!unquoted procedure Container_Boundary($alias, $label, $tags="", $link="") + !if ($tags != "") + !$allTags = $tags + '+container' + !else + !$allTags = 'container' + !endif + ' $type defined via $tag style + Boundary($alias, $label, "", $allTags, $link) +!endprocedure + +' Relationship (redefinition) +' ################################## + +' only Rel is supported in sequence diagram + +' first Rel() supports the $index and $rel argument too; second Rel() overwrites C4.puml definition +' don't add empty lines in procedure otherwise & calls are not working anymore '& a -> b: call' are not working anymore +!unquoted procedure Rel($from, $to, $label, $techn="", $descr="", $sprite="", $tags="", $link="", $index="", $rel="") + !if ($show_index == %true()) + !$pre = $getPrefix($index) + !else + !$pre = "" + !endif + !if ($rel == "") + !$rel = "->" + !endif +$getRel($rel, $from, $to, $pre + $label, $techn, $descr, $sprite, $tags, $link) +!endprocedure +!unquoted procedure Rel($from, $to, $label, $techn="", $descr="", $sprite="", $tags="", $link="") +Rel($from, $to, $label, $techn, $descr, $sprite, $tags, $link, "", "") +!endprocedure \ No newline at end of file diff --git a/generated-diagrams/component-diagram-for-internet-banking-system-c4context.puml b/generated-diagrams/component-diagram-for-internet-banking-system-c4context.puml new file mode 100644 index 0000000..485591e --- /dev/null +++ b/generated-diagrams/component-diagram-for-internet-banking-system-c4context.puml @@ -0,0 +1,23 @@ +@startuml component-diagram-for-internet-banking-system-c4context +!include ..\.c4s\C4_Context.puml + +UpdateElementStyle("system", $bgColor=#D4E6F1,$fontColor=#1A5276,$borderColor=#1A5276,$shadowing="false",$shape=RoundedBoxShape(),$borderStyle=SolidLine(),$borderThickness=2) +UpdateElementStyle("external_system", $bgColor=#F8F9F9,$fontColor=#797D7F,$borderColor=#797D7F,$shadowing="false",$shape=RoundedBoxShape(),$borderStyle=SolidLine(),$borderThickness=1) +UpdateElementStyle("person", $bgColor=#797D7F,$fontColor=#797D7F,$borderColor=#797D7F,$shadowing="false",$shape=RoundedBoxShape(),$borderStyle=SolidLine(),$borderThickness=2) +UpdateElementStyle("component", $bgColor=#FAE5D3,$fontColor=#CA6F1E,$borderColor=#CA6F1E,$shadowing="false",$shape=RoundedBoxShape(),$borderStyle=SolidLine(),$borderThickness=2) +UpdateElementStyle("external_component", $bgColor=#F8F9F9,$fontColor=#797D7F,$borderColor=#797D7F,$shadowing="false",$shape=RoundedBoxShape(),$borderStyle=SolidLine(),$borderThickness=1) +UpdateElementStyle("container", $bgColor=#EAF2F8,$fontColor=#2E86C1,$borderColor=#2E86C1,$shadowing="false",$shape=RoundedBoxShape(),$borderStyle=SolidLine(),$borderThickness=2) +UpdateElementStyle("external_container", $bgColor=#F8F9F9,$fontColor=#797D7F,$borderColor=#797D7F,$shadowing="false",$shape=RoundedBoxShape(),$borderStyle=SolidLine(),$borderThickness=1) +UpdateBoundaryStyle($elementName=system,$bgColor=#F8F9F9,$fontColor=#797D7F,$borderColor=#797D7F,$shadowing="false",$shape=RoundedBoxShape()) +UpdateBoundaryStyle($elementName=container,$bgColor=#F8F9F9,$fontColor=#797D7F,$borderColor=#797D7F,$shadowing="false",$shape=RoundedBoxShape()) +UpdateBoundaryStyle($elementName=enterprise,$bgColor=#F8F9F9,$fontColor=#797D7F,$borderColor=#797D7F,$shadowing="false",$shape=RoundedBoxShape()) +SHOW_PERSON_PORTRAIT() +LAYOUT_TOP_DOWN() + +title Component diagram for Internet Banking System + +Person_Ext(customer, "Personal Banking Customer", "A customer of the bank, with personal bank accounts.") +System(Banking System, "Provides bank statements in CSV/XLS", "") + +Rel(customer, Banking System, "uses") +@enduml diff --git a/generated-diagrams/component-diagram-for-internet-banking-system-diagramtype { value = c4_context, name = context }.puml b/generated-diagrams/component-diagram-for-internet-banking-system-diagramtype { value = c4_context, name = context }.puml new file mode 100644 index 0000000..485591e --- /dev/null +++ b/generated-diagrams/component-diagram-for-internet-banking-system-diagramtype { value = c4_context, name = context }.puml @@ -0,0 +1,23 @@ +@startuml component-diagram-for-internet-banking-system-c4context +!include ..\.c4s\C4_Context.puml + +UpdateElementStyle("system", $bgColor=#D4E6F1,$fontColor=#1A5276,$borderColor=#1A5276,$shadowing="false",$shape=RoundedBoxShape(),$borderStyle=SolidLine(),$borderThickness=2) +UpdateElementStyle("external_system", $bgColor=#F8F9F9,$fontColor=#797D7F,$borderColor=#797D7F,$shadowing="false",$shape=RoundedBoxShape(),$borderStyle=SolidLine(),$borderThickness=1) +UpdateElementStyle("person", $bgColor=#797D7F,$fontColor=#797D7F,$borderColor=#797D7F,$shadowing="false",$shape=RoundedBoxShape(),$borderStyle=SolidLine(),$borderThickness=2) +UpdateElementStyle("component", $bgColor=#FAE5D3,$fontColor=#CA6F1E,$borderColor=#CA6F1E,$shadowing="false",$shape=RoundedBoxShape(),$borderStyle=SolidLine(),$borderThickness=2) +UpdateElementStyle("external_component", $bgColor=#F8F9F9,$fontColor=#797D7F,$borderColor=#797D7F,$shadowing="false",$shape=RoundedBoxShape(),$borderStyle=SolidLine(),$borderThickness=1) +UpdateElementStyle("container", $bgColor=#EAF2F8,$fontColor=#2E86C1,$borderColor=#2E86C1,$shadowing="false",$shape=RoundedBoxShape(),$borderStyle=SolidLine(),$borderThickness=2) +UpdateElementStyle("external_container", $bgColor=#F8F9F9,$fontColor=#797D7F,$borderColor=#797D7F,$shadowing="false",$shape=RoundedBoxShape(),$borderStyle=SolidLine(),$borderThickness=1) +UpdateBoundaryStyle($elementName=system,$bgColor=#F8F9F9,$fontColor=#797D7F,$borderColor=#797D7F,$shadowing="false",$shape=RoundedBoxShape()) +UpdateBoundaryStyle($elementName=container,$bgColor=#F8F9F9,$fontColor=#797D7F,$borderColor=#797D7F,$shadowing="false",$shape=RoundedBoxShape()) +UpdateBoundaryStyle($elementName=enterprise,$bgColor=#F8F9F9,$fontColor=#797D7F,$borderColor=#797D7F,$shadowing="false",$shape=RoundedBoxShape()) +SHOW_PERSON_PORTRAIT() +LAYOUT_TOP_DOWN() + +title Component diagram for Internet Banking System + +Person_Ext(customer, "Personal Banking Customer", "A customer of the bank, with personal bank accounts.") +System(Banking System, "Provides bank statements in CSV/XLS", "") + +Rel(customer, Banking System, "uses") +@enduml diff --git a/generated-diagrams/container-diagram-for-internet-banking-system-v2-c4container.puml b/generated-diagrams/container-diagram-for-internet-banking-system-v2-c4container.puml new file mode 100644 index 0000000..7892687 --- /dev/null +++ b/generated-diagrams/container-diagram-for-internet-banking-system-v2-c4container.puml @@ -0,0 +1,44 @@ +@startuml container-diagram-for-internet-banking-system-v2-c4container +!include ..\.c4s\C4_Container.puml + +UpdateElementStyle("system", $bgColor=#D4E6F1,$fontColor=#1A5276,$borderColor=#1A5276,$shadowing="false",$shape=RoundedBoxShape(),$borderStyle=SolidLine(),$borderThickness=2) +UpdateElementStyle("external_system", $bgColor=#F8F9F9,$fontColor=#797D7F,$borderColor=#797D7F,$shadowing="false",$shape=RoundedBoxShape(),$borderStyle=SolidLine(),$borderThickness=1) +UpdateElementStyle("person", $bgColor=#797D7F,$fontColor=#797D7F,$borderColor=#797D7F,$shadowing="false",$shape=RoundedBoxShape(),$borderStyle=SolidLine(),$borderThickness=2) +UpdateElementStyle("component", $bgColor=#FAE5D3,$fontColor=#CA6F1E,$borderColor=#CA6F1E,$shadowing="false",$shape=RoundedBoxShape(),$borderStyle=SolidLine(),$borderThickness=2) +UpdateElementStyle("external_component", $bgColor=#F8F9F9,$fontColor=#797D7F,$borderColor=#797D7F,$shadowing="false",$shape=RoundedBoxShape(),$borderStyle=SolidLine(),$borderThickness=1) +UpdateElementStyle("container", $bgColor=#EAF2F8,$fontColor=#2E86C1,$borderColor=#2E86C1,$shadowing="false",$shape=RoundedBoxShape(),$borderStyle=SolidLine(),$borderThickness=2) +UpdateElementStyle("external_container", $bgColor=#F8F9F9,$fontColor=#797D7F,$borderColor=#797D7F,$shadowing="false",$shape=RoundedBoxShape(),$borderStyle=SolidLine(),$borderThickness=1) +UpdateBoundaryStyle($elementName=system,$bgColor=#F8F9F9,$fontColor=#797D7F,$borderColor=#797D7F,$shadowing="false",$shape=RoundedBoxShape()) +UpdateBoundaryStyle($elementName=container,$bgColor=#F8F9F9,$fontColor=#797D7F,$borderColor=#797D7F,$shadowing="false",$shape=RoundedBoxShape()) +UpdateBoundaryStyle($elementName=enterprise,$bgColor=#F8F9F9,$fontColor=#797D7F,$borderColor=#797D7F,$shadowing="false",$shape=RoundedBoxShape()) +SHOW_PERSON_PORTRAIT() +LAYOUT_TOP_DOWN() + +title Container diagram for Internet Banking System v2 + +Person_Ext(Customer, "Personal Banking Customer", "A customer of the bank, with personal bank accounts.") +System(BankingSystem, "Internet Banking System", "Allows customers to view information about their bank accounts, and make payments.") +System_Ext(MailSystem, "E-mail system", "The internal Microsoft Exchange e-mail system.") + +System_Boundary(c1, "Internet Banking") { + Container(WebApp, "WebApp", "Web Application:C#, WebApi", "Delivers the static content and the Internet banking SPA") + Container(Spa, "Spa", "Spa:JavaScript, Angular", "Delivers the static content and the Internet banking SPA") + Container(MobileApp, "Mobile App", "Mobile:C#, Xamarin", "Provides a mobile banking experience") + ContainerDb(SqlDatabase, "SqlDatabase", "Database:SQL Database", "Stores user registration information, hashed auth credentials, access logs, etc.") + ContainerQueue(RabbitMQ, "RabbitMQ", "Queue:RabbitMQ", "Stores user registration information, hashed auth credentials, access logs, etc.") + Container(BackendApi, "BackendApi", "Api:Dotnet, Docker Container", "Provides Internet banking functionality via API.") +} + + +Rel(Customer, WebApp, "Uses", "HTTPS") +Rel(Customer, Spa, "Uses", "HTTPS") +Rel(Customer, MobileApp, "Uses") +Rel_Neighbor(WebApp, Spa, "Delivers") +Rel(Spa, BackendApi, "Uses", "async, JSON/HTTPS") +Rel(MobileApp, BackendApi, "Uses", "async, JSON/HTTPS") +Rel_Back_Neighbor(SqlDatabase, BackendApi, "Uses", "async, JSON/HTTPS") +Rel_Back(RabbitMQ, BackendApi, "Uses", "async, JSON") +Rel_Back(Customer, MailSystem, "Sends e-mails to") +Rel_Back(MailSystem, BackendApi, "Sends e-mails using", "sync, SMTP") +Rel_Neighbor(BackendApi, BankingSystem, "Uses", "sync/async, XML/HTTPS") +@enduml diff --git a/generated-diagrams/container-diagram-for-internet-banking-system-v2-diagramtype { value = c4_container, name = container }.puml b/generated-diagrams/container-diagram-for-internet-banking-system-v2-diagramtype { value = c4_container, name = container }.puml new file mode 100644 index 0000000..7892687 --- /dev/null +++ b/generated-diagrams/container-diagram-for-internet-banking-system-v2-diagramtype { value = c4_container, name = container }.puml @@ -0,0 +1,44 @@ +@startuml container-diagram-for-internet-banking-system-v2-c4container +!include ..\.c4s\C4_Container.puml + +UpdateElementStyle("system", $bgColor=#D4E6F1,$fontColor=#1A5276,$borderColor=#1A5276,$shadowing="false",$shape=RoundedBoxShape(),$borderStyle=SolidLine(),$borderThickness=2) +UpdateElementStyle("external_system", $bgColor=#F8F9F9,$fontColor=#797D7F,$borderColor=#797D7F,$shadowing="false",$shape=RoundedBoxShape(),$borderStyle=SolidLine(),$borderThickness=1) +UpdateElementStyle("person", $bgColor=#797D7F,$fontColor=#797D7F,$borderColor=#797D7F,$shadowing="false",$shape=RoundedBoxShape(),$borderStyle=SolidLine(),$borderThickness=2) +UpdateElementStyle("component", $bgColor=#FAE5D3,$fontColor=#CA6F1E,$borderColor=#CA6F1E,$shadowing="false",$shape=RoundedBoxShape(),$borderStyle=SolidLine(),$borderThickness=2) +UpdateElementStyle("external_component", $bgColor=#F8F9F9,$fontColor=#797D7F,$borderColor=#797D7F,$shadowing="false",$shape=RoundedBoxShape(),$borderStyle=SolidLine(),$borderThickness=1) +UpdateElementStyle("container", $bgColor=#EAF2F8,$fontColor=#2E86C1,$borderColor=#2E86C1,$shadowing="false",$shape=RoundedBoxShape(),$borderStyle=SolidLine(),$borderThickness=2) +UpdateElementStyle("external_container", $bgColor=#F8F9F9,$fontColor=#797D7F,$borderColor=#797D7F,$shadowing="false",$shape=RoundedBoxShape(),$borderStyle=SolidLine(),$borderThickness=1) +UpdateBoundaryStyle($elementName=system,$bgColor=#F8F9F9,$fontColor=#797D7F,$borderColor=#797D7F,$shadowing="false",$shape=RoundedBoxShape()) +UpdateBoundaryStyle($elementName=container,$bgColor=#F8F9F9,$fontColor=#797D7F,$borderColor=#797D7F,$shadowing="false",$shape=RoundedBoxShape()) +UpdateBoundaryStyle($elementName=enterprise,$bgColor=#F8F9F9,$fontColor=#797D7F,$borderColor=#797D7F,$shadowing="false",$shape=RoundedBoxShape()) +SHOW_PERSON_PORTRAIT() +LAYOUT_TOP_DOWN() + +title Container diagram for Internet Banking System v2 + +Person_Ext(Customer, "Personal Banking Customer", "A customer of the bank, with personal bank accounts.") +System(BankingSystem, "Internet Banking System", "Allows customers to view information about their bank accounts, and make payments.") +System_Ext(MailSystem, "E-mail system", "The internal Microsoft Exchange e-mail system.") + +System_Boundary(c1, "Internet Banking") { + Container(WebApp, "WebApp", "Web Application:C#, WebApi", "Delivers the static content and the Internet banking SPA") + Container(Spa, "Spa", "Spa:JavaScript, Angular", "Delivers the static content and the Internet banking SPA") + Container(MobileApp, "Mobile App", "Mobile:C#, Xamarin", "Provides a mobile banking experience") + ContainerDb(SqlDatabase, "SqlDatabase", "Database:SQL Database", "Stores user registration information, hashed auth credentials, access logs, etc.") + ContainerQueue(RabbitMQ, "RabbitMQ", "Queue:RabbitMQ", "Stores user registration information, hashed auth credentials, access logs, etc.") + Container(BackendApi, "BackendApi", "Api:Dotnet, Docker Container", "Provides Internet banking functionality via API.") +} + + +Rel(Customer, WebApp, "Uses", "HTTPS") +Rel(Customer, Spa, "Uses", "HTTPS") +Rel(Customer, MobileApp, "Uses") +Rel_Neighbor(WebApp, Spa, "Delivers") +Rel(Spa, BackendApi, "Uses", "async, JSON/HTTPS") +Rel(MobileApp, BackendApi, "Uses", "async, JSON/HTTPS") +Rel_Back_Neighbor(SqlDatabase, BackendApi, "Uses", "async, JSON/HTTPS") +Rel_Back(RabbitMQ, BackendApi, "Uses", "async, JSON") +Rel_Back(Customer, MailSystem, "Sends e-mails to") +Rel_Back(MailSystem, BackendApi, "Sends e-mails using", "sync, SMTP") +Rel_Neighbor(BackendApi, BankingSystem, "Uses", "sync/async, XML/HTTPS") +@enduml diff --git a/generated-diagrams/internet-banking-system-api-application-c4component.puml b/generated-diagrams/internet-banking-system-api-application-c4component.puml new file mode 100644 index 0000000..e22c2c9 --- /dev/null +++ b/generated-diagrams/internet-banking-system-api-application-c4component.puml @@ -0,0 +1,39 @@ +@startuml internet-banking-system-api-application-c4component +!include ..\.c4s\C4_Component.puml + +UpdateElementStyle("system", $bgColor=#D4E6F1,$fontColor=#1A5276,$borderColor=#1A5276,$shadowing="false",$shape=RoundedBoxShape(),$borderStyle=SolidLine(),$borderThickness=2) +UpdateElementStyle("external_system", $bgColor=#F8F9F9,$fontColor=#797D7F,$borderColor=#797D7F,$shadowing="false",$shape=RoundedBoxShape(),$borderStyle=SolidLine(),$borderThickness=1) +UpdateElementStyle("person", $bgColor=#797D7F,$fontColor=#797D7F,$borderColor=#797D7F,$shadowing="false",$shape=RoundedBoxShape(),$borderStyle=SolidLine(),$borderThickness=2) +UpdateElementStyle("component", $bgColor=#FAE5D3,$fontColor=#CA6F1E,$borderColor=#CA6F1E,$shadowing="false",$shape=RoundedBoxShape(),$borderStyle=SolidLine(),$borderThickness=2) +UpdateElementStyle("external_component", $bgColor=#F8F9F9,$fontColor=#797D7F,$borderColor=#797D7F,$shadowing="false",$shape=RoundedBoxShape(),$borderStyle=SolidLine(),$borderThickness=1) +UpdateElementStyle("container", $bgColor=#EAF2F8,$fontColor=#2E86C1,$borderColor=#2E86C1,$shadowing="false",$shape=RoundedBoxShape(),$borderStyle=SolidLine(),$borderThickness=2) +UpdateElementStyle("external_container", $bgColor=#F8F9F9,$fontColor=#797D7F,$borderColor=#797D7F,$shadowing="false",$shape=RoundedBoxShape(),$borderStyle=SolidLine(),$borderThickness=1) +UpdateBoundaryStyle($elementName=system,$bgColor=#F8F9F9,$fontColor=#797D7F,$borderColor=#797D7F,$shadowing="false",$shape=RoundedBoxShape()) +UpdateBoundaryStyle($elementName=container,$bgColor=#F8F9F9,$fontColor=#797D7F,$borderColor=#797D7F,$shadowing="false",$shape=RoundedBoxShape()) +UpdateBoundaryStyle($elementName=enterprise,$bgColor=#F8F9F9,$fontColor=#797D7F,$borderColor=#797D7F,$shadowing="false",$shape=RoundedBoxShape()) +SHOW_PERSON_PORTRAIT() +LAYOUT_LEFT_RIGHT() + +title Internet Banking System API Application + +Container(MobileApp, "MobileApp", "Mobile:C#, Xamarin", "Provides a limited subset of the Internet banking functionality to customers via their mobile device") +ContainerDb(Database, "SqlDatabase", "Database:SQL Database", "Stores user registration information, hashed auth credentials, access logs, etc.") +Container(MobileApp, "MobileApp", "Mobile:C#, Xamarin", "Provides a limited subset of the Internet banking functionality to customers via their mobile device") + +Container_Boundary(c1, "API Application") { + Component(sign, "Sign In Controller", "MVC Controller", "Allows users to sign in to the internet banking system") + Component(accounts, "Accounts Summary Controller", "MVC Controller", "Provides customers with a summary of their bank accounts") + Component(security, "Security Component", "Spring Bean", "Provides functionality related to singing in, changing passwords, etc.") + Component(mbsfacade, "Mainframe Banking System Facade", "Spring Bean", "A facade onto the mainframe banking system.") +} + + +Rel(sign, security, "uses") +Rel(accounts, mbsfacade, "uses") +Rel(security, Database, "Read & write to", "JDBC") +Rel(mbsfacade, MobileApp, "Uses", "XML/HTTPS") +Rel(Spa, sign, "Uses", "JSON/HTTPS") +Rel(Spa, accounts, "Uses", "JSON/HTTPS") +Rel(MobileApp, sign, "Uses", "JSON/HTTPS") +Rel(MobileApp, accounts, "Uses", "JSON/HTTPS") +@enduml diff --git a/generated-diagrams/internet-banking-system-api-application-diagramtype { value = c4_component, name = component }.puml b/generated-diagrams/internet-banking-system-api-application-diagramtype { value = c4_component, name = component }.puml new file mode 100644 index 0000000..e22c2c9 --- /dev/null +++ b/generated-diagrams/internet-banking-system-api-application-diagramtype { value = c4_component, name = component }.puml @@ -0,0 +1,39 @@ +@startuml internet-banking-system-api-application-c4component +!include ..\.c4s\C4_Component.puml + +UpdateElementStyle("system", $bgColor=#D4E6F1,$fontColor=#1A5276,$borderColor=#1A5276,$shadowing="false",$shape=RoundedBoxShape(),$borderStyle=SolidLine(),$borderThickness=2) +UpdateElementStyle("external_system", $bgColor=#F8F9F9,$fontColor=#797D7F,$borderColor=#797D7F,$shadowing="false",$shape=RoundedBoxShape(),$borderStyle=SolidLine(),$borderThickness=1) +UpdateElementStyle("person", $bgColor=#797D7F,$fontColor=#797D7F,$borderColor=#797D7F,$shadowing="false",$shape=RoundedBoxShape(),$borderStyle=SolidLine(),$borderThickness=2) +UpdateElementStyle("component", $bgColor=#FAE5D3,$fontColor=#CA6F1E,$borderColor=#CA6F1E,$shadowing="false",$shape=RoundedBoxShape(),$borderStyle=SolidLine(),$borderThickness=2) +UpdateElementStyle("external_component", $bgColor=#F8F9F9,$fontColor=#797D7F,$borderColor=#797D7F,$shadowing="false",$shape=RoundedBoxShape(),$borderStyle=SolidLine(),$borderThickness=1) +UpdateElementStyle("container", $bgColor=#EAF2F8,$fontColor=#2E86C1,$borderColor=#2E86C1,$shadowing="false",$shape=RoundedBoxShape(),$borderStyle=SolidLine(),$borderThickness=2) +UpdateElementStyle("external_container", $bgColor=#F8F9F9,$fontColor=#797D7F,$borderColor=#797D7F,$shadowing="false",$shape=RoundedBoxShape(),$borderStyle=SolidLine(),$borderThickness=1) +UpdateBoundaryStyle($elementName=system,$bgColor=#F8F9F9,$fontColor=#797D7F,$borderColor=#797D7F,$shadowing="false",$shape=RoundedBoxShape()) +UpdateBoundaryStyle($elementName=container,$bgColor=#F8F9F9,$fontColor=#797D7F,$borderColor=#797D7F,$shadowing="false",$shape=RoundedBoxShape()) +UpdateBoundaryStyle($elementName=enterprise,$bgColor=#F8F9F9,$fontColor=#797D7F,$borderColor=#797D7F,$shadowing="false",$shape=RoundedBoxShape()) +SHOW_PERSON_PORTRAIT() +LAYOUT_LEFT_RIGHT() + +title Internet Banking System API Application + +Container(MobileApp, "MobileApp", "Mobile:C#, Xamarin", "Provides a limited subset of the Internet banking functionality to customers via their mobile device") +ContainerDb(Database, "SqlDatabase", "Database:SQL Database", "Stores user registration information, hashed auth credentials, access logs, etc.") +Container(MobileApp, "MobileApp", "Mobile:C#, Xamarin", "Provides a limited subset of the Internet banking functionality to customers via their mobile device") + +Container_Boundary(c1, "API Application") { + Component(sign, "Sign In Controller", "MVC Controller", "Allows users to sign in to the internet banking system") + Component(accounts, "Accounts Summary Controller", "MVC Controller", "Provides customers with a summary of their bank accounts") + Component(security, "Security Component", "Spring Bean", "Provides functionality related to singing in, changing passwords, etc.") + Component(mbsfacade, "Mainframe Banking System Facade", "Spring Bean", "A facade onto the mainframe banking system.") +} + + +Rel(sign, security, "uses") +Rel(accounts, mbsfacade, "uses") +Rel(security, Database, "Read & write to", "JDBC") +Rel(mbsfacade, MobileApp, "Uses", "XML/HTTPS") +Rel(Spa, sign, "Uses", "JSON/HTTPS") +Rel(Spa, accounts, "Uses", "JSON/HTTPS") +Rel(MobileApp, sign, "Uses", "JSON/HTTPS") +Rel(MobileApp, accounts, "Uses", "JSON/HTTPS") +@enduml diff --git a/generated-diagrams/pharmacy-direct---existing-container-diagram-c4container.puml b/generated-diagrams/pharmacy-direct---existing-container-diagram-c4container.puml new file mode 100644 index 0000000..ce550a3 --- /dev/null +++ b/generated-diagrams/pharmacy-direct---existing-container-diagram-c4container.puml @@ -0,0 +1,52 @@ +@startuml pharmacy-direct---existing-container-diagram-c4container +!include ..\.c4s\C4_Container.puml + +UpdateElementStyle("system", $bgColor=#D4E6F1,$fontColor=#1A5276,$borderColor=#1A5276,$shadowing="false",$shape=RoundedBoxShape(),$borderStyle=SolidLine(),$borderThickness=2) +UpdateElementStyle("external_system", $bgColor=#F8F9F9,$fontColor=#797D7F,$borderColor=#797D7F,$shadowing="false",$shape=RoundedBoxShape(),$borderStyle=SolidLine(),$borderThickness=1) +UpdateElementStyle("person", $bgColor=#797D7F,$fontColor=#797D7F,$borderColor=#797D7F,$shadowing="false",$shape=RoundedBoxShape(),$borderStyle=SolidLine(),$borderThickness=2) +UpdateElementStyle("component", $bgColor=#FAE5D3,$fontColor=#CA6F1E,$borderColor=#CA6F1E,$shadowing="false",$shape=RoundedBoxShape(),$borderStyle=SolidLine(),$borderThickness=2) +UpdateElementStyle("external_component", $bgColor=#F8F9F9,$fontColor=#797D7F,$borderColor=#797D7F,$shadowing="false",$shape=RoundedBoxShape(),$borderStyle=SolidLine(),$borderThickness=1) +UpdateElementStyle("container", $bgColor=#EAF2F8,$fontColor=#2E86C1,$borderColor=#2E86C1,$shadowing="false",$shape=RoundedBoxShape(),$borderStyle=SolidLine(),$borderThickness=2) +UpdateElementStyle("external_container", $bgColor=#F8F9F9,$fontColor=#797D7F,$borderColor=#797D7F,$shadowing="false",$shape=RoundedBoxShape(),$borderStyle=SolidLine(),$borderThickness=1) +UpdateBoundaryStyle($elementName=system,$bgColor=#F8F9F9,$fontColor=#797D7F,$borderColor=#797D7F,$shadowing="false",$shape=RoundedBoxShape()) +UpdateBoundaryStyle($elementName=container,$bgColor=#F8F9F9,$fontColor=#797D7F,$borderColor=#797D7F,$shadowing="false",$shape=RoundedBoxShape()) +UpdateBoundaryStyle($elementName=enterprise,$bgColor=#F8F9F9,$fontColor=#797D7F,$borderColor=#797D7F,$shadowing="false",$shape=RoundedBoxShape()) +SHOW_PERSON_PORTRAIT() +LAYOUT_TOP_DOWN() + +title Pharmacy Direct - Existing Container Diagram + +Person_Ext(FinanceTeam, "Finance Team (Manual)", "Human actors verifying/approving exceptions") +System_Ext(MedicalAidSchemes, "Medical Aid Schemes", "External providers of ERA files") +System_Ext(Bank, "Banking System", "Provides Bank CSV/XLS") +System_Ext(SFTP, "BI Solutions / Allegra SFTP", "ERA files are placed here by Allegra/BI Solutions") + +System_Boundary(pd, "Pharmacy Direct System") { + Container(PowerAutomateWorker, "Power Automate + PD Worker Service", "Api:Fetch/import CSV/XLS or ERA files from SharePoint/SFTP into SQL", "") + ContainerDb(SqlDataWarehouse, "SQL Data Warehouse", "Database:Stores ERA lines, Bank lines, claims, etc.", "") + Container(RemittanceApiGateway, "Remittance API Gateway", "Api:Receives consolidated or partial payloads, publishes to queue", "") + ContainerQueue(RabbitQueue, "RabbitMQ Queue", "Queue:Broker for remittance messages to the processor", "") + Container(RemittanceProcessor, "Remittance Processor Service", "Api:Consumes messages, updates claims/payment tables", "") + Container(AllegraSystem, "Allegra Debtors System", "Web Application:Debtors/Claims system used by PD", "") + Container(PastelAccounting, "Pastel Accounting System", "Web Application:Used by Finance for GL exports", "") + Container(PowerBITracker, "Remittance Advice Tracker (Power BI)", "Web Application:BI dashboards & real-time insights", "") +} + + +Rel(MedicalAidSchemes, SFTP, "Provide ERA files", "SFTP") +Rel(Bank, PowerAutomateWorker, "Send Bank CSV/XLS", "SharePoint/Automate") +Rel(SFTP, PowerAutomateWorker, "ERA .csv/.txt for PD Worker to process") +Rel(PowerAutomateWorker, SqlDataWarehouse, "Parse & load ERA & Bank data") +Rel(SqlDataWarehouse, AllegraSystem, "Partially processed lines") +Rel(AllegraSystem, FinanceTeam, "Manual exception review") +Rel(FinanceTeam, AllegraSystem, "Approve/adjust allocations") +Rel(RemittanceApiGateway, RabbitQueue, "Publish incoming payload") +Rel(RabbitQueue, RemittanceProcessor, "Consume remittance messages") +Rel(RemittanceProcessor, SqlDataWarehouse, "Update claims/payment tables") +Rel(RemittanceProcessor, AllegraSystem, "Apply reconciliations") +Rel(SqlDataWarehouse, PowerBITracker, "Data source (Remittance Advice Tracker)") +Rel(AllegraSystem, PastelAccounting, "Export to GL") +Rel(PastelAccounting, PowerAutomateWorker, "Uploads Pastel CSV to PD environment") +Rel(PowerAutomateWorker, SqlDataWarehouse, "Import Pastel data") +Rel(PowerBITracker, FinanceTeam, "Dashboards & insights") +@enduml diff --git a/generated-diagrams/pharmacy-direct---existing-container-diagram-diagramtype { value = c4_container, name = container }.puml b/generated-diagrams/pharmacy-direct---existing-container-diagram-diagramtype { value = c4_container, name = container }.puml new file mode 100644 index 0000000..ce550a3 --- /dev/null +++ b/generated-diagrams/pharmacy-direct---existing-container-diagram-diagramtype { value = c4_container, name = container }.puml @@ -0,0 +1,52 @@ +@startuml pharmacy-direct---existing-container-diagram-c4container +!include ..\.c4s\C4_Container.puml + +UpdateElementStyle("system", $bgColor=#D4E6F1,$fontColor=#1A5276,$borderColor=#1A5276,$shadowing="false",$shape=RoundedBoxShape(),$borderStyle=SolidLine(),$borderThickness=2) +UpdateElementStyle("external_system", $bgColor=#F8F9F9,$fontColor=#797D7F,$borderColor=#797D7F,$shadowing="false",$shape=RoundedBoxShape(),$borderStyle=SolidLine(),$borderThickness=1) +UpdateElementStyle("person", $bgColor=#797D7F,$fontColor=#797D7F,$borderColor=#797D7F,$shadowing="false",$shape=RoundedBoxShape(),$borderStyle=SolidLine(),$borderThickness=2) +UpdateElementStyle("component", $bgColor=#FAE5D3,$fontColor=#CA6F1E,$borderColor=#CA6F1E,$shadowing="false",$shape=RoundedBoxShape(),$borderStyle=SolidLine(),$borderThickness=2) +UpdateElementStyle("external_component", $bgColor=#F8F9F9,$fontColor=#797D7F,$borderColor=#797D7F,$shadowing="false",$shape=RoundedBoxShape(),$borderStyle=SolidLine(),$borderThickness=1) +UpdateElementStyle("container", $bgColor=#EAF2F8,$fontColor=#2E86C1,$borderColor=#2E86C1,$shadowing="false",$shape=RoundedBoxShape(),$borderStyle=SolidLine(),$borderThickness=2) +UpdateElementStyle("external_container", $bgColor=#F8F9F9,$fontColor=#797D7F,$borderColor=#797D7F,$shadowing="false",$shape=RoundedBoxShape(),$borderStyle=SolidLine(),$borderThickness=1) +UpdateBoundaryStyle($elementName=system,$bgColor=#F8F9F9,$fontColor=#797D7F,$borderColor=#797D7F,$shadowing="false",$shape=RoundedBoxShape()) +UpdateBoundaryStyle($elementName=container,$bgColor=#F8F9F9,$fontColor=#797D7F,$borderColor=#797D7F,$shadowing="false",$shape=RoundedBoxShape()) +UpdateBoundaryStyle($elementName=enterprise,$bgColor=#F8F9F9,$fontColor=#797D7F,$borderColor=#797D7F,$shadowing="false",$shape=RoundedBoxShape()) +SHOW_PERSON_PORTRAIT() +LAYOUT_TOP_DOWN() + +title Pharmacy Direct - Existing Container Diagram + +Person_Ext(FinanceTeam, "Finance Team (Manual)", "Human actors verifying/approving exceptions") +System_Ext(MedicalAidSchemes, "Medical Aid Schemes", "External providers of ERA files") +System_Ext(Bank, "Banking System", "Provides Bank CSV/XLS") +System_Ext(SFTP, "BI Solutions / Allegra SFTP", "ERA files are placed here by Allegra/BI Solutions") + +System_Boundary(pd, "Pharmacy Direct System") { + Container(PowerAutomateWorker, "Power Automate + PD Worker Service", "Api:Fetch/import CSV/XLS or ERA files from SharePoint/SFTP into SQL", "") + ContainerDb(SqlDataWarehouse, "SQL Data Warehouse", "Database:Stores ERA lines, Bank lines, claims, etc.", "") + Container(RemittanceApiGateway, "Remittance API Gateway", "Api:Receives consolidated or partial payloads, publishes to queue", "") + ContainerQueue(RabbitQueue, "RabbitMQ Queue", "Queue:Broker for remittance messages to the processor", "") + Container(RemittanceProcessor, "Remittance Processor Service", "Api:Consumes messages, updates claims/payment tables", "") + Container(AllegraSystem, "Allegra Debtors System", "Web Application:Debtors/Claims system used by PD", "") + Container(PastelAccounting, "Pastel Accounting System", "Web Application:Used by Finance for GL exports", "") + Container(PowerBITracker, "Remittance Advice Tracker (Power BI)", "Web Application:BI dashboards & real-time insights", "") +} + + +Rel(MedicalAidSchemes, SFTP, "Provide ERA files", "SFTP") +Rel(Bank, PowerAutomateWorker, "Send Bank CSV/XLS", "SharePoint/Automate") +Rel(SFTP, PowerAutomateWorker, "ERA .csv/.txt for PD Worker to process") +Rel(PowerAutomateWorker, SqlDataWarehouse, "Parse & load ERA & Bank data") +Rel(SqlDataWarehouse, AllegraSystem, "Partially processed lines") +Rel(AllegraSystem, FinanceTeam, "Manual exception review") +Rel(FinanceTeam, AllegraSystem, "Approve/adjust allocations") +Rel(RemittanceApiGateway, RabbitQueue, "Publish incoming payload") +Rel(RabbitQueue, RemittanceProcessor, "Consume remittance messages") +Rel(RemittanceProcessor, SqlDataWarehouse, "Update claims/payment tables") +Rel(RemittanceProcessor, AllegraSystem, "Apply reconciliations") +Rel(SqlDataWarehouse, PowerBITracker, "Data source (Remittance Advice Tracker)") +Rel(AllegraSystem, PastelAccounting, "Export to GL") +Rel(PastelAccounting, PowerAutomateWorker, "Uploads Pastel CSV to PD environment") +Rel(PowerAutomateWorker, SqlDataWarehouse, "Import Pastel data") +Rel(PowerBITracker, FinanceTeam, "Dashboards & insights") +@enduml diff --git a/generated-diagrams/plantuml.jar b/generated-diagrams/plantuml.jar new file mode 100644 index 0000000..b387226 Binary files /dev/null and b/generated-diagrams/plantuml.jar differ diff --git a/generated-diagrams/sequence-diagram-for-internet-banking-system-c4sequence.puml b/generated-diagrams/sequence-diagram-for-internet-banking-system-c4sequence.puml new file mode 100644 index 0000000..a9b11ff --- /dev/null +++ b/generated-diagrams/sequence-diagram-for-internet-banking-system-c4sequence.puml @@ -0,0 +1,30 @@ +@startuml sequence-diagram-for-internet-banking-system-c4sequence +!include ..\.c4s\C4_Sequence.puml + +UpdateElementStyle("system", $bgColor=#D4E6F1,$fontColor=#1A5276,$borderColor=#1A5276,$shadowing="false",$shape=RoundedBoxShape(),$borderStyle=SolidLine(),$borderThickness=2) +UpdateElementStyle("external_system", $bgColor=#F8F9F9,$fontColor=#797D7F,$borderColor=#797D7F,$shadowing="false",$shape=RoundedBoxShape(),$borderStyle=SolidLine(),$borderThickness=1) +UpdateElementStyle("person", $bgColor=#797D7F,$fontColor=#797D7F,$borderColor=#797D7F,$shadowing="false",$shape=RoundedBoxShape(),$borderStyle=SolidLine(),$borderThickness=2) +UpdateElementStyle("component", $bgColor=#FAE5D3,$fontColor=#CA6F1E,$borderColor=#CA6F1E,$shadowing="false",$shape=RoundedBoxShape(),$borderStyle=SolidLine(),$borderThickness=2) +UpdateElementStyle("external_component", $bgColor=#F8F9F9,$fontColor=#797D7F,$borderColor=#797D7F,$shadowing="false",$shape=RoundedBoxShape(),$borderStyle=SolidLine(),$borderThickness=1) +UpdateElementStyle("container", $bgColor=#EAF2F8,$fontColor=#2E86C1,$borderColor=#2E86C1,$shadowing="false",$shape=RoundedBoxShape(),$borderStyle=SolidLine(),$borderThickness=2) +UpdateElementStyle("external_container", $bgColor=#F8F9F9,$fontColor=#797D7F,$borderColor=#797D7F,$shadowing="false",$shape=RoundedBoxShape(),$borderStyle=SolidLine(),$borderThickness=1) +UpdateBoundaryStyle($elementName=system,$bgColor=#F8F9F9,$fontColor=#797D7F,$borderColor=#797D7F,$shadowing="false",$shape=RoundedBoxShape()) +UpdateBoundaryStyle($elementName=container,$bgColor=#F8F9F9,$fontColor=#797D7F,$borderColor=#797D7F,$shadowing="false",$shape=RoundedBoxShape()) +UpdateBoundaryStyle($elementName=enterprise,$bgColor=#F8F9F9,$fontColor=#797D7F,$borderColor=#797D7F,$shadowing="false",$shape=RoundedBoxShape()) +SHOW_PERSON_PORTRAIT() + +title Sequence diagram for Internet Banking System + +Container(cA, "Single-Page Application", "None:JavaScript and Angular", "Provides all of the Internet banking functionality to customers via their web browser.") + +Container_Boundary(b, "Api Application") + Component(cB, "Sign In Controller", "Spring MVC Rest Controller", "Allows users to sign in to the Internet Banking System.") + Component(cC, "Security Component", "Spring Bean", "Provides functionality Related to signing in, changing passwords, etc.") +Boundary_End() + +ContainerDb(cD, "Database", "Database:Relational Database Schema", "Stores user registration information, hashed authentication credentials, access logs, etc.") + +Rel(cA, cB, "Submits credentials to", "JSON/HTTPS") +Rel(cB, cC, "Calls isAuthenticated() on") +Rel(cC, cD, "select * from users where username = ?o", "JDBCS") +@enduml diff --git a/generated-diagrams/sequence-diagram-for-internet-banking-system-diagramtype { value = c4_sequence, name = sequence }.puml b/generated-diagrams/sequence-diagram-for-internet-banking-system-diagramtype { value = c4_sequence, name = sequence }.puml new file mode 100644 index 0000000..a9b11ff --- /dev/null +++ b/generated-diagrams/sequence-diagram-for-internet-banking-system-diagramtype { value = c4_sequence, name = sequence }.puml @@ -0,0 +1,30 @@ +@startuml sequence-diagram-for-internet-banking-system-c4sequence +!include ..\.c4s\C4_Sequence.puml + +UpdateElementStyle("system", $bgColor=#D4E6F1,$fontColor=#1A5276,$borderColor=#1A5276,$shadowing="false",$shape=RoundedBoxShape(),$borderStyle=SolidLine(),$borderThickness=2) +UpdateElementStyle("external_system", $bgColor=#F8F9F9,$fontColor=#797D7F,$borderColor=#797D7F,$shadowing="false",$shape=RoundedBoxShape(),$borderStyle=SolidLine(),$borderThickness=1) +UpdateElementStyle("person", $bgColor=#797D7F,$fontColor=#797D7F,$borderColor=#797D7F,$shadowing="false",$shape=RoundedBoxShape(),$borderStyle=SolidLine(),$borderThickness=2) +UpdateElementStyle("component", $bgColor=#FAE5D3,$fontColor=#CA6F1E,$borderColor=#CA6F1E,$shadowing="false",$shape=RoundedBoxShape(),$borderStyle=SolidLine(),$borderThickness=2) +UpdateElementStyle("external_component", $bgColor=#F8F9F9,$fontColor=#797D7F,$borderColor=#797D7F,$shadowing="false",$shape=RoundedBoxShape(),$borderStyle=SolidLine(),$borderThickness=1) +UpdateElementStyle("container", $bgColor=#EAF2F8,$fontColor=#2E86C1,$borderColor=#2E86C1,$shadowing="false",$shape=RoundedBoxShape(),$borderStyle=SolidLine(),$borderThickness=2) +UpdateElementStyle("external_container", $bgColor=#F8F9F9,$fontColor=#797D7F,$borderColor=#797D7F,$shadowing="false",$shape=RoundedBoxShape(),$borderStyle=SolidLine(),$borderThickness=1) +UpdateBoundaryStyle($elementName=system,$bgColor=#F8F9F9,$fontColor=#797D7F,$borderColor=#797D7F,$shadowing="false",$shape=RoundedBoxShape()) +UpdateBoundaryStyle($elementName=container,$bgColor=#F8F9F9,$fontColor=#797D7F,$borderColor=#797D7F,$shadowing="false",$shape=RoundedBoxShape()) +UpdateBoundaryStyle($elementName=enterprise,$bgColor=#F8F9F9,$fontColor=#797D7F,$borderColor=#797D7F,$shadowing="false",$shape=RoundedBoxShape()) +SHOW_PERSON_PORTRAIT() + +title Sequence diagram for Internet Banking System + +Container(cA, "Single-Page Application", "None:JavaScript and Angular", "Provides all of the Internet banking functionality to customers via their web browser.") + +Container_Boundary(b, "Api Application") + Component(cB, "Sign In Controller", "Spring MVC Rest Controller", "Allows users to sign in to the Internet Banking System.") + Component(cC, "Security Component", "Spring Bean", "Provides functionality Related to signing in, changing passwords, etc.") +Boundary_End() + +ContainerDb(cD, "Database", "Database:Relational Database Schema", "Stores user registration information, hashed authentication credentials, access logs, etc.") + +Rel(cA, cB, "Submits credentials to", "JSON/HTTPS") +Rel(cB, cC, "Calls isAuthenticated() on") +Rel(cC, cD, "select * from users where username = ?o", "JDBCS") +@enduml diff --git a/generated-diagrams/system-context-diagram-for-internet-banking-system-c4deployment.puml b/generated-diagrams/system-context-diagram-for-internet-banking-system-c4deployment.puml new file mode 100644 index 0000000..85430dd --- /dev/null +++ b/generated-diagrams/system-context-diagram-for-internet-banking-system-c4deployment.puml @@ -0,0 +1,65 @@ +@startuml system-context-diagram-for-internet-banking-system-c4deployment +!include ..\.c4s\C4_Deployment.puml + +UpdateElementStyle("system", $bgColor=#D4E6F1,$fontColor=#1A5276,$borderColor=#1A5276,$shadowing="false",$shape=RoundedBoxShape(),$borderStyle=SolidLine(),$borderThickness=2) +UpdateElementStyle("external_system", $bgColor=#F8F9F9,$fontColor=#797D7F,$borderColor=#797D7F,$shadowing="false",$shape=RoundedBoxShape(),$borderStyle=SolidLine(),$borderThickness=1) +UpdateElementStyle("person", $bgColor=#797D7F,$fontColor=#797D7F,$borderColor=#797D7F,$shadowing="false",$shape=RoundedBoxShape(),$borderStyle=SolidLine(),$borderThickness=2) +UpdateElementStyle("component", $bgColor=#FAE5D3,$fontColor=#CA6F1E,$borderColor=#CA6F1E,$shadowing="false",$shape=RoundedBoxShape(),$borderStyle=SolidLine(),$borderThickness=2) +UpdateElementStyle("external_component", $bgColor=#F8F9F9,$fontColor=#797D7F,$borderColor=#797D7F,$shadowing="false",$shape=RoundedBoxShape(),$borderStyle=SolidLine(),$borderThickness=1) +UpdateElementStyle("container", $bgColor=#EAF2F8,$fontColor=#2E86C1,$borderColor=#2E86C1,$shadowing="false",$shape=RoundedBoxShape(),$borderStyle=SolidLine(),$borderThickness=2) +UpdateElementStyle("external_container", $bgColor=#F8F9F9,$fontColor=#797D7F,$borderColor=#797D7F,$shadowing="false",$shape=RoundedBoxShape(),$borderStyle=SolidLine(),$borderThickness=1) +UpdateBoundaryStyle($elementName=system,$bgColor=#F8F9F9,$fontColor=#797D7F,$borderColor=#797D7F,$shadowing="false",$shape=RoundedBoxShape()) +UpdateBoundaryStyle($elementName=container,$bgColor=#F8F9F9,$fontColor=#797D7F,$borderColor=#797D7F,$shadowing="false",$shape=RoundedBoxShape()) +UpdateBoundaryStyle($elementName=enterprise,$bgColor=#F8F9F9,$fontColor=#797D7F,$borderColor=#797D7F,$shadowing="false",$shape=RoundedBoxShape()) +SHOW_PERSON_PORTRAIT() +LAYOUT_TOP_DOWN() + +title System Context diagram for Internet Banking System + + +Deployment_Node(plc, "Big Bank plc", "Big Bank plc data center") { + Deployment_Node(dn, "bigbank-api*** x8", "Ubuntu 16.04 LTS") { + AddProperty("Java Version", "8") + AddProperty("Xmx", "512M") + AddProperty("Xms", "1024M") + Deployment_Node(apache, "Apache Tomcat", "Apache Tomcat 8.x") { + Container(BackendApi, "BackendApi", "Api:Dotnet, Docker Container", "Provides Internet banking functionality via API.") + } + } + Deployment_Node(bigbankdb01, "bigbank-db01", "Ubuntu 16.04 LTS") { + Deployment_Node(oracle, "Oracle - Primary", "Oracle 12c") { + ContainerDb(Database.1, "OracleDatabase", "Database:Oracle Database", "Stores user registration information, hashed auth credentials, access logs, etc.") + } + } + Deployment_Node(bigbankdb02, "bigbank-db02", "Ubuntu 16.04 LTS") { + Deployment_Node(oracle2, "Oracle - Primary", "Oracle 12c") { + ContainerDb(Database.data.reader, "OracleDatabase", "Database:Oracle Database", "Stores user registration information, hashed auth credentials, access logs, etc.") + } + } + Deployment_Node(bb2, "bigbank-web*** x4", "Ubuntu 16.04 LTS") { + AddProperty("Java Version", "8") + AddProperty("Xmx", "512M") + AddProperty("Xms", "1024M") + Deployment_Node(apache2, "Apache Tomcat", "Apache Tomcat 8.x") { + Container(Corporate.Finance.Limits.Service.ServiceBus, "WebApp", "Web Application:C#, WebApi", "Delivers the static content and the Internet banking SPA") + } + } +} + +Deployment_Node(ios, "Customer's mobile device", "Apple IOS") { +Container(MobileApp, "MobileApp", "Mobile:C#, Xamarin", "Provides a limited subset of the Internet banking functionality to customers via their mobile device") +} + +Deployment_Node(computer, "Customer's computer", "Mircosoft Windows and Apple macOS") { + Deployment_Node(browser, "Web Browser", "Google Chrome, Mozilla Firefox, Apple Safari or Microsoft Edge") { + Container(Spa, "SPA", "Spa:JavaScript, Angular", "Provides all the Internet banking functionality to customers via their web browser") + } +} + +Rel(MobileApp, BackendApi, "Makes API calls to", "json/HTTPS") +Rel(Spa, BackendApi, "Makes API calls to", "json/HTTPS") +Rel_U(Corporate.Finance.Limits.Service.ServiceBus, Spa, "Delivers to the customer's web browser") +Rel(BackendApi, Database.1, "Writes to", "JDBC") +Rel_Back(BackendApi, Database.data.reader, "Reads from", "JDBC") +Rel_R(Database.1, Database.data.reader, "Replicates data to", "JDBC") +@enduml diff --git a/generated-diagrams/system-context-diagram-for-internet-banking-system-diagramtype { value = c4_deployment, name = deployment }.puml b/generated-diagrams/system-context-diagram-for-internet-banking-system-diagramtype { value = c4_deployment, name = deployment }.puml new file mode 100644 index 0000000..85430dd --- /dev/null +++ b/generated-diagrams/system-context-diagram-for-internet-banking-system-diagramtype { value = c4_deployment, name = deployment }.puml @@ -0,0 +1,65 @@ +@startuml system-context-diagram-for-internet-banking-system-c4deployment +!include ..\.c4s\C4_Deployment.puml + +UpdateElementStyle("system", $bgColor=#D4E6F1,$fontColor=#1A5276,$borderColor=#1A5276,$shadowing="false",$shape=RoundedBoxShape(),$borderStyle=SolidLine(),$borderThickness=2) +UpdateElementStyle("external_system", $bgColor=#F8F9F9,$fontColor=#797D7F,$borderColor=#797D7F,$shadowing="false",$shape=RoundedBoxShape(),$borderStyle=SolidLine(),$borderThickness=1) +UpdateElementStyle("person", $bgColor=#797D7F,$fontColor=#797D7F,$borderColor=#797D7F,$shadowing="false",$shape=RoundedBoxShape(),$borderStyle=SolidLine(),$borderThickness=2) +UpdateElementStyle("component", $bgColor=#FAE5D3,$fontColor=#CA6F1E,$borderColor=#CA6F1E,$shadowing="false",$shape=RoundedBoxShape(),$borderStyle=SolidLine(),$borderThickness=2) +UpdateElementStyle("external_component", $bgColor=#F8F9F9,$fontColor=#797D7F,$borderColor=#797D7F,$shadowing="false",$shape=RoundedBoxShape(),$borderStyle=SolidLine(),$borderThickness=1) +UpdateElementStyle("container", $bgColor=#EAF2F8,$fontColor=#2E86C1,$borderColor=#2E86C1,$shadowing="false",$shape=RoundedBoxShape(),$borderStyle=SolidLine(),$borderThickness=2) +UpdateElementStyle("external_container", $bgColor=#F8F9F9,$fontColor=#797D7F,$borderColor=#797D7F,$shadowing="false",$shape=RoundedBoxShape(),$borderStyle=SolidLine(),$borderThickness=1) +UpdateBoundaryStyle($elementName=system,$bgColor=#F8F9F9,$fontColor=#797D7F,$borderColor=#797D7F,$shadowing="false",$shape=RoundedBoxShape()) +UpdateBoundaryStyle($elementName=container,$bgColor=#F8F9F9,$fontColor=#797D7F,$borderColor=#797D7F,$shadowing="false",$shape=RoundedBoxShape()) +UpdateBoundaryStyle($elementName=enterprise,$bgColor=#F8F9F9,$fontColor=#797D7F,$borderColor=#797D7F,$shadowing="false",$shape=RoundedBoxShape()) +SHOW_PERSON_PORTRAIT() +LAYOUT_TOP_DOWN() + +title System Context diagram for Internet Banking System + + +Deployment_Node(plc, "Big Bank plc", "Big Bank plc data center") { + Deployment_Node(dn, "bigbank-api*** x8", "Ubuntu 16.04 LTS") { + AddProperty("Java Version", "8") + AddProperty("Xmx", "512M") + AddProperty("Xms", "1024M") + Deployment_Node(apache, "Apache Tomcat", "Apache Tomcat 8.x") { + Container(BackendApi, "BackendApi", "Api:Dotnet, Docker Container", "Provides Internet banking functionality via API.") + } + } + Deployment_Node(bigbankdb01, "bigbank-db01", "Ubuntu 16.04 LTS") { + Deployment_Node(oracle, "Oracle - Primary", "Oracle 12c") { + ContainerDb(Database.1, "OracleDatabase", "Database:Oracle Database", "Stores user registration information, hashed auth credentials, access logs, etc.") + } + } + Deployment_Node(bigbankdb02, "bigbank-db02", "Ubuntu 16.04 LTS") { + Deployment_Node(oracle2, "Oracle - Primary", "Oracle 12c") { + ContainerDb(Database.data.reader, "OracleDatabase", "Database:Oracle Database", "Stores user registration information, hashed auth credentials, access logs, etc.") + } + } + Deployment_Node(bb2, "bigbank-web*** x4", "Ubuntu 16.04 LTS") { + AddProperty("Java Version", "8") + AddProperty("Xmx", "512M") + AddProperty("Xms", "1024M") + Deployment_Node(apache2, "Apache Tomcat", "Apache Tomcat 8.x") { + Container(Corporate.Finance.Limits.Service.ServiceBus, "WebApp", "Web Application:C#, WebApi", "Delivers the static content and the Internet banking SPA") + } + } +} + +Deployment_Node(ios, "Customer's mobile device", "Apple IOS") { +Container(MobileApp, "MobileApp", "Mobile:C#, Xamarin", "Provides a limited subset of the Internet banking functionality to customers via their mobile device") +} + +Deployment_Node(computer, "Customer's computer", "Mircosoft Windows and Apple macOS") { + Deployment_Node(browser, "Web Browser", "Google Chrome, Mozilla Firefox, Apple Safari or Microsoft Edge") { + Container(Spa, "SPA", "Spa:JavaScript, Angular", "Provides all the Internet banking functionality to customers via their web browser") + } +} + +Rel(MobileApp, BackendApi, "Makes API calls to", "json/HTTPS") +Rel(Spa, BackendApi, "Makes API calls to", "json/HTTPS") +Rel_U(Corporate.Finance.Limits.Service.ServiceBus, Spa, "Delivers to the customer's web browser") +Rel(BackendApi, Database.1, "Writes to", "JDBC") +Rel_Back(BackendApi, Database.data.reader, "Reads from", "JDBC") +Rel_R(Database.1, Database.data.reader, "Replicates data to", "JDBC") +@enduml diff --git a/generated-diagrams/system-enterprise-diagram-for-internet-banking-system-c4context.puml b/generated-diagrams/system-enterprise-diagram-for-internet-banking-system-c4context.puml new file mode 100644 index 0000000..e4138f5 --- /dev/null +++ b/generated-diagrams/system-enterprise-diagram-for-internet-banking-system-c4context.puml @@ -0,0 +1,39 @@ +@startuml system-enterprise-diagram-for-internet-banking-system-c4context +!include ..\.c4s\C4_Context.puml + +UpdateElementStyle("system", $bgColor=#D4E6F1,$fontColor=#1A5276,$borderColor=#1A5276,$shadowing="false",$shape=RoundedBoxShape(),$borderStyle=SolidLine(),$borderThickness=2) +UpdateElementStyle("external_system", $bgColor=#F8F9F9,$fontColor=#797D7F,$borderColor=#797D7F,$shadowing="false",$shape=RoundedBoxShape(),$borderStyle=SolidLine(),$borderThickness=1) +UpdateElementStyle("person", $bgColor=#797D7F,$fontColor=#797D7F,$borderColor=#797D7F,$shadowing="false",$shape=RoundedBoxShape(),$borderStyle=SolidLine(),$borderThickness=2) +UpdateElementStyle("component", $bgColor=#FAE5D3,$fontColor=#CA6F1E,$borderColor=#CA6F1E,$shadowing="false",$shape=RoundedBoxShape(),$borderStyle=SolidLine(),$borderThickness=2) +UpdateElementStyle("external_component", $bgColor=#F8F9F9,$fontColor=#797D7F,$borderColor=#797D7F,$shadowing="false",$shape=RoundedBoxShape(),$borderStyle=SolidLine(),$borderThickness=1) +UpdateElementStyle("container", $bgColor=#EAF2F8,$fontColor=#2E86C1,$borderColor=#2E86C1,$shadowing="false",$shape=RoundedBoxShape(),$borderStyle=SolidLine(),$borderThickness=2) +UpdateElementStyle("external_container", $bgColor=#F8F9F9,$fontColor=#797D7F,$borderColor=#797D7F,$shadowing="false",$shape=RoundedBoxShape(),$borderStyle=SolidLine(),$borderThickness=1) +UpdateBoundaryStyle($elementName=system,$bgColor=#F8F9F9,$fontColor=#797D7F,$borderColor=#797D7F,$shadowing="false",$shape=RoundedBoxShape()) +UpdateBoundaryStyle($elementName=container,$bgColor=#F8F9F9,$fontColor=#797D7F,$borderColor=#797D7F,$shadowing="false",$shape=RoundedBoxShape()) +UpdateBoundaryStyle($elementName=enterprise,$bgColor=#F8F9F9,$fontColor=#797D7F,$borderColor=#797D7F,$shadowing="false",$shape=RoundedBoxShape()) +SHOW_PERSON_PORTRAIT() +LAYOUT_TOP_DOWN() + +title System Enterprise diagram for Internet Banking System + +Person_Ext(customer, "Personal Banking Customer", "A customer of the bank, with personal bank accounts.") + +Enterprise_Boundary(enterprise.boundary, "Domain A") { + System(Banking System, "Provides bank statements in CSV/XLS", "") + +Enterprise_Boundary(enterprise.boundary.1, "Domain Internal Users") { + Person(internalcustomer, "Personal Banking Customer", "An customer of the bank, with personal bank accounts.") +} + + +Enterprise_Boundary(enterprise.boundary.2, "Domain Managers") { + Person(manager, "Manager Banking Customer", "A manager of the bank, with personal bank accounts.") +} + +} + + +Rel(customer, Banking System, "uses") +Rel(internalcustomer, Banking System, "uses") +Rel(manager, Banking System, "uses") +@enduml diff --git a/generated-diagrams/system-enterprise-diagram-for-internet-banking-system-diagramtype { value = c4_context, name = context }.puml b/generated-diagrams/system-enterprise-diagram-for-internet-banking-system-diagramtype { value = c4_context, name = context }.puml new file mode 100644 index 0000000..e4138f5 --- /dev/null +++ b/generated-diagrams/system-enterprise-diagram-for-internet-banking-system-diagramtype { value = c4_context, name = context }.puml @@ -0,0 +1,39 @@ +@startuml system-enterprise-diagram-for-internet-banking-system-c4context +!include ..\.c4s\C4_Context.puml + +UpdateElementStyle("system", $bgColor=#D4E6F1,$fontColor=#1A5276,$borderColor=#1A5276,$shadowing="false",$shape=RoundedBoxShape(),$borderStyle=SolidLine(),$borderThickness=2) +UpdateElementStyle("external_system", $bgColor=#F8F9F9,$fontColor=#797D7F,$borderColor=#797D7F,$shadowing="false",$shape=RoundedBoxShape(),$borderStyle=SolidLine(),$borderThickness=1) +UpdateElementStyle("person", $bgColor=#797D7F,$fontColor=#797D7F,$borderColor=#797D7F,$shadowing="false",$shape=RoundedBoxShape(),$borderStyle=SolidLine(),$borderThickness=2) +UpdateElementStyle("component", $bgColor=#FAE5D3,$fontColor=#CA6F1E,$borderColor=#CA6F1E,$shadowing="false",$shape=RoundedBoxShape(),$borderStyle=SolidLine(),$borderThickness=2) +UpdateElementStyle("external_component", $bgColor=#F8F9F9,$fontColor=#797D7F,$borderColor=#797D7F,$shadowing="false",$shape=RoundedBoxShape(),$borderStyle=SolidLine(),$borderThickness=1) +UpdateElementStyle("container", $bgColor=#EAF2F8,$fontColor=#2E86C1,$borderColor=#2E86C1,$shadowing="false",$shape=RoundedBoxShape(),$borderStyle=SolidLine(),$borderThickness=2) +UpdateElementStyle("external_container", $bgColor=#F8F9F9,$fontColor=#797D7F,$borderColor=#797D7F,$shadowing="false",$shape=RoundedBoxShape(),$borderStyle=SolidLine(),$borderThickness=1) +UpdateBoundaryStyle($elementName=system,$bgColor=#F8F9F9,$fontColor=#797D7F,$borderColor=#797D7F,$shadowing="false",$shape=RoundedBoxShape()) +UpdateBoundaryStyle($elementName=container,$bgColor=#F8F9F9,$fontColor=#797D7F,$borderColor=#797D7F,$shadowing="false",$shape=RoundedBoxShape()) +UpdateBoundaryStyle($elementName=enterprise,$bgColor=#F8F9F9,$fontColor=#797D7F,$borderColor=#797D7F,$shadowing="false",$shape=RoundedBoxShape()) +SHOW_PERSON_PORTRAIT() +LAYOUT_TOP_DOWN() + +title System Enterprise diagram for Internet Banking System + +Person_Ext(customer, "Personal Banking Customer", "A customer of the bank, with personal bank accounts.") + +Enterprise_Boundary(enterprise.boundary, "Domain A") { + System(Banking System, "Provides bank statements in CSV/XLS", "") + +Enterprise_Boundary(enterprise.boundary.1, "Domain Internal Users") { + Person(internalcustomer, "Personal Banking Customer", "An customer of the bank, with personal bank accounts.") +} + + +Enterprise_Boundary(enterprise.boundary.2, "Domain Managers") { + Person(manager, "Manager Banking Customer", "A manager of the bank, with personal bank accounts.") +} + +} + + +Rel(customer, Banking System, "uses") +Rel(internalcustomer, Banking System, "uses") +Rel(manager, Banking System, "uses") +@enduml diff --git a/samples/HealthcareArchitecture/Converters/JsonToC4Converter.cs b/samples/HealthcareArchitecture/Converters/JsonToC4Converter.cs new file mode 100644 index 0000000..c86d394 --- /dev/null +++ b/samples/HealthcareArchitecture/Converters/JsonToC4Converter.cs @@ -0,0 +1,117 @@ +using C4Sharp.Elements; +using C4Sharp.Elements.Relationships; +using HealthcareArchitecture.Models; +using Newtonsoft.Json; +using static C4Sharp.Elements.Relationships.Position; + +namespace HealthcareArchitecture.Converters; + +public class JsonToC4Converter +{ + public static ConfigModel LoadConfig(string configPath) + { + var json = File.ReadAllText(configPath); + return JsonConvert.DeserializeObject(json) ?? new ConfigModel(); + } + + public static IEnumerable ConvertStructures(List structureConfigs) + { + var structures = new List(); + + foreach (var config in structureConfigs) + { + Structure structure = config.Type.ToLower() switch + { + "person" => CreatePerson(config), + "softwaresystem" => CreateSoftwareSystem(config), + "container" => CreateContainer(config), + "component" => CreateComponent(config), + "deploymentnode" => CreateDeploymentNode(config), + _ => CreateSoftwareSystem(config) // Default to SoftwareSystem + }; + + structures.Add(structure); + } + + return structures; + } + + public static IEnumerable ConvertRelationships(List relationshipConfigs) + { + var relationships = new List(); + + foreach (var config in relationshipConfigs) + { + var relationship = new Relationship(config.From, config.To) + { + Label = config.Label, + Protocol = config.Protocol ?? string.Empty + }; + + // Set direction based on config + relationship = config.Direction.ToLower() switch + { + "back" => relationship.Back(), + "bidirectional" => relationship.Bidirectional(), + _ => relationship // Default to Forward + }; + + relationships.Add(relationship); + } + + return relationships; + } + + private static Person CreatePerson(StructureConfig config) + { + var person = Person.None | (config.Alias, config.Label, config.Description); + + if (config.External) + { + person = person | Boundary.External; + } + + return person; + } + + private static SoftwareSystem CreateSoftwareSystem(StructureConfig config) + { + var system = SoftwareSystem.None | (config.Alias, config.Label, config.Description); + + if (config.External) + { + system = system | Boundary.External; + } + + return system; + } + + private static Container CreateContainer(StructureConfig config) + { + var container = Container.None | (config.Alias, config.Label, config.Technology ?? "Technology", config.Description); + + if (config.External) + { + container = container | Boundary.External; + } + + return container; + } + + private static Component CreateComponent(StructureConfig config) + { + var component = Component.None | (config.Alias, config.Label, config.Technology ?? "Technology", config.Description); + + if (config.External) + { + component = component | Boundary.External; + } + + return component; + } + + private static DeploymentNode CreateDeploymentNode(StructureConfig config) + { + return DeploymentNode.None | (config.Alias, config.Label, config.Technology ?? "Technology", config.Description); + } +} diff --git a/samples/HealthcareArchitecture/Diagrams/HealthcareComponentDiagram.cs b/samples/HealthcareArchitecture/Diagrams/HealthcareComponentDiagram.cs new file mode 100644 index 0000000..48c79de --- /dev/null +++ b/samples/HealthcareArchitecture/Diagrams/HealthcareComponentDiagram.cs @@ -0,0 +1,29 @@ +using C4Sharp.Diagrams.Builders; +using C4Sharp.Elements; +using C4Sharp.Elements.Relationships; +using HealthcareArchitecture.Converters; +using HealthcareArchitecture.Models; + +namespace HealthcareArchitecture.Diagrams; + +public class HealthcareComponentDiagram : ComponentDiagram +{ + private readonly ConfigModel _config; + + public HealthcareComponentDiagram(ConfigModel config) + { + _config = config; + } + + public HealthcareComponentDiagram() : this(JsonToC4Converter.LoadConfig("config.json")) + { + } + + protected override string Title => _config.Title + " - Component View"; + + protected override IEnumerable Structures => + JsonToC4Converter.ConvertStructures(_config.Structures); + + protected override IEnumerable Relationships => + JsonToC4Converter.ConvertRelationships(_config.Relationships); +} diff --git a/samples/HealthcareArchitecture/Diagrams/HealthcareContainerDiagram.cs b/samples/HealthcareArchitecture/Diagrams/HealthcareContainerDiagram.cs new file mode 100644 index 0000000..f9196ce --- /dev/null +++ b/samples/HealthcareArchitecture/Diagrams/HealthcareContainerDiagram.cs @@ -0,0 +1,29 @@ +using C4Sharp.Diagrams.Builders; +using C4Sharp.Elements; +using C4Sharp.Elements.Relationships; +using HealthcareArchitecture.Converters; +using HealthcareArchitecture.Models; + +namespace HealthcareArchitecture.Diagrams; + +public class HealthcareContainerDiagram : ContainerDiagram +{ + private readonly ConfigModel _config; + + public HealthcareContainerDiagram(ConfigModel config) + { + _config = config; + } + + public HealthcareContainerDiagram() : this(JsonToC4Converter.LoadConfig("config.json")) + { + } + + protected override string Title => _config.Title + " - Container View"; + + protected override IEnumerable Structures => + JsonToC4Converter.ConvertStructures(_config.Structures); + + protected override IEnumerable Relationships => + JsonToC4Converter.ConvertRelationships(_config.Relationships); +} diff --git a/samples/HealthcareArchitecture/Diagrams/HealthcareContextDiagram.cs b/samples/HealthcareArchitecture/Diagrams/HealthcareContextDiagram.cs new file mode 100644 index 0000000..6431b42 --- /dev/null +++ b/samples/HealthcareArchitecture/Diagrams/HealthcareContextDiagram.cs @@ -0,0 +1,31 @@ +using C4Sharp.Diagrams.Builders; +using C4Sharp.Elements; +using C4Sharp.Elements.Relationships; +using HealthcareArchitecture.Converters; +using HealthcareArchitecture.Models; + +namespace HealthcareArchitecture.Diagrams; + +public class HealthcareContextDiagram : ContextDiagram +{ + private readonly ConfigModel _config; + + public HealthcareContextDiagram(ConfigModel config) + { + _config = config; + } + + public HealthcareContextDiagram() : this(JsonToC4Converter.LoadConfig("config.json")) + { + } + + protected override string Title => _config.Title + " - System Context"; + + protected override IEnumerable Structures => + JsonToC4Converter.ConvertStructures(_config.Structures.Where(s => + s.Type.Equals("Person", StringComparison.OrdinalIgnoreCase) || + s.Type.Equals("SoftwareSystem", StringComparison.OrdinalIgnoreCase)).ToList()); + + protected override IEnumerable Relationships => + JsonToC4Converter.ConvertRelationships(_config.Relationships); +} diff --git a/samples/HealthcareArchitecture/HealthcareArchitecture.csproj b/samples/HealthcareArchitecture/HealthcareArchitecture.csproj new file mode 100644 index 0000000..342ad0e --- /dev/null +++ b/samples/HealthcareArchitecture/HealthcareArchitecture.csproj @@ -0,0 +1,27 @@ + + + + Exe + net8.0 + enable + enable + + + + + + + + + + + + + PreserveNewest + + + PreserveNewest + + + + diff --git a/samples/HealthcareArchitecture/Models/ConfigModel.cs b/samples/HealthcareArchitecture/Models/ConfigModel.cs new file mode 100644 index 0000000..e439b15 --- /dev/null +++ b/samples/HealthcareArchitecture/Models/ConfigModel.cs @@ -0,0 +1,60 @@ +using Newtonsoft.Json; + +namespace HealthcareArchitecture.Models; + +public class ConfigModel +{ + [JsonProperty("title")] + public string Title { get; set; } = string.Empty; + + [JsonProperty("slug")] + public string Slug { get; set; } = string.Empty; + + [JsonProperty("structures")] + public List Structures { get; set; } = new(); + + [JsonProperty("relationships")] + public List Relationships { get; set; } = new(); +} + +public class StructureConfig +{ + [JsonProperty("alias")] + public string Alias { get; set; } = string.Empty; + + [JsonProperty("label")] + public string Label { get; set; } = string.Empty; + + [JsonProperty("description")] + public string Description { get; set; } = string.Empty; + + [JsonProperty("type")] + public string Type { get; set; } = string.Empty; + + [JsonProperty("technology")] + public string? Technology { get; set; } + + [JsonProperty("boundary")] + public string? Boundary { get; set; } + + [JsonProperty("external")] + public bool External { get; set; } = false; +} + +public class RelationshipConfig +{ + [JsonProperty("from")] + public string From { get; set; } = string.Empty; + + [JsonProperty("to")] + public string To { get; set; } = string.Empty; + + [JsonProperty("label")] + public string Label { get; set; } = string.Empty; + + [JsonProperty("protocol")] + public string? Protocol { get; set; } + + [JsonProperty("direction")] + public string Direction { get; set; } = "Forward"; +} diff --git a/samples/HealthcareArchitecture/Program.cs b/samples/HealthcareArchitecture/Program.cs new file mode 100644 index 0000000..b25c28b --- /dev/null +++ b/samples/HealthcareArchitecture/Program.cs @@ -0,0 +1,116 @@ +using C4Sharp.Diagrams; +using C4Sharp.Diagrams.Plantuml; +using C4Sharp.Diagrams.Themes; +using C4Sharp.Diagrams.Drawio; +using HealthcareArchitecture.Diagrams; +using HealthcareArchitecture.Converters; +using System.Diagnostics; + +Console.WriteLine("Building Healthcare Solution Architecture C4 diagrams..."); + +var outputPath = Path.Combine(Directory.GetCurrentDirectory(), "../../generated-diagrams/healthcare"); +Directory.CreateDirectory(outputPath); + +// Load config for JSON-driven approach +var config = JsonToC4Converter.LoadConfig("config.json"); + +var diagrams = new DiagramBuilder[] +{ + new HealthcareContextDiagram(config), + new HealthcareContainerDiagram(config), + new HealthcareComponentDiagram(config) +}; + +var theme = new ParadisoTheme(); + +// Generate PUML files +Console.WriteLine("Generating PUML files..."); +foreach (var diagramBuilder in diagrams) +{ + try + { + Console.WriteLine($"Generating {diagramBuilder.GetType().Name}..."); + + var diagram = diagramBuilder.Build(theme); + var plantuml = diagram.ToPumlString(); + + var fileName = $"{diagram.Title.Replace(" ", "-").Replace(":", "").ToLower()}-{diagram.Type.ToString().ToLower()}.puml"; + var filePath = Path.Combine(outputPath, fileName); + + File.WriteAllText(filePath, plantuml); + Console.WriteLine($"Generated: {fileName}"); + } + catch (Exception ex) + { + Console.WriteLine($"Error generating {diagramBuilder.GetType().Name}: {ex.Message}"); + } +} + +// Generate SVG files using PlantUML +Console.WriteLine("\nGenerating SVG files from PUML..."); +try +{ + var plantumlJarPath = Path.Combine(Directory.GetCurrentDirectory(), "plantuml.jar"); + if (File.Exists(plantumlJarPath)) + { + var processInfo = new ProcessStartInfo + { + FileName = "java", + Arguments = $"-jar \"{plantumlJarPath}\" -tsvg \"{outputPath}\\*.puml\"", + UseShellExecute = false, + RedirectStandardOutput = true, + RedirectStandardError = true, + CreateNoWindow = true + }; + + using var process = Process.Start(processInfo); + if (process != null) + { + process.WaitForExit(); + var output = process.StandardOutput.ReadToEnd(); + var error = process.StandardError.ReadToEnd(); + + if (process.ExitCode == 0) + { + Console.WriteLine("SVG files generated successfully!"); + } + else + { + Console.WriteLine($"PlantUML error: {error}"); + } + } + } + else + { + Console.WriteLine("PlantUML JAR not found. SVG generation skipped."); + } +} +catch (Exception ex) +{ + Console.WriteLine($"Error generating SVG files: {ex.Message}"); +} + +// Generate Draw.io files +Console.WriteLine("\nGenerating Draw.io files..."); +try +{ + var drawioPath = Path.Combine(outputPath, "drawio"); + Directory.CreateDirectory(drawioPath); + + new DrawioContext() + .AddDiagrams(diagrams) + .Export(drawioPath); + + Console.WriteLine("Draw.io files generated successfully!"); +} +catch (Exception ex) +{ + Console.WriteLine($"Error generating Draw.io files: {ex.Message}"); +} + +Console.WriteLine($"\nHealthcare Solution Architecture diagrams generated in: {outputPath}"); +Console.WriteLine("Generated formats: PUML, SVG (if Java available), Draw.io"); +Console.WriteLine("\nDiagram types created:"); +Console.WriteLine("- System Context Diagram (shows high-level systems and users)"); +Console.WriteLine("- Container Diagram (shows system containers and their relationships)"); +Console.WriteLine("- Component Diagram (shows internal components and interactions)"); diff --git a/samples/HealthcareArchitecture/config.json b/samples/HealthcareArchitecture/config.json new file mode 100644 index 0000000..a3f4711 --- /dev/null +++ b/samples/HealthcareArchitecture/config.json @@ -0,0 +1,145 @@ +{ + "title": "Healthcare Solution Architecture", + "slug": "healthcare-solution-architecture", + "structures": [ + { + "alias": "member_portal", + "label": "Member Portal", + "description": "Cloud-native frontend for member interaction. Benefits: Personalized engagement, scalable access, secure communication. Tools: React/Angular/Vue.js, Azure App Service/AWS Amplify/GCP Firebase Hosting, OAuth2/OpenID Connect, Azure AD B2C/AWS Cognito.", + "type": "SoftwareSystem" + }, + { + "alias": "integration_layer", + "label": "Integration Layer", + "description": "Connects cloud portal to on-prem systems ABC and XYZ. Benefits: Real-time data sync, secure API access, ETL capabilities. Tools: Azure API Management/AWS API Gateway, Apache NiFi/Azure Data Factory/Talend, Kafka/Azure Event Grid/AWS EventBridge, MuleSoft/Boomi/WSO2.", + "type": "SoftwareSystem" + }, + { + "alias": "service_orchestration", + "label": "Service Orchestration Layer", + "description": "Coordinates internal microservices and workflows. Benefits: Efficient service communication, modularity, fault isolation. Tools: Kubernetes/Docker Swarm, Istio/Linkerd, Camunda/Temporal/Apache Airflow.", + "type": "SoftwareSystem" + }, + { + "alias": "ai_decision_engine", + "label": "AI Decision Support Engine", + "description": "Provides predictive insights and care recommendations. Benefits: Improved targeting, proactive outreach, personalized care. Tools: Azure Machine Learning/AWS SageMaker/Google Vertex AI, Python (scikit-learn, TensorFlow, PyTorch), MLflow/DVC.", + "type": "SoftwareSystem" + }, + { + "alias": "care_coordination", + "label": "Care Coordination Workflow Engine", + "description": "Automates case management and alerts. Benefits: Reduced manual effort, faster response, better resource allocation. Tools: Salesforce Health Cloud/Microsoft Dynamics 365/ServiceNow Health IT, Custom microservices with workflow logic, BPMN engines like Camunda or Zeebe.", + "type": "SoftwareSystem" + }, + { + "alias": "data_lake", + "label": "Data Lake & Analytics", + "description": "Centralized data storage and reporting. Benefits: Historical analysis, model training, compliance reporting. Tools: Azure Data Lake/AWS S3/Google Cloud Storage, Snowflake/BigQuery/Redshift, Power BI/Tableau/Looker.", + "type": "SoftwareSystem" + }, + { + "alias": "security_compliance", + "label": "Security & Compliance Layer", + "description": "Ensures secure data flow and regulatory alignment. Benefits: POPIA/GDPR compliance, encryption, access control. Tools: Azure Key Vault/AWS KMS/HashiCorp Vault, TLS 1.2+/1.3 AES-256 encryption, SIEM tools like Splunk Sentinel, Compliance frameworks POPIA GDPR HIPAA.", + "type": "SoftwareSystem" + }, + { + "alias": "monitoring_scalability", + "label": "Monitoring & Scalability", + "description": "Tracks system health and performance. Benefits: Autoscaling, uptime assurance, proactive issue detection. Tools: Prometheus + Grafana/Azure Monitor/CloudWatch, Elastic Stack (ELK)/Fluentd, Auto-scaling groups/Kubernetes HPA.", + "type": "SoftwareSystem" + }, + { + "alias": "change_management", + "label": "Change Management", + "description": "Supports adoption and stakeholder alignment. Benefits: Training, feedback loops, smoother transition to digital workflows. Tools: Prosci ADKAR/Kotter's 8-Step Model, Confluence/SharePoint/LMS platforms, Feedback tools Microsoft Forms SurveyMonkey.", + "type": "SoftwareSystem" + }, + { + "alias": "healthcare_member", + "label": "Healthcare Member", + "description": "End user accessing healthcare services through the member portal. Receives personalized care recommendations and manages health information.", + "type": "Person" + }, + { + "alias": "care_manager", + "label": "Care Manager", + "description": "Healthcare professional managing member care coordination. Uses AI insights and workflow automation for proactive care management.", + "type": "Person" + }, + { + "alias": "system_admin", + "label": "System Administrator", + "description": "Technical administrator responsible for system monitoring, security compliance, and change management processes.", + "type": "Person" + } + ], + "relationships": [ + { + "from": "healthcare_member", + "to": "member_portal", + "label": "Accesses healthcare services" + }, + { + "from": "care_manager", + "to": "care_coordination", + "label": "Manages care workflows" + }, + { + "from": "system_admin", + "to": "monitoring_scalability", + "label": "Monitors system health" + }, + { + "from": "member_portal", + "to": "integration_layer", + "label": "Requests member data" + }, + { + "from": "integration_layer", + "to": "service_orchestration", + "label": "Routes to microservices" + }, + { + "from": "service_orchestration", + "to": "ai_decision_engine", + "label": "Requests AI insights" + }, + { + "from": "service_orchestration", + "to": "care_coordination", + "label": "Triggers care workflows" + }, + { + "from": "ai_decision_engine", + "to": "data_lake", + "label": "Accesses training data" + }, + { + "from": "care_coordination", + "to": "data_lake", + "label": "Stores workflow metrics" + }, + { + "from": "security_compliance", + "to": "member_portal", + "label": "Enforces security policies" + }, + { + "from": "security_compliance", + "to": "integration_layer", + "label": "Secures API access" + }, + { + "from": "monitoring_scalability", + "to": "service_orchestration", + "label": "Tracks microservice health" + }, + { + "from": "change_management", + "to": "healthcare_member", + "label": "Provides training support" + } + ] +} diff --git a/samples/HealthcareArchitecture/plantuml.jar b/samples/HealthcareArchitecture/plantuml.jar new file mode 100644 index 0000000..b387226 Binary files /dev/null and b/samples/HealthcareArchitecture/plantuml.jar differ diff --git a/samples/ModelDiagrams/Diagrams/ContextDiagramSample.cs b/samples/ModelDiagrams/Diagrams/ContextDiagramSample.cs index bb3bb7b..f9fab06 100644 --- a/samples/ModelDiagrams/Diagrams/ContextDiagramSample.cs +++ b/samples/ModelDiagrams/Diagrams/ContextDiagramSample.cs @@ -14,16 +14,16 @@ public class ContextDiagramSample : ContextDiagram protected override IEnumerable Structures => [ Customer, - BankingSystem, - Mainframe, - MailSystem + BankingSystem//, + //Mainframe, + //MailSystem ]; - protected override IEnumerable Relationships => - [ + protected override IEnumerable Relationships => new[] + { Customer > BankingSystem, Customer < MailSystem | "Sends e-mails to", BankingSystem > MailSystem | ("Sends e-mails", "SMTP") | Neighbor, BankingSystem > Mainframe - ]; + }; } \ No newline at end of file diff --git a/samples/ModelDiagrams/Diagrams/EnterpriseDiagramSample.cs b/samples/ModelDiagrams/Diagrams/EnterpriseDiagramSample.cs index 3c55745..b1ba7cd 100644 --- a/samples/ModelDiagrams/Diagrams/EnterpriseDiagramSample.cs +++ b/samples/ModelDiagrams/Diagrams/EnterpriseDiagramSample.cs @@ -9,29 +9,29 @@ namespace ModelDiagrams.Diagrams; using static Systems; using static C4Sharp.Elements.Relationships.Position; -public class EnterpriseDiagramSample: ContextDiagram +public class EnterpriseDiagramSample : ContextDiagram { protected override string Title => "System Enterprise diagram for Internet Banking System"; protected override IEnumerable Structures => [ - Customer, - Bound("enterprise.boundary", "Domain A", - BankingSystem, - Bound("enterprise.boundary.1", "Domain Internal Users", InternalCustomer), - Bound("enterprise.boundary.2", "Domain Managers", Manager) - ), - Mainframe, - MailSystem + Customer, + Bound("enterprise.boundary", "Domain A", + BankingSystem, + Bound("enterprise.boundary.1", "Domain Internal Users", InternalCustomer), + Bound("enterprise.boundary.2", "Domain Managers", Manager) + )//, + //Mainframe, // Ensure 'Mainframe' is defined in the 'Systems' static class + //MailSystem // Ensure 'MailSystem' is included in the Structures ]; - protected override IEnumerable Relationships => - [ + protected override IEnumerable Relationships => new[] + { Customer > BankingSystem, InternalCustomer > BankingSystem, Manager > BankingSystem, Customer < MailSystem | "Sends e-mails to", BankingSystem > MailSystem | ("Sends e-mails", "SMTP") | Neighbor, - BankingSystem > Mainframe - ]; -} \ No newline at end of file + BankingSystem > Mainframe, + }; +} diff --git a/samples/ModelDiagrams/Diagrams/RemittanceAdviceContainerDiagram.cs b/samples/ModelDiagrams/Diagrams/RemittanceAdviceContainerDiagram.cs new file mode 100644 index 0000000..38682cd --- /dev/null +++ b/samples/ModelDiagrams/Diagrams/RemittanceAdviceContainerDiagram.cs @@ -0,0 +1,79 @@ +using C4Sharp.Diagrams.Builders; +using C4Sharp.Elements; +using C4Sharp.Elements.Containers; +using C4Sharp.Elements.Relationships; +using static C4Sharp.Elements.ContainerType; + +using ModelDiagrams.Structures; + +namespace ModelDiagrams.Diagrams; + +using static People; +using static Systems; +using static C4Sharp.Elements.Relationships.Position; + + public class RemittanceAdviceContainerDiagram : ContainerDiagram + { + protected override string Title => "Pharmacy Direct - Existing Container Diagram"; + + protected override IEnumerable Structures => new Structure[] + { + // External Person + Person.None | Boundary.External + | ("FinanceTeam", "Finance Team (Manual)", "Human actors verifying/approving exceptions"), + + // External Software Systems + SoftwareSystem.None | Boundary.External + | ("MedicalAidSchemes", "Medical Aid Schemes", "External providers of ERA files"), + + SoftwareSystem.None | Boundary.External + | ("Bank", "Banking System", "Provides Bank CSV/XLS"), + + SoftwareSystem.None | Boundary.External + | ("SFTP", "BI Solutions / Allegra SFTP", "ERA files are placed here by Allegra/BI Solutions"), + + // Pharmacy Direct Environment (Boundary) + Bound("pd", "Pharmacy Direct System", + // Containers inside PD + Container.None | (ContainerType.Api, "PowerAutomateWorker", "Power Automate + PD Worker Service", "Fetch/import CSV/XLS or ERA files from SharePoint/SFTP into SQL"), + Container.None | (ContainerType.Database, "SqlDataWarehouse", "SQL Data Warehouse", "Stores ERA lines, Bank lines, claims, etc."), + Container.None | (ContainerType.Api, "RemittanceApiGateway", "Remittance API Gateway", "Receives consolidated or partial payloads, publishes to queue"), + Container.None | (ContainerType.Queue, "RabbitQueue", "RabbitMQ Queue", "Broker for remittance messages to the processor"), + Container.None | (ContainerType.Api, "RemittanceProcessor", "Remittance Processor Service", "Consumes messages, updates claims/payment tables"), + Container.None | (ContainerType.WebApplication, "AllegraSystem", "Allegra Debtors System", "Debtors/Claims system used by PD"), + Container.None | (ContainerType.WebApplication, "PastelAccounting", "Pastel Accounting System", "Used by Finance for GL exports"), + Container.None | (ContainerType.WebApplication, "PowerBITracker", "Remittance Advice Tracker (Power BI)", "BI dashboards & real-time insights") + ) + }; + + protected override IEnumerable Relationships => new[] + { + // External interactions + this["MedicalAidSchemes"] > this["SFTP"] | ("Provide ERA files", "SFTP"), + this["Bank"] > this["PowerAutomateWorker"] | ("Send Bank CSV/XLS", "SharePoint/Automate"), + + // Worker -> SQL + this["SFTP"] > this["PowerAutomateWorker"] | "ERA .csv/.txt for PD Worker to process", + this["PowerAutomateWorker"] > this["SqlDataWarehouse"] | "Parse & load ERA & Bank data", + + // Internal flows + this["SqlDataWarehouse"] > this["AllegraSystem"] | "Partially processed lines", + this["AllegraSystem"] > this["FinanceTeam"] | "Manual exception review", + this["FinanceTeam"] > this["AllegraSystem"] | "Approve/adjust allocations", + + // API & Messaging + this["RemittanceApiGateway"] > this["RabbitQueue"] | "Publish incoming payload", + this["RabbitQueue"] > this["RemittanceProcessor"] | "Consume remittance messages", + this["RemittanceProcessor"] > this["SqlDataWarehouse"] | "Update claims/payment tables", + this["RemittanceProcessor"] > this["AllegraSystem"] | "Apply reconciliations", + + // BI & Exports + this["SqlDataWarehouse"] > this["PowerBITracker"] | "Data source (Remittance Advice Tracker)", + this["AllegraSystem"] > this["PastelAccounting"] | "Export to GL", + this["PastelAccounting"] > this["PowerAutomateWorker"] | "Uploads Pastel CSV to PD environment", + this["PowerAutomateWorker"] > this["SqlDataWarehouse"] | "Import Pastel data", + this["PowerBITracker"] > this["FinanceTeam"] | "Dashboards & insights" + }; + } + + diff --git a/samples/ModelDiagrams/ModelDiagrams.csproj b/samples/ModelDiagrams/ModelDiagrams.csproj index eb9c49a..f0819a7 100644 --- a/samples/ModelDiagrams/ModelDiagrams.csproj +++ b/samples/ModelDiagrams/ModelDiagrams.csproj @@ -7,6 +7,12 @@ enable + + + + + + diff --git a/samples/ModelDiagrams/Program.cs b/samples/ModelDiagrams/Program.cs index 9333881..6ab0acb 100644 --- a/samples/ModelDiagrams/Program.cs +++ b/samples/ModelDiagrams/Program.cs @@ -1,23 +1,49 @@ -// See https://aka.ms/new-console-template for more information +// See https://aka.ms/new-console-template for more information using C4Sharp.Diagrams; using C4Sharp.Diagrams.Plantuml; using C4Sharp.Diagrams.Themes; using ModelDiagrams.Diagrams; +Console.WriteLine("Building C4 diagrams..."); + +var outputPath = Path.Combine(Directory.GetCurrentDirectory(), "../../generated-diagrams"); +Directory.CreateDirectory(outputPath); + var diagrams = new DiagramBuilder[] { new ContextDiagramSample(), - new ComponentDiagramSample(), + new ComponentDiagramSample(), new ContainerDiagramSample(), new EnterpriseDiagramSample(), new SequenceDiagramSample(), - new DeploymentDiagramSample() + new DeploymentDiagramSample(), + new RemittanceAdviceContainerDiagram() }; -var path = Path.Combine("..", "..", "..", "..", "..", "docs", "images"); +var theme = new ParadisoTheme(); + +foreach (var diagramBuilder in diagrams) +{ + try + { + Console.WriteLine($"Generating {diagramBuilder.GetType().Name}..."); -new PlantumlContext() - .UseDiagramImageBuilder() - .UseDiagramSvgImageBuilder() - .Export(path, diagrams, new ParadisoTheme()); + var diagram = diagramBuilder.Build(theme); + var plantuml = diagram.ToPumlString(); + + var fileName = $"{diagram.Title.Replace(" ", "-").Replace(":", "").ToLower()}-{diagram.Type.ToString().ToLower()}.puml"; + var filePath = Path.Combine(outputPath, fileName); + + File.WriteAllText(filePath, plantuml); + Console.WriteLine($"Generated: {fileName}"); + } + catch (Exception ex) + { + Console.WriteLine($"Error generating {diagramBuilder.GetType().Name}: {ex.Message}"); + } +} + +Console.WriteLine($"\nC4 diagrams generated in: {outputPath}"); +Console.WriteLine("PUML files created successfully!"); + diff --git a/samples/ModelDiagrams/Structures/Containers.cs b/samples/ModelDiagrams/Structures/Containers.cs index 9764d99..41625ef 100644 --- a/samples/ModelDiagrams/Structures/Containers.cs +++ b/samples/ModelDiagrams/Structures/Containers.cs @@ -27,6 +27,21 @@ public static class Containers "Provides a limited subset of the Internet banking functionality to customers via their mobile device", Technology: "C#, Xamarin" ); + public static Mobile MailSystem => new( + Alias: "MobileApp", + Label: "MobileApp", + Description: + "Provides a limited subset of the Internet banking functionality to customers via their mobile device", + Technology: "C#, Xamarin" +); + + public static Mobile Mainframe => new( + Alias: "MobileApp", + Label: "MobileApp", + Description: + "Provides a limited subset of the Internet banking functionality to customers via their mobile device", + Technology: "C#, Xamarin" + ); public static Database SqlDatabase => new ( Alias: "Database", @@ -55,4 +70,50 @@ public static class Containers Description: "Provides Internet banking functionality via API.", Technology: "Dotnet, Docker Container" ); + + + public static SoftwareSystem PharmacyDirectSystem = new SoftwareSystem( + "Pharmacy Direct System", + "Handles bank/ERA ingestion, claims, accounting, and reporting."); + + // Containers inside Pharmacy Direct + public static Api PowerAutomateWorker = new Api( + "Power Automate + PD Worker Service", + "Fetch/import CSV/XLS or ERA files from SharePoint/SFTP into SQL", + "Microsoft Power Automate + Custom Worker"); + + public static Database SqlDataWarehouse = new Database( + "SQL Data Warehouse", + "Central PD data store for bank, ERA, claims, etc.", + "Microsoft SQL Server"); + + public static Api RemittanceApiGateway = new Api( + "Remittance API Gateway", + "Receives consolidated or age-analysis reports from MediMatch, publishes to RabbitMQ", + "ASP.NET Core Web API"); + + public static Queue RabbitMqQueue = new Queue( + "RabbitMQ Queue", + "Message broker to feed remittance data to the Processor service", + "RabbitMQ"); + + public static Api RemittanceProcessor = new Api( + "Remittance Processor Service", + "Applies reconciliation logic, updates claims/payments in Allegra", + "C# Service"); + + public static SoftwareSystem AllegraSystem = new SoftwareSystem( + "Allegra Debtors System", + "Debtors/Claims system integrated with PD environment", + "Allegra platform"); + + public static SoftwareSystem PowerBiTracker = new SoftwareSystem( + "Remittance Advice Tracker (Power BI)", + "BI dashboards for real-time reconciliation insights", + "Microsoft Power BI"); + + public static SoftwareSystem PastelAccounting = new SoftwareSystem( + "Pastel Accounting System", + "Used by Finance team for GL exports, final ledger", + "Sage Pastel"); } \ No newline at end of file diff --git a/samples/ModelDiagrams/Structures/People.cs b/samples/ModelDiagrams/Structures/People.cs index 58f1762..4552f96 100644 --- a/samples/ModelDiagrams/Structures/People.cs +++ b/samples/ModelDiagrams/Structures/People.cs @@ -23,4 +23,12 @@ public static class People label: "Manager Banking Customer", description: "A manager of the bank, with personal bank accounts." ); + public static Person FinanceTeam = new Person( + "Finance Team", + "Human actors verifying and approving exceptions"); + public static Person MedicalAidSchemes = new Person( + "Medical Aid Schemes", + "External providers of ERA files"); + + } \ No newline at end of file diff --git a/samples/ModelDiagrams/Structures/Systems.cs b/samples/ModelDiagrams/Structures/Systems.cs index 614f113..75370a1 100644 --- a/samples/ModelDiagrams/Structures/Systems.cs +++ b/samples/ModelDiagrams/Structures/Systems.cs @@ -5,23 +5,57 @@ namespace ModelDiagrams.Structures; public static class Systems { + public static SoftwareSystem MedicalAidSchemes = new SoftwareSystem( + "Medical Aid Schemes", + "External providers of ERA files"); + + public static SoftwareSystem BankingSystem = new SoftwareSystem( + "Banking System", + "Provides bank statements in CSV/XLS"); + + public static SoftwareSystem AllegraSftp = new SoftwareSystem( + "BI Solutions / Allegra SFTP", + "SFTP location where ERA files are delivered"); + + public static SoftwareSystem MediMatchSystem = new SoftwareSystem( + "MediMatch Middleware", + "Reconciliation engine and APIs"); + public static SoftwareSystem PharmacyDirectSystem => + new("PharmacyDirectSystem", "Pharmacy Direct System", + "Handles bank/ERA ingestion, claims, accounting, and reporting.", Boundary.External); + public static SoftwareSystem PowerAutomate => + new("PowerAutomate", "Power Automate + PD Worker Service", + "Fetches/imports CSV/XLS or ERA files from SharePoint/SFTP into SQL.", Boundary.External); public static SoftwareSystem BankingSystem => new( alias: "BankingSystem", label: "Internet Banking System", description: "Allows customers to view information about their bank accounts, and make payments." ); - public static SoftwareSystem Mainframe => new( - alias: "Mainframe", - label: "Mainframe Banking System", - description: "Stores all of the core banking information about customers, accounts, transactions, etc.", - boundary: Boundary.External - ); + public static SoftwareSystem SqlDataWarehouse => + new("SqlDataWarehouse", "SQL Data Warehouse", + "Central PD data store for bank, ERA, claims, etc.", Boundary.External); + public static SoftwareSystem RemittanceApiGateway => + new("RemittanceApiGateway", "Remittance API Gateway", + "Receives consolidated or age-analysis reports from MediMatch, publishes to RabbitMQ.", Boundary.External); + + public static SoftwareSystem RabbitMqQueue => + new("RabbitMqQueue", "RabbitMQ Queue", + "Message broker to feed remittance data to the Processor service.", Boundary.External); + + public static SoftwareSystem RemittanceProcessor => + new("RemittanceProcessor", "Remittance Processor Service", + "Applies reconciliation logic, updates claims/payments in Allegra.", Boundary.External); + + public static SoftwareSystem AllegraSystem => + new("AllegraSystem", "Allegra Debtors System", + "Debtors/Claims system integrated with PD environment.", Boundary.External); + public static SoftwareSystem PowerBiTracker => + new("PowerBiTracker", "Remittance Advice Tracker (Power BI)", + "Power BI report showing the status of remittance advice processing.", Boundary.External); + + public static SoftwareSystem PowerBiReport => + new("PowerBiReport", "Remittance Advice Tracker (Power BI)", + "Power BI report showing the status of remittance advice processing.", Boundary.External); - public static SoftwareSystem MailSystem => new( - alias: "MailSystem", - label: "E-mail system", - description: "The internal Microsoft Exchange e-mail system.", - boundary: Boundary.External - ); } \ No newline at end of file diff --git a/src/C4Sharp.Diagrams/C4Sharp.Diagrams.csproj b/src/C4Sharp.Diagrams/C4Sharp.Diagrams.csproj new file mode 100644 index 0000000..5336f96 --- /dev/null +++ b/src/C4Sharp.Diagrams/C4Sharp.Diagrams.csproj @@ -0,0 +1,14 @@ + + + + net8.0 + enable + enable + Exe + + + + + + + diff --git a/src/C4Sharp.Diagrams/HealthcareComponentDiagram.cs b/src/C4Sharp.Diagrams/HealthcareComponentDiagram.cs new file mode 100644 index 0000000..1a41678 --- /dev/null +++ b/src/C4Sharp.Diagrams/HealthcareComponentDiagram.cs @@ -0,0 +1,74 @@ +using C4Sharp.Diagrams.Builders; +using C4Sharp.Elements; +using C4Sharp.Elements.Boundaries; +using C4Sharp.Elements.Relationships; +using static C4Sharp.Elements.Relationships.Position; + +namespace C4Sharp.Diagrams +{ + /// + /// Healthcare Component Diagram - Shows the components within the Patient Management Service + /// + public class HealthcareComponentDiagram : ComponentDiagram + { + protected override string Title => "Healthcare Solution - Patient Management Service Components"; + protected override string Description => "The component diagram showing the internal structure of the Patient Management Service"; + + protected override IEnumerable Structures => new Structure[] + { + // External Users + new Person("patient", "Patient", "Healthcare service recipient"), + new Person("doctor", "Doctor", "Healthcare provider"), + + // External Containers + new Container("patient_portal", "Patient Portal", ContainerType.Spa, "React", "Patient web application"), + new Container("provider_portal", "Provider Portal", ContainerType.Spa, "React", "Provider web application"), + new Container("patient_db", "Patient Database", ContainerType.Database, "PostgreSQL", "Patient data storage"), + new Container("message_queue", "Message Queue", ContainerType.Queue, "RabbitMQ", "Event messaging"), + + // Patient Management Service Components + Bound("patient_service", "Patient Management Service", + new Component("patient_controller", "Patient Controller", ".NET 8 Web API", + "REST API controller handling HTTP requests for patient operations"), + new Component("patient_service_impl", "Patient Service", ".NET 8", + "Business logic service for patient management operations"), + new Component("patient_repository", "Patient Repository", ".NET 8, Entity Framework", + "Data access layer for patient information"), + new Component("patient_validator", "Patient Validator", ".NET 8", + "Validates patient data and business rules"), + new Component("patient_mapper", "Patient Mapper", ".NET 8, AutoMapper", + "Maps between domain models and DTOs"), + new Component("event_publisher", "Event Publisher", ".NET 8", + "Publishes patient-related events to message queue"), + new Component("security_service", "Security Service", ".NET 8", + "Handles authentication and authorization for patient data"), + new Component("audit_service", "Audit Service", ".NET 8", + "Logs all patient data access and modifications for compliance") + ) + }; + + protected override IEnumerable Relationships => new[] + { + // External access to service + this["patient_portal"] > this["patient_controller"] | "Makes API calls for patient operations", "HTTPS/JSON", + this["provider_portal"] > this["patient_controller"] | "Makes API calls for patient management", "HTTPS/JSON", + + // Internal component relationships + this["patient_controller"] > this["security_service"] | "Validates user permissions", + this["patient_controller"] > this["patient_validator"] | "Validates request data", + this["patient_controller"] > this["patient_service_impl"] | "Delegates business operations", + this["patient_controller"] > this["patient_mapper"] | "Maps DTOs to domain models", + + this["patient_service_impl"] > this["patient_repository"] | "Performs data operations", + this["patient_service_impl"] > this["event_publisher"] | "Publishes patient events", + this["patient_service_impl"] > this["audit_service"] | "Logs patient data access", + + this["patient_repository"] > this["patient_db"] | "Reads from and writes to", "SQL/TCP", + this["event_publisher"] > this["message_queue"] | "Publishes events", "AMQP", + + // Cross-cutting concerns + this["security_service"] > this["audit_service"] | "Logs security events", + this["patient_validator"] > this["audit_service"] | "Logs validation failures" + }; + } +} diff --git a/src/C4Sharp.Diagrams/HealthcareContainerDiagram.cs b/src/C4Sharp.Diagrams/HealthcareContainerDiagram.cs new file mode 100644 index 0000000..8e183c8 --- /dev/null +++ b/src/C4Sharp.Diagrams/HealthcareContainerDiagram.cs @@ -0,0 +1,116 @@ +using C4Sharp.Diagrams.Builders; +using C4Sharp.Elements; +using C4Sharp.Elements.Containers; +using C4Sharp.Elements.Relationships; +using static C4Sharp.Elements.Relationships.Position; + +namespace C4Sharp.Diagrams +{ + /// + /// Healthcare Container Diagram - Shows the containers within the healthcare system + /// + public class HealthcareContainerDiagram : ContainerDiagram + { + protected override string Title => "Healthcare Solution - Container Diagram"; + protected override string Description => "The container diagram for the healthcare solution showing web applications, APIs, databases, and their interactions"; + + protected override IEnumerable Structures => new Structure[] + { + // People (external to the system) + new Person("patient", "Patient", "Healthcare service recipient"), + new Person("doctor", "Doctor", "Healthcare provider"), + new Person("nurse", "Nurse", "Healthcare professional"), + new Person("admin", "Healthcare Administrator", "Administrative staff"), + + // Healthcare System Boundary with Containers + Bound("healthcare_system", "Healthcare Management System", + // Web Applications + new ClientSideWebApp("patient_portal", "Patient Portal", "React, TypeScript", + "Single-page application providing patients with access to their health information, appointments, and medical records"), + new ClientSideWebApp("provider_portal", "Provider Portal", "React, TypeScript", + "Single-page application for healthcare providers to manage patients, clinical workflows, and medical documentation"), + new ClientSideWebApp("admin_portal", "Admin Portal", "React, TypeScript", + "Administrative interface for system configuration, user management, and operational oversight"), + + // Mobile Applications + new Mobile("mobile_app", "Healthcare Mobile App", "React Native", + "Mobile application for patients to access health services, book appointments, and receive notifications"), + + // Backend Services + new Microservice("api_gateway", "API Gateway", "Kong, Nginx", + "Central entry point for all API requests, handling authentication, rate limiting, and routing"), + new Microservice("patient_service", "Patient Management Service", ".NET 8, C#", + "Microservice handling patient registration, profiles, and personal health information"), + new Microservice("appointment_service", "Appointment Service", ".NET 8, C#", + "Microservice managing appointment scheduling, calendar management, and availability"), + new Microservice("medical_records_service", "Medical Records Service", ".NET 8, C#", + "Microservice for managing electronic health records, clinical notes, and medical history"), + new Microservice("billing_service", "Billing Service", ".NET 8, C#", + "Microservice handling medical billing, insurance claims, and payment processing"), + new Microservice("notification_service", "Notification Service", ".NET 8, C#", + "Microservice for sending notifications via email, SMS, and push notifications"), + + // Databases + new Container("patient_db", "Patient Database", ContainerType.Database, "PostgreSQL", + "Stores patient information, demographics, and personal health data"), + new Container("medical_records_db", "Medical Records Database", ContainerType.Database, "PostgreSQL", + "Stores electronic health records, clinical notes, and medical history"), + new Container("appointment_db", "Appointment Database", ContainerType.Database, "PostgreSQL", + "Stores appointment schedules, availability, and booking information"), + new Container("billing_db", "Billing Database", ContainerType.Database, "PostgreSQL", + "Stores billing information, insurance claims, and payment records"), + + // Message Queues + new Container("message_queue", "Message Queue", ContainerType.Queue, "RabbitMQ", + "Handles asynchronous communication between microservices") + ), + + // External Systems + new SoftwareSystem("ehr_system", "External EHR System", "Third-party electronic health records system"), + new SoftwareSystem("lab_system", "Laboratory System", "External laboratory information system"), + new SoftwareSystem("pharmacy_system", "Pharmacy System", "External pharmacy management system") + }; + + protected override IEnumerable Relationships => new[] + { + // User to Web Applications + this["patient"] > this["patient_portal"] | "Uses web browser to access health information", + this["doctor"] > this["provider_portal"] | "Uses web browser to manage patients and clinical workflows", + this["nurse"] > this["provider_portal"] | "Uses web browser for patient care and documentation", + this["admin"] > this["admin_portal"] | "Uses web browser for system administration", + + // Mobile App Usage + this["patient"] > this["mobile_app"] | "Uses mobile app for health services", + + // Web Applications to API Gateway + this["patient_portal"] > this["api_gateway"] | "Makes API calls", "HTTPS", + this["provider_portal"] > this["api_gateway"] | "Makes API calls", "HTTPS", + this["admin_portal"] > this["api_gateway"] | "Makes API calls", "HTTPS", + this["mobile_app"] > this["api_gateway"] | "Makes API calls", "HTTPS", + + // API Gateway to Microservices + this["api_gateway"] > this["patient_service"] | "Routes patient-related requests", "HTTP/REST", + this["api_gateway"] > this["appointment_service"] | "Routes appointment requests", "HTTP/REST", + this["api_gateway"] > this["medical_records_service"] | "Routes medical records requests", "HTTP/REST", + this["api_gateway"] > this["billing_service"] | "Routes billing requests", "HTTP/REST", + this["api_gateway"] > this["notification_service"] | "Routes notification requests", "HTTP/REST", + + // Microservices to Databases + this["patient_service"] > this["patient_db"] | "Reads from and writes to", "SQL/TCP", + this["appointment_service"] > this["appointment_db"] | "Reads from and writes to", "SQL/TCP", + this["medical_records_service"] > this["medical_records_db"] | "Reads from and writes to", "SQL/TCP", + this["billing_service"] > this["billing_db"] | "Reads from and writes to", "SQL/TCP", + + // Microservices to Message Queue + this["patient_service"] > this["message_queue"] | "Publishes patient events", "AMQP", + this["appointment_service"] > this["message_queue"] | "Publishes appointment events", "AMQP", + this["billing_service"] > this["message_queue"] | "Publishes billing events", "AMQP", + this["notification_service"] < this["message_queue"] | "Consumes notification events", "AMQP", + + // External System Integrations + this["medical_records_service"] > this["ehr_system"] | "Synchronizes medical records", "HL7 FHIR", + this["medical_records_service"] > this["lab_system"] | "Retrieves lab results", "HL7 FHIR", + this["billing_service"] > this["pharmacy_system"] | "Sends prescriptions", "HL7 FHIR" + }; + } +} diff --git a/src/C4Sharp.Diagrams/HealthcareSystemContextDiagram.cs b/src/C4Sharp.Diagrams/HealthcareSystemContextDiagram.cs new file mode 100644 index 0000000..b5288b9 --- /dev/null +++ b/src/C4Sharp.Diagrams/HealthcareSystemContextDiagram.cs @@ -0,0 +1,70 @@ +using C4Sharp.Diagrams.Builders; +using C4Sharp.Elements; +using C4Sharp.Elements.Relationships; +using static C4Sharp.Elements.Relationships.Position; + +namespace C4Sharp.Diagrams +{ + /// + /// Healthcare System Context Diagram - Shows the healthcare system in scope and its relationships with users and other systems + /// + public class HealthcareSystemContextDiagram : ContextDiagram + { + protected override string Title => "Healthcare Solution - System Context"; + protected override string Description => "The system context diagram for the healthcare solution showing external users, systems, and their interactions"; + + protected override IEnumerable Structures => new Structure[] + { + // People + new Person("patient", "Patient", "Healthcare service recipient who accesses medical services and manages their health information"), + new Person("doctor", "Doctor", "Healthcare provider who diagnoses, treats patients, and manages medical records"), + new Person("nurse", "Nurse", "Healthcare professional who provides patient care and assists in medical procedures"), + new Person("admin", "Healthcare Administrator", "Administrative staff who manages healthcare operations and patient data"), + + // Main Healthcare System + new SoftwareSystem("healthcare_system", "Healthcare Management System", + "Comprehensive healthcare platform providing patient management, medical records, appointments, and clinical workflows"), + + // External Systems + new SoftwareSystem("ehr_system", "Electronic Health Records (EHR)", + "External EHR system for storing and managing patient medical records and clinical data"), + new SoftwareSystem("lab_system", "Laboratory Information System", + "External laboratory system for managing lab tests, results, and diagnostic information"), + new SoftwareSystem("pharmacy_system", "Pharmacy Management System", + "External pharmacy system for prescription management and medication dispensing"), + new SoftwareSystem("insurance_system", "Insurance Claims System", + "External insurance system for processing claims, coverage verification, and billing"), + new SoftwareSystem("billing_system", "Medical Billing System", + "External billing system for processing medical charges, payments, and financial transactions"), + new SoftwareSystem("notification_system", "Notification Service", + "External notification system for sending SMS, email, and push notifications") + }; + + protected override IEnumerable Relationships => new[] + { + // Patient interactions + this["patient"] > this["healthcare_system"] | "Books appointments, views medical records, manages health information", + this["healthcare_system"] > this["patient"] | "Provides health information, appointment confirmations, test results", + + // Doctor interactions + this["doctor"] > this["healthcare_system"] | "Manages patient care, updates medical records, schedules procedures", + this["healthcare_system"] > this["doctor"] | "Provides patient information, clinical data, scheduling tools", + + // Nurse interactions + this["nurse"] > this["healthcare_system"] | "Records patient vitals, administers medications, updates care plans", + this["healthcare_system"] > this["nurse"] | "Provides patient care instructions, medication schedules, alerts", + + // Administrator interactions + this["admin"] > this["healthcare_system"] | "Manages system configuration, user accounts, operational reports", + this["healthcare_system"] > this["admin"] | "Provides system analytics, user management tools, audit logs", + + // External system integrations + this["healthcare_system"] > this["ehr_system"] | "Synchronizes patient medical records and clinical data", + this["healthcare_system"] > this["lab_system"] | "Orders lab tests and retrieves results", + this["healthcare_system"] > this["pharmacy_system"] | "Sends prescriptions and medication orders", + this["healthcare_system"] > this["insurance_system"] | "Submits claims and verifies coverage", + this["healthcare_system"] > this["billing_system"] | "Processes medical charges and payments", + this["healthcare_system"] > this["notification_system"] | "Sends appointment reminders and health alerts" + }; + } +} diff --git a/src/C4Sharp.Diagrams/Program.cs b/src/C4Sharp.Diagrams/Program.cs new file mode 100644 index 0000000..e266e87 --- /dev/null +++ b/src/C4Sharp.Diagrams/Program.cs @@ -0,0 +1,85 @@ +using C4Sharp.Diagrams; +using C4Sharp.Diagrams.Plantuml; +using C4Sharp.Diagrams.Drawio; +using C4Sharp.Diagrams.Themes; + +namespace C4Sharp.Diagrams +{ + class Program + { + static void Main(string[] args) + { + Console.WriteLine("Generating C4 Healthcare Solution Diagrams..."); + Console.WriteLine("=============================================="); + + // Define output paths + var baseOutputPath = Path.Combine(Directory.GetCurrentDirectory(), "..", "..", "generated-diagrams"); + var plantumlPath = Path.Combine(baseOutputPath, "c4-plantuml"); + var drawioPath = Path.Combine(baseOutputPath, "c4-drawio"); + + // Ensure output directories exist + Directory.CreateDirectory(plantumlPath); + Directory.CreateDirectory(drawioPath); + + // Create C4 diagram instances + var diagrams = new IDiagramBuilder[] + { + new HealthcareSystemContextDiagram(), + new HealthcareContainerDiagram(), + new HealthcareComponentDiagram() + }; + + try + { + // Export PlantUML diagrams with all formats + Console.WriteLine($"Exporting PlantUML diagrams to: {plantumlPath}"); + new PlantumlContext() + .UseDiagramImageBuilder() // Enable PNG generation + .UseDiagramSvgImageBuilder() // Enable SVG generation + .UseDiagramMermaidBuilder() // Enable Mermaid DSL generation + .Export(plantumlPath, diagrams, new DefaultTheme()); + + Console.WriteLine("PlantUML export completed successfully (PUML, PNG, SVG, Mermaid DSL)."); + } + catch (Exception ex) + { + Console.WriteLine($"Error during PlantUML export: {ex.Message}"); + Console.WriteLine($"Stack trace: {ex.StackTrace}"); + } + + try + { + // Export Draw.io diagrams with all formats + Console.WriteLine($"Exporting Draw.io diagrams to: {drawioPath}"); + new DrawioContext() + .AddDiagrams(diagrams) + .UseSvgExport() // Enable SVG generation + .UsePngExport() // Enable PNG placeholder generation + .Export(drawioPath); + + Console.WriteLine("Draw.io export completed successfully (XML, SVG, PNG)."); + } + catch (Exception ex) + { + Console.WriteLine($"Error during Draw.io export: {ex.Message}"); + Console.WriteLine($"Stack trace: {ex.StackTrace}"); + } + + Console.WriteLine(); + Console.WriteLine("C4 Diagram Generation Complete!"); + Console.WriteLine("================================"); + Console.WriteLine(); + Console.WriteLine("Generated diagrams:"); + Console.WriteLine($"- System Context Diagram: Shows healthcare system and external actors"); + Console.WriteLine($"- Container Diagram: Shows internal containers (web apps, APIs, databases)"); + Console.WriteLine($"- Component Diagram: Shows components within Patient Management Service"); + Console.WriteLine(); + Console.WriteLine("Output formats:"); + Console.WriteLine($"- PlantUML: .puml files, .mermaid.md files (+ PNG/SVG if PlantUML JAR available)"); + Console.WriteLine($"- Draw.io: .drawio XML files, .svg files, .png placeholder files"); + Console.WriteLine(); + Console.WriteLine($"PlantUML files: {plantumlPath}"); + Console.WriteLine($"Draw.io files: {drawioPath}"); + } + } +} diff --git a/src/C4Sharp.Generator/C4Sharp.Generator.csproj b/src/C4Sharp.Generator/C4Sharp.Generator.csproj new file mode 100644 index 0000000..550fe7f --- /dev/null +++ b/src/C4Sharp.Generator/C4Sharp.Generator.csproj @@ -0,0 +1,14 @@ + + + + Exe + net8.0 + enable + enable + + + + + + + diff --git a/src/C4Sharp.Generator/ConfigModels.cs b/src/C4Sharp.Generator/ConfigModels.cs new file mode 100644 index 0000000..c0f615b --- /dev/null +++ b/src/C4Sharp.Generator/ConfigModels.cs @@ -0,0 +1,29 @@ +using System.Collections.Generic; + +namespace C4Sharp.Generator +{ + public class DiagramConfig + { + public string Title { get; set; } + public string Slug { get; set; } + public List Structures { get; set; } + public List Relationships { get; set; } + } + + public class StructureConfig + { + public string Alias { get; set; } + public string Label { get; set; } + public string Description { get; set; } + public string Type { get; set; } + public string Boundary { get; set; } + } + + public class RelationshipConfig + { + public string From { get; set; } + public string To { get; set; } + public string Label { get; set; } + public string Technology { get; set; } + } +} diff --git a/src/C4Sharp.Generator/ConfigurableDiagram.cs b/src/C4Sharp.Generator/ConfigurableDiagram.cs new file mode 100644 index 0000000..c3c0b74 --- /dev/null +++ b/src/C4Sharp.Generator/ConfigurableDiagram.cs @@ -0,0 +1,20 @@ +using C4Sharp.Diagrams.Builders; +using C4Sharp.Elements; +using C4Sharp.Elements.Relationships; +using System.Collections.Generic; + +namespace C4Sharp.Generator +{ + public class ConfigurableDiagram : ContextDiagram + { + public static string CurrentTitle { get; set; } = string.Empty; + public static string CurrentSlug { get; set; } = string.Empty; + public static IEnumerable CurrentStructures { get; set; } = new List(); + public static IEnumerable CurrentRelationships { get; set; } = new List(); + + protected override string Title => CurrentTitle; + protected override IEnumerable Structures => CurrentStructures; + protected override IEnumerable Relationships => CurrentRelationships; + } +} + diff --git a/src/C4Sharp.Generator/Program.cs b/src/C4Sharp.Generator/Program.cs new file mode 100644 index 0000000..bec899e --- /dev/null +++ b/src/C4Sharp.Generator/Program.cs @@ -0,0 +1,104 @@ +using System; +using System.IO; +using System.Text.Json; +using System.Linq; +using C4Sharp.Diagrams; +using C4Sharp.Diagrams.Plantuml; +using C4Sharp.Diagrams.Drawio; +using C4Sharp.Elements; +using C4Sharp.Elements.Relationships; + +namespace C4Sharp.Generator +{ + class Program + { + static void Main(string[] args) + { + var currentDirectory = Directory.GetCurrentDirectory(); + var diagramsRoot = Path.Combine(currentDirectory, "diagrams"); + var outputDirectory = Path.Combine(currentDirectory, "generated-diagrams"); + + if (!Directory.Exists(diagramsRoot)) + { + Console.WriteLine($"Diagrams directory not found at: {diagramsRoot}"); + return; + } + + var configFiles = Directory.GetFiles(diagramsRoot, "config.json", SearchOption.AllDirectories); + + foreach (var configFile in configFiles) + { + Console.WriteLine($"Processing: {configFile}"); + var jsonContent = File.ReadAllText(configFile); + var config = JsonSerializer.Deserialize(jsonContent, new JsonSerializerOptions { PropertyNameCaseInsensitive = true }); + + var structures = config.Structures.Select(CreateStructure).ToArray(); + + var relationships = config.Relationships.Select(r => + { + var fromStructure = structures.First(s => s.Alias == r.From); + var toStructure = structures.First(s => s.Alias == r.To); + return fromStructure > toStructure | r.Label; + }).ToArray(); + + ConfigurableDiagram.CurrentTitle = config.Title; + ConfigurableDiagram.CurrentSlug = config.Slug; + ConfigurableDiagram.CurrentStructures = structures; + ConfigurableDiagram.CurrentRelationships = relationships; + + var diagramBuilder = new ConfigurableDiagram(); + + var plantumlPath = Path.Combine(outputDirectory, "plantuml"); + var drawioPath = Path.Combine(outputDirectory, "drawio"); + + Directory.CreateDirectory(plantumlPath); + Directory.CreateDirectory(drawioPath); + + try + { + Console.WriteLine($"Exporting PlantUML diagrams to: {plantumlPath}"); + new PlantumlContext() + .UseDiagramImageBuilder() // Enable PNG generation + .UseDiagramSvgImageBuilder() // Enable SVG generation + .UseDiagramMermaidBuilder() // Enable Mermaid DSL generation + .Export(plantumlPath, new[] { diagramBuilder }); + + Console.WriteLine("PlantUML export completed successfully (PUML, PNG, SVG, Mermaid DSL)."); + } + catch (Exception ex) + { + Console.WriteLine($"Error during PlantUML export: {ex.Message}"); + Console.WriteLine($"Stack trace: {ex.StackTrace}"); + } + + try + { + Console.WriteLine($"Exporting Draw.io diagrams to: {drawioPath}"); + new DrawioContext() + .AddDiagrams(new[] { diagramBuilder }) + .UseSvgExport() + .UsePngExport() + .Export(drawioPath); + Console.WriteLine("Draw.io export completed successfully (XML, SVG, PNG)."); + } + catch (Exception ex) + { + Console.WriteLine($"Error during Draw.io export: {ex.Message}"); + Console.WriteLine($"Stack trace: {ex.StackTrace}"); + } + } + + Console.WriteLine("Diagram generation complete!"); + } + + private static Structure CreateStructure(StructureConfig config) + { + return config.Type switch + { + "Person" => new Person(config.Alias, config.Label) { Description = config.Description }, + "SoftwareSystem" => new SoftwareSystem(config.Alias, config.Label) { Description = config.Description }, + _ => throw new ArgumentException($"Unknown structure type: {config.Type}") + }; + } + } +} diff --git a/src/C4Sharp/C4Sharp.csproj b/src/C4Sharp/C4Sharp.csproj index 14d8927..4a7db48 100644 --- a/src/C4Sharp/C4Sharp.csproj +++ b/src/C4Sharp/C4Sharp.csproj @@ -1,4 +1,4 @@ - + net8.0;net9.0 @@ -39,4 +39,5 @@ + diff --git a/src/C4Sharp/Diagrams/Drawio/DrawioContext.cs b/src/C4Sharp/Diagrams/Drawio/DrawioContext.cs new file mode 100644 index 0000000..65f94f0 --- /dev/null +++ b/src/C4Sharp/Diagrams/Drawio/DrawioContext.cs @@ -0,0 +1,58 @@ +using System.Collections.Generic; +using System.IO; + +namespace C4Sharp.Diagrams.Drawio +{ + public class DrawioContext + { + private readonly List _diagrams = new(); + private bool _generateSvg = false; + private bool _generatePng = false; + + public DrawioContext AddDiagrams(params DiagramBuilder[] diagrams) + { + _diagrams.AddRange(diagrams); + return this; + } + + public DrawioContext UseSvgExport() + { + _generateSvg = true; + return this; + } + + public DrawioContext UsePngExport() + { + _generatePng = true; + return this; + } + + public void Export(string path) + { + if (!Directory.Exists(path)) + { + Directory.CreateDirectory(path); + } + + foreach (var diagram in _diagrams) + { + var builtDiagram = diagram.Build(); + + // Always export XML + DrawioDiagramExporter.Export(path, builtDiagram); + + // Export SVG if requested + if (_generateSvg) + { + DrawioSvgExporter.ExportSvg(path, builtDiagram); + } + + // Export PNG if requested + if (_generatePng) + { + DrawioPngExporter.ExportPng(path, builtDiagram); + } + } + } + } +} diff --git a/src/C4Sharp/Diagrams/Drawio/DrawioDiagram.cs b/src/C4Sharp/Diagrams/Drawio/DrawioDiagram.cs new file mode 100644 index 0000000..a20dd4c --- /dev/null +++ b/src/C4Sharp/Diagrams/Drawio/DrawioDiagram.cs @@ -0,0 +1,105 @@ +using System.Collections.Generic; +using System.Xml.Serialization; + +namespace C4Sharp.Diagrams.Drawio +{ + [XmlRoot("mxGraphModel", Namespace = "")] + public class MxGraphModel + { + [XmlAttribute("dx")] + public string Dx { get; set; } = "1434"; + + [XmlAttribute("dy")] + public string Dy { get; set; } = "790"; + + [XmlAttribute("grid")] + public int Grid { get; set; } = 1; + + [XmlAttribute("gridSize")] + public int GridSize { get; set; } = 10; + + [XmlAttribute("guides")] + public int Guides { get; set; } = 1; + + [XmlAttribute("tooltips")] + public int Tooltips { get; set; } = 1; + + [XmlAttribute("connect")] + public int Connect { get; set; } = 1; + + [XmlAttribute("arrows")] + public int Arrows { get; set; } = 1; + + [XmlAttribute("fold")] + public int Fold { get; set; } = 1; + + [XmlAttribute("page")] + public int Page { get; set; } = 1; + + [XmlAttribute("pageScale")] + public int PageScale { get; set; } = 1; + + [XmlAttribute("pageWidth")] + public int PageWidth { get; set; } = 850; + + [XmlAttribute("pageHeight")] + public int PageHeight { get; set; } = 1100; + + [XmlElement("root")] + public Root Root { get; set; } + } + + public class Root + { + [XmlElement("mxCell")] + public List MxCells { get; set; } = new List(); + } + + public class MxCell + { + [XmlAttribute("id")] + public string Id { get; set; } + + [XmlAttribute("value")] + public string Value { get; set; } + + [XmlAttribute("style")] + public string Style { get; set; } + + [XmlAttribute("parent")] + public string Parent { get; set; } + + [XmlAttribute("vertex")] + public int Vertex { get; set; } + + [XmlAttribute("edge")] + public int Edge { get; set; } + + [XmlAttribute("source")] + public string Source { get; set; } + + [XmlAttribute("target")] + public string Target { get; set; } + + [XmlElement("mxGeometry")] + public MxGeometry Geometry { get; set; } + } + + public class MxGeometry + { + [XmlAttribute("x")] + public double X { get; set; } + + [XmlAttribute("y")] + public double Y { get; set; } + + [XmlAttribute("width")] + public double Width { get; set; } + + [XmlAttribute("height")] + public double Height { get; set; } + + [XmlAttribute("as")] + public string As { get; set; } + } +} diff --git a/src/C4Sharp/Diagrams/Drawio/DrawioDiagramExporter.cs b/src/C4Sharp/Diagrams/Drawio/DrawioDiagramExporter.cs new file mode 100644 index 0000000..92a2eab --- /dev/null +++ b/src/C4Sharp/Diagrams/Drawio/DrawioDiagramExporter.cs @@ -0,0 +1,265 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Xml.Serialization; +using C4Sharp.Elements; +using C4Sharp.Elements.Boundaries; + +namespace C4Sharp.Diagrams.Drawio +{ + public static class DrawioDiagramExporter + { + private static readonly Dictionary TechnologyIcons = new() + { + { "react", "https://cdn.jsdelivr.net/gh/devicons/devicon/icons/react/react-original.svg" }, + { "angular", "https://cdn.jsdelivr.net/gh/devicons/devicon/icons/angularjs/angularjs-original.svg" }, + { "vue", "https://cdn.jsdelivr.net/gh/devicons/devicon/icons/vuejs/vuejs-original.svg" }, + { "azure", "https://cdn.jsdelivr.net/gh/devicons/devicon/icons/azure/azure-original.svg" }, + { "aws", "https://cdn.jsdelivr.net/gh/devicons/devicon/icons/amazonwebservices/amazonwebservices-original.svg" }, + { "gcp", "https://cdn.jsdelivr.net/gh/devicons/devicon/icons/googlecloud/googlecloud-original.svg" }, + { "kubernetes", "https://cdn.jsdelivr.net/gh/devicons/devicon/icons/kubernetes/kubernetes-plain.svg" }, + { "docker", "https://cdn.jsdelivr.net/gh/devicons/devicon/icons/docker/docker-original.svg" }, + { "python", "https://cdn.jsdelivr.net/gh/devicons/devicon/icons/python/python-original.svg" }, + { "tensorflow", "https://cdn.jsdelivr.net/gh/devicons/devicon/icons/tensorflow/tensorflow-original.svg" }, + { "kafka", "https://cdn.jsdelivr.net/gh/devicons/devicon/icons/apachekafka/apachekafka-original.svg" }, + { "prometheus", "https://cdn.jsdelivr.net/gh/devicons/devicon/icons/prometheus/prometheus-original.svg" }, + { "grafana", "https://cdn.jsdelivr.net/gh/devicons/devicon/icons/grafana/grafana-original.svg" } + }; + + public static void Export(string path, Diagram diagram) + { + var model = new MxGraphModel + { + Root = new Root() + }; + + // Add default cells for layer and background + model.Root.MxCells.Add(new MxCell { Id = "0" }); + model.Root.MxCells.Add(new MxCell { Id = "1", Parent = "0" }); + + var structures = diagram.Structures.ToList(); + var relationships = diagram.Relationships.ToList(); + + // Enhanced layout calculation + var positions = CalculateEnhancedLayout(structures.Count); + var nodeWidth = 280; + var nodeHeight = 200; + + // Add title if available + if (!string.IsNullOrEmpty(diagram.Title)) + { + model.Root.MxCells.Add(new MxCell + { + Id = "title", + Value = diagram.Title, + Style = GetTitleStyle(), + Parent = "1", + Vertex = 1, + Geometry = new MxGeometry + { + X = 50, + Y = 20, + Width = 800, + Height = 40, + As = "geometry" + } + }); + } + + // Create enhanced structure nodes + for (var i = 0; i < structures.Count; i++) + { + var structure = structures[i]; + var position = positions[i]; + + var cellValue = CreateEnhancedNodeContent(structure); + + model.Root.MxCells.Add(new MxCell + { + Id = structure.Alias, + Value = cellValue, + Style = GetEnhancedStyle(structure), + Parent = "1", + Vertex = 1, + Geometry = new MxGeometry + { + X = position.x, + Y = position.y, + Width = nodeWidth, + Height = nodeHeight, + As = "geometry" + } + }); + } + + // Create enhanced relationship edges + foreach (var rel in relationships) + { + model.Root.MxCells.Add(new MxCell + { + Id = $"{rel.From}-{rel.To}-{rel.Label}", + Value = rel.Label, + Style = GetEnhancedEdgeStyle(), + Parent = "1", + Edge = 1, + Source = rel.From, + Target = rel.To, + Geometry = new MxGeometry { As = "geometry" } + }); + } + + var serializer = new XmlSerializer(typeof(MxGraphModel)); + var fileName = !string.IsNullOrEmpty(diagram.Title) + ? diagram.Title.Replace(" ", "-").Replace(":", "").Replace(",", "").ToLowerInvariant() + : "diagram"; + var filePath = Path.Combine(path, $"{fileName}.drawio"); + + using (var writer = new StreamWriter(filePath)) + { + serializer.Serialize(writer, model); + } + } + + private static string CreateEnhancedNodeContent(Structure structure) + { + var content = new StringBuilder(); + + // Add technology icons if available + var icons = GetTechnologyIcons(structure.Description); + if (icons.Any()) + { + content.Append("
"); + foreach (var icon in icons.Take(3)) // Limit to 3 icons + { + content.Append($""); + } + content.Append("
"); + } + + // Component title + content.Append($"
{structure.Label}
"); + + // Description + if (!string.IsNullOrEmpty(structure.Description)) + { + var shortDesc = structure.Description.Length > 80 + ? structure.Description.Substring(0, 77) + "..." + : structure.Description; + content.Append($"
{shortDesc}
"); + } + + // Extract and display benefits and tools from description + var (benefits, tools) = ExtractBenefitsAndTools(structure.Description); + + if (!string.IsNullOrEmpty(benefits)) + { + content.Append($"
Benefits: {benefits}
"); + } + + if (!string.IsNullOrEmpty(tools)) + { + content.Append($"
Tools: {tools}
"); + } + + return content.ToString(); + } + + private static (string benefits, string tools) ExtractBenefitsAndTools(string description) + { + // Simple extraction logic - in a real implementation, you'd parse the JSON config + var benefits = ""; + var tools = ""; + + if (description.Contains("React") || description.Contains("Angular") || description.Contains("Vue")) + { + tools = "React/Angular/Vue, Azure/AWS/GCP"; + } + else if (description.Contains("API") || description.Contains("integration")) + { + tools = "API Gateway, Apache NiFi, Kafka"; + } + else if (description.Contains("Kubernetes") || description.Contains("microservices")) + { + tools = "Kubernetes, Istio, Camunda"; + } + else if (description.Contains("AI") || description.Contains("ML")) + { + tools = "Azure ML, TensorFlow, MLflow"; + } + + return (benefits, tools); + } + + private static List GetTechnologyIcons(string description) + { + var icons = new List(); + + foreach (var tech in TechnologyIcons) + { + if (description.ToLowerInvariant().Contains(tech.Key)) + { + icons.Add(tech.Value); + } + } + + return icons; + } + + private static List<(int x, int y)> CalculateEnhancedLayout(int count) + { + var positions = new List<(int x, int y)>(); + + // Grid-based layout with better spacing + var cols = Math.Min(3, count); // Max 3 columns + var rows = (int)Math.Ceiling((double)count / cols); + + var startX = 100; + var startY = 100; + var spacingX = 320; // Wider spacing for larger nodes + var spacingY = 250; // Taller spacing for larger nodes + + for (var i = 0; i < count; i++) + { + var row = i / cols; + var col = i % cols; + + var x = startX + col * spacingX; + var y = startY + row * spacingY; + + positions.Add((x, y)); + } + + return positions; + } + + private static string GetTitleStyle() + { + return "text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;" + + "whiteSpace=wrap;rounded=0;fontSize=20;fontStyle=1;fontColor=#0366d6;"; + } + + private static string GetEnhancedStyle(Structure structure) + { + var baseStyle = "rounded=1;whiteSpace=wrap;html=1;arcSize=8;strokeWidth=2;" + + "align=left;verticalAlign=top;spacingTop=10;spacingLeft=10;spacingRight=10;"; + + if (structure is Person) + { + return baseStyle + "fillColor=#f6f8fa;fontColor=#24292e;strokeColor=#d1d5da;"; + } + else + { + return baseStyle + "fillColor=#ffffff;fontColor=#24292e;strokeColor=#0366d6;"; + } + } + + private static string GetEnhancedEdgeStyle() + { + return "edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" + + "strokeWidth=2;strokeColor=#0366d6;fontColor=#586069;fontSize=11;" + + "labelBackgroundColor=#ffffff;labelBorderColor=#d1d5da;"; + } + } +} diff --git a/src/C4Sharp/Diagrams/Drawio/DrawioPngExporter.cs b/src/C4Sharp/Diagrams/Drawio/DrawioPngExporter.cs new file mode 100644 index 0000000..2eb210c --- /dev/null +++ b/src/C4Sharp/Diagrams/Drawio/DrawioPngExporter.cs @@ -0,0 +1,70 @@ +using System; +using System.IO; +using System.Linq; +using System.Text; + +namespace C4Sharp.Diagrams.Drawio +{ + public static class DrawioPngExporter + { + public static void ExportPng(string path, Diagram diagram) + { + var fileName = !string.IsNullOrEmpty(diagram.Title) + ? diagram.Title.Replace(" ", "-").Replace(":", "").Replace(",", "").ToLowerInvariant() + : "diagram"; + var pngFilePath = Path.Combine(path, $"{fileName}.png"); + var svgFilePath = Path.Combine(path, $"{fileName}.svg"); + + try + { + // For now, we'll create a placeholder PNG file with instructions + // In a production environment, you would use a library like SkiaSharp, + // ImageSharp, or call external tools like Inkscape or Chrome headless + var placeholderContent = GeneratePngPlaceholder(diagram); + File.WriteAllText(pngFilePath, placeholderContent); + + Console.WriteLine($"PNG export placeholder created: {pngFilePath}"); + Console.WriteLine("To generate actual PNG files, consider integrating:"); + Console.WriteLine("- SkiaSharp for cross-platform SVG to PNG conversion"); + Console.WriteLine("- System.Drawing (Windows only)"); + Console.WriteLine("- External tools like Inkscape or Chrome headless"); + } + catch (Exception ex) + { + Console.WriteLine($"Error generating PNG for {fileName}: {ex.Message}"); + } + } + + // SVG generation is handled by DrawioSvgExporter to avoid conflicts + + private static string GeneratePngPlaceholder(Diagram diagram) + { + var placeholder = new StringBuilder(); + placeholder.AppendLine("PNG Export Placeholder"); + placeholder.AppendLine("======================"); + placeholder.AppendLine(); + placeholder.AppendLine($"Diagram: {diagram.Title}"); + placeholder.AppendLine($"Structures: {diagram.Structures.Count()}"); + placeholder.AppendLine($"Relationships: {diagram.Relationships.Count()}"); + placeholder.AppendLine(); + placeholder.AppendLine("To implement actual PNG generation, you can:"); + placeholder.AppendLine(); + placeholder.AppendLine("1. Install SkiaSharp NuGet package:"); + placeholder.AppendLine(" dotnet add package SkiaSharp"); + placeholder.AppendLine(" dotnet add package SkiaSharp.Svg"); + placeholder.AppendLine(); + placeholder.AppendLine("2. Use System.Drawing (Windows only):"); + placeholder.AppendLine(" dotnet add package System.Drawing.Common"); + placeholder.AppendLine(); + placeholder.AppendLine("3. Use external tools:"); + placeholder.AppendLine(" - Inkscape: inkscape input.svg --export-png=output.png"); + placeholder.AppendLine(" - Chrome: chrome --headless --screenshot=output.png input.html"); + placeholder.AppendLine(); + placeholder.AppendLine("Note: SVG files are generated separately by DrawioSvgExporter"); + placeholder.AppendLine(); + placeholder.AppendLine("Generated at: " + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")); + + return placeholder.ToString(); + } + } +} diff --git a/src/C4Sharp/Diagrams/Drawio/DrawioSvgExporter.cs b/src/C4Sharp/Diagrams/Drawio/DrawioSvgExporter.cs new file mode 100644 index 0000000..bcf6a1c --- /dev/null +++ b/src/C4Sharp/Diagrams/Drawio/DrawioSvgExporter.cs @@ -0,0 +1,165 @@ +using System; +using System.IO; +using System.Linq; +using System.Text; +using System.Xml; +using C4Sharp.Elements; +using C4Sharp.Elements.Relationships; + +namespace C4Sharp.Diagrams.Drawio +{ + public static class DrawioSvgExporter + { + public static void ExportSvg(string path, Diagram diagram) + { + var fileName = !string.IsNullOrEmpty(diagram.Title) + ? diagram.Title.Replace(" ", "-").Replace(":", "").Replace(",", "").ToLowerInvariant() + : "diagram"; + var filePath = Path.Combine(path, $"{fileName}.svg"); + + var svgContent = GenerateSvg(diagram); + File.WriteAllText(filePath, svgContent); + } + + private static string GenerateSvg(Diagram diagram) + { + var structures = diagram.Structures.ToList(); + var relationships = diagram.Relationships.ToList(); + + // Calculate canvas size based on number of elements with proper spacing + var cols = Math.Max(1, (int)Math.Ceiling(Math.Sqrt(structures.Count))); + var rows = (int)Math.Ceiling((double)structures.Count / cols); + var canvasWidth = Math.Max(1000, cols * 200 + 200); // Extra padding + var canvasHeight = Math.Max(800, rows * 120 + 200 + relationships.Count * 5); // Extra padding + + var svg = new StringBuilder(); + svg.AppendLine(""); + svg.AppendLine($""); + + // Add marker definitions for arrows + svg.AppendLine(" "); + svg.AppendLine(" "); + svg.AppendLine(" "); + svg.AppendLine(" "); + svg.AppendLine(" "); + + // Add title + if (!string.IsNullOrEmpty(diagram.Title)) + { + svg.AppendLine($" {diagram.Title}"); + } + + // Calculate positions for structures + var positions = CalculatePositions(structures.Count, canvasWidth, canvasHeight); + + // Draw structures + for (var i = 0; i < structures.Count; i++) + { + var structure = structures[i]; + var position = positions[i]; + DrawStructure(svg, structure, position.x, position.y); + } + + // Draw relationships + foreach (var relationship in relationships) + { + var fromIndex = structures.FindIndex(s => s.Alias == relationship.From); + var toIndex = structures.FindIndex(s => s.Alias == relationship.To); + + if (fromIndex >= 0 && toIndex >= 0) + { + var fromPos = positions[fromIndex]; + var toPos = positions[toIndex]; + DrawRelationship(svg, relationship, fromPos, toPos); + } + } + + svg.AppendLine(""); + return svg.ToString(); + } + + private static void DrawStructure(StringBuilder svg, Structure structure, int x, int y) + { + var width = 160; + var height = 80; + var isPerson = structure is Person; + + // Choose colors based on structure type + var fillColor = isPerson ? "#999999" : "#1168BD"; + var strokeColor = isPerson ? "#666666" : "#0E559C"; + var textColor = "#ffffff"; + + // Draw rectangle + svg.AppendLine($" "); + + // Draw label + var labelY = y + height / 2 - 5; + svg.AppendLine($" {structure.Label}"); + + // Draw description if available + if (!string.IsNullOrEmpty(structure.Description) && structure.Description.Length < 50) + { + var descY = labelY + 15; + svg.AppendLine($" {structure.Description}"); + } + } + + private static void DrawRelationship(StringBuilder svg, Relationship relationship, (int x, int y) fromPos, (int x, int y) toPos) + { + var fromX = fromPos.x + 80; // Center of from structure + var fromY = fromPos.y + 40; + var toX = toPos.x + 80; // Center of to structure + var toY = toPos.y + 40; + + // Draw arrow line + svg.AppendLine($" "); + + // Draw label at midpoint + var midX = (fromX + toX) / 2; + var midY = (fromY + toY) / 2; + + if (!string.IsNullOrEmpty(relationship.Label)) + { + // Background rectangle for label + var labelWidth = relationship.Label.Length * 8; + svg.AppendLine($" "); + + svg.AppendLine($" {relationship.Label}"); + } + } + + private static (int x, int y)[] CalculatePositions(int count, int canvasWidth, int canvasHeight) + { + var positions = new (int x, int y)[count]; + var cols = Math.Max(1, (int)Math.Ceiling(Math.Sqrt(count))); + var rows = (int)Math.Ceiling((double)count / cols); + + var spacingX = (canvasWidth - 200) / Math.Max(1, cols - 1); + var spacingY = (canvasHeight - 200) / Math.Max(1, rows - 1); + + for (var i = 0; i < count; i++) + { + var row = i / cols; + var col = i % cols; + + var x = 100 + col * spacingX; + var y = 80 + row * spacingY; + + positions[i] = (x, y); + } + + return positions; + } + + static DrawioSvgExporter() + { + // This will be called once to set up SVG definitions + } + } +}