From 0ca83ff35dce3746543783fe5a707b39ca9ea147 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Konvi=C4=8Dka?= <konvicka.g630@gmail.com> Date: Thu, 14 Dec 2023 15:25:52 +0100 Subject: [PATCH] feat(#17): Add loop diagram option --- ConsoleApp1/Program.cs | 23 ++++----- .../Diagram/ActivityDiagramBuilder.cs | 36 ++++++++++--- .../Activity/Diagram/DecisionBuilder.cs | 50 ++++++++++++++++++- .../Activity/Interface/IDecisionBuilder.cs | 3 ++ .../Activity/Interface/IDiagramBuilder.cs | 4 ++ .../XML/XmiActivityDiagramUmlBuilder.cs | 5 ++ 6 files changed, 99 insertions(+), 22 deletions(-) diff --git a/ConsoleApp1/Program.cs b/ConsoleApp1/Program.cs index 348b888..bad7b3b 100644 --- a/ConsoleApp1/Program.cs +++ b/ConsoleApp1/Program.cs @@ -67,20 +67,15 @@ Console.WriteLine("Parsing Complete!"); ActivityDiagramBuilderBuilderCreator activityDiagramBuilderBuilderCreator = new ActivityDiagramBuilderBuilderCreator(); DiagramBuilder.Activity.Interface.IDiagramBuilder diagramBuilder = activityDiagramBuilderBuilderCreator.FactoryMethod("ActivityDiagram"); -diagramBuilder.AddAction("jedna").AddDecision("decision", "true", "false") - .AddAction("false1", BranchType.False) - .AddAction("true1", BranchType.True) - .AddDecision("decision2", "true", "false", BranchType.False) - .AddAction("true2", BranchType.True) - .AddAction("false2", BranchType.False) - .AddDecision("decision3", "true", "false", BranchType.True) - .AddAction("true3", BranchType.True) - .AddAction("false3", BranchType.False) - .AddAction("false4", BranchType.False) - .AddMerge("merge3") - .AddMerge("merge2") - .AddAction("false5", BranchType.False) - .AddMerge("merge"); +diagramBuilder + .AddLoop("test", "cond") + .AddDecision("D1", "t","f") + .AddLoop("test2", "cond2", BranchType.True) + .AddAction("a", BranchType.True) + .CloseLoop("loopCLose", BranchType.True) + .AddMerge("merge1") + .CloseLoop("a") + .AddAction("c"); var xmi = diagramBuilder.BuildDiagram(); Console.WriteLine(xmi); File.WriteAllText("/Users/jakubkonvicka/Applications/EA.app/Contents/SharedSupport/prefix/drive_c/xmi/activity.xml", xmi); diff --git a/DiagramBuilder/Activity/Diagram/ActivityDiagramBuilder.cs b/DiagramBuilder/Activity/Diagram/ActivityDiagramBuilder.cs index 7258321..f69d305 100644 --- a/DiagramBuilder/Activity/Diagram/ActivityDiagramBuilder.cs +++ b/DiagramBuilder/Activity/Diagram/ActivityDiagramBuilder.cs @@ -8,10 +8,12 @@ public class ActivityDiagramBuilder : IDiagramBuilder { public XmiActivityDiagramUmlBuilder _xmiActivityDiagramUmlBuilder { get; set; } private string _name { get; set; } - private XmiElement _lastActivity { get; set; } = null; + public XmiElement LastActivity { get; set; } = null; private XmiElement _lastEdge => _xmiActivityDiagramUmlBuilder.LatestEdge; public bool IsDecisionClosed { get; set; } = true; + private Stack<XmiElement> _loopElements { get; set; } = new Stack<XmiElement>(); + private XmiElement _lastClosedDecision { get; set; } = null; internal ActivityDiagramBuilder() { @@ -21,26 +23,46 @@ public class ActivityDiagramBuilder : IDiagramBuilder this._name = name; XmiBuilder xmiBuilder = new XmiBuilder(); _xmiActivityDiagramUmlBuilder = new XmiActivityDiagramUmlBuilder(name, xmiBuilder); - _lastActivity = _xmiActivityDiagramUmlBuilder.InitialNode; + LastActivity = _xmiActivityDiagramUmlBuilder.InitialNode; } public IDiagramBuilder AddAction(string name) { if(_lastEdge == null) - _lastActivity = _xmiActivityDiagramUmlBuilder.AddAction(_xmiActivityDiagramUmlBuilder.ActivityDiagram, name, null, null); + LastActivity = _xmiActivityDiagramUmlBuilder.AddAction(_xmiActivityDiagramUmlBuilder.ActivityDiagram, name, null, null, _lastClosedDecision); else - _lastActivity = _xmiActivityDiagramUmlBuilder.AddAction(_xmiActivityDiagramUmlBuilder.ActivityDiagram, name, new() {_lastEdge}, null); + LastActivity = _xmiActivityDiagramUmlBuilder.AddAction(_xmiActivityDiagramUmlBuilder.ActivityDiagram, name, new() {_lastEdge}, null, _lastClosedDecision); + _lastClosedDecision = null; + return this; + } + + public IDiagramBuilder AddLoop(string name, string condition) + { + if(_lastEdge == null) + LastActivity = _xmiActivityDiagramUmlBuilder.AddDecision(_xmiActivityDiagramUmlBuilder.ActivityDiagram, name, null, null, _lastClosedDecision); + else + LastActivity = _xmiActivityDiagramUmlBuilder.AddDecision(_xmiActivityDiagramUmlBuilder.ActivityDiagram, name, new() {_lastEdge}, null, _lastClosedDecision); + _loopElements.Push(LastActivity); + return this; + } + + public IDiagramBuilder CloseLoop(string name) + { + var lastLoopElement = _loopElements.Pop(); + _xmiActivityDiagramUmlBuilder.AddDirectedEdge(_xmiActivityDiagramUmlBuilder.ActivityDiagram, LastActivity, + lastLoopElement); + _lastClosedDecision = lastLoopElement; return this; } public IDecisionBuilder AddDecision(string name, string trueCondition, string falseCondition) { if(_lastEdge == null) - _lastActivity = _xmiActivityDiagramUmlBuilder.AddDecision(_xmiActivityDiagramUmlBuilder.ActivityDiagram, name, null, null); + LastActivity = _xmiActivityDiagramUmlBuilder.AddDecision(_xmiActivityDiagramUmlBuilder.ActivityDiagram, name, null, null, _lastClosedDecision); else - _lastActivity = _xmiActivityDiagramUmlBuilder.AddDecision(_xmiActivityDiagramUmlBuilder.ActivityDiagram, name, new() {_lastEdge}, null); + LastActivity = _xmiActivityDiagramUmlBuilder.AddDecision(_xmiActivityDiagramUmlBuilder.ActivityDiagram, name, new() {_lastEdge}, null, _lastClosedDecision); - return new DecisionBuilder(this._name, this._xmiActivityDiagramUmlBuilder, _lastEdge, _lastActivity); + return new DecisionBuilder(this._name, this._xmiActivityDiagramUmlBuilder, _lastEdge, LastActivity, this); } public string? BuildDiagram() diff --git a/DiagramBuilder/Activity/Diagram/DecisionBuilder.cs b/DiagramBuilder/Activity/Diagram/DecisionBuilder.cs index cbb75f4..eefd567 100644 --- a/DiagramBuilder/Activity/Diagram/DecisionBuilder.cs +++ b/DiagramBuilder/Activity/Diagram/DecisionBuilder.cs @@ -12,14 +12,17 @@ namespace DiagramBuilder.Activity.Diagram // Dictionary for true and false branch private List<Dictionary<BranchType, XmiElement>> _lastAddedEdge { get; set; } = new(); + private List<Dictionary<BranchType, XmiElement>> _loopElements { get; set; } = new(); private List<Dictionary<BranchType, XmiElement>> _lastAddedNode { get; set; } = new(); + IDiagramBuilder _diagramBuilder { get; set; } private List<BranchType> _lastBranchTypeForDecision { get; set; } = new(); private long _actualDecisionId { get; set; } = 0; - public DecisionBuilder(string name, XmiActivityDiagramUmlBuilder xmiActivityDiagramUmlBuilder, XmiElement trueBranchEdge, XmiElement lastAddedNode) + public DecisionBuilder(string name, XmiActivityDiagramUmlBuilder xmiActivityDiagramUmlBuilder, XmiElement trueBranchEdge, XmiElement lastAddedNode, IDiagramBuilder _diagramBuilder) { + this._diagramBuilder = _diagramBuilder; _xmiActivityDiagramUmlBuilder = xmiActivityDiagramUmlBuilder; _lastAddedEdge.Add(new Dictionary<BranchType, XmiElement>()); _lastAddedNode.Add(new Dictionary<BranchType, XmiElement>()); @@ -53,6 +56,12 @@ namespace DiagramBuilder.Activity.Diagram return this; } + public IDiagramBuilder AddAction(string name) + { + this._diagramBuilder.AddAction(name); + return this._diagramBuilder; + } + public IDecisionBuilder AddMerge(string name) { var mergeNode = _xmiActivityDiagramUmlBuilder.AddMerge( @@ -60,11 +69,15 @@ namespace DiagramBuilder.Activity.Diagram _lastAddedNode.Last()[BranchType.True], _lastAddedNode.Last()[BranchType.False]); _lastAddedEdge.Remove(_lastAddedEdge.Last()); _lastAddedNode.Remove(_lastAddedNode.Last()); + + this._diagramBuilder.LastActivity = mergeNode; + if (_lastAddedNode.Count == 0) return this; _lastAddedNode.Last()[_lastBranchTypeForDecision.Last()] = mergeNode; _lastBranchTypeForDecision.RemoveAt(_lastBranchTypeForDecision.Count-1); + return this; } @@ -93,5 +106,40 @@ namespace DiagramBuilder.Activity.Diagram //_lastAddedEdge.Last().Add(BranchType.False, _xmiActivityDiagramUmlBuilder.LatestEdge); return this; } + + public IDecisionBuilder AddLoop(string name, string condition, BranchType type) + { + + if (!_lastAddedEdge.Last().TryGetValue(type, out var edge)) + { + _lastAddedNode.Last()[type] = _xmiActivityDiagramUmlBuilder.AddDecision( + _xmiActivityDiagramUmlBuilder.ActivityDiagram, name, null, null, _lastAddedNode.Last()[type]); + _lastAddedEdge.Last().Add(type, _xmiActivityDiagramUmlBuilder.LatestEdge); + } + else + { + _lastAddedNode.Last()[type] = _xmiActivityDiagramUmlBuilder.AddDecision( + _xmiActivityDiagramUmlBuilder.ActivityDiagram, name, new List<XmiElement> { _lastAddedEdge.Last()[type] }, null, _lastAddedNode.Last()[type]); + } + + + _loopElements.Add(new Dictionary<BranchType, XmiElement>()); + _loopElements.Last().Add(type, _lastAddedNode.Last()[type]); + return this; + } + + public IDecisionBuilder CloseLoop(string name, BranchType type) + { + _xmiActivityDiagramUmlBuilder.AddDirectedEdge(_xmiActivityDiagramUmlBuilder.ActivityDiagram, _lastAddedNode.Last()[type], + _loopElements.Last()[type]); + _loopElements.Remove(_loopElements.Last()); + return this; + } + + public IDiagramBuilder CloseLoop(string name) + { + this._diagramBuilder.CloseLoop(name); + return this._diagramBuilder; + } } } diff --git a/DiagramBuilder/Activity/Interface/IDecisionBuilder.cs b/DiagramBuilder/Activity/Interface/IDecisionBuilder.cs index 6277107..9d85319 100644 --- a/DiagramBuilder/Activity/Interface/IDecisionBuilder.cs +++ b/DiagramBuilder/Activity/Interface/IDecisionBuilder.cs @@ -7,4 +7,7 @@ public interface IDecisionBuilder public IDecisionBuilder AddAction(string name, BranchType type); public IDecisionBuilder AddMerge(string name); public IDecisionBuilder AddDecision(string name, string trueCondition, string falseCondition, BranchType type); + public IDecisionBuilder AddLoop(string name, string condition, BranchType type); + public IDecisionBuilder CloseLoop(string name, BranchType type); + public IDiagramBuilder CloseLoop(string name); } \ No newline at end of file diff --git a/DiagramBuilder/Activity/Interface/IDiagramBuilder.cs b/DiagramBuilder/Activity/Interface/IDiagramBuilder.cs index 5d9c400..8013b52 100644 --- a/DiagramBuilder/Activity/Interface/IDiagramBuilder.cs +++ b/DiagramBuilder/Activity/Interface/IDiagramBuilder.cs @@ -1,11 +1,15 @@ using DiagramBuilder.Class.Interface; +using DiagramBuilder.XML; namespace DiagramBuilder.Activity.Interface; public interface IDiagramBuilder { public bool IsDecisionClosed { get; set; } + public XmiElement LastActivity { get; set; } public IDiagramBuilder AddAction(string name); + public IDiagramBuilder AddLoop(string name, string condition); + public IDiagramBuilder CloseLoop(string name); public IDecisionBuilder AddDecision(string name, string trueCondition, string falseCondition); public string? BuildDiagram(); } \ No newline at end of file diff --git a/DiagramBuilder/Activity/XML/XmiActivityDiagramUmlBuilder.cs b/DiagramBuilder/Activity/XML/XmiActivityDiagramUmlBuilder.cs index fb510d9..1b96c96 100644 --- a/DiagramBuilder/Activity/XML/XmiActivityDiagramUmlBuilder.cs +++ b/DiagramBuilder/Activity/XML/XmiActivityDiagramUmlBuilder.cs @@ -112,6 +112,11 @@ public class XmiActivityDiagramUmlBuilder : DiagramUmlBuilder return activity; } + public void AddDirectedEdge(XmiElement parent, XmiElement source, XmiElement target) + { + AddEdge(parent, XmiType.UmlControlFlow, source, target); + } + private XmiElement AddActivityFinalNode(XmiElement parent, string name) { string id = name; -- GitLab