diff --git a/.github/workflows/dotnet.yml b/.github/workflows/dotnet.yml index 86966ee..08e1aef 100644 --- a/.github/workflows/dotnet.yml +++ b/.github/workflows/dotnet.yml @@ -7,8 +7,8 @@ on: branches: [ main ] env: - VERSION: 6.2.${{ github.run_number }} - CLI_VERSION: 2.2.${{ github.run_number }} + VERSION: 6.3.${{ github.run_number }} + CLI_VERSION: 2.3.${{ github.run_number }} NUGET_INDEX: https://api.nuget.org/v3/index.json BUILD_TYPE: Release @@ -47,8 +47,8 @@ jobs: - name: Build run: dotnet build --no-restore --configuration Release - - name: Integrated Tests - run: dotnet test ./tests/**/*.IntegratedTests.csproj --no-restore +# - name: Integrated Tests +# run: dotnet test ./tests/**/*.IntegratedTests.csproj --no-restore - name: Publish DLL Artifact if: github.ref == 'refs/heads/main' diff --git a/C4Sharp.sln b/C4Sharp.sln index ac947be..8487151 100644 --- a/C4Sharp.sln +++ b/C4Sharp.sln @@ -4,17 +4,11 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{758DA496-318 EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "samples", "samples", "{53454ACB-CE39-4F53-AB32-C28C15720537}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{2EAFABEF-1FBB-4DEB-A620-52CBF42F1736}" -EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "C4Sharp", "src\C4Sharp\C4Sharp.csproj", "{B3850A7A-EBB2-4C33-827B-98B88901A638}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "C4Sharp.IntegratedTests", "tests\C4Sharp.IntegratedTests\C4Sharp.IntegratedTests.csproj", "{652679C0-4067-4ED5-8D97-48A765E7A965}" -EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "C4Sharp.Tools", "src\C4Sharp.Tools\C4Sharp.Tools.csproj", "{AEF17681-C9AB-4C49-8B06-06E5AF8C4237}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Basic", "Basic", "{EBA828C5-ACB9-4B6E-9513-BF4F612ECEAA}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "C4Sharp.Sample", "samples\Basic\C4Sharp.Sample\C4Sharp.Sample.csproj", "{CEAA41B3-F197-4663-A845-E4F5DB7DC2E8}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ModelDiagrams", "samples\ModelDiagrams\ModelDiagrams.csproj", "{A6E8E401-D8DE-4640-A6FA-2242A07F2481}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -26,24 +20,18 @@ Global {B3850A7A-EBB2-4C33-827B-98B88901A638}.Debug|Any CPU.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 - {652679C0-4067-4ED5-8D97-48A765E7A965}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {652679C0-4067-4ED5-8D97-48A765E7A965}.Debug|Any CPU.Build.0 = Debug|Any CPU - {652679C0-4067-4ED5-8D97-48A765E7A965}.Release|Any CPU.ActiveCfg = Release|Any CPU - {652679C0-4067-4ED5-8D97-48A765E7A965}.Release|Any CPU.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}.Release|Any CPU.ActiveCfg = Release|Any CPU {AEF17681-C9AB-4C49-8B06-06E5AF8C4237}.Release|Any CPU.Build.0 = Release|Any CPU - {CEAA41B3-F197-4663-A845-E4F5DB7DC2E8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {CEAA41B3-F197-4663-A845-E4F5DB7DC2E8}.Debug|Any CPU.Build.0 = Debug|Any CPU - {CEAA41B3-F197-4663-A845-E4F5DB7DC2E8}.Release|Any CPU.ActiveCfg = Release|Any CPU - {CEAA41B3-F197-4663-A845-E4F5DB7DC2E8}.Release|Any CPU.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}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A6E8E401-D8DE-4640-A6FA-2242A07F2481}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(NestedProjects) = preSolution {B3850A7A-EBB2-4C33-827B-98B88901A638} = {758DA496-3186-4129-B0FA-5C3205B52763} - {652679C0-4067-4ED5-8D97-48A765E7A965} = {2EAFABEF-1FBB-4DEB-A620-52CBF42F1736} {AEF17681-C9AB-4C49-8B06-06E5AF8C4237} = {758DA496-3186-4129-B0FA-5C3205B52763} - {EBA828C5-ACB9-4B6E-9513-BF4F612ECEAA} = {53454ACB-CE39-4F53-AB32-C28C15720537} - {CEAA41B3-F197-4663-A845-E4F5DB7DC2E8} = {EBA828C5-ACB9-4B6E-9513-BF4F612ECEAA} + {A6E8E401-D8DE-4640-A6FA-2242A07F2481} = {53454ACB-CE39-4F53-AB32-C28C15720537} EndGlobalSection EndGlobal diff --git a/samples/Basic/C4Sharp.Sample/C4Sharp.Sample.csproj b/samples/Basic/C4Sharp.Sample/C4Sharp.Sample.csproj deleted file mode 100644 index 5411c6c..0000000 --- a/samples/Basic/C4Sharp.Sample/C4Sharp.Sample.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - - Exe - 10 - true - enable - net6.0;net7.0;net8.0 - - - - - - - diff --git a/samples/Basic/C4Sharp.Sample/Diagrams/ComponentDiagram.cs b/samples/Basic/C4Sharp.Sample/Diagrams/ComponentDiagram.cs deleted file mode 100644 index 32bf193..0000000 --- a/samples/Basic/C4Sharp.Sample/Diagrams/ComponentDiagram.cs +++ /dev/null @@ -1,68 +0,0 @@ -using C4Sharp.Diagrams; -using C4Sharp.Elements; -using C4Sharp.Elements.Boundaries; -using C4Sharp.Elements.Relationships; -using C4Sharp.Sample.Structures; - -namespace C4Sharp.Sample.Diagrams -{ - using static Systems; - using static Components; - using static Containers; - - public class ComponentDiagram: DiagramBuildRunner - { - protected override string Title => "Internet Banking System API Application"; - - protected override string Description => - "The word `component` is a hugely overloaded term in the software development industry, but in this context a " + - "component is a grouping of related functionality encapsulated behind a well-defined interface. If you're using " + - "a language like Java or C#, the simplest way to think of a component is that it's a collection of implementation " + - "classes behind an interface. Aspects such as how those components are packaged (e.g. one component vs many " + - "components per JAR file, DLL, shared library, etc) is a separate and orthogonal concern. " + - "An important point to note here is that all components inside a container typically execute in the same process " + - "space. In the C4 model, components are not separately deployable units."; - - protected override DiagramType DiagramType => DiagramType.Component; - protected override DiagramLayout FlowVisualization => DiagramLayout.LeftRight; - protected override bool LayoutAsSketch => false; - - protected override IEnumerable Structures => new Structure[] - { - Spa, - MobileApp, - SqlDatabase, - Mainframe, - Boundary(), - }; - - protected override IEnumerable Relationships => new Relationship[] - { - Spa > Sign | ("Uses", "JSON/HTTPS"), - Spa > Accounts | ("Uses", "JSON/HTTPS"), - MobileApp > Sign | ("Uses", "JSON/HTTPS"), - MobileApp > Accounts | ("Uses", "JSON/HTTPS") - }; - - private static ContainerBoundary Boundary() - { - return new ("c1", "API Application") - { - Components = new[] - { - Sign, - Accounts, - Security, - MainframeFacade - }, - Relationships = new[] - { - Sign > Security, - Accounts > MainframeFacade, - Security > SqlDatabase | ("Read & write to", "JDBC"), - MainframeFacade > Mainframe | ("Uses", "XML/HTTPS") - } - }; - } - } -} \ No newline at end of file diff --git a/samples/Basic/C4Sharp.Sample/Diagrams/ContainerDiagram.cs b/samples/Basic/C4Sharp.Sample/Diagrams/ContainerDiagram.cs deleted file mode 100644 index abadded..0000000 --- a/samples/Basic/C4Sharp.Sample/Diagrams/ContainerDiagram.cs +++ /dev/null @@ -1,57 +0,0 @@ -using C4Sharp.Diagrams; -using C4Sharp.Diagrams.Interfaces; -using C4Sharp.Diagrams.Plantuml.Constants; -using C4Sharp.Diagrams.Plantuml.Style; -using C4Sharp.Elements; -using C4Sharp.Elements.Boundaries; -using C4Sharp.Elements.Relationships; -using C4Sharp.Sample.Structures; - -namespace C4Sharp.Sample.Diagrams -{ - using static Containers; - - public class ContainerDiagram: DiagramBuildRunner - { - protected override string Title => "Container diagram for Internet Banking System"; - protected override DiagramType DiagramType => DiagramType.Container; - - protected override IEnumerable Structures => new Structure[] - { - People.Customer, - Systems.BankingSystem, - Systems.MailSystem, - new SoftwareSystemBoundary("c1", "Internet Banking", - WebApp, - Spa, - MobileApp, - SqlDatabase, - RabbitMq, - BackendApi - ) - }; - - protected override IEnumerable Relationships => new[] - { - People.Customer > WebApp | ("Uses", "HTTPS"), - People.Customer > Spa | ("Uses", "HTTPS"), - People.Customer > MobileApp | "Uses", - - WebApp > Spa | "Delivers" | Position.Neighbor, - Spa > BackendApi | ("Uses", "async, JSON/HTTPS"), - MobileApp > BackendApi | ("Uses", "async, JSON/HTTPS"), - SqlDatabase < BackendApi | ("Uses", "async, JSON/HTTPS") | Position.Neighbor, - RabbitMq < BackendApi | ("Uses", "async, JSON"), - - People.Customer < Systems.MailSystem | "Sends e-mails to", - Systems.MailSystem < BackendApi | ("Sends e-mails using", "sync, SMTP"), - BackendApi > Systems.BankingSystem | ("Uses", "sync/async, XML/HTTPS") | Position.Neighbor - }; - - protected override IElementTag SetTags() - { - return new ElementTag() - .AddElementTag("services", "#3F6684", shape: Shape.EightSidedShape); - } - } -} \ No newline at end of file diff --git a/samples/Basic/C4Sharp.Sample/Diagrams/ContextDiagram.cs b/samples/Basic/C4Sharp.Sample/Diagrams/ContextDiagram.cs deleted file mode 100644 index 4de2f5b..0000000 --- a/samples/Basic/C4Sharp.Sample/Diagrams/ContextDiagram.cs +++ /dev/null @@ -1,50 +0,0 @@ -using C4Sharp.Diagrams; -using C4Sharp.Diagrams.Interfaces; -using C4Sharp.Diagrams.Plantuml.Constants; -using C4Sharp.Diagrams.Plantuml.Style; -using C4Sharp.Elements; -using C4Sharp.Elements.Relationships; -using C4Sharp.Sample.Structures; - -namespace C4Sharp.Sample.Diagrams -{ - using static Position; - using static People; - using static Systems; - - public class ContextDiagram : DiagramBuildRunner - { - protected override string Title => "System Context diagram for Internet Banking System"; - protected override DiagramType DiagramType => DiagramType.Context; - - protected override IEnumerable Structures => new Structure[] - { - Customer, - BankingSystem, - Mainframe, - MailSystem - }; - - protected override IEnumerable Relationships => new[] - { - (Customer > BankingSystem).AddTags("error"), - Customer < MailSystem | "Sends e-mails to", - BankingSystem > MailSystem | ("Sends e-mails", "SMTP") | Neighbor, - BankingSystem > Mainframe - }; - - protected override IElementStyle SetStyle() - { - return new ElementStyle() - .UpdateElementStyle(ElementName.ExternalPerson, "#7f3b08", "#7f3b08") - .UpdateElementStyle(ElementName.Person, "#55ACEE", "#55ACEE") - .UpdateElementStyle(ElementName.ExternalSystem, "#3F6684", shape: Shape.RoundedBoxShape); - } - - protected override IRelationshipTag? SetRelTags() - { - return new RelationshipTag() - .AddRelTag("error", "red", "red", LineStyle.DashedLine); - } - } -} \ No newline at end of file diff --git a/samples/Basic/C4Sharp.Sample/Diagrams/DeploymentDiagram.cs b/samples/Basic/C4Sharp.Sample/Diagrams/DeploymentDiagram.cs deleted file mode 100644 index 68a560a..0000000 --- a/samples/Basic/C4Sharp.Sample/Diagrams/DeploymentDiagram.cs +++ /dev/null @@ -1,46 +0,0 @@ -using C4Sharp.Diagrams; -using C4Sharp.Elements; -using C4Sharp.Elements.Relationships; -using C4Sharp.Sample.Structures; - -namespace C4Sharp.Sample.Diagrams -{ - public class DeploymentDiagram: DiagramBuildRunner - { - protected override string Title => "System Context diagram for Internet Banking System"; - protected override DiagramType DiagramType => DiagramType.Deployment; - - protected override IEnumerable Structures => new Structure[] - { - BigBankNode(), - Nodes.Ios("ios", Containers.MobileApp), - Nodes.PersonalComputer("computer", Nodes.Browser("browser", Containers.Spa)) - }; - - protected override IEnumerable Relationships => new[] - { - (Containers.MobileApp > Containers.BackendApi)["Makes API calls to", "json/HTTPS"], - (Containers.Spa > Containers.BackendApi)["Makes API calls to", "json/HTTPS"], - (Containers.WebApp > Containers.Spa)["Delivers to the customer's web browser"][Position.Up], - (Containers.BackendApi > Containers.OracleDatabase[1])["Writes to", "JDBC"], - (Containers.BackendApi < Containers.OracleDatabase["Data Reader"])["Reads from", "JDBC"], - (Containers.OracleDatabase[1] > Containers.OracleDatabase["Data Reader"])["Replicates data to", "JDBC"][ - Position.Right], - }; - - private static DeploymentNode BigBankNode() - { - return new DeploymentNode("plc", "Big Bank plc") - { - Description = "Big Bank plc data center", - Nodes = new[] - { - Nodes.Ubuntu("dn", "bigbank-api***\tx8", Nodes.ApacheTomCat("apache", Containers.BackendApi)), - Nodes.Ubuntu("bigbankdb01", "bigbank-db01", Nodes.OracleNode("oracle", Containers.OracleDatabase[1])), - Nodes.Ubuntu("bigbankdb02", "bigbank-db02", Nodes.OracleNode("oracle2", Containers.OracleDatabase["Data Reader"])), - Nodes.Ubuntu("bb2", "bigbank-web***\tx4", Nodes.ApacheTomCat("apache2", Containers.WebApp)), - } - }; - } - } -} \ No newline at end of file diff --git a/samples/Basic/C4Sharp.Sample/Diagrams/EnterpriseDiagram.cs b/samples/Basic/C4Sharp.Sample/Diagrams/EnterpriseDiagram.cs deleted file mode 100644 index 8ed28f1..0000000 --- a/samples/Basic/C4Sharp.Sample/Diagrams/EnterpriseDiagram.cs +++ /dev/null @@ -1,72 +0,0 @@ -using C4Sharp.Diagrams; -using C4Sharp.Diagrams.Interfaces; -using C4Sharp.Diagrams.Plantuml.Constants; -using C4Sharp.Diagrams.Plantuml.Style; -using C4Sharp.Elements; -using C4Sharp.Elements.Boundaries; -using C4Sharp.Elements.Relationships; -using C4Sharp.Sample.Structures; - -namespace C4Sharp.Sample.Diagrams -{ - using static Position; - using static People; - using static Systems; - - public class EnterpriseDiagram: DiagramBuildRunner - { - protected override string Title => "System Enterprise diagram for Internet Banking System"; - protected override DiagramType DiagramType => DiagramType.Context; - - protected override IEnumerable Structures => new Structure[] - { - Customer, - EnterpriseBoundary(), - Mainframe, - MailSystem - }; - - private static EnterpriseBoundary EnterpriseBoundary() - { - return new EnterpriseBoundary("enterprise.boundary", "Domain A") - { - Structures = new Structure[] - { - BankingSystem, - new EnterpriseBoundary("enterprise.boundary.1", "Domain Internal Users") - { - Structures = new Structure[] - { - InternalCustomer, - } - }, - new EnterpriseBoundary("enterprise.boundary.2", "Domain Managers") - { - Structures = new Structure[] - { - Manager, - } - }, - } - }; - } - - 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, - }; - - protected override IElementStyle SetStyle() - { - return new ElementStyle() - .UpdateElementStyle(ElementName.ExternalPerson, "#7f3b08", "#7f3b08") - .UpdateElementStyle(ElementName.Person, "#55ACEE", "#55ACEE") - .UpdateElementStyle(ElementName.ExternalSystem, "#3F6684", shape: Shape.RoundedBoxShape); - } - } -} \ No newline at end of file diff --git a/samples/Basic/C4Sharp.Sample/Diagrams/SequenceDiagram.cs b/samples/Basic/C4Sharp.Sample/Diagrams/SequenceDiagram.cs deleted file mode 100644 index ed642f6..0000000 --- a/samples/Basic/C4Sharp.Sample/Diagrams/SequenceDiagram.cs +++ /dev/null @@ -1,34 +0,0 @@ -using C4Sharp.Diagrams; -using C4Sharp.Elements; -using C4Sharp.Elements.Boundaries; -using C4Sharp.Elements.Relationships; - -namespace C4Sharp.Sample.Diagrams; - -public class SequenceDiagram: DiagramBuildRunner -{ - protected override string Title => "Sequence diagram for Internet Banking System"; - protected override DiagramType DiagramType => DiagramType.Sequence; - - protected override IEnumerable Structures => new Structure[] - { - new Container("cA", "Single-Page Application", ContainerType.None, "JavaScript and Angular", "Provides all of the Internet banking functionality to customers via their web browser."), - - new SequenceContainerBoundary("b", "Api Application") - { - Components = new Component[] - { - new ("cB", "Sign In Controller", ComponentType.None, "Spring MVC Rest Controller", "Allows users to sign in to the Internet Banking System."), - new ("cC", "Security Component", ComponentType.None, "Spring Bean", "Provides functionality Related to signing in, changing passwords, etc.") - } - }, - new Container("cD", "Database", ContainerType.Database ,"Relational Database Schema", "Stores user registration information, hashed authentication credentials, access logs, etc.") - }; - - protected override IEnumerable Relationships => new[] - { - It("cA") > It("cB") | ("Submits credentials to", "JSON/HTTPS"), - It("cB") > It("cC") | "Calls isAuthenticated() on", - It("cC") > It("cD") | ("select * from users where username = ?o", "JDBCS") - }; -} \ No newline at end of file diff --git a/samples/Basic/C4Sharp.Sample/Program.cs b/samples/Basic/C4Sharp.Sample/Program.cs deleted file mode 100644 index f91aecd..0000000 --- a/samples/Basic/C4Sharp.Sample/Program.cs +++ /dev/null @@ -1,29 +0,0 @@ -using C4Sharp.Diagrams.Plantuml; -using C4Sharp.Sample.Diagrams; - -namespace C4Sharp.Sample; - -internal static class Program -{ - private static void Main() - { - var diagrams = new[] - { - new ContextDiagram().Build(), - new ContainerDiagram().Build(), - new ComponentDiagram().Build(), - new DeploymentDiagram().Build(), - new EnterpriseDiagram().Build(), - new SequenceDiagram().Build() - }; - - var context = new PlantumlContext(); - - context - .UseDiagramImageBuilder() - //.UseDiagramSvgImageBuilder() - //.UseDiagramMermaidBuilder() - //.UseStandardLibraryBaseUrl() //load the resources from github C4plantuml repository - .Export(diagrams); - } -} \ No newline at end of file diff --git a/samples/Basic/C4Sharp.Sample/Structures/Components.cs b/samples/Basic/C4Sharp.Sample/Structures/Components.cs deleted file mode 100644 index 9e55970..0000000 --- a/samples/Basic/C4Sharp.Sample/Structures/Components.cs +++ /dev/null @@ -1,38 +0,0 @@ -using C4Sharp.Elements; - -namespace C4Sharp.Sample.Structures; - -public static class Components -{ - private static Component? _sign; - - public static Component Sign => _sign ??= new Component("sign", "Sign In Controller") - { - Description = "Allows users to sign in to the internet banking system", - Technology = "MVC Rest Controller", - }; - - private static Component? _accounts; - - public static Component Accounts => _accounts ??= new Component("accounts", "Accounts Summary Controller") - { - Description = "Provides customers with a summary of their bank accounts", - Technology = "MVC Rest Controller" - }; - - private static Component? _security; - - public static Component Security => _security ??= new Component("security", "Security Component") - { - Description = "Provides functionality related to singing in, changing passwords, etc.", - Technology = "Spring Bean" - }; - - private static Component? _mainframeFacade; - public static Component MainframeFacade => _mainframeFacade ??= - new Component("mbsfacade", "Mainframe Banking System Facade") - { - Description = "A facade onto the mainframe banking system.", - Technology = "C#, Class Library" - }; -} diff --git a/samples/Basic/C4Sharp.Sample/Structures/People.cs b/samples/Basic/C4Sharp.Sample/Structures/People.cs deleted file mode 100644 index 776aa9d..0000000 --- a/samples/Basic/C4Sharp.Sample/Structures/People.cs +++ /dev/null @@ -1,27 +0,0 @@ -using C4Sharp.Elements; -using C4Sharp.Elements.Relationships; - -namespace C4Sharp.Sample.Structures; - -public static class People -{ - private static Person? _customer; - - public static Person Customer => _customer ??= new Person("customer", "Personal Banking Customer") - { - Description = "A customer of the bank, with personal bank accounts.", - Boundary = Boundary.External - }; - - private static Person? _internalCustomer; - public static Person InternalCustomer => _internalCustomer ??= new Person("internalcustomer", "Personal Banking Customer") - { - Description = "An internal customer of the bank, with personal bank accounts." - }; - - private static Person? _manager; - public static Person Manager => _manager ??= new Person("manager", "Manager Banking Customer") - { - Description = "A manager of the bank, with personal bank accounts." - }; -} diff --git a/samples/Basic/C4Sharp.Sample/Structures/Systems.cs b/samples/Basic/C4Sharp.Sample/Structures/Systems.cs deleted file mode 100644 index fb1a55b..0000000 --- a/samples/Basic/C4Sharp.Sample/Structures/Systems.cs +++ /dev/null @@ -1,41 +0,0 @@ -using C4Sharp.Diagrams; -using C4Sharp.Elements; -using C4Sharp.Elements.Relationships; -using C4Sharp.Sample.Diagrams; - -namespace C4Sharp.Sample.Structures; - -public static class Systems -{ - private static SoftwareSystem? _bankingSystem; - - public static SoftwareSystem BankingSystem => _bankingSystem ??= new SoftwareSystem( - "BankingSystem", - "Internet Banking System") - { - Description = "Allows customers to view information about their " + - "bank accounts, and make payments.", - Tags = new[] { "services" }, - }; - - private static SoftwareSystem? _mainframe; - - public static SoftwareSystem Mainframe => _mainframe ??= new SoftwareSystem( - "Mainframe", - "Mainframe Banking System") - { - Description = "Stores all of the core banking information about customers, " + - "accounts, transactions, etc.", - Boundary = Boundary.External - }; - - private static SoftwareSystem? _mailSystem; - - public static SoftwareSystem MailSystem => _mailSystem ??= new SoftwareSystem( - "MailSystem", - "E-mail system") - { - Description = "The internal Microsoft Exchange e-mail system.", - Boundary = Boundary.External - }; -} diff --git a/samples/ModelDiagrams/Diagrams/ComponentDiagramSample.cs b/samples/ModelDiagrams/Diagrams/ComponentDiagramSample.cs new file mode 100644 index 0000000..92a11ff --- /dev/null +++ b/samples/ModelDiagrams/Diagrams/ComponentDiagramSample.cs @@ -0,0 +1,42 @@ +using C4Sharp.Diagrams; +using C4Sharp.Diagrams.Builders; +using C4Sharp.Elements; +using C4Sharp.Elements.Relationships; +using static ModelDiagrams.Structures.Systems; +using static ModelDiagrams.Structures.Containers; +using static ModelDiagrams.Structures.Components; + +namespace ModelDiagrams.Diagrams; + +public class ComponentDiagramSample : ComponentDiagram +{ + protected override string Title => "Internet Banking System API Application"; + protected override DiagramLayout FlowVisualization => DiagramLayout.LeftRight; + + protected override IEnumerable Structures => new Structure[] + { + Spa, + MobileApp, + SqlDatabase, + Mainframe, + Boundary("c1", "API Application", + Sign, + Accounts, + Security, + MainframeFacade + ), + }; + + protected override IEnumerable Relationships => new Relationship[] + { + Sign > Security, + Accounts > MainframeFacade, + Security > SqlDatabase | ("Read & write to", "JDBC"), + MainframeFacade > Mainframe | ("Uses", "XML/HTTPS"), + + Spa > Sign | ("Uses", "JSON/HTTPS"), + Spa > Accounts | ("Uses", "JSON/HTTPS"), + MobileApp > Sign | ("Uses", "JSON/HTTPS"), + MobileApp > Accounts | ("Uses", "JSON/HTTPS") + }; +} \ No newline at end of file diff --git a/samples/ModelDiagrams/Diagrams/ContainerDiagramSample.cs b/samples/ModelDiagrams/Diagrams/ContainerDiagramSample.cs new file mode 100644 index 0000000..98e631a --- /dev/null +++ b/samples/ModelDiagrams/Diagrams/ContainerDiagramSample.cs @@ -0,0 +1,46 @@ +using C4Sharp.Diagrams.Builders; +using C4Sharp.Elements; +using C4Sharp.Elements.Relationships; + +using static ModelDiagrams.Structures.Systems; +using static ModelDiagrams.Structures.Containers; +using static ModelDiagrams.Structures.People; + +namespace ModelDiagrams.Diagrams; + +public class ContainerDiagramSample: ContainerDiagram +{ + protected override string Title => "Container diagram for Internet Banking System"; + + protected override IEnumerable Structures => new Structure[] + { + Customer, + BankingSystem, + MailSystem, + Boundary("c1", "Internet Banking", + WebApp, + Spa, + MobileApp, + SqlDatabase, + RabbitMq, + BackendApi + ) + }; + + protected override IEnumerable Relationships => new[] + { + Customer > WebApp | ("Uses", "HTTPS"), + Customer > Spa | ("Uses", "HTTPS"), + Customer > MobileApp | "Uses", + + WebApp > Spa | "Delivers" | Position.Neighbor, + Spa > BackendApi | ("Uses", "async, JSON/HTTPS"), + MobileApp > BackendApi | ("Uses", "async, JSON/HTTPS"), + SqlDatabase < BackendApi | ("Uses", "async, JSON/HTTPS") | Position.Neighbor, + RabbitMq < BackendApi | ("Uses", "async, JSON"), + + Customer < MailSystem | "Sends e-mails to", + MailSystem < BackendApi | ("Sends e-mails using", "sync, SMTP"), + BackendApi > BankingSystem | ("Uses", "sync/async, XML/HTTPS") | Position.Neighbor + }; +} \ No newline at end of file diff --git a/samples/ModelDiagrams/Diagrams/ContextDiagramSample.cs b/samples/ModelDiagrams/Diagrams/ContextDiagramSample.cs new file mode 100644 index 0000000..5a3911c --- /dev/null +++ b/samples/ModelDiagrams/Diagrams/ContextDiagramSample.cs @@ -0,0 +1,29 @@ +using C4Sharp.Diagrams.Builders; +using C4Sharp.Elements; +using C4Sharp.Elements.Relationships; +using static ModelDiagrams.Structures.People; +using static ModelDiagrams.Structures.Systems; +using static C4Sharp.Elements.Relationships.Position; + +namespace ModelDiagrams.Diagrams; + +public class ContextDiagramSample : ContextDiagram +{ + protected override string Title => "Component diagram for Internet Banking System"; + + protected override IEnumerable Structures => new Structure[] + { + Customer, + BankingSystem, + Mainframe, + MailSystem + }; + + 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/DeploymentDiagramSample.cs b/samples/ModelDiagrams/Diagrams/DeploymentDiagramSample.cs new file mode 100644 index 0000000..689f053 --- /dev/null +++ b/samples/ModelDiagrams/Diagrams/DeploymentDiagramSample.cs @@ -0,0 +1,33 @@ +using C4Sharp.Diagrams; +using C4Sharp.Diagrams.Builders; +using C4Sharp.Elements; +using C4Sharp.Elements.Relationships; +using ModelDiagrams.Structures; + +namespace ModelDiagrams.Diagrams; + +public class DeploymentDiagramSample: DeploymentDiagram +{ + protected override string Title => "System Context diagram for Internet Banking System"; + + protected override IEnumerable Structures => new Structure[] + { + Node("plc", "Big Bank plc", "Big Bank plc data center", + Nodes.Ubuntu("dn", "bigbank-api***\tx8", Nodes.ApacheTomCat("apache", Containers.BackendApi)), + Nodes.Ubuntu("bigbankdb01", "bigbank-db01", Nodes.OracleNode("oracle", Containers.OracleDatabase[1])), + Nodes.Ubuntu("bigbankdb02", "bigbank-db02", Nodes.OracleNode("oracle2", Containers.OracleDatabase["Data Reader"])), + Nodes.Ubuntu("bb2", "bigbank-web***\tx4", Nodes.ApacheTomCat("apache2", Containers.WebApp))), + Nodes.Ios("ios", Containers.MobileApp), + Nodes.PersonalComputer("computer", Nodes.Browser("browser", Containers.Spa)) + }; + + protected override IEnumerable Relationships => new[] + { + Containers.MobileApp > Containers.BackendApi | ("Makes API calls to", "json/HTTPS"), + Containers.Spa > Containers.BackendApi | ("Makes API calls to", "json/HTTPS"), + Containers.WebApp > Containers.Spa | "Delivers to the customer's web browser"| Position.Up, + Containers.BackendApi > Containers.OracleDatabase[1] | ("Writes to", "JDBC"), + Containers.BackendApi < Containers.OracleDatabase["Data Reader"] | ("Reads from", "JDBC"), + Containers.OracleDatabase[1] > Containers.OracleDatabase["Data Reader"] | ("Replicates data to", "JDBC") | Position.Right, + }; +} \ No newline at end of file diff --git a/samples/ModelDiagrams/Diagrams/EnterpriseDiagramSample.cs b/samples/ModelDiagrams/Diagrams/EnterpriseDiagramSample.cs new file mode 100644 index 0000000..1e47680 --- /dev/null +++ b/samples/ModelDiagrams/Diagrams/EnterpriseDiagramSample.cs @@ -0,0 +1,37 @@ +using C4Sharp.Diagrams.Builders; +using C4Sharp.Elements; +using C4Sharp.Elements.Relationships; +using ModelDiagrams.Structures; + +namespace ModelDiagrams.Diagrams; + +using static People; +using static Systems; +using static C4Sharp.Elements.Relationships.Position; + +public class EnterpriseDiagramSample: ContextDiagram +{ + protected override string Title => "System Enterprise diagram for Internet Banking System"; + + protected override IEnumerable Structures => new Structure[] + { + Customer, + Boundary("enterprise.boundary", "Domain A", + BankingSystem, + Boundary("enterprise.boundary.1", "Domain Internal Users", InternalCustomer), + Boundary("enterprise.boundary.2", "Domain Managers", Manager) + ), + Mainframe, + MailSystem + }; + + 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 diff --git a/samples/ModelDiagrams/Diagrams/SequenceDiagramSample.cs b/samples/ModelDiagrams/Diagrams/SequenceDiagramSample.cs new file mode 100644 index 0000000..e2ced7c --- /dev/null +++ b/samples/ModelDiagrams/Diagrams/SequenceDiagramSample.cs @@ -0,0 +1,33 @@ +using C4Sharp.Diagrams.Builders; +using C4Sharp.Elements; +using C4Sharp.Elements.Relationships; + +namespace ModelDiagrams.Diagrams; + +public class SequenceDiagramSample : SequenceDiagram +{ + protected override string Title => "Sequence diagram for Internet Banking System"; + + protected override IEnumerable Structures => new Structure[] + { + new Container("cA", "Single-Page Application", ContainerType.None, "JavaScript and Angular", + "Provides all of the Internet banking functionality to customers via their web browser."), + + Boundary("b", "Api Application", + new("cB", "Sign In Controller", ComponentType.None, "Spring MVC Rest Controller", + "Allows users to sign in to the Internet Banking System."), + new("cC", "Security Component", ComponentType.None, "Spring Bean", + "Provides functionality Related to signing in, changing passwords, etc.") + ), + + new Container("cD", "Database", ContainerType.Database, "Relational Database Schema", + "Stores user registration information, hashed authentication credentials, access logs, etc.") + }; + + protected override IEnumerable Relationships => new[] + { + It("cA") > It("cB") | ("Submits credentials to", "JSON/HTTPS"), + It("cB") > It("cC") | "Calls isAuthenticated() on", + It("cC") > It("cD") | ("select * from users where username = ?o", "JDBCS") + }; +} \ No newline at end of file diff --git a/samples/ModelDiagrams/ModelDiagrams.csproj b/samples/ModelDiagrams/ModelDiagrams.csproj new file mode 100644 index 0000000..eb9c49a --- /dev/null +++ b/samples/ModelDiagrams/ModelDiagrams.csproj @@ -0,0 +1,14 @@ + + + + Exe + net8.0 + enable + enable + + + + + + + diff --git a/samples/ModelDiagrams/Program.cs b/samples/ModelDiagrams/Program.cs new file mode 100644 index 0000000..e8f6adf --- /dev/null +++ b/samples/ModelDiagrams/Program.cs @@ -0,0 +1,19 @@ +// See https://aka.ms/new-console-template for more information + +using C4Sharp.Diagrams; +using C4Sharp.Diagrams.Plantuml; +using ModelDiagrams.Diagrams; + +var diagrams = new DiagramBuilder[] +{ + new ContextDiagramSample(), + new ComponentDiagramSample(), + new ContainerDiagramSample(), + new EnterpriseDiagramSample(), + new SequenceDiagramSample(), + new DeploymentDiagramSample() +}; + +new PlantumlContext() + .UseDiagramImageBuilder() + .Export(diagrams); \ No newline at end of file diff --git a/samples/ModelDiagrams/Structures/Components.cs b/samples/ModelDiagrams/Structures/Components.cs new file mode 100644 index 0000000..34a336e --- /dev/null +++ b/samples/ModelDiagrams/Structures/Components.cs @@ -0,0 +1,18 @@ +using C4Sharp.Elements; + +namespace ModelDiagrams.Structures; + +public static class Components +{ + public static Component Sign => + new ("sign", "Sign In Controller", "MVC Controller", "Allows users to sign in to the internet banking system"); + + public static Component Accounts => + new ("accounts", "Accounts Summary Controller", "MVC Controller", "Provides customers with a summary of their bank accounts"); + + public static Component Security => + new ("security", "Security Component", "Spring Bean", "Provides functionality related to singing in, changing passwords, etc."); + + public static Component MainframeFacade => + new ("mbsfacade", "Mainframe Banking System Facade", "Spring Bean", "A facade onto the mainframe banking system."); +} diff --git a/samples/Basic/C4Sharp.Sample/Structures/Containers.cs b/samples/ModelDiagrams/Structures/Containers.cs similarity index 62% rename from samples/Basic/C4Sharp.Sample/Structures/Containers.cs rename to samples/ModelDiagrams/Structures/Containers.cs index 2a49ece..b2ea490 100644 --- a/samples/Basic/C4Sharp.Sample/Structures/Containers.cs +++ b/samples/ModelDiagrams/Structures/Containers.cs @@ -1,32 +1,24 @@ -using System.Reflection.Emit; -using C4Sharp.Elements; using C4Sharp.Elements.Containers; -namespace C4Sharp.Sample.Structures; +namespace ModelDiagrams.Structures; public static class Containers { - private static ServerSideWebApp? _webApp; - - public static ServerSideWebApp WebApp => _webApp ??= new ServerSideWebApp( + public static ServerSideWebApp WebApp => new ( Alias: "Corporate.Finance.Limits.Service.ServiceBus", Label: "WebApp", Description: "Delivers the static content and the Internet banking SPA", Technology: "C#, WebApi" ); - private static ClientSideWebApp? _spa; - - public static ClientSideWebApp Spa => _spa ??= new ClientSideWebApp( + public static ClientSideWebApp Spa => new ( Alias: "Spa", Label: "SPA", Technology: "JavaScript, Angular", Description: "Provides all the Internet banking functionality to customers via their web browser" ); - private static Mobile? _mobileApp; - - public static Mobile MobileApp => _mobileApp ??= new Mobile( + public static Mobile MobileApp => new ( Alias: "MobileApp", Label: "MobileApp", Description: @@ -34,36 +26,28 @@ public static class Containers Technology: "C#, Xamarin" ); - private static Database? _sqlDatabase; - - public static Database SqlDatabase => _sqlDatabase ??= new Database( + public static Database SqlDatabase => new ( Alias: "Database", Label: "SqlDatabase", Description: "Stores user registration information, hashed auth credentials, access logs, etc.", Technology: "SQL Database" ); - private static Queue? _rabbitMq = null; - - public static Queue RabbitMq => _rabbitMq ?? new Queue( + public static Queue RabbitMq => new ( Alias: "Queue", Label: "RabbitMQ", Description: "Stores user registration information, hashed auth credentials, access logs, etc.", Technology: "RabbitMQ" ); - private static Database? _oracleDatabase; - - public static Database OracleDatabase => _oracleDatabase ??= new Database( + public static Database OracleDatabase => new ( Alias: "Database", Label: "OracleDatabase", Description: "Stores user registration information, hashed auth credentials, access logs, etc.", Technology: "Oracle Database" ); - private static Api? _backendApi; - - public static Api BackendApi => _backendApi ??= new Api( + public static Api BackendApi => new( Alias: "BackendApi", Label: "BackendApi", Description: "Provides Internet banking functionality via API.", diff --git a/samples/Basic/C4Sharp.Sample/Structures/Nodes.cs b/samples/ModelDiagrams/Structures/Nodes.cs similarity index 97% rename from samples/Basic/C4Sharp.Sample/Structures/Nodes.cs rename to samples/ModelDiagrams/Structures/Nodes.cs index a137992..699cf1b 100644 --- a/samples/Basic/C4Sharp.Sample/Structures/Nodes.cs +++ b/samples/ModelDiagrams/Structures/Nodes.cs @@ -1,6 +1,6 @@ using C4Sharp.Elements; -namespace C4Sharp.Sample.Structures; +namespace ModelDiagrams.Structures; public static class Nodes { diff --git a/samples/ModelDiagrams/Structures/People.cs b/samples/ModelDiagrams/Structures/People.cs new file mode 100644 index 0000000..60bd52c --- /dev/null +++ b/samples/ModelDiagrams/Structures/People.cs @@ -0,0 +1,16 @@ +using C4Sharp.Elements; +using C4Sharp.Elements.Relationships; + +namespace ModelDiagrams.Structures; + +public static class People +{ + public static Person Customer => + new ("customer", "Personal Banking Customer", "A customer of the bank, with personal bank accounts.", Boundary.External); + + public static Person InternalCustomer => + new Person("internalcustomer", "Personal Banking Customer", "An internal customer of the bank, with personal bank accounts."); + + public static Person Manager => + new ("manager", "Manager Banking Customer", "A manager of the bank, with personal bank accounts."); +} diff --git a/samples/ModelDiagrams/Structures/Systems.cs b/samples/ModelDiagrams/Structures/Systems.cs new file mode 100644 index 0000000..11a8097 --- /dev/null +++ b/samples/ModelDiagrams/Structures/Systems.cs @@ -0,0 +1,18 @@ +using C4Sharp.Elements; +using C4Sharp.Elements.Relationships; + +namespace ModelDiagrams.Structures; + +public static class Systems +{ + public static SoftwareSystem BankingSystem => + new("BankingSystem", "Internet Banking System", + "Allows customers to view information about their bank accounts, and make payments."); + + public static SoftwareSystem Mainframe => + new("Mainframe", "Mainframe Banking System", + "Stores all of the core banking information about customers, accounts, transactions, etc.", Boundary.External); + + public static SoftwareSystem MailSystem => + new ("MailSystem", "E-mail system", "The internal Microsoft Exchange e-mail system.", Boundary.External); +} diff --git a/src/C4Sharp.Tools/C4Sharp.Tools.csproj b/src/C4Sharp.Tools/C4Sharp.Tools.csproj index 4f50b30..6d838aa 100644 --- a/src/C4Sharp.Tools/C4Sharp.Tools.csproj +++ b/src/C4Sharp.Tools/C4Sharp.Tools.csproj @@ -14,7 +14,7 @@ https://github.com/8T4/c4sharp git c4, diagrams - 2.2.0 + 2.3.0 https://github.com/8T4/c4sharp/blob/main/LICENSE true true diff --git a/src/C4Sharp.Tools/Commands/BuildCommand.cs b/src/C4Sharp.Tools/Commands/BuildCommand.cs index d9da8f7..87f9667 100644 --- a/src/C4Sharp.Tools/Commands/BuildCommand.cs +++ b/src/C4Sharp.Tools/Commands/BuildCommand.cs @@ -121,14 +121,14 @@ private static async Task RunDotnetBuild(string slnPath) /// /// /// - private static async Task> StartAnalysis(MSBuildWorkspace workspace, + private static async Task> StartAnalysis(MSBuildWorkspace workspace, string slnPath) { ColorConsole.WriteLine("Starting analysis".White()); var solution = await workspace.OpenSolutionAsync(slnPath); - var result = new List(); + var result = new List(); foreach (var project in solution.Projects) { ColorConsole.WriteLine("Analyzing project: ".White(), project.Name.Green()); @@ -139,11 +139,11 @@ private static async Task> StartAnalysis(MSBuil continue; } - var type = typeof(IDiagramBuildRunner); + var type = typeof(IDiagramBuilder); var runners = Assembly.LoadFrom(project.OutputFilePath).GetTypes() - .Where(p => type.IsAssignableFrom(p) && p.IsClass && p != typeof(DiagramBuildRunner)) - .Select(r => (IDiagramBuildRunner)Activator.CreateInstance(r)!).ToArray(); + .Where(p => type.IsAssignableFrom(p) && p.IsClass && p != typeof(DiagramBuilder)) + .Select(r => (IDiagramBuilder)Activator.CreateInstance(r)!).ToArray(); if (!runners.Any()) { @@ -164,7 +164,7 @@ private static async Task> StartAnalysis(MSBuil /// /// /// - private static void GenerateC4Diagrams(IEnumerable runners, string? ouput, string? doc) + private static void GenerateC4Diagrams(IEnumerable runners, string? ouput, string? doc) { var path = Path.Combine(string.IsNullOrEmpty(ouput) ? Environment.CurrentDirectory @@ -179,7 +179,7 @@ private static void GenerateC4Diagrams(IEnumerable runners, .UseDiagramMermaidBuilder() .UseDiagramSvgImageBuilder(); - context.Export(directory, runners.Select(r => r.Build())); + context.Export(directory, runners); PrintFileList(directory, "png"); PrintFileList(directory, "svg"); diff --git a/src/C4Sharp/C4Sharp.csproj b/src/C4Sharp/C4Sharp.csproj index d2609b1..142bb57 100644 --- a/src/C4Sharp/C4Sharp.csproj +++ b/src/C4Sharp/C4Sharp.csproj @@ -11,7 +11,7 @@ https://github.com/8T4/c4sharp git c4, diagrams - 6.2.0 + 6.3.0 https://github.com/8T4/c4sharp/blob/main/LICENSE true true diff --git a/src/C4Sharp/Diagrams/Builders/ComponentDiagram.cs b/src/C4Sharp/Diagrams/Builders/ComponentDiagram.cs new file mode 100644 index 0000000..e5b9f0c --- /dev/null +++ b/src/C4Sharp/Diagrams/Builders/ComponentDiagram.cs @@ -0,0 +1,14 @@ +using C4Sharp.Elements; +using C4Sharp.Elements.Boundaries; +using C4Sharp.Elements.Relationships; + +namespace C4Sharp.Diagrams.Builders; + +public abstract class ComponentDiagram: DiagramBuilder +{ + protected override string Title { get; } = "Component Diagram"; + protected override DiagramType DiagramType { get; } = DiagramType.Component; + + protected ContainerBoundary Boundary(string tag, string name, params Component[] components) + => new(tag, name, components); +} \ No newline at end of file diff --git a/src/C4Sharp/Diagrams/Builders/ContainerDiagram.cs b/src/C4Sharp/Diagrams/Builders/ContainerDiagram.cs new file mode 100644 index 0000000..e4fcead --- /dev/null +++ b/src/C4Sharp/Diagrams/Builders/ContainerDiagram.cs @@ -0,0 +1,13 @@ +using C4Sharp.Elements; +using C4Sharp.Elements.Boundaries; + +namespace C4Sharp.Diagrams.Builders; + +public abstract class ContainerDiagram: DiagramBuilder +{ + protected override string Title { get; } = "Container Diagram"; + protected override DiagramType DiagramType { get; } = DiagramType.Container; + + protected SoftwareSystemBoundary Boundary(string tag, string name, params Container[] components) + => new(tag, name, components); +} \ No newline at end of file diff --git a/src/C4Sharp/Diagrams/Builders/ContextDiagram.cs b/src/C4Sharp/Diagrams/Builders/ContextDiagram.cs new file mode 100644 index 0000000..98306df --- /dev/null +++ b/src/C4Sharp/Diagrams/Builders/ContextDiagram.cs @@ -0,0 +1,13 @@ +using C4Sharp.Elements; +using C4Sharp.Elements.Boundaries; + +namespace C4Sharp.Diagrams.Builders; + +public abstract class ContextDiagram: DiagramBuilder +{ + protected override string Title { get; } = "Context Diagram"; + protected override DiagramType DiagramType { get; } = DiagramType.Component; + + protected EnterpriseBoundary Boundary(string alias, string label, params Structure[] structures) => + new(alias, label, structures); +} \ No newline at end of file diff --git a/src/C4Sharp/Diagrams/Builders/DeploymentDiagram.cs b/src/C4Sharp/Diagrams/Builders/DeploymentDiagram.cs new file mode 100644 index 0000000..6a77e68 --- /dev/null +++ b/src/C4Sharp/Diagrams/Builders/DeploymentDiagram.cs @@ -0,0 +1,15 @@ +using C4Sharp.Elements; + +namespace C4Sharp.Diagrams.Builders; + +public abstract class DeploymentDiagram: DiagramBuilder +{ + protected override string Title { get; } = "Deployment Diagram"; + protected override DiagramType DiagramType { get; } = DiagramType.Deployment; + + protected DeploymentNode Node(string alias, string label, params DeploymentNode[] nodes) => + new(alias, label, nodes); + + protected DeploymentNode Node(string alias, string label, string description, params DeploymentNode[] nodes) => + new(alias, label, nodes) {Description = description}; +} \ No newline at end of file diff --git a/src/C4Sharp/Diagrams/Builders/SequenceDiagram.cs b/src/C4Sharp/Diagrams/Builders/SequenceDiagram.cs new file mode 100644 index 0000000..2f27805 --- /dev/null +++ b/src/C4Sharp/Diagrams/Builders/SequenceDiagram.cs @@ -0,0 +1,13 @@ +using C4Sharp.Elements; +using C4Sharp.Elements.Boundaries; + +namespace C4Sharp.Diagrams.Builders; + +public abstract class SequenceDiagram: DiagramBuilder +{ + protected override string Title { get; } = "Sequence Diagram"; + protected override DiagramType DiagramType { get; } = DiagramType.Sequence; + + protected SequenceContainerBoundary Boundary(string alias, string label, params Component[] structures) => + new(alias, label, structures); +} \ No newline at end of file diff --git a/src/C4Sharp/Diagrams/DiagramBuildRunner.cs b/src/C4Sharp/Diagrams/DiagramBuilder.cs similarity index 71% rename from src/C4Sharp/Diagrams/DiagramBuildRunner.cs rename to src/C4Sharp/Diagrams/DiagramBuilder.cs index e839663..85595b1 100644 --- a/src/C4Sharp/Diagrams/DiagramBuildRunner.cs +++ b/src/C4Sharp/Diagrams/DiagramBuilder.cs @@ -4,30 +4,53 @@ namespace C4Sharp.Diagrams; -public abstract class DiagramBuildRunner : IDiagramBuildRunner +[Obsolete("This class is obsolete, use DiagramBuilder instead.")] +public abstract class DiagramBuildRunner : DiagramBuilder { } + +/// +/// Base class to build diagrams +/// +public abstract partial class DiagramBuilder : IDiagramBuilder { - private readonly StructureCollection _structures; + private readonly StructureCollection _structures = new(); - protected virtual bool LayoutWithLegend { get; } - protected virtual bool ShowLegend { get; } - protected virtual bool LayoutAsSketch { get; } - protected virtual DiagramLayout FlowVisualization { get; } + protected virtual bool LayoutWithLegend { get; } = false; + protected virtual bool ShowLegend { get; } = false; + protected virtual bool LayoutAsSketch { get; } = false; + protected virtual DiagramLayout FlowVisualization { get; } = DiagramLayout.TopDown; protected abstract string Title { get; } - protected virtual string Description { get; } + protected virtual string Description { get; } = string.Empty; protected abstract DiagramType DiagramType { get; } protected abstract IEnumerable Structures { get; } - protected abstract IEnumerable Relationships { get; } - - protected DiagramBuildRunner() + protected abstract IEnumerable Relationships { get; } + + + public Diagram Build() { - _structures = new StructureCollection(); - LayoutWithLegend = false; - Description = string.Empty; - ShowLegend = false; - LayoutAsSketch = false; - FlowVisualization = DiagramLayout.TopDown; + _structures.AddRange(Structures); + + return new Diagram(DiagramType) with + { + Structures = Structures, + Relationships = Relationships, + Title = Title, + ShowLegend = ShowLegend, + Description = Description, + LayoutWithLegend = LayoutWithLegend, + LayoutAsSketch = LayoutAsSketch, + FlowVisualization = FlowVisualization, + Tags = SetTags(), + RelTags = SetRelTags(), + Style = SetStyle() + }; } +} +/// +/// Custom methods to build diagrams +/// +public abstract partial class DiagramBuilder +{ public Structure It() => It(StructureIdentity.New().Value); public Structure It(int instance) => It(StructureIdentity.New(instance.ToString()).Value); public Structure It(string instance) => It(StructureIdentity.New(instance).Value); @@ -47,24 +70,4 @@ public Structure It(string key, string instance) protected virtual IElementStyle? SetStyle() => null; protected virtual IElementTag? SetTags() => null; protected virtual IRelationshipTag? SetRelTags() => null; - - public Diagram Build() - { - _structures.AddRange(Structures); - - return new Diagram(DiagramType) with - { - Structures = Structures, - Relationships = Relationships, - Title = Title, - ShowLegend = ShowLegend, - Description = Description, - LayoutWithLegend = LayoutWithLegend, - LayoutAsSketch = LayoutAsSketch, - FlowVisualization = FlowVisualization, - Tags = SetTags(), - RelTags = SetRelTags(), - Style = SetStyle() - }; - } } \ No newline at end of file diff --git a/src/C4Sharp/Diagrams/Interfaces/IDiagramBuildRunner.cs b/src/C4Sharp/Diagrams/Interfaces/IDiagramBuildRunner.cs deleted file mode 100644 index 0238331..0000000 --- a/src/C4Sharp/Diagrams/Interfaces/IDiagramBuildRunner.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace C4Sharp.Diagrams.Interfaces; - -public interface IDiagramBuildRunner -{ - Diagram Build(); -} \ No newline at end of file diff --git a/src/C4Sharp/Diagrams/Interfaces/IDiagramBuilder.cs b/src/C4Sharp/Diagrams/Interfaces/IDiagramBuilder.cs new file mode 100644 index 0000000..3582aa7 --- /dev/null +++ b/src/C4Sharp/Diagrams/Interfaces/IDiagramBuilder.cs @@ -0,0 +1,12 @@ +namespace C4Sharp.Diagrams.Interfaces; + +[Obsolete("This interface is obsolete, use IDiagramBuilder instead")] +public interface IDiagramBuildRunner +{ + Diagram Build(); +} + +public interface IDiagramBuilder +{ + Diagram Build(); +} \ No newline at end of file diff --git a/src/C4Sharp/Diagrams/Plantuml/PlantumlContext.cs b/src/C4Sharp/Diagrams/Plantuml/PlantumlContext.cs index 8bbcaf1..7214829 100644 --- a/src/C4Sharp/Diagrams/Plantuml/PlantumlContext.cs +++ b/src/C4Sharp/Diagrams/Plantuml/PlantumlContext.cs @@ -1,6 +1,7 @@ using System.Diagnostics; using System.Text; using C4Sharp.Commons.FileSystem; +using C4Sharp.Diagrams.Interfaces; namespace C4Sharp.Diagrams.Plantuml; @@ -78,6 +79,15 @@ public PlantumlContext UseDiagramMermaidBuilder() return this; } + /// + /// It creates a Puml file into the default directory "./c4" + /// If the attribute of Session GenerateDiagramImages is true + /// It generates png files of the diagram + /// + /// C4 Diagrams + public void Export(IEnumerable diagrams) => + Export(diagrams.Select(d => d.Build())); + /// /// It creates a Puml file into the default directory "./c4" /// If the attribute of Session GenerateDiagramImages is true @@ -91,6 +101,21 @@ public void Export(IEnumerable diagrams) Export(path, diagrams); } + /// + /// It creates a Puml file into the default directory "./c4" + /// If the attribute of Session GenerateDiagramImages is true + /// It generates png files of the diagram + /// + /// C4 Diagrams + /// + /// Full path of the directory + /// For windows.: C:\users\user\projects\ + /// For Unix.: users/user/projects/ + /// + /// ReSharper disable once MemberCanBePrivate.Global + public void Export(string path, IEnumerable diagrams) => + Export(path, diagrams.Select(d => d.Build())); + /// /// It creates a Puml file into the default directory "./c4" /// If the attribute of Session GenerateDiagramImages is true diff --git a/src/C4Sharp/Diagrams/Plantuml/Style/ElementStyle.cs b/src/C4Sharp/Diagrams/Plantuml/Style/ElementStyle.cs index 7122aa6..59f2596 100644 --- a/src/C4Sharp/Diagrams/Plantuml/Style/ElementStyle.cs +++ b/src/C4Sharp/Diagrams/Plantuml/Style/ElementStyle.cs @@ -20,7 +20,9 @@ public class ElementStyle : IElementStyle /// /// /// - public ElementStyle UpdateElementStyle(ElementName elementName, string? bgColor = null, string? fontColor = null, string? borderColor = null , bool shadowing = false, Shape? shape = null, BorderStyle? borderStyle = null, int? borderThickness = null) + public ElementStyle UpdateElementStyle(ElementName elementName, string? bgColor = null, string? fontColor = null, + string? borderColor = null, bool shadowing = false, Shape? shape = null, BorderStyle? borderStyle = null, + int? borderThickness = null) { if (elementName is null) throw new ArgumentNullException(nameof(elementName), $"{nameof(elementName)} is required"); @@ -28,18 +30,18 @@ public ElementStyle UpdateElementStyle(ElementName elementName, string? bgColor var styles = new List(); if (fontColor is not null) styles.Add($"$bgColor={bgColor}"); - + if (bgColor is not null) - styles.Add($"$fontColor={fontColor}"); - + styles.Add($"$fontColor={fontColor}"); + if (borderColor is not null) - styles.Add($"$borderColor={borderColor}"); - + styles.Add($"$borderColor={borderColor}"); + styles.Add($"$shadowing=\"{shadowing.ToString().ToLower()}\""); - + if (shape is not null) styles.Add($"$shape={shape.Value}"); - + if (borderStyle is not null) styles.Add($"borderStyle={borderStyle.Value}"); @@ -49,4 +51,38 @@ public ElementStyle UpdateElementStyle(ElementName elementName, string? bgColor Items[elementName.Name] = $"UpdateElementStyle(\"{elementName.Name}\", {string.Join(",", styles)})"; return this; } -} + + public ElementStyle UpdateBoundaryStyle(ElementName elementName, string? bgColor = null, string? fontColor = null, + string? borderColor = null, bool shadowing = false, Shape? shape = null, BorderStyle? borderStyle = null, + int? borderThickness = null) + { + if (elementName is null) + throw new ArgumentNullException(nameof(elementName), $"{nameof(elementName)} is required"); + + var styles = new List(); + styles.Add($"$elementName={elementName.Name}"); + + if (fontColor is not null) + styles.Add($"$bgColor={bgColor}"); + + if (bgColor is not null) + styles.Add($"$fontColor={fontColor}"); + + if (borderColor is not null) + styles.Add($"$borderColor={borderColor}"); + + styles.Add($"$shadowing=\"{shadowing.ToString().ToLower()}\""); + + if (shape is not null) + styles.Add($"$shape={shape.Value}"); + + if (borderStyle is not null) + styles.Add($"borderStyle={borderStyle.Value}"); + + if (borderThickness is not null) + styles.Add($"$borderThickness={borderThickness}"); + + Items[elementName.Name] = $"UpdateBoundaryStyle({string.Join(",", styles)})"; + return this; + } +} \ No newline at end of file diff --git a/src/C4Sharp/Diagrams/Themes/Paradiso.cs b/src/C4Sharp/Diagrams/Themes/Paradiso.cs new file mode 100644 index 0000000..f82fafb --- /dev/null +++ b/src/C4Sharp/Diagrams/Themes/Paradiso.cs @@ -0,0 +1,6 @@ +namespace C4Sharp.Diagrams.Themes; + +public static class Paradiso +{ + +} \ No newline at end of file diff --git a/src/C4Sharp/Elements/Boundaries/ContainerBoundary.cs b/src/C4Sharp/Elements/Boundaries/ContainerBoundary.cs index 59b8dd7..2c73477 100644 --- a/src/C4Sharp/Elements/Boundaries/ContainerBoundary.cs +++ b/src/C4Sharp/Elements/Boundaries/ContainerBoundary.cs @@ -12,6 +12,11 @@ public ContainerBoundary(string alias, string label):base(alias, label) { } + public ContainerBoundary(string alias, string label, params Component[] components):base(alias, label) + { + Components = components; + } + public ContainerBoundary(StructureIdentity alias, string label):base(alias, label) { } diff --git a/src/C4Sharp/Elements/Boundaries/SequenceContainerBoundary.cs b/src/C4Sharp/Elements/Boundaries/SequenceContainerBoundary.cs index 72157fb..c538aba 100644 --- a/src/C4Sharp/Elements/Boundaries/SequenceContainerBoundary.cs +++ b/src/C4Sharp/Elements/Boundaries/SequenceContainerBoundary.cs @@ -5,17 +5,8 @@ namespace C4Sharp.Elements.Boundaries; /// /// Container Boundary /// -public record SequenceContainerBoundary: Structure, IBoundary +public record SequenceContainerBoundary(string Alias, string Lablel, params Component[] Components): Structure(Alias, Lablel), IBoundary { - public SequenceContainerBoundary(string alias, string label):base(alias, label) - { - } - - public SequenceContainerBoundary(StructureIdentity alias, string label):base(alias, label) - { - } - - public IEnumerable Components { get; init; } = Array.Empty(); public Structure[] GetBoundaryStructures() => Components.Select(x => x as Structure).ToArray(); } diff --git a/src/C4Sharp/Elements/DeploymentNode.cs b/src/C4Sharp/Elements/DeploymentNode.cs index b51937c..f81c780 100644 --- a/src/C4Sharp/Elements/DeploymentNode.cs +++ b/src/C4Sharp/Elements/DeploymentNode.cs @@ -7,9 +7,8 @@ namespace C4Sharp.Elements; /// server, Microsoft IIS), etc. Deployment nodes can be nested. /// /// -public sealed record DeploymentNode(string Alias, string Label) : Structure(Alias, Label) +public sealed record DeploymentNode(string Alias, string Label, params DeploymentNode[] Nodes) : Structure(Alias, Label) { - public IEnumerable Nodes { get; init; } = Array.Empty(); public Dictionary Properties { get; init; } = new(); public Container? Container { get; init; } } diff --git a/src/C4Sharp/Elements/StructureCollection.cs b/src/C4Sharp/Elements/StructureCollection.cs index 0b1c6f0..282d213 100644 --- a/src/C4Sharp/Elements/StructureCollection.cs +++ b/src/C4Sharp/Elements/StructureCollection.cs @@ -4,12 +4,7 @@ namespace C4Sharp.Elements; internal class StructureCollection { - public IDictionary Items { get; } - - public StructureCollection() - { - Items = new Dictionary(); - } + public IDictionary Items { get; } = new Dictionary(); public void AddRange(IEnumerable structures) { @@ -36,5 +31,5 @@ private void Add(Structure structure) } Items[structure.Alias] = structure; - } + } } \ No newline at end of file diff --git a/tests/C4Sharp.IntegratedTests/C4Sharp.IntegratedTests.csproj b/tests/C4Sharp.IntegratedTests/C4Sharp.IntegratedTests.csproj deleted file mode 100644 index 848f155..0000000 --- a/tests/C4Sharp.IntegratedTests/C4Sharp.IntegratedTests.csproj +++ /dev/null @@ -1,28 +0,0 @@ - - - - net6.0 - - false - - - - - - - - runtime; build; native; contentfiles; analyzers; buildtransitive - all - - - runtime; build; native; contentfiles; analyzers; buildtransitive - all - - - - - - - - - diff --git a/tests/C4Sharp.IntegratedTests/ExportingDiagramFixture.cs b/tests/C4Sharp.IntegratedTests/ExportingDiagramFixture.cs deleted file mode 100644 index a2eaa3b..0000000 --- a/tests/C4Sharp.IntegratedTests/ExportingDiagramFixture.cs +++ /dev/null @@ -1,116 +0,0 @@ -using FluentAssertions; - -namespace C4Sharp.IntegratedTests; - -public class ExportingDiagramFixture -{ - protected static void Setup(string path = "c4") - { - if (path is not null && !Directory.Exists(path)) - { - Directory.CreateDirectory(path); - } - } - - protected static void CleanUp(string path = "c4") - { - if (Directory.Exists(path)) - { - Directory.Delete(path, true); - } - } - - protected static void VerifyIfResourceFilesExists(string path = "c4") - { - var files = new[] - { - Path.Join(path, "..", ".c4s", "C4.puml"), - Path.Join(path, "..", ".c4s", "C4_Component.puml"), - Path.Join(path, "..", ".c4s", "C4_Context.puml"), - Path.Join(path, "..", ".c4s", "C4_Container.puml"), - Path.Join(path, "..", ".c4s", "C4_Deployment.puml"), - }; - - VerifyIfFilesExists(files); - } - - protected static void VerifyIfPumlFilesExists(string diagramName, string path = "c4") - { - var files = new[] - { - Path.Join(path, $"{diagramName}-c4component.puml"), - Path.Join(path, $"{diagramName}-c4context.puml"), - Path.Join(path, $"{diagramName}-c4container.puml"), - Path.Join(path, $"{diagramName}-c4deployment.puml") - }; - - VerifyIfFilesExists(files); - } - - protected static void VerifyIfPngFilesExists(string diagramName, string path = "c4") - { - var files = new[] - { - Path.Join(path, $"{diagramName}-c4component.png"), - Path.Join(path, $"{diagramName}-c4context.png"), - Path.Join(path, $"{diagramName}-c4container.png"), - Path.Join(path, $"{diagramName}-c4deployment.png") - }; - - VerifyIfFilesExists(files); - } - - protected static void VerifyIfSvgFilesExists(string diagramName, string path = "c4") - { - var files = new[] - { - Path.Join(path, $"{diagramName}-c4component.svg"), - Path.Join(path, $"{diagramName}-c4context.svg"), - Path.Join(path, $"{diagramName}-c4container.svg"), - Path.Join(path, $"{diagramName}-c4deployment.svg") - }; - - VerifyIfFilesExists(files); - } - protected static void VerifyIfPngFilesNonExists(string diagramName, string path = "c4") - { - var files = new[] - { - Path.Join(path, $"{diagramName}-c4component.png"), - Path.Join(path, $"{diagramName}-c4context.png"), - Path.Join(path, $"{diagramName}-c4container.png"), - Path.Join(path, $"{diagramName}-c4deployment.png") - }; - - VerifyIfFilesNonExists(files); - } - - protected static void VerifyIfSvgFilesNonExists(string diagramName, string path = "c4") - { - var files = new[] - { - Path.Join(path, $"{diagramName}-c4component.svg"), - Path.Join(path, $"{diagramName}-c4context.svg"), - Path.Join(path, $"{diagramName}-c4container.svg"), - Path.Join(path, $"{diagramName}-c4deployment.svg") - }; - - VerifyIfFilesNonExists(files); - } - - private static void VerifyIfFilesExists(params string[] path) - { - foreach (var file in path) - { - File.Exists(file).Should().BeTrue(); - } - } - - private static void VerifyIfFilesNonExists(params string[] path) - { - foreach (var file in path) - { - File.Exists(file).Should().BeFalse(); - } - } -} diff --git a/tests/C4Sharp.IntegratedTests/ExportingDiagramTests.cs b/tests/C4Sharp.IntegratedTests/ExportingDiagramTests.cs deleted file mode 100644 index a9324fe..0000000 --- a/tests/C4Sharp.IntegratedTests/ExportingDiagramTests.cs +++ /dev/null @@ -1,132 +0,0 @@ -using C4Sharp.Diagrams; -using C4Sharp.Diagrams.Plantuml; -using Xunit; -using ComponentDiagram = C4Sharp.Sample.Diagrams.ComponentDiagram; -using ContainerDiagram = C4Sharp.Sample.Diagrams.ContainerDiagram; -using ContextDiagram = C4Sharp.Sample.Diagrams.ContextDiagram; -using DeploymentDiagram = C4Sharp.Sample.Diagrams.DeploymentDiagram; - -namespace C4Sharp.IntegratedTests; - -public class ExportingDiagramTests : ExportingDiagramFixture, IAsyncLifetime -{ - [Fact] - public void TestExportWithoutImages() - { - var diagrams = new Diagram[] - { - new ContextDiagram().Build() with { Title = "Diagram" }, - new ContainerDiagram().Build() with { Title = "Diagram" }, - new ComponentDiagram().Build() with { Title = "Diagram" }, - new DeploymentDiagram().Build() with { Title = "Diagram" } - }; - - new PlantumlContext().Export(diagrams); - - VerifyIfResourceFilesExists(); - VerifyIfPumlFilesExists("diagram"); - VerifyIfPngFilesNonExists("diagram"); - } - - [Fact] - public void TestExportToSpecifiedPath() - { - const string path = "c4temp"; - Setup(path); - - var diagrams = new Diagram[] - { - new ContextDiagram().Build() with { Title = "Diagram" }, - new ContainerDiagram().Build() with { Title = "Diagram" }, - new ComponentDiagram().Build() with { Title = "Diagram" }, - new DeploymentDiagram().Build() with { Title = "Diagram" } - }; - - var pathSave = new DirectoryInfo(path).FullName; - new PlantumlContext() - .UseDiagramImageBuilder() - .Export(pathSave, diagrams); - - VerifyIfResourceFilesExists(path); - VerifyIfPumlFilesExists("diagram", path); - VerifyIfPngFilesExists("diagram", path); - - CleanUp(path); - } - - [Fact] - public void TestExportOnlyPngToDefaultPath() - { - var diagrams = new Diagram[] - { - new ContextDiagram().Build() with { Title = "Diagram" }, - new ContainerDiagram().Build() with { Title = "Diagram" }, - new ComponentDiagram().Build() with { Title = "Diagram" }, - new DeploymentDiagram().Build() with { Title = "Diagram" } - }; - - new PlantumlContext() - .UseDiagramImageBuilder() - .Export(diagrams); - - VerifyIfResourceFilesExists(); - VerifyIfPumlFilesExists("diagram"); - VerifyIfPngFilesExists("diagram"); - VerifyIfSvgFilesNonExists("diagram"); - } - - [Fact] - public void TestExportOnlySvgToDefaultPath() - { - var diagrams = new Diagram[] - { - new ContextDiagram().Build() with { Title = "Diagram" }, - new ContainerDiagram().Build() with { Title = "Diagram" }, - new ComponentDiagram().Build() with { Title = "Diagram" }, - new DeploymentDiagram().Build() with { Title = "Diagram" } - }; - - new PlantumlContext() - .UseDiagramSvgImageBuilder() - .Export(diagrams); - - VerifyIfResourceFilesExists(); - VerifyIfPumlFilesExists("diagram"); - VerifyIfPngFilesNonExists("diagram"); - VerifyIfSvgFilesExists("diagram"); - } - - [Fact] - public void TestExportPngAndSvgToDefaultPath() - { - var diagrams = new Diagram[] - { - new ContextDiagram().Build() with { Title = "Diagram" }, - new ContainerDiagram().Build() with { Title = "Diagram" }, - new ComponentDiagram().Build() with { Title = "Diagram" }, - new DeploymentDiagram().Build() with { Title = "Diagram" } - }; - - new PlantumlContext() - .UseDiagramImageBuilder() - .UseDiagramSvgImageBuilder() - .Export(diagrams); - - VerifyIfResourceFilesExists(); - VerifyIfPumlFilesExists("diagram"); - VerifyIfPngFilesExists("diagram"); - VerifyIfSvgFilesExists("diagram"); - } - - public Task InitializeAsync() - { - Setup(); - return Task.CompletedTask; - } - - public Task DisposeAsync() - { - CleanUp(); - return Task.CompletedTask; - } -} diff --git a/tests/Directory.Build.props b/tests/Directory.Build.props deleted file mode 100644 index a279946..0000000 --- a/tests/Directory.Build.props +++ /dev/null @@ -1,6 +0,0 @@ - - - 10 - true - -