From 492c3dc05f11ea5ebe86c60fdb9a86f7022ff748 Mon Sep 17 00:00:00 2001 From: Michael Hoffmeister Date: Tue, 7 Nov 2023 23:28:10 +0100 Subject: [PATCH] * multiple SAMM versions * creat SM instance --- src/AasxCore.Samm2_2_0/SammClasses.cs | 534 +++++++++++++----- src/AasxPackageExplorer/debug.MIHO.script | 5 +- .../options-debug.MIHO.json | 2 +- .../DispEditHelperEntities.cs | 3 +- .../DispEditHelperSammModules.cs | 381 +++++++++---- 5 files changed, 662 insertions(+), 263 deletions(-) diff --git a/src/AasxCore.Samm2_2_0/SammClasses.cs b/src/AasxCore.Samm2_2_0/SammClasses.cs index 7917d80ac..9cc81fe5d 100644 --- a/src/AasxCore.Samm2_2_0/SammClasses.cs +++ b/src/AasxCore.Samm2_2_0/SammClasses.cs @@ -7,9 +7,11 @@ This source code is licensed under the Apache License 2.0 (see LICENSE.txt). This source code may use other Open Source software components (see LICENSE.txt). */ +using System; using System.Collections; using System.Drawing; using System.Linq.Expressions; +using System.Reflection; using System.Reflection.PortableExecutable; using System.Runtime.Serialization; using AasCore.Aas3_0; @@ -93,10 +95,12 @@ public SammMultiLineAttribute(int maxLines = -1) public class SammPropertyUriAttribute : System.Attribute { public string Uri = ""; + public SammVersion Version = SammVersion.V_1_0_0; - public SammPropertyUriAttribute(string uri) + public SammPropertyUriAttribute(string uri, SammVersion version) { Uri = uri; + Version = version; } } @@ -108,10 +112,12 @@ public SammPropertyUriAttribute(string uri) public class SammCollectionContentUriAttribute : System.Attribute { public string Uri = ""; + public SammVersion Version = SammVersion.V_1_0_0; - public SammCollectionContentUriAttribute(string uri) + public SammCollectionContentUriAttribute(string uri, SammVersion version) { Uri = uri; + Version = version; } } @@ -136,10 +142,12 @@ public SammPropertyFlagsAttribute(string flags) public class SammPropertyPrefixAttribute : System.Attribute { public string Prefix = ""; + public SammVersion Version = SammVersion.V_1_0_0; - public SammPropertyPrefixAttribute(string prefix) + public SammPropertyPrefixAttribute(string prefix, SammVersion version) { Prefix = prefix; + Version = version; } } @@ -157,7 +165,7 @@ public interface ISammSelfDescription /// /// Get URN of this element class. /// - string GetSelfUrn(); + string GetSelfUrn(SammVersion version); } /// @@ -193,7 +201,8 @@ public class ModelElement /// times for different languages but only once for a specific language. There should /// be at least one preferredName defined with an "en" language tag. /// - [SammPropertyUri("bamm:preferredName")] + [SammPropertyUri("bamm:preferredName", SammVersion.V_1_0_0)] + [SammPropertyUri("samm:preferredName", SammVersion.V_2_0_0)] public List? PreferredName { get; set; } = null; // Note: Description is already in the Referable @@ -209,7 +218,8 @@ public class ModelElement /// A reference to a related element in an external taxonomy, ontology or other standards document. /// The datatype is xsd:anyURI. This attribute may be defined multiple times. /// - [SammPropertyUri("bamm:see")] + [SammPropertyUri("bamm:see", SammVersion.V_1_0_0)] + [SammPropertyUri("samm:see", SammVersion.V_2_0_0)] [SammPropertyFlags("anyuri")] public List? See { get; set; } = null; } @@ -495,6 +505,10 @@ public bool AddOrIgnore(string prefix, string uri) // not found .. give whole back return input; } + + public bool ContainsPrefix(string prefix) => Map.ContainsKey(prefix); + + public NamespaceMapItem GetFromPrefix(string prefix) => Map[prefix]; } /// @@ -507,7 +521,7 @@ public class Constraint : ModelElement, ISammSelfDescription { // self description public string GetSelfName() => "samm-constraint"; - public string GetSelfUrn() => "bamm-c:Constraint"; + public string GetSelfUrn(SammVersion v) => (v == SammVersion.V_1_0_0) ? "bamm-c:Constraint" : "samm-c:Constraint"; } /// @@ -519,13 +533,14 @@ public class LanguageConstraint : Constraint, ISammSelfDescription { // self description public new string GetSelfName() => "samm-language-constraint"; - public new string GetSelfUrn() => "bamm-c:LanguageConstraint"; + public new string GetSelfUrn(SammVersion v) => (v == SammVersion.V_1_0_0) ? "bamm-c:LanguageConstraint" : "samm-c:LanguageConstraint"; /// /// An ISO 639-1 [iso639] language code for the language of the value of the constrained Property, /// e.g., "de". /// - [SammPropertyUri("bamm-c:languageCode")] + [SammPropertyUri("bamm-c:languageCode", SammVersion.V_1_0_0)] + [SammPropertyUri("samm-c:languageCode", SammVersion.V_2_0_0)] public string? LanguageCode { get; set; } } @@ -538,12 +553,13 @@ public class LocaleConstraint : Constraint, ISammSelfDescription { // self description public new string GetSelfName() => "samm-locale-constraint"; - public new string GetSelfUrn() => "bamm-c:LocaleConstraint"; + public new string GetSelfUrn(SammVersion v) => (v == SammVersion.V_1_0_0) ? "bamm-c:LocaleConstraint" : "samm-c:LocaleConstraint"; /// /// An IETF BCP 47 language code for the locale of the value of the constrained Property, e.g., "de-DE". /// - [SammPropertyUri("bamm-c:localeCode")] + [SammPropertyUri("bamm-c:localeCode", SammVersion.V_1_0_0)] + [SammPropertyUri("samm-c:localeCode", SammVersion.V_2_0_0)] public string? LocaleCode { get; set; } } @@ -555,34 +571,40 @@ public class RangeConstraint : Constraint, ISammSelfDescription { // self description public new string GetSelfName() => "samm-range-constraint"; - public new string GetSelfUrn() => "bamm-c:RangeConstraint"; + public new string GetSelfUrn(SammVersion v) => (v == SammVersion.V_1_0_0) ? "bamm-c:RangeConstraint" : "samm-c:RangeConstraint"; /// /// The upper bound of a range. /// - [SammPropertyUri("bamm-c:maxValue")] + [SammPropertyUri("bamm-c:maxValue", SammVersion.V_1_0_0)] + [SammPropertyUri("samm-c:maxValue", SammVersion.V_2_0_0)] public string? MaxValue { get; set; } /// /// The lower bound of a range. /// - [SammPropertyUri("bamm-c:minValue")] + [SammPropertyUri("bamm-c:minValue", SammVersion.V_1_0_0)] + [SammPropertyUri("samm-c:minValue", SammVersion.V_2_0_0)] public string? MinValue { get; set; } /// /// Defines whether the upper bound of a range is inclusive or exclusive. Possible values are /// AT_MOST and LESS_THAN. /// - [SammPropertyUri("bamm-c:upperBoundDefinition")] - [SammPropertyPrefix("bamm-c:")] + [SammPropertyUri("bamm-c:upperBoundDefinition", SammVersion.V_1_0_0)] + [SammPropertyUri("samm-c:upperBoundDefinition", SammVersion.V_2_0_0)] + [SammPropertyPrefix("bamm-c:", SammVersion.V_1_0_0)] + [SammPropertyPrefix("samm-c:", SammVersion.V_2_0_0)] public SammUpperBoundDefinition? UpperBoundDefinition { get; set; } /// /// Defines whether the lower bound of a range is inclusive or exclusive. Possible values are /// AT_LEAST and GREATER_THAN. /// - [SammPropertyUri("bamm-c:lowerBoundDefinition")] - [SammPropertyPrefix("bamm-c:")] + [SammPropertyUri("bamm-c:lowerBoundDefinition", SammVersion.V_1_0_0)] + [SammPropertyUri("samm-c:lowerBoundDefinition", SammVersion.V_2_0_0)] + [SammPropertyPrefix("bamm-c:", SammVersion.V_1_0_0)] + [SammPropertyPrefix("samm-c:", SammVersion.V_2_0_0)] public SammLowerBoundDefinition? LowerBoundDefinition { get; set; } } @@ -595,14 +617,16 @@ public class EncodingConstraint : Constraint, ISammSelfDescription { // self description public new string GetSelfName() => "samm-encoding-constraint"; - public new string GetSelfUrn() => "bamm-c:EncodingConstraint"; + public new string GetSelfUrn(SammVersion v) => (v == SammVersion.V_1_0_0) ? "bamm-c:EncodingConstraint" : "samm-c:EncodingConstraint"; /// /// Configures the encoding. This must be one of the following: /// US-ASCII, ISO-8859-1, UTF-8, UTF-16, UTF-16BE or UTF-16LE. /// - [SammPropertyUri("bamm-c:value")] - [SammPropertyPrefix("bamm-c:")] + [SammPropertyUri("bamm-c:value", SammVersion.V_1_0_0)] + [SammPropertyUri("samm-c:value", SammVersion.V_2_0_0)] + [SammPropertyPrefix("bamm-c:", SammVersion.V_1_0_0)] + [SammPropertyPrefix("samm-c:", SammVersion.V_2_0_0)] public SammEncoding? Value { get; set; } } @@ -619,18 +643,20 @@ public class LengthConstraint : Constraint, ISammSelfDescription { // self description public new string GetSelfName() => "samm-length-constraint"; - public new string GetSelfUrn() => "bamm-c:LengthConstraint"; + public new string GetSelfUrn(SammVersion v) => (v == SammVersion.V_1_0_0) ? "bamm-c:LengthConstraint" : "samm-c:LengthConstraint"; /// /// The maximum length. Must be given as xsd:nonNegativeInteger. /// - [SammPropertyUri("bamm-c:maxValue")] + [SammPropertyUri("bamm-c:maxValue", SammVersion.V_1_0_0)] + [SammPropertyUri("samm-c:maxValue", SammVersion.V_2_0_0)] public uint? MaxValue { get; set; } /// /// The minimum length. Must be given as xsd:nonNegativeInteger. /// - [SammPropertyUri("bamm-c:minValue")] + [SammPropertyUri("bamm-c:minValue", SammVersion.V_1_0_0)] + [SammPropertyUri("samm-c:minValue", SammVersion.V_2_0_0)] public uint? MinValue { get; set; } } @@ -645,13 +671,14 @@ public class RegularExpressionConstraint : Constraint, ISammSelfDescription { // self description public new string GetSelfName() => "samm-regular-expression-constraint"; - public new string GetSelfUrn() => "bamm-c:RegularExpressionConstraint"; + public new string GetSelfUrn(SammVersion v) => (v == SammVersion.V_1_0_0) ? "bamm-c:RegularExpressionConstraint" : "samm-c:RegularExpressionConstraint"; /// /// The regular expression. /// /// - [SammPropertyUri("bamm-c:value")] + [SammPropertyUri("bamm:value", SammVersion.V_1_0_0)] + [SammPropertyUri("samm:value", SammVersion.V_2_0_0)] public string? Value { get; set; } } @@ -665,14 +692,15 @@ public class FixedPointConstraint : Constraint, ISammSelfDescription { // self description public new string GetSelfName() => "samm-fixed-point-constraint"; - public new string GetSelfUrn() => "bamm-c:FixedPointConstraint"; + public new string GetSelfUrn(SammVersion v) => (v == SammVersion.V_1_0_0) ? "bamm-c:FixedPointConstraint" : "samm-c:FixedPointConstraint"; /// /// The scaling factor for a fixed point number. E.g., if a fixedpoint number is 123.04, the /// scaling factor is 2 (the number of digits after the decimal point). /// Must be given as xsd:positiveInteger. /// - [SammPropertyUri("bamm-c:scale")] + [SammPropertyUri("bamm-c:scale", SammVersion.V_1_0_0)] + [SammPropertyUri("samm-c:scale", SammVersion.V_2_0_0)] public uint? Scale { get; set; } /// @@ -680,7 +708,8 @@ public class FixedPointConstraint : Constraint, ISammSelfDescription /// is 123.04, the integer factor is 3 (the number of digits before the decimal point). /// Must be given as xsd:positiveInteger. /// - [SammPropertyUri("bamm-c:integer")] + [SammPropertyUri("bamm-c:integer", SammVersion.V_1_0_0)] + [SammPropertyUri("samm-c:integer", SammVersion.V_2_0_0)] public uint? Integer { get; set; } } @@ -694,7 +723,7 @@ public class Characteristic : ModelElement, ISammSelfDescription, ISammStructure { // self description public string GetSelfName() => "samm-characteristic"; - public string GetSelfUrn() => "bamm:Characteristic"; + public string GetSelfUrn(SammVersion v) => (v == SammVersion.V_1_0_0) ? "bamm:Characteristic" : "samm:Characteristic"; // structure model public bool IsTopElement() => false; @@ -709,7 +738,8 @@ public IEnumerable DescendOnce() /// Also the scalar data types (e.g. xsd:decimal) are treated as references in the first degree. /// [SammPresetList("SammXsdDataTypes")] - [SammPropertyUri("bamm:dataType")] + [SammPropertyUri("bamm:dataType", SammVersion.V_1_0_0)] + [SammPropertyUri("samm:dataType", SammVersion.V_2_0_0)] public SammReference DataType { get; set; } public Characteristic() @@ -729,7 +759,7 @@ public class Trait : Characteristic, ISammSelfDescription, ISammStructureModel { // self description public new string GetSelfName() => "samm-trait"; - public new string GetSelfUrn() => "bamm-c:Trait"; + public new string GetSelfUrn(SammVersion v) => (v == SammVersion.V_1_0_0) ? "bamm-c:Trait" : "samm-c:Trait"; // structure model public new bool IsTopElement() => false; @@ -746,14 +776,16 @@ public class Trait : Characteristic, ISammSelfDescription, ISammStructureModel /// The Characterstic that is being constrained. /// Identified via preferredName in any language /// - [SammPropertyUri("bamm-c:baseCharacteristic")] + [SammPropertyUri("bamm-c:baseCharacteristic", SammVersion.V_1_0_0)] + [SammPropertyUri("samm-c:baseCharacteristic", SammVersion.V_2_0_0)] public SammReference? BaseCharacteristic { get; set; } /// /// A Constraint that is applicable to the base Characteristic. This attribute may be used multiple times, /// to add multiple Constraints to the base Characteristic. /// - [SammPropertyUri("bamm-c:constraint")] + [SammPropertyUri("bamm-c:constraint", SammVersion.V_1_0_0)] + [SammPropertyUri("samm-c:constraint", SammVersion.V_2_0_0)] [SammPropertyFlags("constraints")] public List? Constraint { get; set; } } @@ -768,12 +800,13 @@ public class Quantifiable : Characteristic, ISammSelfDescription { // self description public new string GetSelfName() => "samm-quantifiable"; - public new string GetSelfUrn() => "bamm-c:Quantifiable"; + public new string GetSelfUrn(SammVersion v) => (v == SammVersion.V_1_0_0) ? "bamm-c:Quantifiable" : "samm-c:Quantifiable"; /// /// Reference to a Unit as defined in the Unit catalog /// - [SammPropertyUri("bamm-c:unit")] + [SammPropertyUri("bamm-c:unit", SammVersion.V_1_0_0)] + [SammPropertyUri("samm-c:unit", SammVersion.V_2_0_0)] public SammReference? Unit { get; set; } } @@ -786,12 +819,13 @@ public class Measurement : Characteristic, ISammSelfDescription { // self description public new string GetSelfName() => "samm-measurement"; - public new string GetSelfUrn() => "bamm-c:Measurement"; + public new string GetSelfUrn(SammVersion v) => (v == SammVersion.V_1_0_0) ? "bamm-c:Measurement" : "samm-c:Measurement"; /// /// Reference to a Unit as defined in the Unit catalog /// - [SammPropertyUri("bamm-c:unit")] + [SammPropertyUri("bamm-c:unit", SammVersion.V_1_0_0)] + [SammPropertyUri("samm-c:unit", SammVersion.V_2_0_0)] public SammReference Unit { get; set; } public Measurement() @@ -809,13 +843,14 @@ public class Enumeration : Characteristic, ISammSelfDescription { // self description public new string GetSelfName() => "samm-enumeration"; - public new string GetSelfUrn() => "bamm-c:Enumeration"; + public new string GetSelfUrn(SammVersion v) => (v == SammVersion.V_1_0_0) ? "bamm-c:Enumeration" : "samm-c:Enumeration"; /// /// List of possible values. The dataType of each of the values must match the /// dataType of the Enumeration. /// - [SammPropertyUri("bamm-c:values")] + [SammPropertyUri("bamm-c:values", SammVersion.V_1_0_0)] + [SammPropertyUri("samm-c:values", SammVersion.V_2_0_0)] public List Values { get; set; } public Enumeration() @@ -833,12 +868,13 @@ public class State : Enumeration, ISammSelfDescription { // self description public new string GetSelfName() => "samm-state"; - public new string GetSelfUrn() => "bamm-c:State"; + public new string GetSelfUrn(SammVersion v) => (v == SammVersion.V_1_0_0) ? "bamm-c:State" : "samm-c:State"; /// /// The default value for the state. /// - [SammPropertyUri("bamm-c:defaultValue")] + [SammPropertyUri("bamm-c:defaultValue", SammVersion.V_1_0_0)] + [SammPropertyUri("samm-c:defaultValue", SammVersion.V_2_0_0)] public string DefaultValue { get; set; } public State() @@ -856,7 +892,7 @@ public class Duration : Characteristic, ISammSelfDescription { // self description public new string GetSelfName() => "samm-duration"; - public new string GetSelfUrn() => "bamm-c:Duration"; + public new string GetSelfUrn(SammVersion v) => (v == SammVersion.V_1_0_0) ? "bamm-c:Duration" : "samm-c:Duration"; /// /// Reference to a Unit as defined in the Unit catalog. The referenced unit or its referenceUnit @@ -868,7 +904,8 @@ public class Duration : Characteristic, ISammSelfDescription /// unit:poisePerBar unit:poisePerPascal unit:reciprocalMinute unit:secondUnitOfTime /// unit:shake unit:siderealYear unit:tropicalYear unit:week unit:year /// - [SammPropertyUri("bamm-c:unit")] + [SammPropertyUri("bamm-c:unit", SammVersion.V_1_0_0)] + [SammPropertyUri("samm-c:unit", SammVersion.V_2_0_0)] public SammReference Unit { get; set; } public Duration() @@ -887,12 +924,13 @@ public class Collection : Characteristic, ISammSelfDescription { // self description public new string GetSelfName() => "samm-collection"; - public new string GetSelfUrn() => "bamm-c:Collection"; + public new string GetSelfUrn(SammVersion v) => (v == SammVersion.V_1_0_0) ? "bamm-c:Collection" : "samm-c:Collection"; /// /// Reference to a Characteristic which describes the individual elements contained in the Collection. /// - [SammPropertyUri("bamm-c:elementCharacteristic")] + [SammPropertyUri("bamm-c:elementCharacteristic", SammVersion.V_1_0_0)] + [SammPropertyUri("samm-c:elementCharacteristic", SammVersion.V_2_0_0)] public SammReference ElementCharacteristic { get; set; } public Collection() @@ -910,7 +948,7 @@ public class List : Collection, ISammSelfDescription { // self description public new string GetSelfName() => "samm-list"; - public new string GetSelfUrn() => "bamm-c:List"; + public new string GetSelfUrn(SammVersion v) => (v == SammVersion.V_1_0_0) ? "bamm-c:List" : "samm-c:List"; } /// @@ -922,7 +960,7 @@ public class Set : Collection, ISammSelfDescription { // self description public new string GetSelfName() => "samm-set"; - public new string GetSelfUrn() => "bamm-c:Set"; + public new string GetSelfUrn(SammVersion v) => (v == SammVersion.V_1_0_0) ? "bamm-c:Set" : "samm-c:Set"; } /// @@ -934,7 +972,7 @@ public class SortedSet : Collection, ISammSelfDescription { // self description public new string GetSelfName() => "samm-sorted-set"; - public new string GetSelfUrn() => "bamm-c:SortedSet"; + public new string GetSelfUrn(SammVersion v) => (v == SammVersion.V_1_0_0) ? "bamm-c:SortedSet" : "samm-c:SortedSet"; } /// @@ -946,7 +984,7 @@ public class TimeSeries : SortedSet, ISammSelfDescription { // self description public new string GetSelfName() => "samm-time-series"; - public new string GetSelfUrn() => "bamm-c:TimeSeries"; + public new string GetSelfUrn(SammVersion v) => (v == SammVersion.V_1_0_0) ? "bamm-c:TimeSeries" : "samm-c:TimeSeries"; // For DataType // Set to samm-e:TimeSeriesEntity. This Entity consists of two Properties, namely samm-e:timestamp @@ -967,7 +1005,7 @@ public class Code : Characteristic, ISammSelfDescription { // self description public new string GetSelfName() => "samm-code"; - public new string GetSelfUrn() => "bamm-c:Code"; + public new string GetSelfUrn(SammVersion v) => (v == SammVersion.V_1_0_0) ? "bamm-c:Code" : "samm-c:Code"; } /// @@ -981,18 +1019,20 @@ public class Either : Characteristic, ISammSelfDescription { // self description public new string GetSelfName() => "samm-either"; - public new string GetSelfUrn() => "bamm-c:Either"; + public new string GetSelfUrn(SammVersion v) => (v == SammVersion.V_1_0_0) ? "bamm-c:Either" : "samm-c:Either"; /// /// The left side of the Either. The attribute references another Characteristic which describes the value. /// - [SammPropertyUri("bamm-c:left")] + [SammPropertyUri("bamm-c:left", SammVersion.V_1_0_0)] + [SammPropertyUri("samm-c:left", SammVersion.V_2_0_0)] public string Left { get; set; } /// /// The right side of the Either. The attribute references another Characteristic which describes the value. /// - [SammPropertyUri("bamm-c:right")] + [SammPropertyUri("bamm-c:right", SammVersion.V_1_0_0)] + [SammPropertyUri("samm-c:right", SammVersion.V_2_0_0)] public string Right { get; set; } public Either() @@ -1012,7 +1052,7 @@ public class SingleEntity : Characteristic, ISammSelfDescription { // self description public new string GetSelfName() => "samm-single-entity"; - public new string GetSelfUrn() => "bamm-c:SingleEntity"; + public new string GetSelfUrn(SammVersion v) => (v == SammVersion.V_1_0_0) ? "bamm-c:SingleEntity" : "samm-c:SingleEntity"; } /// @@ -1027,7 +1067,7 @@ public class StructuredValue: Characteristic, ISammSelfDescription { // self description public new string GetSelfName() => "samm-structured-value"; - public new string GetSelfUrn() => "bamm-c:StructuredValue"; + public new string GetSelfUrn(SammVersion v) => (v == SammVersion.V_1_0_0) ? "bamm-c:StructuredValue" : "samm-c:StructuredValue"; /// /// The regular expression used to deconstruct the value into parts that are mapped to separate @@ -1035,14 +1075,16 @@ public class StructuredValue: Characteristic, ISammSelfDescription /// are Properties given in the elements list. The n​th capture group maps to the n​th Property /// in the elements list. /// - [SammPropertyUri("bamm-c:deconstructionRule")] + [SammPropertyUri("bamm-c:deconstructionRule", SammVersion.V_1_0_0)] + [SammPropertyUri("samm-c:deconstructionRule", SammVersion.V_2_0_0)] public string DeconstructionRule { get; set; } /// /// A list of entries each of which can either be a Property reference or a string literal. /// The list must contain at least one Property reference. /// - [SammPropertyUri("bamm-c:elements")] + [SammPropertyUri("bamm-c:elements", SammVersion.V_1_0_0)] + [SammPropertyUri("samm-c:elements", SammVersion.V_2_0_0)] public List Elements { get; set; } public StructuredValue() @@ -1062,6 +1104,7 @@ public class Property : ModelElement, ISammSelfDescription, ISammStructureModel // self description public string GetSelfName() => "samm-property"; public string GetSelfUrn() => "bamm:Property"; + public string GetSelfUrn(SammVersion v) => (v == SammVersion.V_1_0_0) ? "bamm:Property" : "samm:Property"; // structure model public bool IsTopElement() => false; @@ -1076,14 +1119,16 @@ public IEnumerable DescendOnce() /// in a corresponding Characteristic. It is important to ensure that the data type has the correct format. /// Find the Data Types (SAMM 2.1.0) with an example value. /// - [SammPropertyUri("bamm:exampleValue")] + [SammPropertyUri("bamm:exampleValue", SammVersion.V_1_0_0)] + [SammPropertyUri("samm:exampleValue", SammVersion.V_2_0_0)] public string? ExampleValue { get; set; } /// /// One Property has exactly one Characteristic. /// [SammPresetList("Characteristics")] - [SammPropertyUri("bamm:characteristic")] + [SammPropertyUri("bamm:characteristic", SammVersion.V_1_0_0)] + [SammPropertyUri("samm:characteristic", SammVersion.V_2_0_0)] public SammReference Characteristic { get; set; } public Property() @@ -1099,7 +1144,7 @@ public class Entity : ModelElement, ISammSelfDescription, ISammStructureModel { // self description public string GetSelfName() => "samm-entity"; - public string GetSelfUrn() => "bamm:Entity"; + public string GetSelfUrn(SammVersion v) => (v == SammVersion.V_1_0_0) ? "bamm:Entity" : "samm:Entity"; // structure model public bool IsTopElement() => false; @@ -1111,8 +1156,10 @@ public IEnumerable DescendOnce() } // own - [SammPropertyUri("bamm:properties")] - [SammCollectionContentUri("bamm:property")] + [SammPropertyUri("bamm:properties", SammVersion.V_1_0_0)] + [SammPropertyUri("samm:properties", SammVersion.V_2_0_0)] + [SammCollectionContentUri("bamm:property", SammVersion.V_1_0_0)] + [SammCollectionContentUri("samm:property", SammVersion.V_2_0_0)] public List Properties { get; set; } = new List(); } @@ -1126,7 +1173,7 @@ public class Aspect : ModelElement, ISammSelfDescription, ISammStructureModel { // self description public string GetSelfName() => "samm-aspect"; - public string GetSelfUrn() => "bamm:Aspect"; + public string GetSelfUrn(SammVersion v) => (v == SammVersion.V_1_0_0) ? "bamm:Aspect" : "samm:Aspect"; // structure model public bool IsTopElement() => true; @@ -1154,22 +1201,28 @@ public IEnumerable DescendOnce() /// A Property represents a named value. This element is optional and can appear /// multiple times in a model ([0..n]). /// - [SammPropertyUri("bamm:properties")] - [SammCollectionContentUri("bamm:property")] + [SammPropertyUri("bamm:properties", SammVersion.V_1_0_0)] + [SammPropertyUri("samm:properties", SammVersion.V_2_0_0)] + [SammCollectionContentUri("bamm:property", SammVersion.V_1_0_0)] + [SammCollectionContentUri("samm:property", SammVersion.V_2_0_0)] public List Properties { get; set; } = new List(); /// /// An Event is a model element that represents a single occurence where the timing is important. /// - [SammPropertyUri("bamm:events")] - [SammCollectionContentUri("bamm:event")] + [SammPropertyUri("bamm:events", SammVersion.V_1_0_0)] + [SammPropertyUri("samm:events", SammVersion.V_2_0_0)] + [SammCollectionContentUri("bamm:event", SammVersion.V_1_0_0)] + [SammCollectionContentUri("samm:event", SammVersion.V_2_0_0)] public List Events { get; set; } = new List(); /// /// An Operation represents an action that can be triggered on the Aspect. /// - [SammPropertyUri("bamm:operations")] - [SammCollectionContentUri("bamm:operation")] + [SammPropertyUri("bamm:operations", SammVersion.V_1_0_0)] + [SammPropertyUri("samm:operations", SammVersion.V_2_0_0)] + [SammCollectionContentUri("bamm:operation", SammVersion.V_1_0_0)] + [SammCollectionContentUri("samm:operation", SammVersion.V_2_0_0)] public List Operations { get; set; } = new List(); } @@ -1177,115 +1230,329 @@ public class Unit : ModelElement, ISammSelfDescription { // self description public string GetSelfName() => "samm-unit"; - public string GetSelfUrn() => "bamm:Unit"; + public string GetSelfUrn(SammVersion v) => (v == SammVersion.V_1_0_0) ? "bamm:Unit" : "samm:Unit"; /// /// Normalized short code for unit; please refer to the original /// specification for more details. /// - [SammPropertyUri("bamm:commonCode")] + [SammPropertyUri("bamm:commonCode", SammVersion.V_1_0_0)] + [SammPropertyUri("samm:commonCode", SammVersion.V_2_0_0)] public string? CommonCode { get; set; } = null; /// /// If the unit is derived from a reference unit, the human readable /// multiplication factor, e.g., "10⁻²⁸ m²" /// - [SammPropertyUri("bamm:conversionFactor")] + [SammPropertyUri("bamm:conversionFactor", SammVersion.V_1_0_0)] + [SammPropertyUri("samm:conversionFactor", SammVersion.V_2_0_0)] public string? ConversionFactor { get; set; } = null; /// /// If the unit is derived from a reference unit, the numeric /// multiplication factor, e.g., "1.0E-28" /// - [SammPropertyUri("bamm:numericConversionFactor")] + [SammPropertyUri("bamm:numericConversionFactor", SammVersion.V_1_0_0)] + [SammPropertyUri("samm:numericConversionFactor", SammVersion.V_2_0_0)] public string? NumericConversionFactor { get; set; } = null; /// /// The list of quantity kinds, for example unit litre has quantity kind volume, unit /// metre has quantity kinds length, distance, diameter etc. /// - [SammPropertyUri("bamm:quantityKind")] + [SammPropertyUri("bamm:quantityKind", SammVersion.V_1_0_0)] + [SammPropertyUri("samm:quantityKind", SammVersion.V_2_0_0)] public string? QuantityKind { get; set; } = null; /// /// The unit this unit is derived from, e.g., centimetre is derived from metre. /// - [SammPropertyUri("bamm:referenceUnit")] + [SammPropertyUri("bamm:referenceUnit", SammVersion.V_1_0_0)] + [SammPropertyUri("samm:referenceUnit", SammVersion.V_2_0_0)] public SammReference? ReferenceUnit { get; set; } = null; /// /// The unit’s symbol, e.g., for centimetre the symbol is cm /// - [SammPropertyUri("bamm:symbol")] + [SammPropertyUri("bamm:symbol", SammVersion.V_1_0_0)] + [SammPropertyUri("samm:symbol", SammVersion.V_2_0_0)] public string? symbol { get; set; } = null; } + public enum SammVersion { V_1_0_0, V_2_0_0 }; + /// - /// Provides some constant values to the model. + /// This class hold all prefixes/ namespaces, which are "switched" on a version + /// change. /// - public static class Constants + public class SammIdSet { - public static string NamespaceURN = "urn:samm:org.eclipse.esmf.samm:"; + /// + /// SAMM version, which is to be matched. + /// "Key" of the record. + /// + public SammVersion Version = SammVersion.V_1_0_0; + + /// + /// When matching the version of a turtle file, this key/ value will + /// be checked for identity. + /// + public NamespaceMapItem Detector = new NamespaceMapItem( + "bamm:", "urn:bamm:io.openmanufacturing:meta-model:1.0.0#"); /// /// XSD uri for "a" /// - public static string PredicateA = "http://www.w3.org/1999/02/22-rdf-syntax-ns#type"; + public string PredicateA = "http://www.w3.org/1999/02/22-rdf-syntax-ns#type"; /// /// XSD datatype of uint /// - public static string XsdNonNegInt = "http://www.w3.org/2001/XMLSchema#nonNegativeInteger"; + public string XsdNonNegInt = "http://www.w3.org/2001/XMLSchema#nonNegativeInteger"; /// /// XSD datatype of bool /// - public static string XsdBoolean = "http://www.w3.org/2001/XMLSchema#boolean"; + public string XsdBoolean = "http://www.w3.org/2001/XMLSchema#boolean"; /// /// XSD datatype of string /// - public static string XsdString = "http://www.w3.org/2001/XMLSchema#string"; + public string XsdString = "http://www.w3.org/2001/XMLSchema#string"; /// /// Accordng to standard of RDF collection, the first element relationship /// - public static string RdfCollFirst = "http://www.w3.org/1999/02/22-rdf-syntax-ns#first"; + public string RdfCollFirst = "http://www.w3.org/1999/02/22-rdf-syntax-ns#first"; /// /// Accordng to standard of RDF collection, the res element relationship /// - public static string RdfCollRest = "http://www.w3.org/1999/02/22-rdf-syntax-ns#rest"; + public string RdfCollRest = "http://www.w3.org/1999/02/22-rdf-syntax-ns#rest"; /// /// Accordng to standard of RDF collection, the end element /// - public static string RdfCollNil = "http://www.w3.org/1999/02/22-rdf-syntax-ns#nil"; + public string RdfCollNil = "http://www.w3.org/1999/02/22-rdf-syntax-ns#nil"; /// /// In RDF collections of SAMM references, the pointer to the content itself /// - public static string RdfCollProperty = "urn:bamm:io.openmanufacturing:meta-model:1.0.0#property"; + public string RdfCollProperty = "urn:bamm:io.openmanufacturing:meta-model:1.0.0#property"; /// /// In RDF collections of SAMM references, the optional flag /// - public static string RdfCollOptional = "urn:bamm:io.openmanufacturing:meta-model:1.0.0#optional"; + public string RdfCollOptional = "urn:bamm:io.openmanufacturing:meta-model:1.0.0#optional"; /// /// The head to be used for auto generated instances /// - public static string DefaultInstanceURN = "https://admin-shell.io/samm-import#"; + public string DefaultInstanceURN = "https://admin-shell.io/samm-import#"; /// /// Holds attribute URI name with prefix for the description attribute of a SAMM element. /// - public static string SammDescription = "bamm:description"; + public string SammDescription = "bamm:description"; /// /// Holds attribute URI name with prefix for the name attribute of a SAMM element. /// - public static string SammName = "bamm:name"; + public string SammName = "bamm:name"; + + /// + /// The namespaces/ prefixes used by the own functionality + /// + public NamespaceMap SelfNamespaces = new NamespaceMap(); + + public SammIdSet() + { + // init namespaces, as being used by self / reflection information + SelfNamespaces = new NamespaceMap(); + SelfNamespaces.AddOrIgnore("bamm:", "urn:bamm:io.openmanufacturing:meta-model:1.0.0#"); + SelfNamespaces.AddOrIgnore("bamm-c:", "urn:bamm:io.openmanufacturing:characteristic:1.0.0#"); + SelfNamespaces.AddOrIgnore("bamm-e:", "urn:bamm:io.openmanufacturing:entity:1.0.0#"); + SelfNamespaces.AddOrIgnore("unit:", "urn:bamm:io.openmanufacturing:unit:1.0.0#"); + SelfNamespaces.AddOrIgnore("rdf:", "http://www.w3.org/1999/02/22-rdf-syntax-ns#"); + SelfNamespaces.AddOrIgnore("rdfs:", "http://www.w3.org/2000/01/rdf-schema#"); + SelfNamespaces.AddOrIgnore("xsd:", "http://www.w3.org/2001/XMLSchema#"); + } + + public Dictionary SammUrnToType = new Dictionary(); + + public Dictionary SammTypeToName = new Dictionary(); + + public SammIdSet Init() + { + // dictionary from URN to type + foreach (var st in Constants.AddableElements) + { + if (Activator.CreateInstance(st, new object[] { }) is ISammSelfDescription ssd) + { + // assumption: RDF matching is case sensitive?! + var fullUri = SelfNamespaces.ExtendUri(ssd.GetSelfUrn(Version)); + + if (fullUri != null) + { + SammUrnToType.Add(fullUri, st); + SammTypeToName.Add(st, "" + ssd.GetSelfName()); + } + } + } + + return this; + } + + /// + /// This function assumes, that the idSet is on version 1.0.0 + /// with all attributes and wants to be upgraded. + /// + public SammIdSet? SwitchToVersion(SammVersion version) + { + // initial version? + if (version == SammVersion.V_1_0_0) + return this; + + // + // 2.0.0 + // + + if (version == SammVersion.V_2_0_0) + { + // individual attributes + Version = SammVersion.V_2_0_0; + RdfCollProperty = "urn:samm:org.eclipse.esmf.samm:meta-model:2.0.0#property"; + RdfCollOptional = "urn:samm:org.eclipse.esmf.samm:meta-model:2.0.0#optional"; + + // init namespaces, as being used by self / reflection information + SelfNamespaces = new NamespaceMap(); + SelfNamespaces.AddOrIgnore("samm:", "urn:samm:org.eclipse.esmf.samm:meta-model:2.0.0#"); + SelfNamespaces.AddOrIgnore("samm-c:", "urn:samm:org.eclipse.esmf.samm:characteristic:2.0.0#"); + SelfNamespaces.AddOrIgnore("samm-e:", "urn:samm:org.eclipse.esmf.samm:entity:2.0.0#"); + SelfNamespaces.AddOrIgnore("unit:", "urn:samm:org.eclipse.esmf.samm:unit:2.0.0#"); + SelfNamespaces.AddOrIgnore("rdf:", "http://www.w3.org/1999/02/22-rdf-syntax-ns#"); + SelfNamespaces.AddOrIgnore("rdfs:", "http://www.w3.org/2000/01/rdf-schema#"); + SelfNamespaces.AddOrIgnore("xsd:", "http://www.w3.org/2001/XMLSchema#"); + + Detector = new NamespaceMapItem( + "samm:", "urn:samm:org.eclipse.esmf.samm:meta-model:2.0.0#"); + + // ok + return this; + } + + // + // not found? + return null; + } + + public Type? GetTypeFromUrn(string? urn) + { + if (urn == null) + return null; + if (SammUrnToType.ContainsKey(urn)) + return SammUrnToType[urn]; + return null; + } + + public string? GetNameFromSammType(Type? sammType) + { + if (sammType == null) + return null; + if (SammTypeToName.ContainsKey(sammType)) + return SammTypeToName[sammType]; + return null; + } + } + + /// + /// This class holds predefined id sets for all relevant SAMM versions + /// + public static class SammIdSets + { + public static Dictionary IdSets + = new Dictionary(); + + public static void AddSet(SammIdSet? set) + { + if (set == null) + return; + IdSets.Add(set.Version, set); + } + + public static SammIdSet? GetDefaultVersion() + { + return IdSets.Values.LastOrDefault(); + } + + static SammIdSets() + { + AddSet(new SammIdSet().Init()); + AddSet(new SammIdSet().SwitchToVersion(SammVersion.V_2_0_0)?.Init()); + } + + public static Tuple? GetAnyIdSetTypeFromUrn(string? urn) + { + if (urn == null) + return null; + foreach (var idset in IdSets.Values) + { + var found = idset.GetTypeFromUrn(urn); + if (found != null) + return new Tuple(idset, found); + } + return null; + } + + public static string? GetAnyNameFromSammType(Type? sammType) + { + if (sammType == null) + return null; + foreach (var idset in IdSets.Values) + { + var found = idset.GetNameFromSammType(sammType); + if (found != null) + return found; + } + return null; + } + + public static SammIdSet? DetectVersion(NamespaceMap external) + { + // access + if (external == null) + return null; + + // loop + foreach (var idSet in IdSets.Values) + { + // need a prefix to compare + var pf = idSet?.Detector?.Prefix; + if (pf == null) + continue; + + // now compare + if (external.ContainsPrefix(pf) && idSet?.SelfNamespaces.ContainsPrefix(pf) == true + && external.GetFromPrefix(pf)?.Uri == idSet.SelfNamespaces.GetFromPrefix(pf)?.Uri) + return idSet; + } + + return null; + } + } + + /// + /// Provides some constant values to the model. + /// + public static class Constants + { + /// + /// Start of namespace(s) to efficiently recognize a SAMM element. + /// + public static string[] PossibleNamespaceURN = { + "urn:samm:org.eclipse.esmf.samm:", + "urn:bamm:io.openmanufacturing:" + }; public static Type[] AddableCharacteristic = { @@ -1394,7 +1661,7 @@ public void Add( return null; } - public static NamespaceMap SelfNamespaces = new NamespaceMap(); + static Constants() { @@ -1549,17 +1816,7 @@ static Constants() Abbreviation = "E", Foreground = 0xFF000000, Background = 0xFFB9D8FA - }); - - // init namespaces, as being used by self / reflection information - SelfNamespaces = new NamespaceMap(); - SelfNamespaces.AddOrIgnore("bamm:", "urn:bamm:io.openmanufacturing:meta-model:1.0.0#"); - SelfNamespaces.AddOrIgnore("bamm-c:", "urn:bamm:io.openmanufacturing:characteristic:1.0.0#"); - SelfNamespaces.AddOrIgnore("bamm-e:", "urn:bamm:io.openmanufacturing:entity:1.0.0#"); - SelfNamespaces.AddOrIgnore("unit:", "urn:bamm:io.openmanufacturing:unit:1.0.0#"); - SelfNamespaces.AddOrIgnore("rdf:", "http://www.w3.org/1999/02/22-rdf-syntax-ns#"); - SelfNamespaces.AddOrIgnore("rdfs:", "http://www.w3.org/2000/01/rdf-schema#"); - SelfNamespaces.AddOrIgnore("xsd:", "http://www.w3.org/2001/XMLSchema#"); + }); } public static uint RenderBackground = 0xFFEFEFF0; @@ -1632,9 +1889,12 @@ public static bool HasSammSemanticId(Aas.IHasSemantics hasSem) return false; if (hasSem.SemanticId.Count() != 1) return false; - if (!hasSem.SemanticId.Keys[0].Value.StartsWith(Constants.NamespaceURN)) - return false; - return true; + + foreach (var ns in Constants.PossibleNamespaceURN) + if (!hasSem.SemanticId.Keys[0].Value.StartsWith(ns)) + return true; + + return false; } public static string? GetSammUrn(Aas.IHasSemantics hasSem) @@ -1646,47 +1906,6 @@ public static bool HasSammSemanticId(Aas.IHasSemantics hasSem) return hasSem.SemanticId.Keys[0].Value; } - public static Dictionary SammUrnToType = new Dictionary(); - - public static Dictionary SammTypeToName = new Dictionary(); - - static Util() - { - // dictionary from URN to type - foreach (var st in Constants.AddableElements) - { - if (Activator.CreateInstance(st, new object[] { }) is ISammSelfDescription ssd) - { - // assumption: RDF matching is case sensitive?! - var fullUri = Constants.SelfNamespaces.ExtendUri(ssd.GetSelfUrn()); - - if (fullUri != null) - { - SammUrnToType.Add(fullUri, st); - SammTypeToName.Add(st, "" + ssd.GetSelfName()); - } - } - } - } - - public static Type? GetTypeFromUrn(string? urn) - { - if (urn == null) - return null; - if (SammUrnToType.ContainsKey(urn)) - return SammUrnToType[urn]; - return null; - } - - public static string? GetNameFromSammType(Type? sammType) - { - if (sammType == null) - return null; - if (SammTypeToName.ContainsKey(sammType)) - return SammTypeToName[sammType]; - return null; - } - /// /// Any chars which are sitting between "meaningful words" within a URI /// @@ -1735,5 +1954,24 @@ static Util() return uri.Substring(li + 1); return elseStr; } + + public static SammPropertyUriAttribute? FindAnySammPropertyUriAttribute( + PropertyInfo pi, SammVersion version) + { + foreach (var attr in pi.GetCustomAttributes(typeof(SammPropertyUriAttribute))) + if (attr is SammPropertyUriAttribute pua && pua.Version == version) + return pua; + return null; + } + + public static SammCollectionContentUriAttribute? FindAnySammCollectionContentUriAttribute( + PropertyInfo pi, SammVersion version) + { + foreach (var attr in pi.GetCustomAttributes(typeof(SammCollectionContentUriAttribute))) + if (attr is SammCollectionContentUriAttribute pua && pua.Version == version) + return pua; + return null; + } + } } \ No newline at end of file diff --git a/src/AasxPackageExplorer/debug.MIHO.script b/src/AasxPackageExplorer/debug.MIHO.script index 45f8d4754..55cc138a0 100644 --- a/src/AasxPackageExplorer/debug.MIHO.script +++ b/src/AasxPackageExplorer/debug.MIHO.script @@ -6,7 +6,8 @@ // Select("Submodel", "Next"); // Tool("exportsmtasciidoc", "File", "C:\\HOMI\\Develop\\Aasx\\repo\\new.zip", "ExportHtml", "true"); // Tool("Exit"); -Tool("sammaspectimport", "File", "C:\\HOMI\\Develop\\Aasx\\repo\\BatteryPass-spiel.ttl"); +// Tool("sammaspectimport", "File", "C:\\HOMI\\Develop\\Aasx\\repo\\samm-test\\BatteryPass-spiel.ttl"); +Tool("sammaspectimport", "File", "C:\\HOMI\\Develop\\Aasx\\repo\\samm-test\\Batch-MM-2_0_0.ttl"); Tool("editkey"); Select("ConceptDescription", "First"); // Select("ConceptDescription", "Next"); @@ -14,5 +15,5 @@ Select("ConceptDescription", "First"); // Select("ConceptDescription", "Next"); // Select("ConceptDescription", "Next"); // Select("ConceptDescription", "Next"); -// Tool("sammaspectexport", "File", "C:\\HOMI\\Develop\\Aasx\\repo\\out.ttl"); +// Tool("sammaspectexport", "File", "C:\\HOMI\\Develop\\Aasx\\repo\\samm-test\\out.ttl"); Tool("submodelinstancefromsammaspect"); \ No newline at end of file diff --git a/src/AasxPackageExplorer/options-debug.MIHO.json b/src/AasxPackageExplorer/options-debug.MIHO.json index 8141ef50c..b5d770634 100644 --- a/src/AasxPackageExplorer/options-debug.MIHO.json +++ b/src/AasxPackageExplorer/options-debug.MIHO.json @@ -26,7 +26,7 @@ // "AasxToLoad": "C:\\HOMI\\Develop\\Aasx\\repo\\SMT_Sample_B.aasx", // "AuxToLoad": "C:\\HOMI\\Develop\\Aasx\\repo\\SMT_Sample_A.aasx", // "AasxToLoad": "C:\\HOMI\\Develop\\Aasx\\repo\\00_FestoDemoBox-Module-2-Kopie2.aasx", - "AasxToLoad": "C:\\HOMI\\Develop\\Aasx\\repo\\samm_spiel_empty.aasx", + "AasxToLoad": "C:\\HOMI\\Develop\\Aasx\\repo\\samm-test\\samm_spiel_empty.aasx", "WindowLeft": 200, "WindowTop": -1, "WindowWidth": 900, diff --git a/src/AasxPackageLogic/DispEditHelperEntities.cs b/src/AasxPackageLogic/DispEditHelperEntities.cs index f122c0d54..49a289b74 100644 --- a/src/AasxPackageLogic/DispEditHelperEntities.cs +++ b/src/AasxPackageLogic/DispEditHelperEntities.cs @@ -23,6 +23,7 @@ This source code may use other Open Source software components (see LICENSE.txt) using System.Windows.Documents; using static System.Windows.Forms.VisualStyles.VisualStyleElement.Window; using Aas = AasCore.Aas3_0; +using AasCore.Samm2_2_0; namespace AasxPackageLogic { @@ -464,7 +465,7 @@ public void DisplayOrEditAasEntityAasEnv( ticketMenu: new AasxMenu() .AddAction("add-aas", "Add AAS", "Adds an AAS with blank information.") - .AddAction("add-cd", "Add AasConceptDescription", + .AddAction("add-cd", "Add ConceptDescription", "Adds an ConceptDescription with blank information.") .AddAction("add-sm-inst", "Add Submodel instance", "Adds an Submodel instance without direct reference in AAS.", diff --git a/src/AasxPackageLogic/DispEditHelperSammModules.cs b/src/AasxPackageLogic/DispEditHelperSammModules.cs index a369db5ed..145d9dab1 100644 --- a/src/AasxPackageLogic/DispEditHelperSammModules.cs +++ b/src/AasxPackageLogic/DispEditHelperSammModules.cs @@ -50,6 +50,24 @@ namespace AasxPackageLogic /// public class DispEditHelperSammModules : DispEditHelperModules { + public SammIdSet SammExtensionHelperSelectSammVersion(IEnumerable idsets) + { + // create choices + var fol = new List(); + foreach (var idset in idsets) + fol.Add(new AnyUiDialogueListItem("" + idset.Version, idset)); + + // prompt for this list + var uc = new AnyUiDialogueDataSelectFromList( + caption: "Select SAMM version to use .."); + uc.ListOfItems = fol; + this.context.StartFlyoverModal(uc); + if (uc.Result && uc.ResultItem != null && uc.ResultItem.Tag != null && + uc.ResultItem.Tag.GetType().IsAssignableTo(typeof(Samm.SammIdSet))) + return (SammIdSet)uc.ResultItem.Tag; + return null; + } + public Type SammExtensionHelperSelectSammType(Type[] addableElements) { // create choices @@ -103,6 +121,7 @@ public static void SammExtensionHelperUpdateJson(Aas.IExtension se, Type sammTyp public AnyUiLambdaActionBase SammExtensionHelperSammReferenceAction( Aas.Environment env, + SammIdSet idSet, Aas.IReferable relatedReferable, int actionIndex, T sr, @@ -203,7 +222,7 @@ public AnyUiLambdaActionBase SammExtensionHelperSammReferenceAction( semanticId: new Aas.Reference(ReferenceTypes.ExternalReference, (new[] { new Aas.Key(KeyTypes.GlobalReference, - "" + Samm.Constants.SelfNamespaces.ExtendUri(newSammSsd.GetSelfUrn())) + "" + idSet?.SelfNamespaces.ExtendUri(newSammSsd.GetSelfUrn(idSet.Version))) }) .Cast().ToList()), value: ""); @@ -233,7 +252,8 @@ public AnyUiLambdaActionBase SammExtensionHelperSammReferenceAction( } public void SammExtensionHelperAddSammReference( - Aas.Environment env, AnyUiStackPanel stack, string caption, + Aas.Environment env, SammIdSet idSet, + AnyUiStackPanel stack, string caption, Samm.ModelElement sammInst, Aas.IReferable relatedReferable, T sr, @@ -269,7 +289,8 @@ public void SammExtensionHelperAddSammReference( auxButtonLambda: (i) => { return SammExtensionHelperSammReferenceAction( - env, relatedReferable, + env, idSet, + relatedReferable, i, sr: sr, setValue: setValue, @@ -297,7 +318,8 @@ public void SammExtensionHelperAddSammReference( } public void SammExtensionHelperAddListOfSammReference( - Aas.Environment env, AnyUiStackPanel stack, string caption, + Aas.Environment env, SammIdSet idSet, + AnyUiStackPanel stack, string caption, Samm.ModelElement sammInst, Aas.IReferable relatedReferable, List value, @@ -343,7 +365,8 @@ public void SammExtensionHelperAddListOfSammReference( // Stack in the 1st column var sp1 = AddSmallStackPanelTo(sg, 1 + lsri, 0); SammExtensionHelperAddSammReference( - env, sp1, $"[{1 + lsri}]", + env, idSet, + sp1, $"[{1 + lsri}]", (Samm.ModelElement)sammInst, relatedReferable, value[lsri], noFirstColumnWidth: true, @@ -412,7 +435,7 @@ public void SammExtensionHelperAddListOfSammReference( case 5: case 6: return SammExtensionHelperSammReferenceAction( - env, relatedReferable, + env, idSet, relatedReferable, sr: value[theLsri], actionIndex: ti - 3, presetList: null, @@ -438,7 +461,8 @@ public void SammExtensionHelperAddListOfSammReference( } public void SammExtensionHelperAddCompleteModelElement( - Aas.Environment env, AnyUiStackPanel stack, + Aas.Environment env, SammIdSet idSet, + AnyUiStackPanel stack, Samm.ModelElement sammInst, Aas.IReferable relatedReferable, Action setValue) @@ -473,7 +497,7 @@ public void SammExtensionHelperAddCompleteModelElement( addableElements = Samm.Constants.AddableConstraints; SammExtensionHelperAddListOfSammReference( - env, stack, caption: "" + pii.Name, + env, idSet, stack, caption: "" + pii.Name, (ModelElement)sammInst, relatedReferable, editOptionalFlag: false, @@ -490,7 +514,7 @@ public void SammExtensionHelperAddCompleteModelElement( if (pii.PropertyType.IsAssignableTo(typeof(List))) { SammExtensionHelperAddListOfSammReference( - env, stack, caption: "" + pii.Name, + env, idSet, stack, caption: "" + pii.Name, (ModelElement)sammInst, relatedReferable, editOptionalFlag: true, @@ -653,7 +677,8 @@ public void SammExtensionHelperAddCompleteModelElement( } SammExtensionHelperAddSammReference( - env, stack, "" + pii.Name, (Samm.ModelElement)sammInst, relatedReferable, + env, idSet, + stack, "" + pii.Name, (Samm.ModelElement)sammInst, relatedReferable, sr, presetList: presetValues, setValue: (v) => { @@ -873,9 +898,9 @@ public static Type CheckReferableForSammExtensionType(Aas.IReferable rf) // find any? foreach (var se in rf.Extensions) { - var sammType = Samm.Util.GetTypeFromUrn(Samm.Util.GetSammUrn(se)); - if (sammType != null) - return sammType; + var sammIdSetType = Samm.SammIdSets.GetAnyIdSetTypeFromUrn(Samm.Util.GetSammUrn(se)); + if (sammIdSetType != null) + return sammIdSetType.Item2; } // no? @@ -892,8 +917,8 @@ public static IEnumerable CheckReferableForSammElements(Aas.IRefer foreach (var se in rf.Extensions) { // get type - var sammType = Samm.Util.GetTypeFromUrn(Samm.Util.GetSammUrn(se)); - if (sammType == null) + var sammIdSetType = Samm.SammIdSets.GetAnyIdSetTypeFromUrn(Samm.Util.GetSammUrn(se)); + if (sammIdSetType == null) continue; // get instance data @@ -903,7 +928,7 @@ public static IEnumerable CheckReferableForSammElements(Aas.IRefer try { if (se.Value != null) - sammInst = JsonConvert.DeserializeObject(se.Value, sammType) as ModelElement; + sammInst = JsonConvert.DeserializeObject(se.Value, sammIdSetType.Item2) as ModelElement; } catch (Exception ex) { @@ -925,11 +950,12 @@ public static IEnumerable CheckReferableForSammElements(Aas.IRefer /// Null, if not a SAMM model element public static string CheckReferableForSammExtensionTypeName(Type sammType) { - return Samm.Util.GetNameFromSammType(sammType); + return Samm.SammIdSets.GetAnyNameFromSammType(sammType); } public void DisplayOrEditEntitySammExtensions( - Aas.Environment env, AnyUiStackPanel stack, + Aas.Environment env, + AnyUiStackPanel stack, List sammExtension, Action> setOutput, string[] addPresetNames = null, List[] addPresetKeyLists = null, @@ -968,6 +994,10 @@ public void DisplayOrEditEntitySammExtensions( return new AnyUiLambdaActionRedrawEntity(); })) { + // Note: the buttons will use a "detected version" (see below) + // of the id set + SammIdSet detectedIdSet = null; + // head control if (editMode) { @@ -1008,9 +1038,10 @@ public void DisplayOrEditEntitySammExtensions( } if (buttonNdx == 4) - { + { // select - var sammTypeToCreate = SammExtensionHelperSelectSammType(Samm.Constants.AddableElements); + var sammTypeToCreate = SammExtensionHelperSelectSammType( + Samm.Constants.AddableElements); if (sammTypeToCreate != null) { @@ -1018,20 +1049,33 @@ public void DisplayOrEditEntitySammExtensions( newChar = Activator.CreateInstance( sammTypeToCreate, new object[] { }) as Samm.ModelElement; } - - if (newChar != null && newChar is Samm.ISammSelfDescription ssd) - sammExtension.Add( - new Aas.Extension( - name: ssd.GetSelfName(), - semanticId: new Aas.Reference(ReferenceTypes.ExternalReference, - (new[] { - new Aas.Key(KeyTypes.GlobalReference, - "" + Samm.Constants.SelfNamespaces.ExtendUri(ssd.GetSelfUrn())) - }) - .Cast().ToList()), - value: "")); } + // create a new element + if (newChar != null && newChar is Samm.ISammSelfDescription ssd) + { + // which id set to use + if (detectedIdSet == null) + detectedIdSet = SammExtensionHelperSelectSammVersion( + Samm.SammIdSets.IdSets.Values); + if (detectedIdSet == null) + return new AnyUiLambdaActionNone(); + + // now add + sammExtension.Add( + new Aas.Extension( + name: ssd.GetSelfName(), + semanticId: new Aas.Reference(ReferenceTypes.ExternalReference, + (new[] { + new Aas.Key(KeyTypes.GlobalReference, + "" + detectedIdSet.SelfNamespaces.ExtendUri( + ssd.GetSelfUrn(detectedIdSet.Version))) + }) + .Cast().ToList()), + value: "")); + } + + // remove if (buttonNdx == 5) { if (sammExtension.Count > 0) @@ -1054,11 +1098,15 @@ public void DisplayOrEditEntitySammExtensions( { // get type var se = sammExtension[i]; - var sammType = Samm.Util.GetTypeFromUrn(Samm.Util.GetSammUrn(se)); - if (sammType == null) - { + var idSetType = Samm.SammIdSets.GetAnyIdSetTypeFromUrn(Samm.Util.GetSammUrn(se)); + if (idSetType?.Item1 == null || idSetType.Item2 == null) continue; - } + var sammType = idSetType.Item2; + var idSet = idSetType.Item1; + + // remeber as detected .. (for later dialogs described above!) + if (detectedIdSet == null) + detectedIdSet = idSet; // more then one? this.AddHintBubble( @@ -1137,7 +1185,7 @@ public void DisplayOrEditEntitySammExtensions( } SammExtensionHelperAddCompleteModelElement( - env, stack, + env, idSet, stack, sammInst: sammInst, relatedReferable: relatedReferable, setValue: (si) => @@ -1226,16 +1274,18 @@ public static INode SafeCreateLiteralNode(IGraph g, string text, string language return g.CreateLiteralNode(text, l2); } - public static INode CreateUriOrLiteralNode(IGraph g, string text, bool isUri) + public static INode CreateUriOrLiteralNode( + IGraph g, SammIdSet idSet, + string text, bool isUri) { // access - if (g == null || text == null) + if (g == null || idSet == null || text == null) return null; if (isUri) return g.CreateUriNode(new Uri(text, UriKind.RelativeOrAbsolute)); else - return g.CreateLiteralNode(text, datatype: new Uri(Samm.Constants.XsdString)); + return g.CreateLiteralNode(text, datatype: new Uri(idSet.XsdString)); } public static Aas.LangStringTextType ParseLangStringFromNode(INode node) @@ -1279,13 +1329,13 @@ public class SammImportExport /// Note: this string will be changed, when the Aspect element is visited /// and prefixes are known better. /// - public string AutoFillHeadId = Samm.Constants.DefaultInstanceURN; + public string AutoFillHeadId = ""; /// /// Parses an rdf:Collection and reads out either SammReference or OptionalSammReference /// public List ImportRdfCollection( - IGraph g, + IGraph g, SammIdSet idSet, INode collectionStart, string contentRelationshipUri, Func createInstance) where T : SammReference @@ -1293,6 +1343,11 @@ public List ImportRdfCollection( // Try parse a rdf:Collection // see: https://ontola.io/blog/ordered-data-in-rdf + // access + if (g == null || idSet == null) + return null; + + // start var lsr = new List(); INode collPtr = collectionStart; @@ -1301,10 +1356,10 @@ public List ImportRdfCollection( // only a single member is given var litVal = RdfHelper.GetTerminalStrValue(collPtr); if (litVal?.HasContent() == true - && litVal != Samm.Constants.RdfCollNil) + && litVal != idSet.RdfCollNil) lsr.Add(createInstance?.Invoke(litVal, false)); } - else + else { // a chain of instances is given while (collPtr != null && collPtr.NodeType == NodeType.Blank) @@ -1312,7 +1367,7 @@ public List ImportRdfCollection( // the collection pointer needs to have a first relationship var firstRel = g.GetTriplesWithSubjectPredicate( subj: collPtr, - pred: new UriNode(new Uri(Samm.Constants.RdfCollFirst))) + pred: new UriNode(new Uri(idSet.RdfCollFirst))) .FirstOrDefault(); if (firstRel?.Object == null) break; @@ -1337,8 +1392,8 @@ public List ImportRdfCollection( new Uri(contentRelationshipUri)))) propElem = x3.Object.ToSafeString(); if (x3.Predicate.Equals( - new UriNode(new Uri(Samm.Constants.RdfCollOptional)))) - optional = x3.Object.ToSafeString() == + new UriNode(new Uri(idSet.RdfCollOptional)))) + optional = x3.Object.ToSafeString() == "true^^http://www.w3.org/2001/XMLSchema#boolean"; } @@ -1349,7 +1404,7 @@ public List ImportRdfCollection( // iterate further var restRel = g.GetTriplesWithSubjectPredicate( subj: collPtr, - pred: new UriNode(new Uri(Samm.Constants.RdfCollRest))) + pred: new UriNode(new Uri(idSet.RdfCollRest))) .FirstOrDefault(); collPtr = restRel?.Object; } @@ -1395,9 +1450,13 @@ public class ImportSammInfo /// public SammReference ImportParseSingleSammReference( Aas.IEnvironment env, - IGraph g, + IGraph g, SammIdSet idSet, INode subjectNode) { + // access + if (g == null || idSet == null) + return null; + // anonymous node or note if (RdfHelper.IsTerminalNode(subjectNode)) { @@ -1410,21 +1469,21 @@ public SammReference ImportParseSingleSammReference( // the "a" relationship behind it var trpA = g.GetTriplesWithSubjectPredicate( subj: subjectNode, - pred: new UriNode(new Uri(Samm.Constants.PredicateA)))?.FirstOrDefault(); + pred: new UriNode(new Uri(idSet.PredicateA)))?.FirstOrDefault(); if (trpA == null) return null; // create an samm instance var sammInfo = ImportCreateSubjectAndFill( - env, g, trpA.Subject, trpA.Object); + env, g, idSet, trpA.Subject, trpA.Object); if (sammInfo?.IsValidInst() != true) return null; // create CD for this ImportCreateCDandIds( - env, sammInfo, autoFillIdShortAndId: true); + env, idSet, sammInfo, autoFillIdShortAndId: true); // set this as reference .. return new SammReference(sammInfo.NewId); } @@ -1433,6 +1492,7 @@ public SammReference ImportParseSingleSammReference( public ImportSammInfo ImportCreateSubjectAndFill( Aas.IEnvironment env, IGraph g, + SammIdSet idSet, INode subjectNode, INode typeObjNode) { @@ -1442,7 +1502,7 @@ public ImportSammInfo ImportCreateSubjectAndFill( // check, if there is a SAMM type behind the object var sammElemUri = RdfHelper.GetTerminalStrValue(typeObjNode); - var sammType = Samm.Util.GetTypeFromUrn(sammElemUri); + var sammType = idSet.GetTypeFromUrn(sammElemUri); if (sammType == null) { Log.Singleton.Info($"Potential SAMM element found but unknown URI={sammElemUri}"); @@ -1462,22 +1522,19 @@ public ImportSammInfo ImportCreateSubjectAndFill( var propInfo = sammInst.GetType().GetProperties(); for (int pi = 0; pi < propInfo.Length; pi++) { - //// is the object marked to be skipped? - //var x3 = pi.GetCustomAttribute(); - //if (x3 != null) - // continue; + // reflection var pii = propInfo[pi]; var propType = pii.PropertyType; var underlyingType = Nullable.GetUnderlyingType(propType); // need to have a custom attribute to identify the subject uri of the turtle triples - var propSearchUri = pii.GetCustomAttribute()?.Uri; + var propSearchUri = Samm.Util.FindAnySammPropertyUriAttribute(pii, idSet.Version)?.Uri; if (propSearchUri == null) continue; // extend this - propSearchUri = Samm.Constants.SelfNamespaces.ExtendUri(propSearchUri); + propSearchUri = idSet.SelfNamespaces.ExtendUri(propSearchUri); //// now try to find triples with: //// Subject = trpSammElem.Subject and @@ -1528,21 +1585,22 @@ public ImportSammInfo ImportCreateSubjectAndFill( // need a special uri for each content element // but not fully mandatory - var collContentUri = pii.GetCustomAttribute()?.Uri; + var collContentUri = Samm.Util.FindAnySammCollectionContentUriAttribute( + pii, idSet.Version)?.Uri; // there are two possibilities, by spec/ knowledge not // easy to distinguish: an optional _single_ SammReference, which // should be added to the list or a _list_ of SammReferences. // Approach: be open for the first, if not, check the second. - var sr = ImportParseSingleSammReference(env, g, trpProp.Object); + var sr = ImportParseSingleSammReference(env, g, idSet, trpProp.Object); if (sr != null) lsr.Add(sr); else lsr.AddRange( ImportRdfCollection( - g, collectionStart: trpProp.Object, + g, idSet, collectionStart: trpProp.Object, contentRelationshipUri: - Samm.Constants.SelfNamespaces.ExtendUri(collContentUri), + idSet.SelfNamespaces.ExtendUri(collContentUri), createInstance: (sr, opt) => new SammReference(sr))); // write found references back @@ -1558,16 +1616,15 @@ public ImportSammInfo ImportCreateSubjectAndFill( lsr = new List(); // need a special uri for each content element - var collContentUri = pii.GetCustomAttribute()?.Uri; - if (collContentUri == null) - continue; + var collContentUri = Samm.Util.FindAnySammCollectionContentUriAttribute( + pii, idSet.Version)?.Uri; // put it lsr.AddRange( ImportRdfCollection( - g, collectionStart: trpProp.Object, + g, idSet, collectionStart: trpProp.Object, contentRelationshipUri: - Samm.Constants.SelfNamespaces.ExtendUri(collContentUri), + idSet.SelfNamespaces.ExtendUri(collContentUri), createInstance: (sr, opt) => new OptionalSammReference(sr, opt))); // write found references back @@ -1577,7 +1634,7 @@ public ImportSammInfo ImportCreateSubjectAndFill( // just SammReference if (pii.PropertyType.IsAssignableTo(typeof(Samm.SammReference))) { - var sr = ImportParseSingleSammReference(env, g, trpProp.Object); + var sr = ImportParseSingleSammReference(env, g, idSet, trpProp.Object); if (sr != null) pii.SetValue(sammInst, sr); } @@ -1625,6 +1682,7 @@ public ImportSammInfo ImportCreateSubjectAndFill( public void ImportCreateCDandIds( Aas.IEnvironment env, + SammIdSet idSet, ImportSammInfo si, string givenUriId = null, string overIdShort = null, @@ -1632,7 +1690,7 @@ public void ImportCreateCDandIds( List cdDesc = null) { // access - if (si?.IsValidInst() != true) + if (si?.IsValidInst() != true || idSet == null) return; // which identifiers? @@ -1677,7 +1735,7 @@ public void ImportCreateCDandIds( semanticId: new Aas.Reference(ReferenceTypes.ExternalReference, (new[] { new Aas.Key(KeyTypes.GlobalReference, - "" + Samm.Constants.SelfNamespaces.ExtendUri(newSammSsd.GetSelfUrn())) + "" + idSet.SelfNamespaces.ExtendUri(newSammSsd.GetSelfUrn(idSet.Version))) }) .Cast().ToList()), value: ""); @@ -1691,7 +1749,7 @@ public void ImportCreateCDandIds( } public void ImportSammModelToConceptDescriptions( - Aas.IEnvironment env, + Aas.IEnvironment env, string fn) { // do it @@ -1719,8 +1777,17 @@ public void ImportSammModelToConceptDescriptions( globalNamespaces.AddOrIgnore(prefix, g.NamespaceMap.GetNamespaceUri(pf).ToSafeString()); } + // figure out, which idSet to be used + // var idSet = Samm.SammIdSets.IdSets.Values.Last(); + var idSet = Samm.SammIdSets.DetectVersion(globalNamespaces); + if (idSet == null) + { + Log.Singleton.Error("Cannot determine SAMM version for the model file. Aborting!"); + return; + } + // find all potential SAMM elements " :xxx a bamm:XXXX" - foreach (var trpSammElem in g.GetTriplesWithPredicate(new Uri(Samm.Constants.PredicateA))) + foreach (var trpSammElem in g.GetTriplesWithPredicate(new Uri(idSet.PredicateA))) { // it only make sense, that the subject of the found triples is a // UriNode. A anonymous node would NOT make sense, here @@ -1731,14 +1798,14 @@ public void ImportSammModelToConceptDescriptions( // create the samm element var sammInfo = ImportCreateSubjectAndFill( - env, g, trpSammElem.Subject, trpSammElem.Object); + env, g, idSet, trpSammElem.Subject, trpSammElem.Object); if (sammInfo?.IsValidInst() != true) continue; // description of Referable is a special case List cdDesc = null; - var descPred = Samm.Constants.SelfNamespaces.ExtendUri(Samm.Constants.SammDescription); + var descPred = idSet.SelfNamespaces.ExtendUri(idSet.SammDescription); foreach (var trpProp in g.GetTriplesWithSubjectPredicate( subj: trpSammElem.Subject, pred: new VDS.RDF.UriNode(new Uri(descPred)))) @@ -1755,7 +1822,7 @@ public void ImportSammModelToConceptDescriptions( // name of elements is a special case. Can become idShort string elemName = null; - var elemPred = Samm.Constants.SelfNamespaces.ExtendUri(Samm.Constants.SammName); + var elemPred = idSet.SelfNamespaces.ExtendUri(idSet.SammName); foreach (var trpProp in g.GetTriplesWithSubjectPredicate( subj: trpSammElem.Subject, pred: new VDS.RDF.UriNode(new Uri(elemPred)))) @@ -1769,6 +1836,7 @@ public void ImportSammModelToConceptDescriptions( siAspect.Namespaces = globalNamespaces; siAspect.Comments = globalComments; + AutoFillHeadId = idSet.DefaultInstanceURN; var afid = globalNamespaces.ExtendUri(":"); if (afid?.HasContent() == true) AutoFillHeadId = afid; @@ -1776,7 +1844,7 @@ public void ImportSammModelToConceptDescriptions( // after this, the sammInst is fine; we need to prepare the outside ImportCreateCDandIds( - env, sammInfo, + env, idSet, sammInfo, givenUriId: RdfHelper.GetTerminalStrValue(trpSammElem.Subject), overIdShort: elemName, cdDesc: cdDesc?.Cast().ToList()); @@ -1822,12 +1890,13 @@ public IEnumerable AllSammReferences(Samm.ModelElement me) protected INode ExportSammOptionalReference( Aas.IEnvironment env, IGraph g, + SammIdSet idSet, Samm.Aspect asp, Samm.OptionalSammReference osr, string contentRelationshipUri) { // access - if (g == null || asp?.Namespaces == null || osr == null) + if (g == null || idSet == null || asp?.Namespaces == null || osr == null) return null; // make a blank node @@ -1842,10 +1911,10 @@ protected INode ExportSammOptionalReference( // add optional g.Assert(new Triple( orNode, - g.CreateUriNode(new Uri(Samm.Constants.RdfCollOptional)), + g.CreateUriNode(new Uri(idSet.RdfCollOptional)), g.CreateLiteralNode( osr.Optional ? "true" : "false", - datatype: new Uri(Samm.Constants.XsdBoolean)))); + datatype: new Uri(idSet.XsdBoolean)))); // result return orNode; @@ -1854,12 +1923,13 @@ protected INode ExportSammOptionalReference( protected INode ExportRdfCollection( Aas.IEnvironment env, IGraph g, + SammIdSet idSet, Samm.Aspect asp, List coll, Func lambdaCreateContentNode) { // access - if (g == null || asp?.Namespaces == null || coll == null) + if (g == null || idSet == null || asp?.Namespaces == null || coll == null) return null; // make a blank node and start @@ -1875,7 +1945,7 @@ protected INode ExportRdfCollection( { g.Assert( currNode, - g.CreateUriNode(new Uri(Samm.Constants.RdfCollFirst)), + g.CreateUriNode(new Uri(idSet.RdfCollFirst)), contentNode); } @@ -1888,7 +1958,7 @@ protected INode ExportRdfCollection( // link to this g.Assert( currNode, - g.CreateUriNode(new Uri(Samm.Constants.RdfCollRest)), + g.CreateUriNode(new Uri(idSet.RdfCollRest)), nextNode); // increment @@ -1900,8 +1970,8 @@ protected INode ExportRdfCollection( // finalize g.Assert( currNode, - g.CreateUriNode(new Uri(Samm.Constants.RdfCollRest)), - g.CreateUriNode(new Uri(Samm.Constants.RdfCollNil))); + g.CreateUriNode(new Uri(idSet.RdfCollRest)), + g.CreateUriNode(new Uri(idSet.RdfCollNil))); break; } } @@ -1912,18 +1982,19 @@ protected INode ExportRdfCollection( public void ExportSammOneElement( Aas.IEnvironment env, IGraph g, + SammIdSet idSet, Samm.Aspect asp, Aas.IConceptDescription cd, ModelElement me) { // access - if (g == null || me == null || cd == null || asp?.Namespaces == null) + if (g == null || idSet == null || me == null || cd == null || asp?.Namespaces == null) return; // check self description and add triple type if (!(me is Samm.ISammSelfDescription ssd)) return; - var meUrn = ssd.GetSelfUrn(); + var meUrn = ssd.GetSelfUrn(idSet.Version); if (meUrn?.HasContent() != true) return; @@ -1943,7 +2014,7 @@ public void ExportSammOneElement( // special case: name g.Assert(new Triple( subjectNode, - g.CreateUriNode(Samm.Constants.SammName), + g.CreateUriNode(idSet.SammName), g.CreateLiteralNode(cd.IdShort))); // special case: description @@ -1952,7 +2023,7 @@ public void ExportSammOneElement( { g.Assert(new Triple( g.CreateUriNode(asp.Namespaces.PrefixUri(cd.Id)), - g.CreateUriNode(Samm.Constants.SammDescription), + g.CreateUriNode(idSet.SammDescription), RdfHelper.SafeCreateLiteralNode(g, ls.Text, ls.Language))); } @@ -1961,7 +2032,7 @@ public void ExportSammOneElement( { // the property needs to have a custom attribute to // identify the predicate uri of the turtle triples - var propUri = pi.GetCustomAttribute()?.Uri; + var propUri = Samm.Util.FindAnySammPropertyUriAttribute(pi, idSet.Version)?.Uri; if (propUri == null) continue; @@ -1982,7 +2053,7 @@ public void ExportSammOneElement( g.Assert(new Triple( g.CreateUriNode(asp.Namespaces.PrefixUri(cd.Id)), g.CreateUriNode(propUri), - RdfHelper.CreateUriOrLiteralNode(g, s.ToSafeString(), isUri))); + RdfHelper.CreateUriOrLiteralNode(g, idSet, s.ToSafeString(), isUri))); } } @@ -1997,7 +2068,7 @@ public void ExportSammOneElement( g.CreateUriNode(asp.Namespaces.PrefixUri(cd.Id)), g.CreateUriNode(propUri), g.CreateLiteralNode(ui.Value.ToSafeString(), - datatype: new Uri(Samm.Constants.XsdNonNegInt)))); + datatype: new Uri(idSet.XsdNonNegInt)))); } } @@ -2046,7 +2117,7 @@ public void ExportSammOneElement( g.Assert(new Triple( g.CreateUriNode(asp.Namespaces.PrefixUri(cd.Id)), g.CreateUriNode(propUri), - RdfHelper.CreateUriOrLiteralNode(g, ls.ToSafeString(), isUri))); + RdfHelper.CreateUriOrLiteralNode(g, idSet, ls.ToSafeString(), isUri))); } } @@ -2097,7 +2168,7 @@ public void ExportSammOneElement( if (losr != null && losr.Count >= 1) { // do a collection - var collNode = ExportRdfCollection(env, g, asp, losr, (osr) => + var collNode = ExportRdfCollection(env, g, idSet, asp, losr, (osr) => { if (osr.Optional == false) // direct content @@ -2105,7 +2176,7 @@ public void ExportSammOneElement( asp.Namespaces.PrefixUri(osr?.Value.ToSafeString())); else // anonymous node - return ExportSammOptionalReference(env, g, asp, osr, + return ExportSammOptionalReference(env, g, idSet, asp, osr, collContentUri); }); if (collNode != null) @@ -2125,7 +2196,7 @@ public void ExportSammOneElement( if (lsr != null && lsr.Count >= 1) { // do a collection - var collNode = ExportRdfCollection(env, g, asp, lsr, (sr) => + var collNode = ExportRdfCollection(env, g, idSet, asp, lsr, (sr) => { return g.CreateUriNode( asp.Namespaces.PrefixUri(sr?.Value.ToSafeString())); @@ -2153,7 +2224,7 @@ public void ExportSammOneElement( var me2 = DispEditHelperSammModules.CheckReferableForSammElements(cd2).FirstOrDefault(); if (cd2 != null && me2 != null) if (cd2?.Id?.HasContent() == true && !_visitedCdIds.ContainsKey(cd2.Id)) - ExportSammOneElement(env, g, asp, cd2, me2); + ExportSammOneElement(env, g, idSet, asp, cd2, me2); } } @@ -2169,6 +2240,9 @@ public void ExportSammModelFromConceptDescription( // Reserve the graph, but make only by Aspect Graph g = null; + // choose the right idSet + var idSet = new SammIdSet(); + // Reserve text for comments string globalComments = ""; Samm.Aspect globalAspect = null; @@ -2180,7 +2254,7 @@ public void ExportSammModelFromConceptDescription( // determine base uri var buri = asp.Namespaces.ExtendUri(":"); if (buri?.HasContent() != true) - buri = Samm.Constants.DefaultInstanceURN; + buri = idSet.DefaultInstanceURN; // globals globalAspect = asp; @@ -2205,7 +2279,7 @@ public void ExportSammModelFromConceptDescription( g.NamespaceMap.AddNamespace("this", new Uri(buri)); // export - ExportSammOneElement(env, g, globalAspect, aspectCd, asp); + ExportSammOneElement(env, g, idSet, globalAspect, aspectCd, asp); } else Log.Singleton.Error($"ConceptDescription {aspectCd?.IdShort} is missing SAMM model element " + @@ -2256,6 +2330,76 @@ public static Aas.IQualifier CreateQualifierSmtCardinality(SmtCardinality card) }).ToList()), value: "" + card); } + + public static Aas.IQualifier CreateQualifierSmtAllowedValue(string regex) + { + return new Aas.Qualifier( + type: "SMT/AllowedValue", + valueType: DataTypeDefXsd.String, + kind: QualifierKind.TemplateQualifier, + semanticId: new Aas.Reference(ReferenceTypes.ExternalReference, + (new Aas.IKey[] { + new Aas.Key(KeyTypes.GlobalReference, + "https://admin-shell.io/SubmodelTemplates/AllowedValue/1/0") + }).ToList()), + value: "" + regex); + } + + public static Aas.IQualifier CreateQualifierSmtExampleValue(string exampleValue) + { + return new Aas.Qualifier( + type: "SMT/ExampleValue", + valueType: DataTypeDefXsd.String, + kind: QualifierKind.TemplateQualifier, + semanticId: new Aas.Reference(ReferenceTypes.ExternalReference, + (new Aas.IKey[] { + new Aas.Key(KeyTypes.GlobalReference, + "https://admin-shell.io/SubmodelTemplates/ExampleValue/1/0") + }).ToList()), + value: "" + exampleValue); + } + + public static Aas.IQualifier CreateQualifierSmtDefaultValue(string defaultValue) + { + return new Aas.Qualifier( + type: "SMT/DefaultValue", + valueType: DataTypeDefXsd.String, + kind: QualifierKind.TemplateQualifier, + semanticId: new Aas.Reference(ReferenceTypes.ExternalReference, + (new Aas.IKey[] { + new Aas.Key(KeyTypes.GlobalReference, + "https://admin-shell.io/SubmodelTemplates/DefaultValue/1/0") + }).ToList()), + value: "" + defaultValue); + } + + public static Aas.IQualifier CreateQualifierSmtEitherOr(string equivalencyClass) + { + return new Aas.Qualifier( + type: "SMT/EitherOr", + valueType: DataTypeDefXsd.String, + kind: QualifierKind.TemplateQualifier, + semanticId: new Aas.Reference(ReferenceTypes.ExternalReference, + (new Aas.IKey[] { + new Aas.Key(KeyTypes.GlobalReference, + "https://admin-shell.io/SubmodelTemplates/Cardinality/1/0") + }).ToList()), + value: "" + equivalencyClass); + } + + public static Aas.IQualifier CreateQualifierSmtRequiredLang(string reqLang) + { + return new Aas.Qualifier( + type: "SMT/RequiredLang", + valueType: DataTypeDefXsd.String, + kind: QualifierKind.TemplateQualifier, + semanticId: new Aas.Reference(ReferenceTypes.ExternalReference, + (new Aas.IKey[] { + new Aas.Key(KeyTypes.GlobalReference, + "https://admin-shell.io/SubmodelTemplates/RequiredLang/1/0") + }).ToList()), + value: "" + reqLang); + } } /// @@ -2446,20 +2590,29 @@ public void CreateSubmodelElementsInto( if (meProp == null) continue; + if (sitProp?.CD?.IdShort == "catenaXId") + ; + // keep track for later use Aas.ISubmodelElement addedElem = null; - + var qualiferToAdd = new List(); + + // may be already 1st qualifer + if (osrProp.Optional) + // Cardinality + qualiferToAdd.Add( + AasPresetHelper.CreateQualifierSmtCardinality(AasPresetHelper.SmtCardinality.ZeroToOne)); + // ok, a Submodel element shall be created. // But more details (SMC? Property?) are only avilable via // Characteristic -> dataType .. var sitChar = store.Lookup(meProp.Characteristic); var meChar = sitChar?.ME as Samm.Characteristic; - - // first check the case, that the Characteristic -> dataType goes to an entity var meDt = store.Lookup(meChar?.DataType); if (meDt != null && meDt.ME is Samm.Entity meDtEnt) { - // make a SMC and add directl + // Characteristic -> dataType goes to an entity + // make a SMC and add directly var newSmc = new Aas.SubmodelElementCollection( idShort: "" + sitProp.CD.IdShort, semanticId: CreateSemanticId(meDt.CD.Id), @@ -2472,7 +2625,7 @@ public void CreateSubmodelElementsInto( env, store, aspect, newSmc.Value, meDtEnt.Properties); - } + } else { // if in doubt, create a Property with xsd:string @@ -2505,18 +2658,24 @@ public void CreateSubmodelElementsInto( aasElems.Add(newProp); } - // elaborate added element further - if (addedElem != null) + // add further information + + if (sitChar?.ME is Samm.Trait charTrait) { - if (osrProp.Optional) + foreach (var sitCons in store.LookupFor(charTrait.Constraint)) { - // add [0..1] - addedElem.Qualifiers = new List + if (sitCons.ME is Samm.RegularExpressionConstraint regexCons) { - AasPresetHelper.CreateQualifierSmtCardinality(AasPresetHelper.SmtCardinality.ZeroToOne) - }; + // AllowedValue == Regex + qualiferToAdd.Add( + AasPresetHelper.CreateQualifierSmtAllowedValue(regexCons.Value)); + } } } + + // elaborate added element further + if (addedElem != null && qualiferToAdd.Count > 0) + addedElem.Qualifiers = qualiferToAdd; } }