From 9d95bb5cc3c34d1b1c32bd7469ceb829f33fb06f Mon Sep 17 00:00:00 2001 From: Andrija Stevanovic Date: Sun, 8 Feb 2026 21:32:24 +0100 Subject: [PATCH] implement --- .../Validation/Rules/ColorFormatRule.cs | 29 +++++++++++++++++++ .../Common/Validation/Rules/MaxValueRule.cs | 23 +++++++++++++++ .../Common/Validation/Rules/MinValueRule.cs | 23 +++++++++++++++ .../Domain/Common/ValueObjects/Color.cs | 23 +++++++++++++++ .../Models/Shape/Enums/ShapeTypeEnum.cs | 9 ++++++ dotnet/AipsCore/Domain/Models/Shape/Shape.cs | 23 +++++++++++++++ .../Domain/Models/Shape/Sub/Arrow/Arrow.cs | 19 ++++++++++++ .../Domain/Models/Shape/Sub/Line/Line.cs | 19 ++++++++++++ .../Models/Shape/Sub/Rectangle/Rectangle.cs | 22 ++++++++++++++ .../Models/Shape/Sub/TextShape/TextShape.cs | 22 ++++++++++++++ .../TextShape/ValueObjects/TextShapeSize.cs | 27 +++++++++++++++++ .../TextShape/ValueObjects/TextShapeValue.cs | 19 ++++++++++++ .../Models/Shape/ValueObjects/Position.cs | 23 +++++++++++++++ .../Models/Shape/ValueObjects/ShapeId.cs | 5 ++++ .../Models/Shape/ValueObjects/Thickness.cs | 27 +++++++++++++++++ 15 files changed, 313 insertions(+) create mode 100644 dotnet/AipsCore/Domain/Common/Validation/Rules/ColorFormatRule.cs create mode 100644 dotnet/AipsCore/Domain/Common/Validation/Rules/MaxValueRule.cs create mode 100644 dotnet/AipsCore/Domain/Common/Validation/Rules/MinValueRule.cs create mode 100644 dotnet/AipsCore/Domain/Common/ValueObjects/Color.cs create mode 100644 dotnet/AipsCore/Domain/Models/Shape/Enums/ShapeTypeEnum.cs create mode 100644 dotnet/AipsCore/Domain/Models/Shape/Shape.cs create mode 100644 dotnet/AipsCore/Domain/Models/Shape/Sub/Arrow/Arrow.cs create mode 100644 dotnet/AipsCore/Domain/Models/Shape/Sub/Line/Line.cs create mode 100644 dotnet/AipsCore/Domain/Models/Shape/Sub/Rectangle/Rectangle.cs create mode 100644 dotnet/AipsCore/Domain/Models/Shape/Sub/TextShape/TextShape.cs create mode 100644 dotnet/AipsCore/Domain/Models/Shape/Sub/TextShape/ValueObjects/TextShapeSize.cs create mode 100644 dotnet/AipsCore/Domain/Models/Shape/Sub/TextShape/ValueObjects/TextShapeValue.cs create mode 100644 dotnet/AipsCore/Domain/Models/Shape/ValueObjects/Position.cs create mode 100644 dotnet/AipsCore/Domain/Models/Shape/ValueObjects/ShapeId.cs create mode 100644 dotnet/AipsCore/Domain/Models/Shape/ValueObjects/Thickness.cs diff --git a/dotnet/AipsCore/Domain/Common/Validation/Rules/ColorFormatRule.cs b/dotnet/AipsCore/Domain/Common/Validation/Rules/ColorFormatRule.cs new file mode 100644 index 0000000..98d2dd1 --- /dev/null +++ b/dotnet/AipsCore/Domain/Common/Validation/Rules/ColorFormatRule.cs @@ -0,0 +1,29 @@ +using AipsCore.Domain.Abstract.Rule; + +namespace AipsCore.Domain.Common.Validation.Rules; + +public class ColorFormatRule : AbstractRule +{ + private readonly string _colorValue; + protected override string ErrorCode => "color_format"; + protected override string ErrorMessage => "Color should be in format '#000000'"; + + public ColorFormatRule(string colorValue) + { + _colorValue = colorValue; + } + + public override bool Validate() + { + if (_colorValue.Length != 7) return false; + + if (_colorValue[0] != '#') return false; + + for (int i = 1; i < _colorValue.Length; i++) + { + if (!char.IsAsciiHexDigit(_colorValue[i])) return false; + } + + return true; + } +} \ No newline at end of file diff --git a/dotnet/AipsCore/Domain/Common/Validation/Rules/MaxValueRule.cs b/dotnet/AipsCore/Domain/Common/Validation/Rules/MaxValueRule.cs new file mode 100644 index 0000000..4d0381d --- /dev/null +++ b/dotnet/AipsCore/Domain/Common/Validation/Rules/MaxValueRule.cs @@ -0,0 +1,23 @@ +using System.Numerics; +using AipsCore.Domain.Abstract.Rule; + +namespace AipsCore.Domain.Common.Validation.Rules; + +public class MaxValueRule : AbstractRule where T : INumber +{ + private readonly T _value; + private readonly T _maximum; + + public MaxValueRule(T value, T maximum) + { + _value = value; + _maximum = maximum; + } + + protected override string ErrorCode => "max_value"; + protected override string ErrorMessage => $"Value of '{ValueObjectName}' should be at most {_maximum}"; + public override bool Validate() + { + return _value <= _maximum; + } +} \ No newline at end of file diff --git a/dotnet/AipsCore/Domain/Common/Validation/Rules/MinValueRule.cs b/dotnet/AipsCore/Domain/Common/Validation/Rules/MinValueRule.cs new file mode 100644 index 0000000..ada04e2 --- /dev/null +++ b/dotnet/AipsCore/Domain/Common/Validation/Rules/MinValueRule.cs @@ -0,0 +1,23 @@ +using System.Numerics; +using AipsCore.Domain.Abstract.Rule; + +namespace AipsCore.Domain.Common.Validation.Rules; + +public class MinValueRule: AbstractRule where T : INumber +{ + private readonly T _value; + private readonly T _minimum; + + public MinValueRule(T value, T minimum) + { + _value = value; + _minimum = minimum; + } + + protected override string ErrorCode => "min_value"; + protected override string ErrorMessage => $"Value of '{ValueObjectName}' should be at least {_minimum}"; + public override bool Validate() + { + return _value >= _minimum; + } +} \ No newline at end of file diff --git a/dotnet/AipsCore/Domain/Common/ValueObjects/Color.cs b/dotnet/AipsCore/Domain/Common/ValueObjects/Color.cs new file mode 100644 index 0000000..8443bb0 --- /dev/null +++ b/dotnet/AipsCore/Domain/Common/ValueObjects/Color.cs @@ -0,0 +1,23 @@ +using AipsCore.Domain.Abstract.Rule; +using AipsCore.Domain.Abstract.ValueObject; +using AipsCore.Domain.Common.Validation.Rules; + +namespace AipsCore.Domain.Common.ValueObjects; + +public record Color : AbstractValueObject +{ + public string Value { get; } + + public Color(string value) + { + Value = value; + } + + protected override ICollection GetValidationRules() + { + return + [ + new ColorFormatRule(Value) + ]; + } +} \ No newline at end of file diff --git a/dotnet/AipsCore/Domain/Models/Shape/Enums/ShapeTypeEnum.cs b/dotnet/AipsCore/Domain/Models/Shape/Enums/ShapeTypeEnum.cs new file mode 100644 index 0000000..52fe3ed --- /dev/null +++ b/dotnet/AipsCore/Domain/Models/Shape/Enums/ShapeTypeEnum.cs @@ -0,0 +1,9 @@ +namespace AipsCore.Domain.Models.Shape.Enums; + +public enum ShapeTypeEnum +{ + Rectangle, + Line, + Arrow, + Text +} \ No newline at end of file diff --git a/dotnet/AipsCore/Domain/Models/Shape/Shape.cs b/dotnet/AipsCore/Domain/Models/Shape/Shape.cs new file mode 100644 index 0000000..3be68f2 --- /dev/null +++ b/dotnet/AipsCore/Domain/Models/Shape/Shape.cs @@ -0,0 +1,23 @@ +using System.Drawing; +using AipsCore.Domain.Models.Shape.Enums; +using AipsCore.Domain.Models.Shape.ValueObjects; + +namespace AipsCore.Domain.Models.Shape; + +public abstract class Shape +{ + public ShapeId Id { get; } + + public abstract ShapeTypeEnum ShapeType { get; } + + public Position Position { get; private set; } + + public Color Color { get; private set; } + + protected Shape(ShapeId id, Position position, Color color) + { + Id = id; + Position = position; + Color = color; + } +} \ No newline at end of file diff --git a/dotnet/AipsCore/Domain/Models/Shape/Sub/Arrow/Arrow.cs b/dotnet/AipsCore/Domain/Models/Shape/Sub/Arrow/Arrow.cs new file mode 100644 index 0000000..bf8b9c1 --- /dev/null +++ b/dotnet/AipsCore/Domain/Models/Shape/Sub/Arrow/Arrow.cs @@ -0,0 +1,19 @@ +using System.Drawing; +using AipsCore.Domain.Models.Shape.Enums; +using AipsCore.Domain.Models.Shape.ValueObjects; + +namespace AipsCore.Domain.Models.Shape.Sub.Arrow; + +public class Arrow : Shape +{ + public Position EndPosition { get; private set; } + public Thickness Thickness { get; private set; } + + public Arrow(ShapeId id, Position position, Color color, Position endPosition, Thickness thickness) : base(id, position, color) + { + EndPosition = endPosition; + Thickness = thickness; + } + + public override ShapeTypeEnum ShapeType => ShapeTypeEnum.Arrow; +} \ No newline at end of file diff --git a/dotnet/AipsCore/Domain/Models/Shape/Sub/Line/Line.cs b/dotnet/AipsCore/Domain/Models/Shape/Sub/Line/Line.cs new file mode 100644 index 0000000..b3ea13a --- /dev/null +++ b/dotnet/AipsCore/Domain/Models/Shape/Sub/Line/Line.cs @@ -0,0 +1,19 @@ +using System.Drawing; +using AipsCore.Domain.Models.Shape.Enums; +using AipsCore.Domain.Models.Shape.ValueObjects; + +namespace AipsCore.Domain.Models.Shape.Sub.Line; + +public class Line : Shape +{ + public Position EndPosition { get; private set; } + public Thickness Thickness { get; private set; } + + public Line(ShapeId id, Position position, Color color, Position endPosition, Thickness thickness) : base(id, position, color) + { + EndPosition = endPosition; + Thickness = thickness; + } + + public override ShapeTypeEnum ShapeType => ShapeTypeEnum.Line; +} \ No newline at end of file diff --git a/dotnet/AipsCore/Domain/Models/Shape/Sub/Rectangle/Rectangle.cs b/dotnet/AipsCore/Domain/Models/Shape/Sub/Rectangle/Rectangle.cs new file mode 100644 index 0000000..743176d --- /dev/null +++ b/dotnet/AipsCore/Domain/Models/Shape/Sub/Rectangle/Rectangle.cs @@ -0,0 +1,22 @@ +using System.Drawing; +using AipsCore.Domain.Models.Shape.Enums; +using AipsCore.Domain.Models.Shape.ValueObjects; + +namespace AipsCore.Domain.Models.Shape.Sub.Rectangle; + +public class Rectangle : Shape +{ + public override ShapeTypeEnum ShapeType => ShapeTypeEnum.Rectangle; + + public Position EndPosition { get; } + + public Thickness BorderThickness { get; } + + public Rectangle(ShapeId id, Position position, Color color, Position endPosition, Thickness borderThickness) + : base(id, position, color) + { + EndPosition = endPosition; + BorderThickness = borderThickness; + } + +} \ No newline at end of file diff --git a/dotnet/AipsCore/Domain/Models/Shape/Sub/TextShape/TextShape.cs b/dotnet/AipsCore/Domain/Models/Shape/Sub/TextShape/TextShape.cs new file mode 100644 index 0000000..057d0d2 --- /dev/null +++ b/dotnet/AipsCore/Domain/Models/Shape/Sub/TextShape/TextShape.cs @@ -0,0 +1,22 @@ +using System.Drawing; +using AipsCore.Domain.Models.Shape.Enums; +using AipsCore.Domain.Models.Shape.Sub.TextShape.ValueObjects; +using AipsCore.Domain.Models.Shape.ValueObjects; + +namespace AipsCore.Domain.Models.Shape.Sub.TextShape; + +public class TextShape : Shape +{ + public TextShapeValue TextShapeValue { get; private set; } + + public TextShapeSize TextShapeSize { get; private set; } + + public TextShape(ShapeId id, Position position, Color color, TextShapeValue textShapeValue, TextShapeSize textShapeSize) + : base(id, position, color) + { + TextShapeValue = textShapeValue; + TextShapeSize = textShapeSize; + } + + public override ShapeTypeEnum ShapeType => ShapeTypeEnum.Text; +} \ No newline at end of file diff --git a/dotnet/AipsCore/Domain/Models/Shape/Sub/TextShape/ValueObjects/TextShapeSize.cs b/dotnet/AipsCore/Domain/Models/Shape/Sub/TextShape/ValueObjects/TextShapeSize.cs new file mode 100644 index 0000000..a699f18 --- /dev/null +++ b/dotnet/AipsCore/Domain/Models/Shape/Sub/TextShape/ValueObjects/TextShapeSize.cs @@ -0,0 +1,27 @@ +using AipsCore.Domain.Abstract.Rule; +using AipsCore.Domain.Abstract.ValueObject; +using AipsCore.Domain.Common.Validation.Rules; + +namespace AipsCore.Domain.Models.Shape.Sub.TextShape.ValueObjects; + +public record TextShapeSize : AbstractValueObject +{ + public const int MaxTextShapeSize = 72; + public const int MinTextShapeSize = 8; + + public int Size { get; } + + public TextShapeSize(int size) + { + Size = size; + } + + protected override ICollection GetValidationRules() + { + return + [ + new MaxValueRule(Size, MaxTextShapeSize), + new MinValueRule(Size, MinTextShapeSize) + ]; + } +} \ No newline at end of file diff --git a/dotnet/AipsCore/Domain/Models/Shape/Sub/TextShape/ValueObjects/TextShapeValue.cs b/dotnet/AipsCore/Domain/Models/Shape/Sub/TextShape/ValueObjects/TextShapeValue.cs new file mode 100644 index 0000000..8835787 --- /dev/null +++ b/dotnet/AipsCore/Domain/Models/Shape/Sub/TextShape/ValueObjects/TextShapeValue.cs @@ -0,0 +1,19 @@ +using AipsCore.Domain.Abstract.Rule; +using AipsCore.Domain.Abstract.ValueObject; + +namespace AipsCore.Domain.Models.Shape.Sub.TextShape.ValueObjects; + +public record TextShapeValue: AbstractValueObject +{ + public string Text { get; } + + public TextShapeValue(string text) + { + Text = text; + } + + protected override ICollection GetValidationRules() + { + return []; + } +} \ No newline at end of file diff --git a/dotnet/AipsCore/Domain/Models/Shape/ValueObjects/Position.cs b/dotnet/AipsCore/Domain/Models/Shape/ValueObjects/Position.cs new file mode 100644 index 0000000..22af8a8 --- /dev/null +++ b/dotnet/AipsCore/Domain/Models/Shape/ValueObjects/Position.cs @@ -0,0 +1,23 @@ +using AipsCore.Domain.Abstract.Rule; +using AipsCore.Domain.Abstract.ValueObject; + +namespace AipsCore.Domain.Models.Shape.ValueObjects; + +public record Position : AbstractValueObject +{ + public int X { get; } + public int Y { get; } + + public Position(int x, int y) + { + X = x; + Y = y; + } + + protected override ICollection GetValidationRules() + { + return [ + + ]; + } +}; \ No newline at end of file diff --git a/dotnet/AipsCore/Domain/Models/Shape/ValueObjects/ShapeId.cs b/dotnet/AipsCore/Domain/Models/Shape/ValueObjects/ShapeId.cs new file mode 100644 index 0000000..bfc6cc4 --- /dev/null +++ b/dotnet/AipsCore/Domain/Models/Shape/ValueObjects/ShapeId.cs @@ -0,0 +1,5 @@ +using AipsCore.Domain.Common.ValueObjects; + +namespace AipsCore.Domain.Models.Shape.ValueObjects; + +public record ShapeId(string Value) : DomainId(Value); \ No newline at end of file diff --git a/dotnet/AipsCore/Domain/Models/Shape/ValueObjects/Thickness.cs b/dotnet/AipsCore/Domain/Models/Shape/ValueObjects/Thickness.cs new file mode 100644 index 0000000..ce38c61 --- /dev/null +++ b/dotnet/AipsCore/Domain/Models/Shape/ValueObjects/Thickness.cs @@ -0,0 +1,27 @@ +using AipsCore.Domain.Abstract.Rule; +using AipsCore.Domain.Abstract.ValueObject; +using AipsCore.Domain.Common.Validation.Rules; + +namespace AipsCore.Domain.Models.Shape.ValueObjects; + +public record Thickness : AbstractValueObject +{ + private const int MaxThickness = 8; + private const int MinThickness = 1; + + private readonly int _value; + + public Thickness(int value) + { + _value = value; + } + + protected override ICollection GetValidationRules() + { + return + [ + new MinValueRule(_value, MinThickness), + new MaxValueRule(_value, MaxThickness), + ]; + } +} \ No newline at end of file