diff --git a/.github/workflows/dotnet.yml b/.github/workflows/dotnet.yml
index a45d4d3..cdd2716 100644
--- a/.github/workflows/dotnet.yml
+++ b/.github/workflows/dotnet.yml
@@ -7,7 +7,7 @@ on:
branches: [ main ]
env:
- VERSION: 3.1.${{ github.run_number }}
+ VERSION: 3.2.${{ github.run_number }}
NUGET_INDEX: https://api.nuget.org/v3/index.json
BUILD_TYPE: Release
diff --git a/src/components/C4Sharp/C4Sharp.csproj b/src/components/C4Sharp/C4Sharp.csproj
index 4b9735b..beba49d 100644
--- a/src/components/C4Sharp/C4Sharp.csproj
+++ b/src/components/C4Sharp/C4Sharp.csproj
@@ -11,7 +11,7 @@
https://github.com/8T4/c4sharp
git
c4, diagrams
- 3.1.0
+ 3.2.0
https://github.com/8T4/c4sharp/blob/main/LICENSE
true
true
diff --git a/src/components/C4Sharp/Diagrams/Core/ComponentDiagram.cs b/src/components/C4Sharp/Diagrams/Core/ComponentDiagram.cs
index 6a530df..7c9d09f 100644
--- a/src/components/C4Sharp/Diagrams/Core/ComponentDiagram.cs
+++ b/src/components/C4Sharp/Diagrams/Core/ComponentDiagram.cs
@@ -5,13 +5,5 @@
/// components are, their responsibilities and the technology/implementation details.
///
///
- public record ComponentDiagram: Diagram
- {
- ///
- /// Constructor
- ///
- public ComponentDiagram() : base("C4_Component")
- {
- }
- }
+ public record ComponentDiagram() : Diagram("C4_Component");
}
\ No newline at end of file
diff --git a/src/components/C4Sharp/Diagrams/Core/ContainerDiagram.cs b/src/components/C4Sharp/Diagrams/Core/ContainerDiagram.cs
index df3230a..b6fdacd 100644
--- a/src/components/C4Sharp/Diagrams/Core/ContainerDiagram.cs
+++ b/src/components/C4Sharp/Diagrams/Core/ContainerDiagram.cs
@@ -7,13 +7,5 @@
/// support/operations staff alike.
///
///
- public record ContainerDiagram: Diagram
- {
- ///
- /// Constructor
- ///
- public ContainerDiagram() : base("C4_Container")
- {
- }
- }
+ public record ContainerDiagram() : Diagram("C4_Container");
}
\ No newline at end of file
diff --git a/src/components/C4Sharp/Diagrams/Core/ContextDiagram.cs b/src/components/C4Sharp/Diagrams/Core/ContextDiagram.cs
index ee117b0..ca6b37a 100644
--- a/src/components/C4Sharp/Diagrams/Core/ContextDiagram.cs
+++ b/src/components/C4Sharp/Diagrams/Core/ContextDiagram.cs
@@ -6,14 +6,5 @@
/// by its users and the other systems that it interacts with.
///
///
- public record ContextDiagram: Diagram
- {
- ///
- /// Constructor
- ///
- public ContextDiagram() : base("C4_Context")
- {
-
- }
- }
+ public record ContextDiagram() : Diagram("C4_Context");
}
\ No newline at end of file
diff --git a/src/components/C4Sharp/Diagrams/Diagram.cs b/src/components/C4Sharp/Diagrams/Diagram.cs
index 674063d..6e268cc 100644
--- a/src/components/C4Sharp/Diagrams/Diagram.cs
+++ b/src/components/C4Sharp/Diagrams/Diagram.cs
@@ -1,4 +1,5 @@
-using C4Sharp.Extensions;
+using System;
+using C4Sharp.Extensions;
using C4Sharp.Models;
using C4Sharp.Models.Relationships;
@@ -30,8 +31,8 @@ protected Diagram(string name)
ShowLegend = false;
FlowVisualization = DiagramLayout.TopDown;
Name = name;
- Structures = default;
- Relationships = default;
+ Structures = Array.Empty();
+ Relationships = Array.Empty();
}
///
diff --git a/src/components/C4Sharp/Diagrams/Supplementary/DeploymentDiagram.cs b/src/components/C4Sharp/Diagrams/Supplementary/DeploymentDiagram.cs
index 302a184..bff2d37 100644
--- a/src/components/C4Sharp/Diagrams/Supplementary/DeploymentDiagram.cs
+++ b/src/components/C4Sharp/Diagrams/Supplementary/DeploymentDiagram.cs
@@ -9,13 +9,5 @@ namespace C4Sharp.Diagrams.Supplementary
/// (e.g. a database server, Java EE web/application server, Microsoft IIS), etc. Deployment nodes can be nested.
///
///
- public record DeploymentDiagram : Diagram
- {
- ///
- /// Constructor
- ///
- public DeploymentDiagram() : base("C4_Deployment")
- {
- }
- }
+ public record DeploymentDiagram() : Diagram("C4_Deployment");
}
\ No newline at end of file
diff --git a/src/components/C4Sharp/FileSystem/C4Directory.cs b/src/components/C4Sharp/FileSystem/C4SharpDirectory.cs
similarity index 94%
rename from src/components/C4Sharp/FileSystem/C4Directory.cs
rename to src/components/C4Sharp/FileSystem/C4SharpDirectory.cs
index fa484e9..da62fea 100644
--- a/src/components/C4Sharp/FileSystem/C4Directory.cs
+++ b/src/components/C4Sharp/FileSystem/C4SharpDirectory.cs
@@ -7,7 +7,7 @@ namespace C4Sharp.FileSystem
///
/// Manipulate the C4 folder and their resoucers
///
- internal static class C4Directory
+ internal static class C4SharpDirectory
{
///
/// Default Directory Name
@@ -16,7 +16,7 @@ internal static class C4Directory
///
/// Default Resource Folder Name
///
- public static string ResourcesFolderName => "resources";
+ public static string ResourcesFolderName => Path.Join("..", ".c4s");
///
/// Load all C4_Plantuml files
diff --git a/src/components/C4Sharp/Models/EnterpriseBoundary.cs b/src/components/C4Sharp/Models/EnterpriseBoundary.cs
new file mode 100644
index 0000000..8e120df
--- /dev/null
+++ b/src/components/C4Sharp/Models/EnterpriseBoundary.cs
@@ -0,0 +1,10 @@
+using System;
+using System.Collections.Generic;
+
+namespace C4Sharp.Models
+{
+ public record EnterpriseBoundary(string Alias, string Label) : Structure(Alias, Label)
+ {
+ public IEnumerable Structures { get; init; } = Array.Empty();
+ }
+}
\ No newline at end of file
diff --git a/src/components/C4Sharp/Models/Plantuml/PlantumlDiagram.cs b/src/components/C4Sharp/Models/Plantuml/PlantumlDiagram.cs
index 7e73968..0548c90 100644
--- a/src/components/C4Sharp/Models/Plantuml/PlantumlDiagram.cs
+++ b/src/components/C4Sharp/Models/Plantuml/PlantumlDiagram.cs
@@ -81,7 +81,7 @@ private static string GetPumlFilePath(this Diagram diagram, bool useUrlInclude)
return useUrlInclude
? $"{standardLibraryBaseUrl}/{pumlFileName}"
- : Path.Join(C4Directory.ResourcesFolderName, pumlFileName);
+ : Path.Join(C4SharpDirectory.ResourcesFolderName, pumlFileName);
}
}
}
\ No newline at end of file
diff --git a/src/components/C4Sharp/Models/Plantuml/PlantumlFile.cs b/src/components/C4Sharp/Models/Plantuml/PlantumlFile.cs
index 066c53b..cbffd6f 100644
--- a/src/components/C4Sharp/Models/Plantuml/PlantumlFile.cs
+++ b/src/components/C4Sharp/Models/Plantuml/PlantumlFile.cs
@@ -11,6 +11,8 @@ namespace C4Sharp.Models.Plantuml
///
public static class PlantumlFile
{
+ private static readonly object Lock = new object();
+
///
/// It creates a Puml file into the default directory "./c4"
/// If the attribute of Session GenerateDiagramImages is true
@@ -21,7 +23,7 @@ public static class PlantumlFile
public static void Export(this PlantumlSession session, IEnumerable diagrams)
{
var dirPath = Directory.GetCurrentDirectory();
- var path = Path.Join(dirPath, C4Directory.DirectoryName);
+ var path = Path.Join(dirPath, C4SharpDirectory.DirectoryName);
Export(session, path, diagrams);
}
@@ -66,9 +68,13 @@ private static void Save(Diagram diagram, string path, PlantumlSession session)
{
try
{
- C4Directory.LoadResources(path);
- var filePath = Path.Combine(path, $"{diagram.Slug()}.puml");
- File.WriteAllText(filePath, diagram.ToPumlString(session.StandardLibraryBaseUrl));
+ lock (Lock)
+ {
+ C4SharpDirectory.LoadResources(path);
+ var filePath = Path.Combine(path, $"{diagram.Slug()}.puml");
+ Directory.CreateDirectory(path);
+ File.WriteAllText(filePath, diagram.ToPumlString(session.StandardLibraryBaseUrl));
+ }
}
catch (Exception e)
{
diff --git a/src/components/C4Sharp/Models/Plantuml/PlantumlSession.cs b/src/components/C4Sharp/Models/Plantuml/PlantumlSession.cs
index a984f52..86da69c 100644
--- a/src/components/C4Sharp/Models/Plantuml/PlantumlSession.cs
+++ b/src/components/C4Sharp/Models/Plantuml/PlantumlSession.cs
@@ -92,12 +92,12 @@ public PlantumlSession UseDiagramSvgImageBuilder()
///
internal void Execute(string path, bool processWholeDirectory, string generatedImageFormat)
{
- var directory = processWholeDirectory
- ? path
- : new FileInfo(path)?.Directory?.FullName;
-
try
{
+ var directory = processWholeDirectory
+ ? path
+ : new FileInfo(path)?.Directory?.FullName;
+
if (string.IsNullOrEmpty(directory))
{
throw new PlantumlException($"{nameof(PlantumlException)}: puml file not found.");
@@ -134,6 +134,53 @@ private string CalculateJarCommand(bool useStandardLibrary, string generatedImag
return $"-jar {FilePath} {resourcesOriginArg} {imageFormatOutputArg} -verbose -o \"{directory}\" -charset UTF-8";
}
+ ///
+ /// Using the -pipe option, you can easily use PlantUML in your scripts.
+ /// With this option, a diagram description is received through standard input and the PNG file is generated to standard output.
+ /// No file is written on the local file system.
+ ///
+ /// puml content
+ ///
+ internal (string, Stream) GetStream(string input)
+ {
+ try
+ {
+ var results = new StringBuilder();
+
+ var jar = StandardLibraryBaseUrl
+ ? $"-jar {FilePath} -verbose -charset UTF-8"
+ : $"-jar {FilePath} -DRELATIVE_INCLUDE=\".\" -verbose -charset UTF-8";
+
+ var fileName = Guid.NewGuid().ToString("N");
+
+ ProcessInfo.Arguments = $"{jar} -pipe > {fileName}.png";
+ ProcessInfo.RedirectStandardOutput = true;
+ ProcessInfo.RedirectStandardInput = true;
+ ProcessInfo.StandardOutputEncoding = Encoding.UTF8;
+
+ var process = new Process { StartInfo = ProcessInfo };
+
+ process.OutputDataReceived += (p, args) =>
+ {
+ results.AppendLine(args.Data);
+ };
+
+ process.Start();
+ process.StandardInput.Write(input);
+ process.StandardInput.Flush();
+ process.StandardInput.Close();
+ process.BeginOutputReadLine();
+ process.WaitForExit();
+
+ var buffer = Encoding.UTF8.GetBytes(results.ToString());
+ return (fileName, new MemoryStream(buffer));
+ }
+ catch (Exception e)
+ {
+ throw new PlantumlException($"{nameof(PlantumlException)}: puml file not found.", e);
+ }
+ }
+
///
/// Clear Plantuml Resource
///
diff --git a/src/components/C4Sharp/Models/Plantuml/PlantumlStream.cs b/src/components/C4Sharp/Models/Plantuml/PlantumlStream.cs
new file mode 100644
index 0000000..57ce704
--- /dev/null
+++ b/src/components/C4Sharp/Models/Plantuml/PlantumlStream.cs
@@ -0,0 +1,20 @@
+using System.Collections.Generic;
+using System.IO;
+using C4Sharp.Diagrams;
+
+namespace C4Sharp.Models.Plantuml
+{
+ public static class PlantumlStream
+ {
+ private static readonly object Lock = new object();
+
+ public static (string, Stream) GetStream(this PlantumlSession session, Diagram diagram)
+ {
+ lock (Lock)
+ {
+ var puml = diagram.ToPumlString(session.StandardLibraryBaseUrl);
+ return session.GetStream(puml);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/components/C4Sharp/Models/Plantuml/PlantumlStructure.cs b/src/components/C4Sharp/Models/Plantuml/PlantumlStructure.cs
index fbb56e6..89561f2 100644
--- a/src/components/C4Sharp/Models/Plantuml/PlantumlStructure.cs
+++ b/src/components/C4Sharp/Models/Plantuml/PlantumlStructure.cs
@@ -24,6 +24,7 @@ public static string ToPumlString(this Structure structure)
Component component => component.ToPumlString(),
Container container => container.ToPumlString(),
ContainerBoundary containerBoundary => containerBoundary.ToPumlString(),
+ EnterpriseBoundary enterpriseBoundary => enterpriseBoundary.ToPumlString(),
_ => string.Empty
};
}
@@ -56,7 +57,26 @@ private static string ToPumlString(this SoftwareSystemBoundary boundary)
stream.AppendLine("}");
return stream.ToString();
- }
+ }
+
+ private static string ToPumlString(this EnterpriseBoundary boundary)
+ {
+ var stream = new StringBuilder();
+ stream.AppendLine();
+ stream.AppendLine($"Enterprise_Boundary({boundary.Alias}, \"{boundary.Label}\") {{");
+
+ foreach (var structure in boundary.Structures)
+ {
+ if (structure is (Person or SoftwareSystem or EnterpriseBoundary))
+ {
+ stream.AppendLine($"{SpaceMethods.Indent()}{structure.ToPumlString()}");
+ }
+ }
+
+ stream.AppendLine("}");
+
+ return stream.ToString();
+ }
private static string ToPumlString(this Component component)
{
diff --git a/src/samples/C4Sharp.Sample/Diagrams/EnterpriseDiagramBuilder.cs b/src/samples/C4Sharp.Sample/Diagrams/EnterpriseDiagramBuilder.cs
new file mode 100644
index 0000000..054f7e8
--- /dev/null
+++ b/src/samples/C4Sharp.Sample/Diagrams/EnterpriseDiagramBuilder.cs
@@ -0,0 +1,58 @@
+using C4Sharp.Diagrams.Core;
+using C4Sharp.Models;
+using C4Sharp.Models.Relationships;
+using C4Sharp.Sample.Structures;
+
+namespace C4Sharp.Sample.Diagrams
+{
+ using static Position;
+ using static People;
+ using static Systems;
+
+ public class EnterpriseDiagramBuilder
+ {
+ public static ContextDiagram Build()
+ {
+ return new ()
+ {
+ Title = "System Enterprise diagram for Internet Banking System",
+ Structures = new Structure[]
+ {
+ Customer,
+ new EnterpriseBoundary("eboundary", "Domain A")
+ {
+ Structures = new Structure []
+ {
+ BankingSystem,
+ new EnterpriseBoundary("eboundary1", "Domain Internal Users")
+ {
+ Structures = new Structure []
+ {
+ InternalCustomer,
+ }
+ },
+ new EnterpriseBoundary("eboundary2", "Domain Managers")
+ {
+ Structures = new Structure []
+ {
+ Manager,
+ }
+ },
+ }
+ },
+ Mainframe,
+ MailSystem
+ },
+ 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/src/samples/C4Sharp.Sample/Program.cs b/src/samples/C4Sharp.Sample/Program.cs
index 4b6c2f6..6a587c6 100644
--- a/src/samples/C4Sharp.Sample/Program.cs
+++ b/src/samples/C4Sharp.Sample/Program.cs
@@ -1,5 +1,5 @@
-using System;
-using C4Sharp.Diagrams;
+using C4Sharp.Diagrams;
+using C4Sharp.Models;
using C4Sharp.Models.Plantuml;
using C4Sharp.Sample.Diagrams;
@@ -14,11 +14,13 @@ private static void Main(string[] args)
ContextDiagramBuilder.Build(),
ContainerDiagramBuilder.Build(),
ComponentDiagramBuilder.Build(),
- DeploymentDiagramBuilder.Build()
+ DeploymentDiagramBuilder.Build(),
+ EnterpriseDiagramBuilder.Build(),
};
new PlantumlSession()
.UseDiagramImageBuilder()
+ .UseDiagramSvgImageBuilder()
.UseStandardLibraryBaseUrl()
.Export(diagrams);
}
diff --git a/src/samples/C4Sharp.Sample/Structures/Containers.cs b/src/samples/C4Sharp.Sample/Structures/Containers.cs
index 9315899..7b6961b 100644
--- a/src/samples/C4Sharp.Sample/Structures/Containers.cs
+++ b/src/samples/C4Sharp.Sample/Structures/Containers.cs
@@ -7,7 +7,7 @@ public static class Containers
private static Container _webApp;
public static Container WebApp => _webApp ??= new Container(
- "WebApp", "WebApp")
+ "Corporate.Finance.Limits.Service.ServiceBus", "WebApp")
{
ContainerType = ContainerType.WebApplication,
Description = "Delivers the static content and the Internet banking SPA",
diff --git a/src/samples/C4Sharp.Sample/Structures/People.cs b/src/samples/C4Sharp.Sample/Structures/People.cs
index c495f39..d208a91 100644
--- a/src/samples/C4Sharp.Sample/Structures/People.cs
+++ b/src/samples/C4Sharp.Sample/Structures/People.cs
@@ -1,4 +1,5 @@
using C4Sharp.Models;
+using C4Sharp.Models.Relationships;
namespace C4Sharp.Sample.Structures
{
@@ -8,7 +9,20 @@ public static class People
public static Person Customer => _customer ??= new Person("customer", "Personal Banking Customer")
{
- Description = "A customer of the bank, with personal bank accounts."
+ 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."
+ };
}
}
\ No newline at end of file
diff --git a/src/samples/C4Sharp.Sample/Structures/Systems.cs b/src/samples/C4Sharp.Sample/Structures/Systems.cs
index a831afc..e2262c6 100644
--- a/src/samples/C4Sharp.Sample/Structures/Systems.cs
+++ b/src/samples/C4Sharp.Sample/Structures/Systems.cs
@@ -11,7 +11,8 @@ public static class Systems
"BankingSystem",
"Internet Banking System")
{
- Description = "Allows customers to view information about their bank accounts, and make payments."
+ Description = "Allows customers to view information about their " +
+ "bank accounts, and make payments."
};
private static SoftwareSystem _mainframe;
@@ -20,7 +21,8 @@ public static class Systems
"Mainframe",
"Mainframe Banking System")
{
- Description = "Stores all of the core banking information about customers, accounts, transactions, etc.",
+ Description = "Stores all of the core banking information about customers, " +
+ "accounts, transactions, etc.",
Boundary = Boundary.External
};
diff --git a/src/tests/C4Sharp.IntegratedTests/ExportingDiagramFixture.cs b/src/tests/C4Sharp.IntegratedTests/ExportingDiagramFixture.cs
index 1da5ef5..a0cad0a 100644
--- a/src/tests/C4Sharp.IntegratedTests/ExportingDiagramFixture.cs
+++ b/src/tests/C4Sharp.IntegratedTests/ExportingDiagramFixture.cs
@@ -21,11 +21,11 @@ protected static void VerifyIfResourceFilesExists(string path = "c4")
{
var files = new[]
{
- Path.Join(path, "resources", "C4.puml"),
- Path.Join(path, "resources", "C4_Component.puml"),
- Path.Join(path, "resources", "C4_Context.puml"),
- Path.Join(path, "resources", "C4_Container.puml"),
- Path.Join(path, "resources", "C4_Deployment.puml"),
+ 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);
diff --git a/src/tests/C4Sharp.IntegratedTests/GettingStreamDiagramTests.cs b/src/tests/C4Sharp.IntegratedTests/GettingStreamDiagramTests.cs
new file mode 100644
index 0000000..82f8b91
--- /dev/null
+++ b/src/tests/C4Sharp.IntegratedTests/GettingStreamDiagramTests.cs
@@ -0,0 +1,22 @@
+using C4Sharp.Diagrams;
+using C4Sharp.IntegratedTests.Stubs.Diagrams;
+using C4Sharp.Models.Plantuml;
+using FluentAssertions;
+using Xunit;
+
+namespace C4Sharp.IntegratedTests
+{
+ public class GettingStreamDiagramTests
+ {
+ [Fact]
+ public void TestGetStream()
+ {
+ var diagram = ContextDiagramBuilder.Build() with { Title = "Diagram" };
+
+ var session = new PlantumlSession();
+ var (_, results) = session.GetStream(diagram);
+
+ results.Should().NotBeNull();
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/tests/C4Sharp.UnitTests/C4Sharp.UnitTests.csproj b/src/tests/C4Sharp.UnitTests/C4Sharp.UnitTests.csproj
index a14ec47..2c912a6 100644
--- a/src/tests/C4Sharp.UnitTests/C4Sharp.UnitTests.csproj
+++ b/src/tests/C4Sharp.UnitTests/C4Sharp.UnitTests.csproj
@@ -22,6 +22,7 @@
+
diff --git a/src/tests/C4Sharp.UnitTests/Diagrams/DiagramTests.cs b/src/tests/C4Sharp.UnitTests/Diagrams/DiagramTests.cs
index 01018e2..dbeab6b 100644
--- a/src/tests/C4Sharp.UnitTests/Diagrams/DiagramTests.cs
+++ b/src/tests/C4Sharp.UnitTests/Diagrams/DiagramTests.cs
@@ -1,6 +1,10 @@
+using System;
using C4Sharp.Diagrams;
using C4Sharp.Diagrams.Core;
using C4Sharp.Diagrams.Supplementary;
+using C4Sharp.Models.Plantuml;
+using C4Sharp.Models.Relationships;
+using C4Sharp.Sample.Diagrams;
using FluentAssertions;
using Xunit;
@@ -44,7 +48,7 @@ public void TestWhenSlugContainerDiagram(string title)
[InlineData("TEST A")]
public void TestWhenSlugDeploymentDiagram(string title)
{
- var diagram = new DeploymentDiagram { Title = title};
+ var diagram = new DeploymentDiagram { Title = title };
diagram.Slug().Should().Be("test-a-c4deployment");
}