From a3fe68c1a16583ab112922d73c99a52594282b4b Mon Sep 17 00:00:00 2001 From: samatstarion Date: Wed, 9 Oct 2024 16:47:08 +0200 Subject: [PATCH] [Add] EnumerationReader and EnumerationLiteralReader --- uml4net.xmi.Tests/UMLXmiReaderTestFixture.cs | 20 ++- uml4net.xmireader/Packages/PackageReader.cs | 5 +- .../EnumerationLiteralReader.cs | 116 ++++++++++++++++ .../SimpleClassifiers/EnumerationReader.cs | 126 ++++++++++++++++++ uml4net/POCO/SimpleClassifiers/Enumeration.cs | 8 ++ .../SimpleClassifiers/EnumerationLiteral.cs | 18 ++- .../POCO/SimpleClassifiers/IEnumeration.cs | 11 ++ .../SimpleClassifiers/IEnumerationLiteral.cs | 14 ++ 8 files changed, 315 insertions(+), 3 deletions(-) create mode 100644 uml4net.xmireader/SimpleClassifiers/EnumerationLiteralReader.cs create mode 100644 uml4net.xmireader/SimpleClassifiers/EnumerationReader.cs diff --git a/uml4net.xmi.Tests/UMLXmiReaderTestFixture.cs b/uml4net.xmi.Tests/UMLXmiReaderTestFixture.cs index 91d4d327..13f8c6fc 100644 --- a/uml4net.xmi.Tests/UMLXmiReaderTestFixture.cs +++ b/uml4net.xmi.Tests/UMLXmiReaderTestFixture.cs @@ -28,8 +28,9 @@ namespace uml4net.xmi.Tests using NUnit.Framework; using uml4net.POCO.Packages; + using uml4net.POCO.SimpleClassifiers; using uml4net.POCO.StructuredClassifiers; - + [TestFixture] public class UMLXmiReaderTestFixture { @@ -89,6 +90,23 @@ public void Verify_that_UML_XMI_can_be_read() Assert.That(classOwnedComment.Body, Is.EqualTo("A Class classifies a set of objects and specifies the features that characterize the structure and behavior of those objects. A Class may have an internal structure and Ports.\r\n")); Assert.That(@class.Generalization.Count, Is.EqualTo(2)); + + var structuredClassifiersPackageEnumerations = structuredClassifiersPackage.PackagedElement.OfType(); + + Assert.That(structuredClassifiersPackageEnumerations.Count, Is.EqualTo(1)); + + var connectorKindEnumeration = structuredClassifiersPackageEnumerations.Single(); + + Assert.That(connectorKindEnumeration.Name, Is.EqualTo("ConnectorKind")); + Assert.That(connectorKindEnumeration.OwnedComment.First().Body, Is.EqualTo("ConnectorKind is an enumeration that defines whether a Connector is an assembly or a delegation.")); + + Assert.That(connectorKindEnumeration.OwnedLiteral.Count, Is.EqualTo(2)); + + var connectorKindEnumerationEnumerationLiteralAssembly = connectorKindEnumeration.OwnedLiteral.First(); + + Assert.That(connectorKindEnumerationEnumerationLiteralAssembly.Name, Is.EqualTo("assembly")); + Assert.That(connectorKindEnumerationEnumerationLiteralAssembly.OwnedComment.First().Body, Is.EqualTo("Indicates that the Connector is an assembly Connector.")); + } } } diff --git a/uml4net.xmireader/Packages/PackageReader.cs b/uml4net.xmireader/Packages/PackageReader.cs index f572b956..c06f7a66 100644 --- a/uml4net.xmireader/Packages/PackageReader.cs +++ b/uml4net.xmireader/Packages/PackageReader.cs @@ -30,6 +30,7 @@ namespace uml4net.xmi.Packages using uml4net.POCO.Packages; using uml4net.xmi.CommonStructure; + using uml4net.xmi.SimpleClassifiers; using uml4net.xmi.StructuredClassifiers; /// @@ -181,7 +182,9 @@ private void ReadPackagedElements(IPackage package, XmlReader xmlReader) case "uml:Enumeration": using (var enumerationXmlReader = xmlReader.ReadSubtree()) { - this.logger.LogDebug("uml:Enumeration not yet implements"); + var enumerationReader = new EnumerationReader(); + var enumeration = enumerationReader.Read(enumerationXmlReader); + package.PackagedElement.Add(enumeration); } break; case "uml:Package": diff --git a/uml4net.xmireader/SimpleClassifiers/EnumerationLiteralReader.cs b/uml4net.xmireader/SimpleClassifiers/EnumerationLiteralReader.cs new file mode 100644 index 00000000..03922b5a --- /dev/null +++ b/uml4net.xmireader/SimpleClassifiers/EnumerationLiteralReader.cs @@ -0,0 +1,116 @@ +// ------------------------------------------------------------------------------------------------- +// +// +// Copyright 2019-2024 Starion Group S.A. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, softwareUseCases +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// +// ------------------------------------------------------------------------------------------------ + +namespace uml4net.xmi.SimpleClassifiers +{ + using System; + using System.Xml; + + using Microsoft.Extensions.Logging; + using Microsoft.Extensions.Logging.Abstractions; + + using uml4net.POCO.CommonStructure; + using uml4net.POCO.SimpleClassifiers; + using uml4net.POCO.StructuredClassifiers; + using uml4net.xmi.Classification; + using uml4net.xmi.CommonStructure; + + /// + /// The purpose of the is to read an instance of + /// from the XMI document + /// + public class EnumerationLiteralReader + { + /// + /// The (injected) used to setup logging + /// + private readonly ILoggerFactory loggerFactory; + + /// + /// The used to log + /// + private readonly ILogger logger; + + /// + /// Initializes a new instance of the class. + /// + /// + /// The (injected) used to setup logging + /// + public EnumerationLiteralReader(ILoggerFactory loggerFactory = null) + { + this.loggerFactory = loggerFactory; + + this.logger = this.loggerFactory == null ? NullLogger.Instance : this.loggerFactory.CreateLogger(); + } + + /// + /// Reads the object from its XML representation + /// + /// + /// an instance of + /// + /// + /// an instance of + /// + public IEnumerationLiteral Read(XmlReader xmlReader) + { + IEnumerationLiteral enumerationLiteral = new EnumerationLiteral(); + + if (xmlReader.MoveToContent() == XmlNodeType.Element) + { + enumerationLiteral.XmiId = xmlReader.GetAttribute("xmi:id"); + + var xmiType = xmlReader.GetAttribute("xmi:type"); + + if (xmiType != "uml:EnumerationLiteral") + { + throw new XmlException($"The XmiType should be: uml:EnumerationLiteral while it is {xmiType}"); + } + + enumerationLiteral.XmiType = xmlReader.GetAttribute("xmi:type"); + + enumerationLiteral.Name = xmlReader.GetAttribute("name"); + + while (xmlReader.Read()) + { + if (xmlReader.NodeType == XmlNodeType.Element) + { + switch (xmlReader.LocalName) + { + case "ownedComment": + using (var ownedCommentXmlReader = xmlReader.ReadSubtree()) + { + var commentReader = new CommentReader(this.loggerFactory); + var comment = commentReader.Read(ownedCommentXmlReader); + enumerationLiteral.OwnedComment.Add(comment); + } + break; + default: + throw new NotImplementedException($"EnumerationLiteralReader: {xmlReader.LocalName}"); + } + } + } + } + + return enumerationLiteral; + } + } +} \ No newline at end of file diff --git a/uml4net.xmireader/SimpleClassifiers/EnumerationReader.cs b/uml4net.xmireader/SimpleClassifiers/EnumerationReader.cs new file mode 100644 index 00000000..a5b25cfa --- /dev/null +++ b/uml4net.xmireader/SimpleClassifiers/EnumerationReader.cs @@ -0,0 +1,126 @@ +// ------------------------------------------------------------------------------------------------- +// +// +// Copyright 2019-2024 Starion Group S.A. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, softwareUseCases +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// +// ------------------------------------------------------------------------------------------------ + +namespace uml4net.xmi.SimpleClassifiers +{ + using System; + using System.Xml; + + using Microsoft.Extensions.Logging; + using Microsoft.Extensions.Logging.Abstractions; + + using uml4net.POCO.CommonStructure; + using uml4net.POCO.SimpleClassifiers; + using uml4net.POCO.StructuredClassifiers; + using uml4net.xmi.Classification; + using uml4net.xmi.CommonStructure; + + /// + /// The purpose of the is to read an instance of + /// from the XMI document + /// + public class EnumerationReader + { + /// + /// The (injected) used to setup logging + /// + private readonly ILoggerFactory loggerFactory; + + /// + /// The used to log + /// + private readonly ILogger logger; + + /// + /// Initializes a new instance of the class. + /// + /// + /// The (injected) used to setup logging + /// + public EnumerationReader(ILoggerFactory loggerFactory = null) + { + this.loggerFactory = loggerFactory; + + this.logger = this.loggerFactory == null ? NullLogger.Instance : this.loggerFactory.CreateLogger(); + } + + /// + /// Reads the object from its XML representation + /// + /// + /// an instance of + /// + /// + /// an instance of + /// + public IEnumeration Read(XmlReader xmlReader) + { + IEnumeration enumeration = new Enumeration(); + + if (xmlReader.MoveToContent() == XmlNodeType.Element) + { + enumeration.XmiId = xmlReader.GetAttribute("xmi:id"); + + var xmiType = xmlReader.GetAttribute("xmi:type"); + + if (xmiType != "uml:Enumeration") + { + throw new XmlException($"The XmiType should be: uml:Enumeration while it is {xmiType}"); + } + + enumeration.XmiType = xmlReader.GetAttribute("xmi:type"); + + enumeration.Name = xmlReader.GetAttribute("name"); + + while (xmlReader.Read()) + { + if (xmlReader.NodeType == XmlNodeType.Element) + { + switch (xmlReader.LocalName) + { + case "ownedComment": + using (var ownedCommentXmlReader = xmlReader.ReadSubtree()) + { + var commentReader = new CommentReader(this.loggerFactory); + var comment = commentReader.Read(ownedCommentXmlReader); + enumeration.OwnedComment.Add(comment); + } + break; + case "ownedLiteral": + using (var ownedLiteralXmlReader = xmlReader.ReadSubtree()) + { + var enumerationLiteralReader = new EnumerationLiteralReader(this.loggerFactory); + var enumerationLiteral = enumerationLiteralReader.Read(ownedLiteralXmlReader); + enumeration.OwnedLiteral.Add(enumerationLiteral); + + this.logger.LogInformation("ClassReader.ownedRule not yet implemented"); + } + break; + default: + throw new NotImplementedException($"ClassReader: {xmlReader.LocalName}"); + } + } + } + } + + return enumeration; + } + } +} \ No newline at end of file diff --git a/uml4net/POCO/SimpleClassifiers/Enumeration.cs b/uml4net/POCO/SimpleClassifiers/Enumeration.cs index 7b8f7340..b4ba2863 100644 --- a/uml4net/POCO/SimpleClassifiers/Enumeration.cs +++ b/uml4net/POCO/SimpleClassifiers/Enumeration.cs @@ -354,5 +354,13 @@ public class Enumeration : IEnumeration [Property(aggregation: AggregationKind.None, lowerValue: 0, upperValue: int.MaxValue, isReadOnly: true, isDerived: true, isDerivedUnion: true)] [Implements(implementation: "IRedefinableElement.RedefinitionContext")] public IClassifier RedefinitionContext => throw new NotImplementedException(); + + /// + /// The ordered set of literals owned by this Enumeration. + /// + [Property(aggregation: AggregationKind.Composite, lowerValue: 0, upperValue: int.MaxValue)] + [SubsettedProperty("Namespace-ownedMember")] + [Implements(implementation: "IEnumeration.OwnedLiteral")] + public List OwnedLiteral { get; set; } = new(); } } diff --git a/uml4net/POCO/SimpleClassifiers/EnumerationLiteral.cs b/uml4net/POCO/SimpleClassifiers/EnumerationLiteral.cs index 086e1ede..b2ed9d45 100644 --- a/uml4net/POCO/SimpleClassifiers/EnumerationLiteral.cs +++ b/uml4net/POCO/SimpleClassifiers/EnumerationLiteral.cs @@ -142,7 +142,7 @@ public class EnumerationLiteral : IEnumerationLiteral /// [Property(aggregation: AggregationKind.None, lowerValue: 0, upperValue: int.MaxValue)] [Implements("IInstanceSpecification.Classifier")] - public List Classifier { get; set; } = new List(); + List IInstanceSpecification.Classifier { get; set; } = new List(); /// /// A Slot giving the value or values of a StructuralFeature of the instance. An InstanceSpecification @@ -161,5 +161,21 @@ public class EnumerationLiteral : IEnumerationLiteral [Property(aggregation: AggregationKind.Composite, lowerValue: 0, upperValue: 1)] [Implements("IInstanceSpecification.Specification")] public IValueSpecification Specification { get; set; } + + /// + /// The classifier of this EnumerationLiteral derived to be equal to its Enumeration. + /// + [Property(aggregation: AggregationKind.None, lowerValue: 0, upperValue: 1, isReadOnly: true, isDerived: true)] + [RedefinedProperty("InstanceSpecification-classifier")] + [Implements("IEnumeration.Classifier")] + public IEnumeration Classifier => throw new NotImplementedException(); + + /// + /// The Enumeration that this EnumerationLiteral is a member of. + /// + [Property(aggregation: AggregationKind.None, lowerValue: 1, upperValue: 1)] + [SubsettedProperty("NamedElement-namespace")] + [Implements("IEnumeration.Enumeration")] + public IEnumeration Enumeration { get; set; } } } diff --git a/uml4net/POCO/SimpleClassifiers/IEnumeration.cs b/uml4net/POCO/SimpleClassifiers/IEnumeration.cs index e93b2a74..a2b77ffe 100644 --- a/uml4net/POCO/SimpleClassifiers/IEnumeration.cs +++ b/uml4net/POCO/SimpleClassifiers/IEnumeration.cs @@ -20,10 +20,21 @@ namespace uml4net.POCO.SimpleClassifiers { + using System.Collections.Generic; + + using uml4net.Decorators; + using uml4net.POCO.Classification; + /// /// An Enumeration is a DataType whose values are enumerated in the model as EnumerationLiterals. /// public interface IEnumeration : IDataType { + /// + /// The ordered set of literals owned by this Enumeration. + /// + [Property(aggregation: AggregationKind.Composite, lowerValue: 0, upperValue: int.MaxValue)] + [SubsettedProperty("Namespace-ownedMember")] + public List OwnedLiteral { get; set; } } } diff --git a/uml4net/POCO/SimpleClassifiers/IEnumerationLiteral.cs b/uml4net/POCO/SimpleClassifiers/IEnumerationLiteral.cs index 68292e7c..f96514a0 100644 --- a/uml4net/POCO/SimpleClassifiers/IEnumerationLiteral.cs +++ b/uml4net/POCO/SimpleClassifiers/IEnumerationLiteral.cs @@ -20,6 +20,7 @@ namespace uml4net.POCO.SimpleClassifiers { + using uml4net.Decorators; using uml4net.POCO.Classification; /// @@ -27,5 +28,18 @@ namespace uml4net.POCO.SimpleClassifiers /// public interface IEnumerationLiteral : IInstanceSpecification { + /// + /// The classifier of this EnumerationLiteral derived to be equal to its Enumeration. + /// + [Property(aggregation: AggregationKind.None, lowerValue: 1, upperValue: 1, isReadOnly:true, isDerived:true)] + [RedefinedProperty("InstanceSpecification-classifier")] + public new IEnumeration Classifier { get; } + + /// + /// The Enumeration that this EnumerationLiteral is a member of. + /// + [Property(aggregation: AggregationKind.None, lowerValue: 1, upperValue: 1)] + [SubsettedProperty("NamedElement-namespace")] + public IEnumeration Enumeration { get; set; } } }