From 048bfb10c8e5dc06cc9d8818f38efd4a6e1857fb Mon Sep 17 00:00:00 2001 From: nathanael smiechowski Date: Tue, 12 Nov 2024 15:51:27 +0100 Subject: [PATCH 1/4] [FIX] #60 --- uml4net.Extensions/ClassExtensions.cs | 78 +++++++++++++++++++ uml4net.Extensions/PropertyExtensions.cs | 62 ++++++++------- uml4net.HandleBars/PropertyHelper.cs | 74 ++++++++++++++++-- .../Generators/ModelInspectorTestFixture.cs | 2 +- .../uml4net.Reporting.Tests.csproj | 3 + uml4net.xmi.Tests/AssemblerTestFixture.cs | 62 ++++++++++++++- uml4net.xmi.Tests/uml4net.xmi.Tests.csproj | 3 + uml4net.xmireader/Cache/Assembler.cs | 24 +----- uml4net.xmireader/Cache/IXmiReaderCache.cs | 20 ++++- uml4net.xmireader/Cache/XmiReaderCache.cs | 33 +++++--- uml4net/Extend/ClassExtensions.cs | 46 +++++++++++ .../HandCoded/StructuredClassifiers/Class.cs | 37 --------- uml4net/POCO/StructuredClassifiers/Class.cs | 2 +- 13 files changed, 338 insertions(+), 108 deletions(-) create mode 100644 uml4net.Extensions/ClassExtensions.cs create mode 100644 uml4net/Extend/ClassExtensions.cs delete mode 100644 uml4net/POCO/HandCoded/StructuredClassifiers/Class.cs diff --git a/uml4net.Extensions/ClassExtensions.cs b/uml4net.Extensions/ClassExtensions.cs new file mode 100644 index 00000000..77047301 --- /dev/null +++ b/uml4net.Extensions/ClassExtensions.cs @@ -0,0 +1,78 @@ +// ------------------------------------------------------------------------------------------------- +// +// +// 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.Extensions +{ + using System; + using System.Collections.Generic; + using System.Linq; + + using HtmlAgilityPack; + using POCO.Packages; + using POCO.SimpleClassifiers; + + using uml4net.POCO.Classification; + using uml4net.POCO.CommonStructure; + using uml4net.POCO.StructuredClassifiers; + + /// + /// Extension methods for interface + /// + public static class ClassExtensions + { + /// + /// Retrieves all properties from the specified class's abstract superclasses and any interfaces + /// implemented by those classes, traversing up the inheritance hierarchy to gather properties. + /// + /// + /// The instance for which to query properties from abstract base classes and interfaces. + /// + /// + /// An containing all properties defined in each abstract superclass + /// and each associated interface. Each property is yielded immediately upon discovery for lazy enumeration. + /// + /// + /// This method first collects properties from the direct abstract superclass of the specified class, including + /// properties from any interfaces implemented by that superclass. It then proceeds up the inheritance chain, + /// repeating this process for each abstract superclass encountered until no more superclasses are found. + /// + public static IEnumerable QueryAllAttribute(this IClass @class) + { + var baseClass = @class; + var interfaceProperties = @class.QueryInterfaces().SelectMany(x => x.Attribute); + + while (baseClass is not null) + { + foreach (var attribute in baseClass.OwnedAttribute) + { + yield return attribute; + } + + foreach (var interfaceProperty in interfaceProperties) + { + yield return interfaceProperty; + } + + interfaceProperties = baseClass.QueryInterfaces().SelectMany(x => x.Attribute).Distinct(); + baseClass = baseClass.SuperClass.FirstOrDefault(x => x.IsAbstract); + } + } + } +} \ No newline at end of file diff --git a/uml4net.Extensions/PropertyExtensions.cs b/uml4net.Extensions/PropertyExtensions.cs index 4579877e..e5d0c8b2 100644 --- a/uml4net.Extensions/PropertyExtensions.cs +++ b/uml4net.Extensions/PropertyExtensions.cs @@ -22,7 +22,8 @@ namespace uml4net.Extensions { using POCO.Values; using System; - + using System.Collections.Generic; + using System.Linq; using uml4net.POCO.Classification; using uml4net.POCO.SimpleClassifiers; using uml4net.POCO.StructuredClassifiers; @@ -43,21 +44,48 @@ public static class PropertyExtensions /// public static bool QueryIsEnum(this IProperty property) { - return property.Type is IEnumeration; + return property.DataType is IEnumeration || property.Type is IEnumeration; } /// - /// Queries whether the type of the is an + /// Queries whether the type of the is of type boolean /// /// /// The subject /// /// - /// true of the type is a , false if not + /// true if the type is a , false if not /// - public static bool QueryIsPrimitiveType(this IProperty property) + public static bool QueryIsBool(this IProperty property) { - return property.Type is IPrimitiveType; + return property?.Type?.Name?.IndexOf("bool", StringComparison.InvariantCultureIgnoreCase) >= 0; + } + + /// + /// Queries whether the type of the is a numeric type (e.g., int, double, decimal, float, etc.) + /// + /// + /// The subject + /// + /// + /// true if the type is a numeric type (e.g., int, double, decimal, float), false otherwise. + /// + public static bool QueryIsNumeric(this IProperty property) + { + if (property?.Type?.Name == null) + { + return false; + } + + var typeName = property.Type.Name.ToLowerInvariant(); + + return typeName.Contains("int") || + typeName.Contains("float") || + typeName.Contains("double") || + typeName.Contains("decimal") || + typeName.Contains("short") || + typeName.Contains("long") || + typeName.Contains("byte"); } /// @@ -71,7 +99,7 @@ public static bool QueryIsPrimitiveType(this IProperty property) /// public static bool QueryIsEnumerable(this IProperty property) { - var value = property.UpperValue switch + var value = property?.UpperValue switch { ILiteralUnlimitedNatural literalUnlimitedNatural => literalUnlimitedNatural.Value, ILiteralInteger literalInteger => literalInteger.Value, @@ -154,27 +182,9 @@ public static string QueryTypeName(this IProperty property) /// /// A /// - /// - /// The and are concrete subtypes of the - /// concrete type - /// public static bool QueryIsValueProperty(this IProperty property) { - return property.Type is IDataType; - } - - /// - /// Queries a value indicating whether the specified is a reference type - /// - /// - /// The subject - /// - /// - /// A - /// - public static bool QueryIsReferenceProperty(this IProperty property) - { - return property.Type is not IDataType; + return property.Type is IPrimitiveType or IEnumeration; } /// diff --git a/uml4net.HandleBars/PropertyHelper.cs b/uml4net.HandleBars/PropertyHelper.cs index ce2a4b11..013b699f 100644 --- a/uml4net.HandleBars/PropertyHelper.cs +++ b/uml4net.HandleBars/PropertyHelper.cs @@ -54,7 +54,7 @@ public static void RegisterStructuralFeatureHelper(this IHandlebars handlebars) return property.QueryIsEnumerable(); }); - + handlebars.RegisterHelper("Property.IsEnumerable", (output, options, context, arguments) => { if (arguments.Length != 1) @@ -115,7 +115,7 @@ public static void RegisterStructuralFeatureHelper(this IHandlebars handlebars) return property.QueryIsEnum(); }); - handlebars.RegisterHelper("Property.IsEnum", (output, options, context, arguments) => + handlebars.RegisterHelper("Property.IsEnum", (context, arguments) => { if (arguments.Length != 1) { @@ -124,12 +124,76 @@ public static void RegisterStructuralFeatureHelper(this IHandlebars handlebars) var property = arguments.Single() as IProperty; - var isEnum = property.QueryIsEnum(); + return property.QueryIsEnum(); + }); - if (isEnum) + handlebars.RegisterHelper("Property.QueryIsBool", (context, arguments) => + { + if (arguments.Length != 1) { - options.Template(output, context); + throw new HandlebarsException("{{#Property.QueryIsBool}} helper must have exactly one argument"); + } + + var property = arguments.Single() as IProperty; + + return property.QueryIsBool(); + }); + + handlebars.RegisterHelper("Property.QueryIsNumeric", (context, arguments) => + { + if (arguments.Length != 1) + { + throw new HandlebarsException("{{#Property.QueryIsNumeric}} helper must have exactly one argument"); + } + + var property = arguments.Single() as IProperty; + + return property.QueryIsNumeric(); + }); + + handlebars.RegisterHelper("Property.QueryIsInteger", (context, arguments) => + { + if (arguments.Length != 1) + { + throw new HandlebarsException("{{#Property.QueryIsInteger}} helper must have exactly one argument"); } + + var property = arguments.Single() as IProperty; + + return property?.Type?.Name.ToLowerInvariant().Contains("int"); + }); + + handlebars.RegisterHelper("Property.QueryIsFloat", (context, arguments) => + { + if (arguments.Length != 1) + { + throw new HandlebarsException("{{#Property.QueryIsFloat}} helper must have exactly one argument"); + } + + var typeName = (arguments.Single() as IProperty)?.Type?.Name?.ToLowerInvariant(); + return typeName is not null && (typeName.Contains("single") || typeName.Contains("float")); + }); + + handlebars.RegisterHelper("Property.QueryIsDouble", (context, arguments) => + { + if (arguments.Length != 1) + { + throw new HandlebarsException("{{#Property.QueryIsDouble}} helper must have exactly one argument"); + } + + var typeName = (arguments.Single() as IProperty)?.Type?.Name?.ToLowerInvariant(); + return typeName?.Contains("double"); + }); + + handlebars.RegisterHelper("Property.QueryIsDateTime", (context, arguments) => + { + if (arguments.Length != 1) + { + throw new HandlebarsException("{{#Property.QueryIsDouble}} helper must have exactly one argument"); + } + + var typeName = (arguments.Single() as IProperty)?.Type?.Name?.ToLowerInvariant(); + return typeName?.Contains("date"); }); handlebars.RegisterHelper("Property.QueryHasDefaultValue", (context, arguments) => diff --git a/uml4net.Reporting.Tests/Generators/ModelInspectorTestFixture.cs b/uml4net.Reporting.Tests/Generators/ModelInspectorTestFixture.cs index 81ec9e06..8de73f57 100644 --- a/uml4net.Reporting.Tests/Generators/ModelInspectorTestFixture.cs +++ b/uml4net.Reporting.Tests/Generators/ModelInspectorTestFixture.cs @@ -78,7 +78,7 @@ public void Verify_that_Inspection_report_can_be_executed() .WithLogger(this.loggerFactory) .Build(); - var packages = reader.Read(Path.Combine(rootPath, "UML.xmi")); + var packages = reader.Read(Path.Combine(rootPath, "model.xmi")); var rootPackage = packages.Single(); diff --git a/uml4net.Reporting.Tests/uml4net.Reporting.Tests.csproj b/uml4net.Reporting.Tests/uml4net.Reporting.Tests.csproj index 4006e6fd..e309dfb3 100644 --- a/uml4net.Reporting.Tests/uml4net.Reporting.Tests.csproj +++ b/uml4net.Reporting.Tests/uml4net.Reporting.Tests.csproj @@ -48,6 +48,9 @@ Always + + Always + diff --git a/uml4net.xmi.Tests/AssemblerTestFixture.cs b/uml4net.xmi.Tests/AssemblerTestFixture.cs index 68ffe2bc..a5e82834 100644 --- a/uml4net.xmi.Tests/AssemblerTestFixture.cs +++ b/uml4net.xmi.Tests/AssemblerTestFixture.cs @@ -26,6 +26,7 @@ namespace uml4net.xmi.Tests using System; using POCO.Classification; using POCO.SimpleClassifiers; + using System.Linq; using uml4net.POCO.CommonStructure; using uml4net.POCO.StructuredClassifiers; using uml4net.POCO.Values; @@ -112,6 +113,63 @@ public void Synchronize_ShouldSetMultiValueReference() }); } + [Test] + public void Synchronize_ShouldSetMultiValueReferenceFromExternalXmi() + { + // Arrange + const string externalXmi0 = "otherxmi"; + const string externalXmi1 = "anotherone"; + + var classElement0 = new Class { XmiId = Guid.NewGuid().ToString(), Name = "TestClass0"}; + var classElement1 = new Class { XmiId = Guid.NewGuid().ToString(), Name = "TestClass1" }; + var stringType = new PrimitiveType { XmiId = Guid.NewGuid().ToString(), Name = "string" }; + + var attribute0 = new Property + { + XmiId = Guid.NewGuid().ToString(), + SingleValueReferencePropertyIdentifiers = { { nameof(Property.Type), $"{externalXmi1}#{stringType.XmiId}" } } + }; + + var attribute1 = new Property + { + XmiId = Guid.NewGuid().ToString(), + SingleValueReferencePropertyIdentifiers = { { nameof(Property.Type), $"{externalXmi1}#{classElement1.XmiId}" } } + }; + + var comment1 = new Comment { XmiId = Guid.NewGuid().ToString(), Body = "Comment 1" }; + var comment2 = new Comment { XmiId = Guid.NewGuid().ToString(), Body = "Comment 2" }; + + classElement0.MultiValueReferencePropertyIdentifiers.Add("OwnedComment", [comment1.XmiId, comment2.XmiId]); + classElement0.MultiValueReferencePropertyIdentifiers.Add("OwnedAttribute", [$"{externalXmi0}#{attribute0.XmiId}", $"{externalXmi1}#{attribute1.XmiId}"]); + + this.cache.Add(classElement0.XmiId, classElement0); + this.cache.Add(comment1.XmiId, comment1); + this.cache.Add(comment2.XmiId, comment2); + + this.cache.SwitchContext(externalXmi0); + this.cache.Add(attribute0.XmiId, attribute0); + + this.cache.SwitchContext(externalXmi1); + this.cache.Add(attribute1.XmiId, attribute1); + this.cache.Add(classElement1.XmiId, classElement1); + this.cache.Add(stringType.XmiId, stringType); + + // Act + this.assembler.Synchronize(); + + // Assert + Assert.Multiple(() => + { + Assert.That(classElement0.OwnedComment.Count, Is.EqualTo(2)); + Assert.That(classElement0.OwnedComment.Contains(comment1)); + Assert.That(classElement0.OwnedComment.Contains(comment2)); + Assert.That(classElement0.OwnedAttribute.Contains(attribute0)); + Assert.That(classElement0.OwnedAttribute.Contains(attribute1)); + Assert.That(classElement0.OwnedAttribute.Single(x => x.XmiId == attribute1.XmiId).Type, Is.SameAs(classElement1)); + Assert.That(classElement0.OwnedAttribute.Single(x => x.XmiId == attribute0.XmiId).Type, Is.SameAs(stringType)); + }); + } + [Test] public void Synchronize_ShouldSetSingleValueReferenceAndMultipleValuesReference() { @@ -251,7 +309,7 @@ public void Synchronize_ShouldThrow_WhenElementNotIReferenceable() [Test] public void Synchronize_verify_that_type_is_set() { - var property = new Property() + var property = new Property { XmiId = "Property-aggregation", Name = "aggregation" @@ -259,7 +317,7 @@ public void Synchronize_verify_that_type_is_set() property.SingleValueReferencePropertyIdentifiers.Add("type", "AggregationKind"); - var enumeration = new Enumeration() + var enumeration = new Enumeration { XmiId = "AggregationKind", Name = "AggregationKind", diff --git a/uml4net.xmi.Tests/uml4net.xmi.Tests.csproj b/uml4net.xmi.Tests/uml4net.xmi.Tests.csproj index 0fd98eb0..dcd92d62 100644 --- a/uml4net.xmi.Tests/uml4net.xmi.Tests.csproj +++ b/uml4net.xmi.Tests/uml4net.xmi.Tests.csproj @@ -43,6 +43,9 @@ Always + + Always + diff --git a/uml4net.xmireader/Cache/Assembler.cs b/uml4net.xmireader/Cache/Assembler.cs index 498d71c2..21af07bd 100644 --- a/uml4net.xmireader/Cache/Assembler.cs +++ b/uml4net.xmireader/Cache/Assembler.cs @@ -126,27 +126,9 @@ public void ResolveReferences(IXmiElement element) /// true if the referenced element was successfully retrieved; otherwise, false. private bool TryGetReferencedElement(string referenceIdKey, out IXmiElement element) { - var isContextResolved = this.cache.TryResolveContext(referenceIdKey, out var resolvedContextAndResource); - - if (isContextResolved) - { - var isValueFound = this.cache.TryGetValue(resolvedContextAndResource.Context, resolvedContextAndResource.ResourceId, out element); - return isValueFound; - } - - foreach (var globalCacheKey in this.cache.GlobalCache.Keys) - { - var cache = this.cache.GlobalCache[globalCacheKey]; - var isFallbackFound = cache.TryGetValue(referenceIdKey, out element); - - if (isFallbackFound) - { - return true; - } - } - - element = null; - return false; + return this.cache.TryResolveContext(referenceIdKey, out var resolvedContextAndResource, true) + ? this.cache.TryGetValue(resolvedContextAndResource.Context, resolvedContextAndResource.ResourceId, out element) + : this.cache.Cache.TryGetValue(referenceIdKey, out element); } /// diff --git a/uml4net.xmireader/Cache/IXmiReaderCache.cs b/uml4net.xmireader/Cache/IXmiReaderCache.cs index bc6eef7d..b6bd9188 100644 --- a/uml4net.xmireader/Cache/IXmiReaderCache.cs +++ b/uml4net.xmireader/Cache/IXmiReaderCache.cs @@ -95,9 +95,21 @@ public interface IXmiReaderCache /// /// Attempts to resolve the context and resource ID from the specified resource key. /// - /// The key representing the resource, which may contain context and resource ID separated by '#'. - /// When this method returns, contains a tuple with the context and resource ID if resolved successfully; otherwise, (null, null). - /// true if the context and resource ID were successfully resolved; otherwise, false. - bool TryResolveContext(string resourceKey, out (string Context, string ResourceId) resolvedContextAndResource); + /// + /// The key representing the resource, which may contain context and resource ID separated by '#'. + /// + /// + /// When this method returns, contains a tuple with the resolved context and resource ID if successful; + /// otherwise, (null, null) if unsuccessful. + /// + /// + /// If true, checks whether the resolved context exists in the global cache. If false, + /// performs no such check. + /// + /// + /// true if the context and resource ID were successfully resolved and, if applicable, the + /// context exists in the global cache; otherwise, false. + /// + bool TryResolveContext(string resourceKey, out (string Context, string ResourceId) resolvedContextAndResource, bool validateContextExistence = false); } } diff --git a/uml4net.xmireader/Cache/XmiReaderCache.cs b/uml4net.xmireader/Cache/XmiReaderCache.cs index 003f7352..03d2781b 100644 --- a/uml4net.xmireader/Cache/XmiReaderCache.cs +++ b/uml4net.xmireader/Cache/XmiReaderCache.cs @@ -147,21 +147,32 @@ public void Add(string id, IXmiElement element) /// /// Attempts to resolve the context and resource ID from the specified resource key. /// - /// The key representing the resource, which may contain context and resource ID separated by '#'. - /// When this method returns, contains a tuple with the context and resource ID if resolved successfully; otherwise, (null, null). - /// true if the context and resource ID were successfully resolved; otherwise, false. - public bool TryResolveContext(string resourceKey, out (string Context, string ResourceId) resolvedContextAndResource) + /// + /// The key representing the resource, which may contain context and resource ID separated by '#'. + /// + /// + /// When this method returns, contains a tuple with the resolved context and resource ID if successful; + /// otherwise, (null, null) if unsuccessful. + /// + /// + /// If true, checks whether the resolved context exists in the global cache. If false, + /// performs no such check. + /// + /// + /// true if the context and resource ID were successfully resolved and, if applicable, the + /// context exists in the global cache; otherwise, false. + /// + public bool TryResolveContext(string resourceKey, out (string Context, string ResourceId) resolvedContextAndResource, bool validateContextExistence = false) { var referenceString = resourceKey.Split(['#'], StringSplitOptions.RemoveEmptyEntries); - if (referenceString.Length == 2) + resolvedContextAndResource = referenceString.Length switch { - resolvedContextAndResource = (referenceString[0], referenceString[1]); - return true; - } - - resolvedContextAndResource = (null, null); - return false; + 2 => (referenceString[0], referenceString[1]), + _ => (DefaultKey, resourceKey) + }; + + return !validateContextExistence || this.GlobalCache.ContainsKey(resolvedContextAndResource.Context); } } } diff --git a/uml4net/Extend/ClassExtensions.cs b/uml4net/Extend/ClassExtensions.cs new file mode 100644 index 00000000..9038b0b0 --- /dev/null +++ b/uml4net/Extend/ClassExtensions.cs @@ -0,0 +1,46 @@ +// ------------------------------------------------------------------------------------------------- +// +// +// 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.Extend +{ + using System.Collections.Generic; + using System.Linq; + + using uml4net.POCO.StructuredClassifiers; + + /// + /// The class provides extensions methods for the + /// + public static class ClassExtensions + { + /// + /// Retrieves the list of immediate superclasses for the specified class, based on its generalizations. + /// + /// + /// The instance whose superclasses are being queried. + /// + /// + /// A list of objects representing the immediate superclasses of the specified class. + /// If no superclasses are defined, returns an empty list. + /// + public static List QuerySuperClass(this IClass @class) => + @class.Generalization.Select(x => x.General).OfType().ToList(); + } +} \ No newline at end of file diff --git a/uml4net/POCO/HandCoded/StructuredClassifiers/Class.cs b/uml4net/POCO/HandCoded/StructuredClassifiers/Class.cs deleted file mode 100644 index 07f83e57..00000000 --- a/uml4net/POCO/HandCoded/StructuredClassifiers/Class.cs +++ /dev/null @@ -1,37 +0,0 @@ -// ------------------------------------------------------------------------------------------------- -// -// -// 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.POCO.StructuredClassifiers -{ - using System.Collections.Generic; - using System.Linq; - - /// - /// 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 - /// - public partial class Class - { - /// - /// Queries the superclasses of a Class, derived from its Generalizations. - /// - private List QuerySuperClass() => this.Generalization.Select(x => x.General).OfType().ToList(); - } -} diff --git a/uml4net/POCO/StructuredClassifiers/Class.cs b/uml4net/POCO/StructuredClassifiers/Class.cs index 35356b10..98197bd7 100644 --- a/uml4net/POCO/StructuredClassifiers/Class.cs +++ b/uml4net/POCO/StructuredClassifiers/Class.cs @@ -37,7 +37,7 @@ namespace uml4net.POCO.StructuredClassifiers /// 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 /// - public partial class Class : XmiElement, IClass + public class Class : XmiElement, IClass { /// /// The Comments owned by this Element. From 1efdc3c34345495b3b82db9d69a03a0f2c651ebd Mon Sep 17 00:00:00 2001 From: nathanael smiechowski Date: Tue, 12 Nov 2024 17:43:42 +0100 Subject: [PATCH 2/4] [FIX] build --- .../Generators/ModelInspectorTestFixture.cs | 4 ++-- uml4net.Reporting.Tests/uml4net.Reporting.Tests.csproj | 5 +---- uml4net.xmi.Tests/uml4net.xmi.Tests.csproj | 5 +---- 3 files changed, 4 insertions(+), 10 deletions(-) diff --git a/uml4net.Reporting.Tests/Generators/ModelInspectorTestFixture.cs b/uml4net.Reporting.Tests/Generators/ModelInspectorTestFixture.cs index 8de73f57..611767fc 100644 --- a/uml4net.Reporting.Tests/Generators/ModelInspectorTestFixture.cs +++ b/uml4net.Reporting.Tests/Generators/ModelInspectorTestFixture.cs @@ -1,4 +1,4 @@ -// ------------------------------------------------------------------------------------------------- +// ------------------------------------------------------------------------------------------------- // // // Copyright 2019-2024 Starion Group S.A. @@ -78,7 +78,7 @@ public void Verify_that_Inspection_report_can_be_executed() .WithLogger(this.loggerFactory) .Build(); - var packages = reader.Read(Path.Combine(rootPath, "model.xmi")); + var packages = reader.Read(Path.Combine(rootPath, "UML.xmi")); var rootPackage = packages.Single(); diff --git a/uml4net.Reporting.Tests/uml4net.Reporting.Tests.csproj b/uml4net.Reporting.Tests/uml4net.Reporting.Tests.csproj index e309dfb3..8760415f 100644 --- a/uml4net.Reporting.Tests/uml4net.Reporting.Tests.csproj +++ b/uml4net.Reporting.Tests/uml4net.Reporting.Tests.csproj @@ -1,4 +1,4 @@ - + net8.0 @@ -48,9 +48,6 @@ Always - - Always - diff --git a/uml4net.xmi.Tests/uml4net.xmi.Tests.csproj b/uml4net.xmi.Tests/uml4net.xmi.Tests.csproj index dcd92d62..ee34e4d7 100644 --- a/uml4net.xmi.Tests/uml4net.xmi.Tests.csproj +++ b/uml4net.xmi.Tests/uml4net.xmi.Tests.csproj @@ -1,4 +1,4 @@ - + net8.0 @@ -43,9 +43,6 @@ Always - - Always - From a9b782ab3ee6d2a3b251b9cb97193996fbc62d76 Mon Sep 17 00:00:00 2001 From: nathanael smiechowski Date: Wed, 13 Nov 2024 07:44:23 +0100 Subject: [PATCH 3/4] [FIX] Rebase gone wrong --- uml4net.Extensions/ClassExtensions.cs | 6 ------ uml4net.Extensions/PropertyExtensions.cs | 16 ++++++++++++++-- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/uml4net.Extensions/ClassExtensions.cs b/uml4net.Extensions/ClassExtensions.cs index 77047301..e988e0dd 100644 --- a/uml4net.Extensions/ClassExtensions.cs +++ b/uml4net.Extensions/ClassExtensions.cs @@ -20,16 +20,10 @@ namespace uml4net.Extensions { - using System; using System.Collections.Generic; using System.Linq; - using HtmlAgilityPack; - using POCO.Packages; - using POCO.SimpleClassifiers; - using uml4net.POCO.Classification; - using uml4net.POCO.CommonStructure; using uml4net.POCO.StructuredClassifiers; /// diff --git a/uml4net.Extensions/PropertyExtensions.cs b/uml4net.Extensions/PropertyExtensions.cs index e5d0c8b2..d06344ca 100644 --- a/uml4net.Extensions/PropertyExtensions.cs +++ b/uml4net.Extensions/PropertyExtensions.cs @@ -22,8 +22,6 @@ namespace uml4net.Extensions { using POCO.Values; using System; - using System.Collections.Generic; - using System.Linq; using uml4net.POCO.Classification; using uml4net.POCO.SimpleClassifiers; using uml4net.POCO.StructuredClassifiers; @@ -173,6 +171,20 @@ public static string QueryTypeName(this IProperty property) return property.Type?.Name; } + /// + /// Queries a value indicating whether the specified is a reference type + /// + /// + /// The subject + /// + /// + /// A + /// + public static bool QueryIsReferenceProperty(this IProperty property) + { + return property.Type is not IDataType; + } + /// /// Queries a value indicating whether the specified type is a value type or /// From 5db0f4c095239e6bb9de00b7d96a3e10a5818fc2 Mon Sep 17 00:00:00 2001 From: nathanael smiechowski Date: Wed, 13 Nov 2024 16:54:46 +0100 Subject: [PATCH 4/4] [FIX] Comments --- uml4net.Extensions/ClassExtensions.cs | 45 +++++++------------ uml4net.Extensions/ClassifierExtensions.cs | 52 ++++++++++++++++++++++ uml4net.Extensions/PropertyExtensions.cs | 4 +- 3 files changed, 70 insertions(+), 31 deletions(-) create mode 100644 uml4net.Extensions/ClassifierExtensions.cs diff --git a/uml4net.Extensions/ClassExtensions.cs b/uml4net.Extensions/ClassExtensions.cs index e988e0dd..e164a3db 100644 --- a/uml4net.Extensions/ClassExtensions.cs +++ b/uml4net.Extensions/ClassExtensions.cs @@ -21,6 +21,7 @@ namespace uml4net.Extensions { using System.Collections.Generic; + using System.Collections.ObjectModel; using System.Linq; using uml4net.POCO.Classification; @@ -32,41 +33,27 @@ namespace uml4net.Extensions public static class ClassExtensions { /// - /// Retrieves all properties from the specified class's abstract superclasses and any interfaces - /// implemented by those classes, traversing up the inheritance hierarchy to gather properties. + /// Queries all the properties that are implemented by the class directly or through superclasses + /// or interface implementations /// - /// - /// The instance for which to query properties from abstract base classes and interfaces. - /// - /// - /// An containing all properties defined in each abstract superclass - /// and each associated interface. Each property is yielded immediately upon discovery for lazy enumeration. - /// - /// - /// This method first collects properties from the direct abstract superclass of the specified class, including - /// properties from any interfaces implemented by that superclass. It then proceeds up the inheritance chain, - /// repeating this process for each abstract superclass encountered until no more superclasses are found. - /// - public static IEnumerable QueryAllAttribute(this IClass @class) + /// The from which to query the properties + /// A of + public static ReadOnlyCollection QueryAllProperties(this IClass @class) { - var baseClass = @class; - var interfaceProperties = @class.QueryInterfaces().SelectMany(x => x.Attribute); + var result = new List(); - while (baseClass is not null) - { - foreach (var attribute in baseClass.OwnedAttribute) - { - yield return attribute; - } + var superClassifiers = @class.QueryAllGeneralClassifiers(); - foreach (var interfaceProperty in interfaceProperties) + foreach (var classifier in superClassifiers) + { + if (classifier is IClass c) { - yield return interfaceProperty; + result.AddRange(c.OwnedAttribute); + result.AddRange(c.QueryInterfaces().SelectMany(x => x.Attribute).Distinct()); } - - interfaceProperties = baseClass.QueryInterfaces().SelectMany(x => x.Attribute).Distinct(); - baseClass = baseClass.SuperClass.FirstOrDefault(x => x.IsAbstract); } + + return result.Distinct().ToList().AsReadOnly(); } } -} \ No newline at end of file +} diff --git a/uml4net.Extensions/ClassifierExtensions.cs b/uml4net.Extensions/ClassifierExtensions.cs new file mode 100644 index 00000000..c2e47be3 --- /dev/null +++ b/uml4net.Extensions/ClassifierExtensions.cs @@ -0,0 +1,52 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) 2024 Starion Group N.V. +// +// Author: Seliman Niakate, Sebastien d'Antuono, Nathanael Smiechowski, Amine Nemmaoui, Amir Janati. +// +// This file is part of the SafePlace solution. +// +// SafePlace is distributed under the terms and conditions of the +// European Space Agency Public License (ESA-PL) Weak Copyleft (Type 2) – v2.4 +// +// -------------------------------------------------------------------------------------------------------------------- + +namespace uml4net.Extensions +{ + using POCO.Classification; + using System.Collections.Generic; + + using System.Collections.ObjectModel; + using System.Linq; + + /// + /// The class provides extensions methods for the + /// + public static class ClassifierExtensions + { + /// + /// Queries all the general s of the subject + /// + /// + /// the subject + /// + /// + /// a readonly collection of s, including the subject , of + /// all the super classifiers + /// + public static ReadOnlyCollection QueryAllGeneralClassifiers(this IClassifier classifier) + { + var result = new List { classifier }; + + if (classifier.Generalization != null) + { + foreach (var generalization in classifier.Generalization) + { + result.AddRange(generalization.General.QueryAllGeneralClassifiers()); + } + } + + return result.Distinct().ToList().AsReadOnly(); + } + } +} diff --git a/uml4net.Extensions/PropertyExtensions.cs b/uml4net.Extensions/PropertyExtensions.cs index d06344ca..5870c9e6 100644 --- a/uml4net.Extensions/PropertyExtensions.cs +++ b/uml4net.Extensions/PropertyExtensions.cs @@ -42,7 +42,7 @@ public static class PropertyExtensions /// public static bool QueryIsEnum(this IProperty property) { - return property.DataType is IEnumeration || property.Type is IEnumeration; + return property.Type is IEnumeration; } /// @@ -196,7 +196,7 @@ public static bool QueryIsReferenceProperty(this IProperty property) /// public static bool QueryIsValueProperty(this IProperty property) { - return property.Type is IPrimitiveType or IEnumeration; + return property.Type is IDataType; } ///