diff --git a/ConsoleApp1/Program.cs b/ConsoleApp1/Program.cs index 348b88898760879b338f1e41a4ba7d04cab242d7..bad7b3b86b61d032463233cbb379dcacf2abf2bf 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 7258321f2687292303294e823e6f98abc7949fb2..f69d305ad55cbf9381cd6a271d2e0e58d442a807 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 cbb75f4ceae3a2d7697752f53111e2c2d92754c6..eefd56785a3e81c71a83b7ce259a82da6de8e8a6 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 6277107552fd2a2e744439f79252a5ba1ac2d9d0..9d85319e21195e69d98fa5a1463660431faec2a3 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 5d9c400b3fe211fc87df2c5e7e041910e3a075aa..8013b5289cf3c066bce2da5889f8e9a7ebc9174c 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 fb510d9e8e5a80e3c7ac39a7fa8d3a2bf49fe871..1b96c9602fd891514369251cf222c07d85a8d26a 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;