diff --git a/src/AasxCore.Samm2_2_0/SammClasses.cs b/src/AasxCore.Samm2_2_0/SammClasses.cs index 50fc576f4..0bba28e3b 100644 --- a/src/AasxCore.Samm2_2_0/SammClasses.cs +++ b/src/AasxCore.Samm2_2_0/SammClasses.cs @@ -330,6 +330,23 @@ public SammReference(string val = "") } } + /// + /// When Properties are used in Aspects and Entities, they can be marked as optional + /// (not possible for properties of Abstract Entities). + /// This means that a Property’s usage is optional, not the Property itself, which + /// would make reusing a Property more difficult. + /// + public class OptionalSammReference : SammReference + { + public bool Optional { get; set; } = false; + + public OptionalSammReference(string val = "", bool optional = false) + { + Value = val; + Optional = optional; + } + } + /// /// Single item for NamespaceMap. /// @@ -417,7 +434,7 @@ public bool AddOrIgnore(string prefix, string uri) /// Base class for other constraints that constrain a Characteristic in some way, e.g., the Range Constraint /// limits the value range for a Property. /// - /// + /// /// public class Constraint : ModelElement { @@ -426,7 +443,7 @@ public class Constraint : ModelElement /// /// Restricts a value to a specific language. /// - /// + /// /// public class LanguageConstraint : Constraint { @@ -434,19 +451,21 @@ public class LanguageConstraint : Constraint /// An ISO 639-1 [iso639] language code for the language of the value of the constrained Property, /// e.g., "de". /// + [SammPropertyUri("bamm-c:languageCode")] public string? LanguageCode; } /// /// Restricts a value to a specific locale, i.e., a language with additional region information. /// - /// + /// /// public class LocaleConstraint : Constraint { /// /// An IETF BCP 47 language code for the locale of the value of the constrained Property, e.g., "de-DE". /// + [SammPropertyUri("bamm-c:localeCode")] public string? LocaleCode; } @@ -459,30 +478,34 @@ public class RangeConstraint : Constraint /// /// The upper bound of a range. /// + [SammPropertyUri("bamm-c:maxValue")] public string? MaxValue; /// /// The lower bound of a range. /// + [SammPropertyUri("bamm-c:minValue")] public string? MinValue; /// /// Defines whether the upper bound of a range is inclusive or exclusive. Possible values are /// AT_MOST and LESS_THAN. /// + [SammPropertyUri("bamm-c:upperBoundDefinition")] public SammUpperBoundDefinition? UpperBoundDefinition; /// /// Defines whether the lower bound of a range is inclusive or exclusive. Possible values are /// AT_LEAST and GREATER_THAN. /// + [SammPropertyUri("bamm-c:lowerBoundDefinition")] public SammLowerBoundDefinition? LowerBoundDefinition; } /// /// Restricts the encoding of a Property. /// - /// + /// /// public class EncodingConstraint : Constraint { @@ -490,6 +513,7 @@ public class EncodingConstraint : Constraint /// 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:value")] public SammEncoding? Value; } @@ -500,18 +524,20 @@ public class EncodingConstraint : Constraint /// Collection Characteristics (Collection, Set, Sorted Set, List). In this case the Constraint restricts the /// number of elements in the collection. /// - /// + /// /// public class LengthConstraint : Constraint { /// /// The maximum length. Must be given as xsd:nonNegativeInteger. /// + [SammPropertyUri("bamm-c:maxValue")] public uint? MaxValue; /// /// The minimum length. Must be given as xsd:nonNegativeInteger. /// + [SammPropertyUri("bamm-c:minValue")] public uint? MinValue; } @@ -520,7 +546,7 @@ public class LengthConstraint : Constraint /// and Operators [xpath-functions]. /// /// - /// + /// /// public class RegularExpressionConstraint : Constraint { @@ -528,6 +554,7 @@ public class RegularExpressionConstraint : Constraint /// The regular expression. /// /// + [SammPropertyUri("bamm-c:value")] public string? Value; } @@ -535,7 +562,7 @@ public class RegularExpressionConstraint : Constraint /// Defines the scaling factor as well as the amount of integral numbers for a fixed point number. /// The constraint may only be used in conjunction with Characteristics which use the xsd:decimal data type. /// - /// + /// /// public class FixedPointConstraint : Constraint { @@ -544,6 +571,7 @@ public class FixedPointConstraint : Constraint /// scaling factor is 2 (the number of digits after the decimal point). /// Must be given as xsd:positiveInteger. /// + [SammPropertyUri("bamm-c:scale")] public uint? Scale; /// @@ -551,6 +579,7 @@ public class FixedPointConstraint : Constraint /// 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")] public uint? Integer; } @@ -558,13 +587,15 @@ public class FixedPointConstraint : Constraint /// Base class of all characteristics. This Characteristics Class can also be instantiated directly /// (i.e., without creating a subclass). /// - /// + /// /// public class Characteristic : ModelElement, ISammSelfDescription, ISammStructureModel { // self description public string GetSelfName() => "samm-characteristic"; - public string GetSelfUrn() => "urn:samm:org.eclipse.esmf.samm:characteristic:2.1.0#Characteristic"; + // public string GetSelfUrn() => "urn:bamm:io.openmanufacturing:characteristic:1.0.0#Characteristic"; + // FIX: seems to use bamm: instead of bamm-c: !! + public string GetSelfUrn() => "urn:bamm:io.openmanufacturing:meta-model:1.0.0#Characteristic"; // structure model public bool IsTopElement() => false; @@ -577,8 +608,9 @@ public IEnumerable DescendOnce() /// /// Reference to a scalar or complex (Entity) data type. See Section "Type System" in the Aspect Meta Model. /// Also the scalar data types (e.g. xsd:decimal) are treated as references in the first degree. - /// + /// [SammPresetList("SammXsdDataTypes")] + [SammPropertyUri("bamm:dataType")] public SammReference DataType { get; set; } public Characteristic() @@ -592,24 +624,26 @@ public Characteristic() /// referred to as the "base Characteristic". A Trait itself has no samm:dataType, /// because it inherits the type of its samm-c:baseCharacteristic. /// - /// + /// /// public class Trait : Characteristic, ISammSelfDescription { // self description public new string GetSelfName() => "samm-trait"; - public new string GetSelfUrn() => "urn:samm:org.eclipse.esmf.samm:characteristic:2.1.0#Trait"; + public new string GetSelfUrn() => "urn:bamm:io.openmanufacturing:characteristic:1.0.0#Trait"; /// /// The Characterstic that is being constrained. /// Identified via preferredName in any language /// + [SammPropertyUri("bamm-c:baseCharacteristic")] 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")] public List? Constraint { get; set; } } @@ -617,34 +651,36 @@ public class Trait : Characteristic, ISammSelfDescription /// A value which can be quantified and may have a unit, e.g., the number of bolts required for a /// processing step or the expected torque with which these bolts should be tightened. /// - /// + /// /// public class Quantifiable : Characteristic, ISammSelfDescription { // self description public new string GetSelfName() => "samm-quantifiable"; - public new string GetSelfUrn() => "urn:samm:org.eclipse.esmf.samm:characteristic:2.1.0#Quantifiable"; + public new string GetSelfUrn() => "urn:bamm:io.openmanufacturing:characteristic:1.0.0#Quantifiable"; /// /// Reference to a Unit as defined in the Unit catalog /// + [SammPropertyUri("bamm-c:unit")] public SammReference? Unit { get; set; } } /// /// A measurement is a numeric value with an associated unit and quantity kind. /// - /// + /// /// public class Measurement : Characteristic, ISammSelfDescription { // self description public new string GetSelfName() => "samm-measurement"; - public new string GetSelfUrn() => "urn:samm:org.eclipse.esmf.samm:characteristic:2.1.0#Measurement"; + public new string GetSelfUrn() => "urn:bamm:io.openmanufacturing:characteristic:1.0.0#Measurement"; /// /// Reference to a Unit as defined in the Unit catalog /// + [SammPropertyUri("bamm-c:unit")] public SammReference Unit { get; set; } public Measurement() @@ -656,18 +692,19 @@ public Measurement() /// /// An enumeration represents a list of possible values. /// - /// + /// /// public class Enumeration : Characteristic, ISammSelfDescription { // self description public new string GetSelfName() => "samm-enumeration"; - public new string GetSelfUrn() => "urn:samm:org.eclipse.esmf.samm:characteristic:2.1.0#Enumeration"; + public new string GetSelfUrn() => "urn:bamm:io.openmanufacturing:characteristic:1.0.0#Enumeration"; /// /// List of possible values. The dataType of each of the values must match the /// dataType of the Enumeration. /// + [SammPropertyUri("bamm-c:values")] public List Values { get; set; } public Enumeration() @@ -679,17 +716,18 @@ public Enumeration() /// /// A state is subclass of Enumeration with a default value. /// - /// + /// /// public class State : Enumeration, ISammSelfDescription { // self description public new string GetSelfName() => "samm-state"; - public new string GetSelfUrn() => "urn:samm:org.eclipse.esmf.samm:characteristic:2.1.0#State"; + public new string GetSelfUrn() => "urn:bamm:io.openmanufacturing:characteristic:1.0.0#State"; /// /// The default value for the state. /// + [SammPropertyUri("bamm-c:defaultValue")] public string DefaultValue { get; set; } public State() @@ -701,13 +739,13 @@ public State() /// /// A time duration. /// - /// + /// /// public class Duration : Characteristic, ISammSelfDescription { // self description public new string GetSelfName() => "samm-duration"; - public new string GetSelfUrn() => "urn:samm:org.eclipse.esmf.samm:characteristic:2.1.0#Duration"; + public new string GetSelfUrn() => "urn:bamm:io.openmanufacturing:characteristic:1.0.0#Duration"; /// /// Reference to a Unit as defined in the Unit catalog. The referenced unit or its referenceUnit @@ -719,6 +757,7 @@ 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")] public SammReference Unit { get; set; } public Duration() @@ -731,17 +770,18 @@ public Duration() /// A group of values which may be either of a scalar or Entity type. The values may be duplicated and /// are not ordered (i.e., bag semantics). /// - /// + /// /// public class Collection : Characteristic, ISammSelfDescription { // self description public new string GetSelfName() => "samm-collection"; - public new string GetSelfUrn() => "urn:samm:org.eclipse.esmf.samm:characteristic:2.1.0#Collection"; + public new string GetSelfUrn() => "urn:bamm:io.openmanufacturing:characteristic:1.0.0#Collection"; /// /// Reference to a Characteristic which describes the individual elements contained in the Collection. /// + [SammPropertyUri("bamm-c:elementCharacteristic")] public SammReference ElementCharacteristic { get; set; } public Collection() @@ -753,49 +793,49 @@ public Collection() /// /// A subclass of Collection which may contain duplicates and is ordered. /// - /// + /// /// public class List : Collection, ISammSelfDescription { // self description public new string GetSelfName() => "samm-list"; - public new string GetSelfUrn() => "urn:samm:org.eclipse.esmf.samm:characteristic:2.1.0#List"; + public new string GetSelfUrn() => "urn:bamm:io.openmanufacturing:characteristic:1.0.0#List"; } /// /// A subclass of Collection which may not contain duplicates and is unordered. /// - /// + /// /// public class Set : Collection, ISammSelfDescription { // self description public new string GetSelfName() => "samm-set"; - public new string GetSelfUrn() => "urn:samm:org.eclipse.esmf.samm:characteristic:2.1.0#Set"; + public new string GetSelfUrn() => "urn:bamm:io.openmanufacturing:characteristic:1.0.0#Set"; } /// /// A subclass of Collection which may not contain duplicates and is ordered. /// - /// + /// /// public class SortedSet : Collection, ISammSelfDescription { // self description public new string GetSelfName() => "samm-sorted-set"; - public new string GetSelfUrn() => "urn:samm:org.eclipse.esmf.samm:characteristic:2.1.0#SortedSet"; + public new string GetSelfUrn() => "urn:bamm:io.openmanufacturing:characteristic:1.0.0#SortedSet"; } /// /// A subclass of Sorted Set containing values with the exact point in time when the values where recorded. /// - /// + /// /// public class TimeSeries : SortedSet, ISammSelfDescription { // self description public new string GetSelfName() => "samm-time-series"; - public new string GetSelfUrn() => "urn:samm:org.eclipse.esmf.samm:characteristic:2.1.0#TimeSeries"; + public new string GetSelfUrn() => "urn:bamm:io.openmanufacturing:characteristic:1.0.0#TimeSeries"; // For DataType // Set to samm-e:TimeSeriesEntity. This Entity consists of two Properties, namely samm-e:timestamp @@ -810,13 +850,13 @@ public class TimeSeries : SortedSet, ISammSelfDescription /// Describes a Property which contains any kind of code. Note that this Characteristic does not /// define a samm:dataType, this must therefore be done when instantiating the Characteristic. /// - /// + /// /// public class Code : Characteristic, ISammSelfDescription { // self description public new string GetSelfName() => "samm-code"; - public new string GetSelfUrn() => "urn:samm:org.eclipse.esmf.samm:characteristic:2.1.0#Code"; + public new string GetSelfUrn() => "urn:bamm:io.openmanufacturing:characteristic:1.0.0#Code"; } /// @@ -824,22 +864,24 @@ public class Code : Characteristic, ISammSelfDescription /// This Characteristic does not have one explicit samm:dataType, as it can be the datatype of either /// the left or the right. /// - /// "/> + /// "/> /// public class Either : Characteristic, ISammSelfDescription { // self description public new string GetSelfName() => "samm-either"; - public new string GetSelfUrn() => "urn:samm:org.eclipse.esmf.samm:characteristic:2.1.0#Either"; + public new string GetSelfUrn() => "urn:bamm:io.openmanufacturing:characteristic:1.0.0#Either"; /// /// The left side of the Either. The attribute references another Characteristic which describes the value. /// + [SammPropertyUri("bamm-c:left")] public string Left { get; set; } /// /// The right side of the Either. The attribute references another Characteristic which describes the value. /// + [SammPropertyUri("bamm-c:right")] public string Right { get; set; } public Either() @@ -853,13 +895,13 @@ public Either() /// Describes a Property whose data type is an Entity. The Entity used as data type could be defined in the /// same Aspect Model or the shared Entity namespace of the Semantic Aspect Meta Model. /// - /// + /// /// public class SingleEntity : Characteristic, ISammSelfDescription { // self description public new string GetSelfName() => "samm-single-entity"; - public new string GetSelfUrn() => "urn:samm:org.eclipse.esmf.samm:characteristic:2.1.0#SingleEntity"; + public new string GetSelfUrn() => "urn:bamm:io.openmanufacturing:characteristic:1.0.0#SingleEntity"; } /// @@ -868,13 +910,13 @@ public class SingleEntity : Characteristic, ISammSelfDescription /// linking to a separate Property definition for each part. To define the parts, the value must be /// deconstructed using a regular expression. /// - /// + /// /// public class StructuredValue: Characteristic, ISammSelfDescription { // self description public new string GetSelfName() => "samm-structured-value"; - public new string GetSelfUrn() => "urn:samm:org.eclipse.esmf.samm:characteristic:2.1.0#StructuredValue"; + public new string GetSelfUrn() => "urn:bamm:io.openmanufacturing:characteristic:1.0.0#StructuredValue"; /// /// The regular expression used to deconstruct the value into parts that are mapped to separate @@ -882,12 +924,14 @@ 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")] 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")] public List Elements { get; set; } public StructuredValue() @@ -921,12 +965,14 @@ 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")] public string? ExampleValue { get; set; } /// /// One Property has exactly one Characteristic. /// [SammPresetList("Characteristics")] + [SammPropertyUri("bamm:characteristic")] public SammReference Characteristic { get; set; } public Property() @@ -954,6 +1000,7 @@ public IEnumerable DescendOnce() } // own + [SammPropertyUri("bamm:properties")] public List Properties { get; set; } public Entity() @@ -995,18 +1042,71 @@ public IEnumerable DescendOnce() [SammMultiLine(maxLines: 5)] public string Comments { get; set; } = ""; + /// + /// A Property represents a named value. This element is optional and can appear + /// multiple times in a model ([0..n]). + /// [SammPropertyUri("bamm:properties")] - public List Properties { get; set; } - - public List Events { get; set; } - public List Operations { get; set; } + public List Properties { get; set; } = new List(); - public Aspect() - { - Properties = new List(); - Events = new List(); - Operations = new List(); - } + /// + /// An Event is a model element that represents a single occurence where the timing is important. + /// + [SammPropertyUri("bamm:events")] + public List Events { get; set; } = new List(); + + /// + /// An Operation represents an action that can be triggered on the Aspect. + /// + [SammPropertyUri("bamm:operations")] + public List Operations { get; set; } = new List(); + } + + public class Unit : ModelElement, ISammSelfDescription + { + // self description + public string GetSelfName() => "samm-unit"; + public string GetSelfUrn() => "urn:bamm:io.openmanufacturing:meta-model:1.0.0#Unit"; + + /// + /// Normalized short code for unit; please refer to the original + /// specification for more details. + /// + [SammPropertyUri("bamm:commonCode")] + 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")] + 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")] + 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")] + public string? QuantityKind { get; set; } = null; + + /// + /// The unit this unit is derived from, e.g., centimetre is derived from metre. + /// + [SammPropertyUri("bamm:referenceUnit")] + public SammReference? ReferenceUnit { get; set; } = null; + + /// + /// The unit’s symbol, e.g., for centimetre the symbol is cm + /// + [SammPropertyUri("bamm:symbol")] + public string? symbol { get; set; } = null; } /// @@ -1262,7 +1362,8 @@ static Util() { if (Activator.CreateInstance(st, new object[] { }) is ISammSelfDescription ssd) { - SammUrnToType.Add(ssd.GetSelfUrn().ToLower(), st); + // assumption: RDF matching is case sensitive?! + SammUrnToType.Add(ssd.GetSelfUrn(), st); SammTypeToName.Add(st, "" + ssd.GetSelfName()); } } @@ -1272,8 +1373,8 @@ static Util() { if (urn == null) return null; - if (SammUrnToType.ContainsKey(urn.ToLower())) - return SammUrnToType[urn.ToLower()]; + if (SammUrnToType.ContainsKey(urn)) + return SammUrnToType[urn]; return null; } diff --git a/src/AasxPackageExplorer/debug.MIHO.script b/src/AasxPackageExplorer/debug.MIHO.script index 1afc3eb2b..f7f53a963 100644 --- a/src/AasxPackageExplorer/debug.MIHO.script +++ b/src/AasxPackageExplorer/debug.MIHO.script @@ -6,4 +6,4 @@ // 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-short.ttl"); \ No newline at end of file +Tool("sammaspectimport", "File", "C:\\HOMI\\Develop\\Aasx\\repo\\BatteryPass-spiel.ttl"); \ No newline at end of file diff --git a/src/AasxPackageExplorer/options-debug.MIHO.json b/src/AasxPackageExplorer/options-debug.MIHO.json index fbca1b4d3..8141ef50c 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.aasx", + "AasxToLoad": "C:\\HOMI\\Develop\\Aasx\\repo\\samm_spiel_empty.aasx", "WindowLeft": 200, "WindowTop": -1, "WindowWidth": 900, diff --git a/src/AasxPackageLogic/DispEditHelperBasics.cs b/src/AasxPackageLogic/DispEditHelperBasics.cs index 3ce0f4540..54b047484 100644 --- a/src/AasxPackageLogic/DispEditHelperBasics.cs +++ b/src/AasxPackageLogic/DispEditHelperBasics.cs @@ -301,7 +301,9 @@ public void AddKeyValueExRef( AnyUiLambdaActionBase takeOverLambdaAction = null, bool limitToOneRowForNoEdit = false, int comboBoxMinWidth = -1, - bool noFirstColumnWidth = false) + bool noFirstColumnWidth = false, + int maxLines = -1, + bool keyVertCenter = false) { AddKeyValue( view, key, value, nullValue, repo, setValue, comboBoxItems, comboBoxIsEditable, @@ -310,7 +312,9 @@ public void AddKeyValueExRef( (value == null) ? 0 : value.GetHashCode(), containingObject: containingObject, limitToOneRowForNoEdit: limitToOneRowForNoEdit, comboBoxMinWidth: comboBoxMinWidth, - noFirstColumnWidth: noFirstColumnWidth); + noFirstColumnWidth: noFirstColumnWidth, + maxLines: maxLines, + keyVertCenter: keyVertCenter); } /// @@ -347,7 +351,9 @@ public void AddKeyValue( object containingObject = null, bool limitToOneRowForNoEdit = false, int comboBoxMinWidth = -1, - bool noFirstColumnWidth = false) + bool noFirstColumnWidth = false, + int maxLines = -1, + bool keyVertCenter = false) { // draw anyway? if (repo != null && value == null) @@ -399,7 +405,13 @@ public void AddKeyValue( } // Label for key - AddSmallLabelTo(g, 0, 0, padding: new AnyUiThickness(5, 0, 0, 0), content: "" + key + ":"); + var klb = AddSmallLabelTo(g, 0, 0, padding: new AnyUiThickness(5, 0, 0, 0), content: "" + key + ":"); + if (keyVertCenter) + { + klb.VerticalAlignment = AnyUiVerticalAlignment.Center; + klb.VerticalContentAlignment = AnyUiVerticalAlignment.Center; + klb.Margin = new AnyUiThickness(0, -1, 0, 0); + } // Label / TextBox for value if (repo == null) @@ -443,6 +455,8 @@ public void AddKeyValue( { // use plain text box var tb = AddSmallTextBoxTo(g, 0, 1, margin: new AnyUiThickness(4, 2, 2, 2), text: "" + value); + if (maxLines > 0) + tb.MaxLines = maxLines; AnyUiUIElement.RegisterControl(tb, setValue, takeOverLambda: takeOverLambdaAction); @@ -478,8 +492,6 @@ public void AddKeyValue( view.Children.Add(g); } - - public void AddKeyDropTarget( AnyUiStackPanel view, string key, string value, string nullValue = null, ModifyRepo repo = null, Func setValue = null, int minHeight = 0) diff --git a/src/AasxPackageLogic/DispEditHelperModules.cs b/src/AasxPackageLogic/DispEditHelperModules.cs index a73b150a6..f807aade4 100644 --- a/src/AasxPackageLogic/DispEditHelperModules.cs +++ b/src/AasxPackageLogic/DispEditHelperModules.cs @@ -31,6 +31,7 @@ This source code may use other Open Source software components (see LICENSE.txt) using System.Text.RegularExpressions; using System.Runtime.Intrinsics.X86; using Lucene.Net.Tartarus.Snowball.Ext; +using Lucene.Net.Util; namespace AasxPackageLogic { @@ -2467,13 +2468,14 @@ public static void SammExtensionHelperUpdateJson(Aas.IExtension se, Type sammTyp se.ValueType = DataTypeDefXsd.String; } - public AnyUiLambdaActionBase SammExtensionHelperSammReferenceAction( + public AnyUiLambdaActionBase SammExtensionHelperSammReferenceAction( Aas.Environment env, Aas.IReferable relatedReferable, - Samm.SammReference sr, - Action setValue, int actionIndex, - string[] presetList = null) + T sr, + Action setValue, + Func createInstance, + string[] presetList = null) where T : SammReference { if (actionIndex == 0 && presetList != null && presetList.Length > 0) { @@ -2485,7 +2487,7 @@ public AnyUiLambdaActionBase SammExtensionHelperSammReferenceAction( if (uc.Result && uc.ResultItem != null && uc.ResultItem.Tag != null && uc.ResultItem.Tag is string prs) { - setValue?.Invoke(new Samm.SammReference("" + prs)); + setValue?.Invoke(createInstance?.Invoke("" + prs)); return new AnyUiLambdaActionRedrawEntity(); } } @@ -2498,7 +2500,7 @@ public AnyUiLambdaActionBase SammExtensionHelperSammReferenceAction( "ConceptDescription"); if (k2 != null && k2.Count >= 1) { - setValue?.Invoke(new Samm.SammReference("" + k2[0].Value)); + setValue?.Invoke(createInstance?.Invoke("" + k2[0].Value)); return new AnyUiLambdaActionRedrawEntity(); } } @@ -2547,7 +2549,7 @@ public AnyUiLambdaActionBase SammExtensionHelperSammReferenceAction( } // add the new name to the current element - setValue?.Invoke(new Samm.SammReference(newUri)); + setValue?.Invoke(createInstance?.Invoke(newUri)); // now create a new CD for the new SAMM element var newCD = new Aas.ConceptDescription( @@ -2564,7 +2566,7 @@ public AnyUiLambdaActionBase SammExtensionHelperSammReferenceAction( name: "" + newSammSsd?.GetSelfName(), semanticId: new Aas.Reference(ReferenceTypes.ExternalReference, (new[] { new Aas.Key(KeyTypes.GlobalReference, - newSammSsd.GetSelfUrn()) }) + newSammSsd.GetSelfUrn()) }) .Cast().ToList()), value: ""); newCD.Extensions = new List { newSammExt }; @@ -2592,24 +2594,31 @@ public AnyUiLambdaActionBase SammExtensionHelperSammReferenceAction( return new AnyUiLambdaActionNone(); } - public void SammExtensionHelperAddSammReference( + public void SammExtensionHelperAddSammReference( Aas.Environment env, AnyUiStackPanel stack, string caption, Samm.ModelElement sammInst, Aas.IReferable relatedReferable, - Samm.SammReference sr, - Action setValue, + T sr, + Action setValue, + Func createInstance, bool noFirstColumnWidth = false, string[] presetList = null, - bool showButtons = true) - { + bool showButtons = true, + bool editOptionalFlag = false) where T : SammReference + { + var grid = AddSmallGrid(1, 2, colWidths: new[] { "*", "#" }); + stack.Add(grid); + var g1stack = AddSmallStackPanelTo(grid, 0, 0, margin: new AnyUiThickness(0)); + AddKeyValueExRef( - stack, "" + caption, sammInst, + g1stack, "" + caption, sammInst, value: "" + sr?.Value, null, repo, setValue: v => { - setValue?.Invoke(new Samm.SammReference((string)v)); + setValue?.Invoke(createInstance?.Invoke((string)v)); return new AnyUiLambdaActionNone(); }, + keyVertCenter: true, noFirstColumnWidth: noFirstColumnWidth, auxButtonTitles: !showButtons ? null : new[] { "Preset", "Existing", "New", "Jump" }, auxButtonToolTips: !showButtons ? null : new[] { @@ -2620,16 +2629,176 @@ public void SammExtensionHelperAddSammReference( }, auxButtonLambda: (i) => { - return SammExtensionHelperSammReferenceAction( - env, relatedReferable, sr, setValue, i, - presetList: presetList); + return SammExtensionHelperSammReferenceAction( + env, relatedReferable, + i, + sr: sr, + setValue: setValue, + createInstance: createInstance, + presetList: presetList); }); + + if (editOptionalFlag && sr is OptionalSammReference osr) + { + AnyUiUIElement.RegisterControl( + AddSmallCheckBoxTo(grid, 0, 1, + margin: new AnyUiThickness(2, 2, 2, 2), + verticalAlignment: AnyUiVerticalAlignment.Center, + verticalContentAlignment: AnyUiVerticalAlignment.Center, + content: "Opt.", + isChecked: osr.Optional), + (v) => + { + osr.Optional = (bool) v; + setValue?.Invoke(sr); + return new AnyUiLambdaActionNone(); + }); + } } - /// - /// Shall provide rather quick access to information .. - /// - public static Type CheckReferableForSammExtensionType(Aas.IReferable rf) + public void SammExtensionHelperAddListOfSammReference( + Aas.Environment env, AnyUiStackPanel stack, string caption, + Samm.ModelElement sammInst, + Aas.IReferable relatedReferable, + List value, + Action> setValue, + Func createInstance, + bool editOptionalFlag) where T : SammReference + { + this.AddVerticalSpace(stack); + + if (this.SafeguardAccess(stack, repo, value, "" + caption + ":", + "Create data element!", + v => { + setValue?.Invoke(new List(new T[] { createInstance?.Invoke("") })); + return new AnyUiLambdaActionRedrawEntity(); + })) + { + // Head + var sg = this.AddSubGrid(stack, "" + caption + ":", + rows: 1 + value.Count, cols: 2, + minWidthFirstCol: GetWidth(FirstColumnWidth.Standard), + paddingCaption: new AnyUiThickness(5, 0, 0, 0), + colWidths: new[] { "*", "#" }); + + AnyUiUIElement.RegisterControl( + AddSmallButtonTo(sg, 0, 1, + margin: new AnyUiThickness(2, 2, 2, 2), + padding: new AnyUiThickness(1, 0, 1, 0), + content: "\u2795"), + (v) => + { + value.Add(createInstance?.Invoke("")); + setValue?.Invoke(value); + return new AnyUiLambdaActionRedrawEntity(); + }); + + // individual references + for (int lsri = 0; lsri < value.Count; lsri++) + { + // remember lambda safe + var theLsri = lsri; + + // Stack in the 1st column + var sp1 = AddSmallStackPanelTo(sg, 1 + lsri, 0); + SammExtensionHelperAddSammReference( + env, sp1, $"[{1 + lsri}]", + (Samm.ModelElement)sammInst, relatedReferable, + value[lsri], + noFirstColumnWidth: true, + showButtons: false, + editOptionalFlag: editOptionalFlag, + setValue: (v) => { + value[theLsri] = v; + setValue?.Invoke(value); + }, + createInstance: createInstance); + + if (false) + { + // remove button + AnyUiUIElement.RegisterControl( + AddSmallButtonTo(sg, 1 + lsri, 1, + margin: new AnyUiThickness(2, 2, 2, 2), + padding: new AnyUiThickness(5, 0, 5, 0), + content: "-"), + (v) => + { + value.RemoveAt(theLsri); + setValue?.Invoke(value); + return new AnyUiLambdaActionRedrawEntity(); + }); + } + else + { + // button [hamburger] + AddSmallContextMenuItemTo( + sg, 1 + lsri, 1, + "\u22ee", + repo, new[] { + "\u2702", "Delete", + "\u25b2", "Move Up", + "\u25bc", "Move Down", + "\U0001F4D1", "Select from preset", + "\U0001F517", "Select from existing CDs", + "\U0001f516", "Create new CD for SAMM", + "\U0001f872", "Jump to" + }, + margin: new AnyUiThickness(2, 2, 2, 2), + padding: new AnyUiThickness(5, 0, 5, 0), + menuItemLambda: (o) => + { + var action = false; + + if (o is int ti) + switch (ti) + { + case 0: + value.RemoveAt(theLsri); + action = true; + break; + case 1: + MoveElementInListUpwards(value, value[theLsri]); + action = true; + break; + case 2: + MoveElementInListDownwards(value, value[theLsri]); + action = true; + break; + case 3: + case 4: + case 5: + case 6: + return SammExtensionHelperSammReferenceAction( + env, relatedReferable, + sr: value[theLsri], + actionIndex: ti - 3, + presetList: null, + setValue: (srv) => + { + value[theLsri] = srv; + setValue?.Invoke(value); + }, + createInstance: createInstance); + } + + if (action) + { + setValue?.Invoke(value); + return new AnyUiLambdaActionRedrawEntity(); + } + return new AnyUiLambdaActionNone(); + }); + } + } + } + + } + + /// + /// Shall provide rather quick access to information .. + /// + public static Type CheckReferableForSammExtensionType(Aas.IReferable rf) { // access if (rf?.Extensions == null) @@ -2919,143 +3088,39 @@ public void DisplayOrEditEntitySammExtensions( // List of SammReference? if (pii.PropertyType.IsAssignableTo(typeof(List))) { - this.AddVerticalSpace(stack); - - var lsr = (List)pii.GetValue(sammInst); - - Action> lambdaSetValue = (v) => - { - pii.SetValue(sammInst, v); - WriteSammInstBack(); - }; - - if (this.SafeguardAccess(stack, repo, lsr, "" + pii.Name + ":", - "Create data element!", - v => { - lambdaSetValue(new List()); - return new AnyUiLambdaActionRedrawEntity(); - })) - { - // Head - var sg = this.AddSubGrid(stack, "" + pii.Name + ":", - rows: 1 + lsr.Count, cols: 2, - minWidthFirstCol: GetWidth(FirstColumnWidth.Standard), - paddingCaption: new AnyUiThickness(5, 0, 0, 0), - colWidths: new[] { "*", "#" }); - - AnyUiUIElement.RegisterControl( - AddSmallButtonTo(sg, 0, 1, - margin: new AnyUiThickness(2, 2, 2, 2), - padding: new AnyUiThickness(1, 0, 1, 0), - content: "\u2795"), - (v) => - { - lsr.Add(new Samm.SammReference()); - lambdaSetValue(lsr); - return new AnyUiLambdaActionRedrawEntity(); - }); - - // individual references - for (int lsri = 0; lsri < lsr.Count; lsri++) + SammExtensionHelperAddListOfSammReference( + env, stack, caption: "" + pii.Name, + (ModelElement)sammInst, + relatedReferable, + editOptionalFlag: false, + value: (List)pii.GetValue(sammInst), + setValue: (v) => { - // remember lambda safe - var theLsri = lsri; - - // Stack in the 1st column - var sp1 = AddSmallStackPanelTo(sg, 1 + lsri, 0); - SammExtensionHelperAddSammReference( - env, sp1, $"[{lsri}]", - (Samm.ModelElement)sammInst, relatedReferable, - lsr[lsri], - noFirstColumnWidth: true, - showButtons: false, - setValue: (v) => { - lsr[theLsri] = v; - lambdaSetValue(lsr); - }); + pii.SetValue(sammInst, v); + WriteSammInstBack(); + }, + createInstance: (sr) => new SammReference(sr)); + } - if (false) - { - // remove button - AnyUiUIElement.RegisterControl( - AddSmallButtonTo(sg, 1 + lsri, 1, - margin: new AnyUiThickness(2, 2, 2, 2), - padding: new AnyUiThickness(5, 0, 5, 0), - content: "-"), - (v) => - { - lsr.RemoveAt(theLsri); - lambdaSetValue(lsr); - return new AnyUiLambdaActionRedrawEntity(); - }); - } - else - { - // button [hamburger] - AddSmallContextMenuItemTo( - sg, 1 + lsri, 1, - "\u22ee", - repo, new[] { - "\u2702", "Delete", - "\u25b2", "Move Up", - "\u25bc", "Move Down", - "\U0001F4D1", "Select from preset", - "\U0001F517", "Select from existing CDs", - "\U0001f516", "Create new CD for SAMM", - "\U0001f872", "Jump to" - }, - margin: new AnyUiThickness(2, 2, 2, 2), - padding: new AnyUiThickness(5, 0, 5, 0), - menuItemLambda: (o) => - { - var action = false; - - if (o is int ti) - switch (ti) - { - case 0: - lsr.RemoveAt(theLsri); - action = true; - break; - case 1: - MoveElementInListUpwards(lsr, lsr[theLsri]); - action = true; - break; - case 2: - MoveElementInListDownwards(lsr, lsr[theLsri]); - action = true; - break; - case 3: - case 4: - case 5: - case 6: - return SammExtensionHelperSammReferenceAction( - env, relatedReferable, - sr: lsr[theLsri], - actionIndex: ti - 3, - presetList: null, - setValue: (srv) => - { - lsr[theLsri] = srv; - lambdaSetValue(lsr); - - }); - } - - if (action) - { - lambdaSetValue(lsr); - return new AnyUiLambdaActionRedrawEntity(); - } - return new AnyUiLambdaActionNone(); - }); - } - } - } + // List of optional SammReference? + if (pii.PropertyType.IsAssignableTo(typeof(List))) + { + SammExtensionHelperAddListOfSammReference( + env, stack, caption: "" + pii.Name, + (ModelElement)sammInst, + relatedReferable, + editOptionalFlag: true, + value: (List)pii.GetValue(sammInst), + setValue: (v) => + { + pii.SetValue(sammInst, v); + WriteSammInstBack(); + }, + createInstance: (sr) => new OptionalSammReference(sr)); } - // NamespaceMap - if (pii.PropertyType.IsAssignableTo(typeof(Samm.NamespaceMap))) + // NamespaceMap + if (pii.PropertyType.IsAssignableTo(typeof(Samm.NamespaceMap))) { this.AddVerticalSpace(stack); @@ -3163,14 +3228,15 @@ public void DisplayOrEditEntitySammExtensions( presetValues = Samm.Constants.GetPresetsForListName(x3.PresetListName); } - SammExtensionHelperAddSammReference( + SammExtensionHelperAddSammReference( env, stack, "" + pii.Name, (Samm.ModelElement) sammInst, relatedReferable, sr, presetList: presetValues, setValue: (v) => { pii.SetValue(sammInst, v); WriteSammInstBack(); - }); + }, + createInstance: (sr) => new SammReference(sr)); } // List of string? @@ -3255,11 +3321,15 @@ public void DisplayOrEditEntitySammExtensions( } else { + // makes sense to have a bit vertical space + AddVerticalSpace(stack); + // multi line AddKeyValueExRef( stack, "" + pii.Name, sammInst, (string)pii.GetValue(sammInst), null, repo, setValue: setValueLambda, limitToOneRowForNoEdit: true, + maxLines: isMultiLineAttr.MaxLines.Value, auxButtonTitles: new[] { "\u2261" }, auxButtonToolTips: new[] { "Edit in multiline editor" }, auxButtonLambda: (buttonNdx) => @@ -3287,6 +3357,79 @@ public void DisplayOrEditEntitySammExtensions( } } + /// + /// Parses an rdf:Collection and reads out either SammReference or OptionalSammReference + /// + public static List ImportSammModelParseRdfCollection( + IGraph g, + INode collectionStart, + Func createInstance) where T : SammReference + { + // Try parse a rdf:Collection + // see: https://ontola.io/blog/ordered-data-in-rdf + + var lsr = new List(); + INode collPtr = collectionStart; + while (collPtr != null && collPtr.NodeType == NodeType.Blank) + { + // the collection pointer needs to have a first relationship + var firstRel = g.GetTriplesWithSubjectPredicate( + subj: collPtr, + pred: new UriNode(new Uri("http://www.w3.org/1999/02/22-rdf-syntax-ns#first"))) + .FirstOrDefault(); + if (firstRel?.Object == null) + break; + + // investigate, if first.object is a automatic/composite or an end node + if (firstRel.Object.NodeType == NodeType.Uri + || firstRel.Object.NodeType == NodeType.Literal) + { + // first.object is something tangible + lsr.Add(createInstance?.Invoke(firstRel.Object.ToSafeString(), false)); + } + else + { + // crawl firstRel.Object further to get individual end notes + string propElem = null; + bool? optional = null; + + foreach (var x3 in g.GetTriplesWithSubject(firstRel.Object)) + { + if (x3.Predicate.Equals(new UriNode( + new Uri("urn:bamm:io.openmanufacturing:meta-model:1.0.0#property")))) + propElem = x3.Object.ToSafeString(); + if (x3.Predicate.Equals( + new UriNode(new Uri("urn:bamm:io.openmanufacturing:meta-model:1.0.0#optional")))) + optional = x3.Object.ToSafeString() == "true^^http://www.w3.org/2001/XMLSchema#boolean"; + } + + if (propElem != null) + lsr.Add(createInstance?.Invoke(propElem, optional.Value)); + } + + // iterate further + var restRel = g.GetTriplesWithSubjectPredicate( + subj: collPtr, + pred: new UriNode(new Uri("http://www.w3.org/1999/02/22-rdf-syntax-ns#rest"))) + .FirstOrDefault(); + collPtr = restRel?.Object; + } + + return lsr; + } + + public static class RdfHelper + { + public static string GetLiteralStrValue(INode node) + { + if (node == null) + return ""; + if (node is LiteralNode ln) + return ln.Value; + return node.ToSafeString(); + } + } + public static void ImportSammModelToConceptDescriptions( Aas.Environment env, string fn) @@ -3365,7 +3508,7 @@ public static void ImportSammModelToConceptDescriptions( // now let the property type decide, how to // put in the property - var objStr = trpProp.Object.ToSafeString(); + var objStr = RdfHelper.GetLiteralStrValue(trpProp.Object); // List of Samm.LangString if (pii.PropertyType.IsAssignableTo(typeof(List))) @@ -3402,66 +3545,43 @@ public static void ImportSammModelToConceptDescriptions( if (lsr == null) lsr = new List(); - // if (trpProp.Object.NodeType == NodeType.Blank) - // { - // foreach (var x1 in g.GetTriplesWithSubject(trpProp.Object)) - // { - // ; - // foreach (var x2 in g.GetTriplesWithSubject(x1.Object)) - // { - // ; - // } - //} - // } - + lsr.AddRange( + ImportSammModelParseRdfCollection( + g, collectionStart: trpProp.Object, + createInstance: (sr, opt) => new SammReference(sr))); - // Try parse a rdf:Collection - // see: https://ontola.io/blog/ordered-data-in-rdf - - INode collPtr = trpProp.Object; - while (collPtr != null && collPtr.NodeType == NodeType.Blank) - { - // the collection pointer needs to have a first relationship - var firstRel = g.GetTriplesWithSubjectPredicate( - subj: collPtr, - pred: new UriNode(new Uri("http://www.w3.org/1999/02/22-rdf-syntax-ns#first"))).FirstOrDefault(); - if (firstRel?.Object == null) - break; + // write found references back + pii.SetValue(sammInst, lsr); + } - // investigate, if first.object is a automatic/composite or an end node - if (firstRel.Object.NodeType == NodeType.Uri - || firstRel.Object.NodeType == NodeType.Literal) - { - // first.object is something tangible - lsr.Add(new SammReference(firstRel.Object.ToSafeString())); - } - else - { - // crawl firstRel.Object further to get individual end notes - string propElem = null; - bool? optional = null; + // List of OptionalSammReference + if (pii.PropertyType.IsAssignableTo(typeof(List))) + { + var lsr = (List)pii.GetValue(sammInst); + if (lsr == null) + lsr = new List(); - foreach (var x3 in g.GetTriplesWithSubject(firstRel.Object)) - { - if (x3.Predicate.Equals(new UriNode(new Uri("urn:bamm:io.openmanufacturing:meta-model:1.0.0#property")))) - propElem = x3.Object.ToSafeString(); - if (x3.Predicate.Equals(new UriNode(new Uri("urn:bamm:io.openmanufacturing:meta-model:1.0.0#optional")))) - optional = x3.Object.ToSafeString() == "true^^http://www.w3.org/2001/XMLSchema#boolean"; - } + lsr.AddRange( + ImportSammModelParseRdfCollection( + g, collectionStart: trpProp.Object, + createInstance: (sr, opt) => new OptionalSammReference(sr, opt))); - if (propElem != null) - lsr.Add(new SammReference(propElem)); - } + // write found references back + pii.SetValue(sammInst, lsr); + } - // iterate further - var restRel = g.GetTriplesWithSubjectPredicate( - subj: collPtr, - pred: new UriNode(new Uri("http://www.w3.org/1999/02/22-rdf-syntax-ns#rest"))).FirstOrDefault(); - collPtr = restRel?.Object; - } + // just SammReference + if (pii.PropertyType.IsAssignableTo(typeof(Samm.SammReference))) + { + // simply set the value + pii.SetValue(sammInst, new SammReference(objStr)); + } - // write found references back - pii.SetValue(sammInst, lsr); + // just string + if (pii.PropertyType.IsAssignableTo(typeof(string))) + { + // simply set the value + pii.SetValue(sammInst, objStr); } } } @@ -3488,12 +3608,12 @@ public static void ImportSammModelToConceptDescriptions( // name of elements is a special case. Can become idShort string elemName = null; - var delemPred = Samm.Constants.SelfNamespaces.ExtendUri("bamm:name"); + var elemPred = Samm.Constants.SelfNamespaces.ExtendUri("bamm:name"); foreach (var trpProp in g.GetTriplesWithSubjectPredicate( subj: trpSammElem.Subject, - pred: new VDS.RDF.UriNode(new Uri(descPred)))) + pred: new VDS.RDF.UriNode(new Uri(elemPred)))) { - elemName = trpProp.Object.ToSafeString(); + elemName = RdfHelper.GetLiteralStrValue(trpProp.Object); } // Aspect is another special case