-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add relationship arrows for class diagrams
- Loading branch information
Showing
5 changed files
with
455 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
namespace PlantUml.Builder.ClassDiagrams; | ||
|
||
public partial class Arrow | ||
{ | ||
private readonly string arrowHeads = new(new[] { | ||
ArrowParts.Right, | ||
ArrowParts.Left, | ||
ArrowParts.Generalization, | ||
ArrowParts.Composition, | ||
ArrowParts.Aggregation, | ||
ArrowParts.ProvidedInterface, | ||
ArrowParts.LeftRequiredInterface, | ||
ArrowParts.RightRequiredInterface, | ||
ArrowParts.Note, | ||
ArrowParts.Termination | ||
} | ||
); | ||
|
||
public readonly string LeftHead = string.Empty; | ||
public readonly string RightHead = string.Empty; | ||
public readonly bool Dashed = false; | ||
|
||
public Arrow(string arrow) | ||
{ | ||
ArgumentException.ThrowIfNullOrWhitespace(arrow); | ||
|
||
var value = arrow.Trim(); | ||
|
||
if (value.Length < 2) throw new System.ArgumentException("The arrow type must be at least 2 characters long", nameof(arrow)); | ||
if (!value.Contains(ArrowParts.SolidLine) && !value.Contains(ArrowParts.DashedLine)) throw new System.ArgumentException("The arrow must contain at least 1 line character ('-', '.')", nameof(arrow)); | ||
if (value.Contains(ArrowParts.SolidLine) && value.Contains(ArrowParts.DashedLine)) throw new System.ArgumentException("The arrow must contain either a dashed line ('.') or a solid line ('-'), but not both.", nameof(arrow)); | ||
|
||
this.Parse(value, out List<char> left, out List<char> line, out List<char> right); | ||
|
||
if (left.Count > 0) | ||
{ | ||
this.LeftHead = new string(left.ToArray()); | ||
} | ||
|
||
if (line.Contains(ArrowParts.DashedLine)) | ||
{ | ||
this.Dashed = true; | ||
} | ||
|
||
if (right.Count > 0) | ||
{ | ||
this.RightHead = new string(right.ToArray()); | ||
} | ||
} | ||
|
||
public override string ToString() | ||
{ | ||
return $"{this.LeftHead}{(this.Dashed ? ".." : "--")}{this.RightHead}"; | ||
} | ||
|
||
public static implicit operator Arrow(string arrow) | ||
{ | ||
return new Arrow(arrow); | ||
} | ||
|
||
public static implicit operator string(Arrow arrow) | ||
{ | ||
return arrow.ToString(); | ||
} | ||
|
||
private void Parse(string value, out List<char> left, out List<char> line, out List<char> right) | ||
{ | ||
left = new List<char>(value.Length); | ||
line = new List<char>(value.Length); | ||
right = new List<char>(value.Length); | ||
|
||
var mode = ArrowPart.LeftHead; | ||
|
||
for (var i = 0; i < value.Length; i++) | ||
{ | ||
if (mode == ArrowPart.LeftHead) | ||
{ | ||
if (!this.arrowHeads.Contains(value[i])) | ||
{ | ||
mode = ArrowPart.Body; | ||
} | ||
else | ||
{ | ||
left.Add(value[i]); | ||
} | ||
} | ||
|
||
if (mode == ArrowPart.Body) | ||
{ | ||
if (this.arrowHeads.Contains(value[i])) | ||
{ | ||
mode = ArrowPart.RightHead; | ||
} | ||
else | ||
{ | ||
line.Add(value[i]); | ||
} | ||
} | ||
|
||
if (mode == ArrowPart.RightHead) | ||
{ | ||
right.Add(value[i]); | ||
} | ||
} | ||
} | ||
|
||
private enum ArrowPart | ||
{ | ||
LeftHead, | ||
Body, | ||
RightHead | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
namespace PlantUml.Builder.ClassDiagrams; | ||
|
||
internal class ArrowParts | ||
{ | ||
// Line types | ||
public const char DashedLine = '.'; | ||
public const char SolidLine = '-'; | ||
|
||
// Arrowhead types | ||
public const char Aggregation = 'o'; | ||
public const char Composition = '*'; | ||
public const char Generalization = '|'; | ||
public const char LeftRequiredInterface = '}'; | ||
public const char Note = '#'; | ||
public const char ProvidedInterface = '+'; | ||
public const char RightRequiredInterface = '{'; | ||
public const char Termination = 'x'; | ||
|
||
// Directional arrowheads | ||
public const char Left = '<'; | ||
public const char Right = '>'; | ||
} |
140 changes: 140 additions & 0 deletions
140
src/PlantUml.Builder/ClassDiagrams/Relationship.Defaults.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,140 @@ | ||
namespace PlantUml.Builder.ClassDiagrams | ||
{ | ||
/// <summary> | ||
/// Defines constants for various types of UML relationships. | ||
/// </summary> | ||
public partial class Relationship | ||
{ | ||
#pragma warning disable CA2211 // Non-constant fields should not be visible | ||
/// <summary> | ||
/// Represents a simple association between two classes. | ||
/// </summary> | ||
public static Arrow Associates = "--"; | ||
|
||
/// <summary> | ||
/// Represents a simple association from the perspective of the second class. | ||
/// </summary> | ||
public static Arrow IsAssociatedWith = "--"; | ||
|
||
/// <summary> | ||
/// Represents a directed association between two classes. | ||
/// </summary> | ||
public static Arrow AssociatesDirectlyWith = "<--"; | ||
|
||
/// <summary> | ||
/// Represents a directed association from the perspective of the second class. | ||
/// </summary> | ||
public static Arrow IsDirectlyAssociatedWith = "-->"; | ||
|
||
/// <summary> | ||
/// Represents a strong or special form of association. | ||
/// </summary> | ||
public static Arrow AssociatesStrongly = "--+"; | ||
|
||
/// <summary> | ||
/// Represents a strong or special form of association from the perspective of the second class. | ||
/// </summary> | ||
public static Arrow IsStronglyAssociatedWith = "+--"; | ||
|
||
/// <summary> | ||
/// Represents a special form of association denoted by a custom symbol. | ||
/// </summary> | ||
public static Arrow AssociatesSpeciallyWith = "--#"; | ||
|
||
/// <summary> | ||
/// Represents a special form of association from the perspective of the second class. | ||
/// </summary> | ||
public static Arrow IsSpeciallyAssociatedWith = "#--"; | ||
|
||
/// <summary> | ||
/// Represents a disallowed or broken relationship. | ||
/// </summary> | ||
public static Arrow Disallows = "--x"; | ||
|
||
/// <summary> | ||
/// Represents a disallowed or broken relationship from the perspective of the second class. | ||
/// </summary> | ||
public static Arrow IsDisallowedBy = "x--"; | ||
|
||
/// <summary> | ||
/// Represents an aggregation relationship. | ||
/// </summary> | ||
public static Arrow Aggregates = "--o"; | ||
|
||
/// <summary> | ||
/// Represents an aggregation relationship from the perspective of the second class. | ||
/// </summary> | ||
public static Arrow IsAggregatedBy = "o--"; | ||
|
||
/// <summary> | ||
/// Represents a composition relationship. | ||
/// </summary> | ||
public static Arrow Composes = "--*"; | ||
|
||
/// <summary> | ||
/// Represents a composition relationship from the perspective of the second class. | ||
/// </summary> | ||
public static Arrow IsComposedBy = "*--"; | ||
|
||
/// <summary> | ||
/// Represents a directed composition relationship. | ||
/// </summary> | ||
public static Arrow ComposesDirectly = "*-->"; | ||
|
||
/// <summary> | ||
/// Represents a directed composition relationship from the perspective of the second class. | ||
/// </summary> | ||
public static Arrow IsDirectlyComposedBy = "<--*"; | ||
|
||
/// <summary> | ||
/// Represents an inheritance relationship. | ||
/// </summary> | ||
public static Arrow InheritsFrom = "<|--"; | ||
|
||
/// <summary> | ||
/// Represents an inheritance relationship from the perspective of the second class. | ||
/// </summary> | ||
public static Arrow IsInheritedBy = "--|>"; | ||
|
||
/// <summary> | ||
/// Represents a realization or implementation relationship. | ||
/// </summary> | ||
public static Arrow Realizes = "<|.."; | ||
|
||
/// <summary> | ||
/// Represents a realization or implementation relationship from the perspective of the second class. | ||
/// </summary> | ||
public static Arrow IsRealizedBy = "..|>"; | ||
|
||
/// <summary> | ||
/// Represents a dependency relationship. | ||
/// </summary> | ||
public static Arrow DependsOn = ".."; | ||
|
||
/// <summary> | ||
/// Represents a dependency relationship from the perspective of the second class. | ||
/// </summary> | ||
public static Arrow IsDependedUponBy = ".."; | ||
|
||
/// <summary> | ||
/// Represents a directed dependency relationship. | ||
/// </summary> | ||
public const string DependsDirectlyOn = "..>"; | ||
|
||
/// <summary> | ||
/// Represents a directed dependency relationship from the perspective of the second class. | ||
/// </summary> | ||
public const string IsDirectlyDependedUponBy = "<.."; | ||
|
||
/// <summary> | ||
/// Represents a "contains many of" relationship, often used to denote cardinality. | ||
/// </summary> | ||
public const string ContainsManyOf = "}--"; | ||
|
||
/// <summary> | ||
/// Represents a "is contained by many" relationship, often used to denote cardinality. | ||
/// </summary> | ||
public const string IsContainedBy = "--{"; | ||
#pragma warning restore CA2211 // Non-constant fields should not be visible | ||
} | ||
} |
Oops, something went wrong.