From bd35f6866333268a1b7da69f28d9cc823377a597 Mon Sep 17 00:00:00 2001 From: Michael Hoffmeister Date: Thu, 2 Nov 2023 14:55:49 +0100 Subject: [PATCH] * de-serialize and combo box of enum types in Constraints --- src/AasxCore.Samm2_2_0/SammClasses.cs | 171 +++- src/AasxPackageLogic/DispEditHelperModules.cs | 819 +++++++++++------- 2 files changed, 648 insertions(+), 342 deletions(-) diff --git a/src/AasxCore.Samm2_2_0/SammClasses.cs b/src/AasxCore.Samm2_2_0/SammClasses.cs index 6091173e6..ef0818408 100644 --- a/src/AasxCore.Samm2_2_0/SammClasses.cs +++ b/src/AasxCore.Samm2_2_0/SammClasses.cs @@ -95,6 +95,20 @@ public SammPropertyUriAttribute(string uri) } } + /// + /// Some string based flags to attach to the property + /// + [System.AttributeUsage(System.AttributeTargets.Field | System.AttributeTargets.Property, AllowMultiple = true)] + public class SammPropertyFlagsAttribute : System.Attribute + { + public string Flags = ""; + + public SammPropertyFlagsAttribute(string flags) + { + Flags = flags; + } + } + /// /// Shall be implemented by all non-abstract model elements /// @@ -436,8 +450,11 @@ public bool AddOrIgnore(string prefix, string uri) /// /// /// - public class Constraint : ModelElement - { + public class Constraint : ModelElement, ISammSelfDescription + { + // self description + public string GetSelfName() => "samm-constraint"; + public string GetSelfUrn() => "bamm-c:Constraint"; } /// @@ -445,14 +462,18 @@ public class Constraint : ModelElement /// /// /// - public class LanguageConstraint : Constraint + public class LanguageConstraint : Constraint, ISammSelfDescription { + // self description + public new string GetSelfName() => "samm-language-constraint"; + public new string GetSelfUrn() => "bamm-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")] - public string? LanguageCode; + public string? LanguageCode { get; set; } } /// @@ -460,46 +481,54 @@ public class LanguageConstraint : Constraint /// /// /// - public class LocaleConstraint : Constraint + public class LocaleConstraint : Constraint, ISammSelfDescription { + // self description + public new string GetSelfName() => "samm-locale-constraint"; + public new string GetSelfUrn() => "bamm-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")] - public string? LocaleCode; + public string? LocaleCode { get; set; } } /// /// Restricts the value range of a Property. At least one of maxValue or minValue must be present in a /// Range Constraint. /// - public class RangeConstraint : Constraint + public class RangeConstraint : Constraint, ISammSelfDescription { + // self description + public new string GetSelfName() => "samm-range-constraint"; + public new string GetSelfUrn() => "bamm-c:RangeConstraint"; + /// /// The upper bound of a range. /// [SammPropertyUri("bamm-c:maxValue")] - public string? MaxValue; + public string? MaxValue { get; set; } /// /// The lower bound of a range. /// [SammPropertyUri("bamm-c:minValue")] - public string? MinValue; + 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")] - public SammUpperBoundDefinition? UpperBoundDefinition; + 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")] - public SammLowerBoundDefinition? LowerBoundDefinition; + public SammLowerBoundDefinition? LowerBoundDefinition { get; set; } } /// @@ -507,14 +536,18 @@ public class RangeConstraint : Constraint /// /// /// - public class EncodingConstraint : Constraint + public class EncodingConstraint : Constraint, ISammSelfDescription { + // self description + public new string GetSelfName() => "samm-encoding-constraint"; + public new string GetSelfUrn() => "bamm-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:value")] - public SammEncoding? Value; + public SammEncoding? Value { get; set; } } /// @@ -526,19 +559,23 @@ public class EncodingConstraint : Constraint /// /// /// - public class LengthConstraint : Constraint + public class LengthConstraint : Constraint, ISammSelfDescription { + // self description + public new string GetSelfName() => "samm-length-constraint"; + public new string GetSelfUrn() => "bamm-c:LengthConstraint"; + /// /// The maximum length. Must be given as xsd:nonNegativeInteger. /// [SammPropertyUri("bamm-c:maxValue")] - public uint? MaxValue; + public uint? MaxValue { get; set; } /// /// The minimum length. Must be given as xsd:nonNegativeInteger. /// [SammPropertyUri("bamm-c:minValue")] - public uint? MinValue; + public uint? MinValue { get; set; } } /// @@ -548,14 +585,18 @@ public class LengthConstraint : Constraint /// /// /// - public class RegularExpressionConstraint : Constraint + public class RegularExpressionConstraint : Constraint, ISammSelfDescription { + // self description + public new string GetSelfName() => "samm-regular-expression-constraint"; + public new string GetSelfUrn() => "bamm-c:RegularExpressionConstraint"; + /// /// The regular expression. /// /// [SammPropertyUri("bamm-c:value")] - public string? Value; + public string? Value { get; set; } } /// @@ -564,15 +605,19 @@ public class RegularExpressionConstraint : Constraint /// /// /// - public class FixedPointConstraint : Constraint + public class FixedPointConstraint : Constraint, ISammSelfDescription { + // self description + public new string GetSelfName() => "samm-fixed-point-constraint"; + public new string GetSelfUrn() => "bamm-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")] - public uint? Scale; + public uint? Scale { get; set; } /// /// The number of integral digits for a fixed point number. E.g., if a fixedpoint number @@ -580,7 +625,7 @@ public class FixedPointConstraint : Constraint /// Must be given as xsd:positiveInteger. /// [SammPropertyUri("bamm-c:integer")] - public uint? Integer; + public uint? Integer { get; set; } } /// @@ -593,8 +638,6 @@ public class Characteristic : ModelElement, ISammSelfDescription, ISammStructure { // self description public string GetSelfName() => "samm-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() => "bamm:Characteristic"; // structure model @@ -626,12 +669,23 @@ public Characteristic() /// /// /// - public class Trait : Characteristic, ISammSelfDescription + public class Trait : Characteristic, ISammSelfDescription, ISammStructureModel { // self description public new string GetSelfName() => "samm-trait"; public new string GetSelfUrn() => "bamm-c:Trait"; + // structure model + public new bool IsTopElement() => false; + public new IEnumerable DescendOnce() + { + if (BaseCharacteristic != null) + yield return BaseCharacteristic; + if (Constraint != null) + foreach (var cn in Constraint) + yield return cn; + } + /// /// The Characterstic that is being constrained. /// Identified via preferredName in any language @@ -644,6 +698,7 @@ public class Trait : Characteristic, ISammSelfDescription /// to add multiple Constraints to the base Characteristic. /// [SammPropertyUri("bamm-c:constraint")] + [SammPropertyFlags("constraints")] public List? Constraint { get; set; } } @@ -1135,12 +1190,25 @@ public static class Constants typeof(StructuredValue) }; + public static Type[] AddableConstraints = + { + typeof(Constraint), + typeof(LanguageConstraint), + typeof(LocaleConstraint), + typeof(RangeConstraint), + typeof(EncodingConstraint), + typeof(LengthConstraint), + typeof(RegularExpressionConstraint), + typeof(FixedPointConstraint) + }; + public static Type[] AddableElements = { // Top level typeof(Aspect), typeof(Property), typeof(Entity), + typeof(Unit), // Characteristic typeof(Characteristic), typeof(Trait), @@ -1157,7 +1225,16 @@ public static class Constants typeof(Code), typeof(Either), typeof(SingleEntity), - typeof(StructuredValue) + typeof(StructuredValue), + // Constraints + typeof(Constraint), + typeof(LanguageConstraint), + typeof(LocaleConstraint), + typeof(RangeConstraint), + typeof(EncodingConstraint), + typeof(LengthConstraint), + typeof(RegularExpressionConstraint), + typeof(FixedPointConstraint) }; /// @@ -1296,13 +1373,43 @@ static Constants() Background = 0xFFB9AB50 }); - _renderInfo.Add(typeof(Constraint), new SammElementRenderInfo() - { - DisplayName = "Constraint", - Abbreviation = "C", - Foreground = 0xFF000000, - Background = 0xFF74AEAF - }); + _renderInfo.Add( + types: new[] { + typeof(Constraint), + typeof(LanguageConstraint), + typeof(LocaleConstraint), + typeof(RangeConstraint), + typeof(EncodingConstraint), + typeof(LengthConstraint), + typeof(RegularExpressionConstraint), + typeof(FixedPointConstraint) + }, + displayNames: new[] { + "Constraint", + "LanguageConstraint", + "LocaleConstraint", + "RangeConstraint", + "EncodingConstraint", + "LengthConstraint", + "RegularExpressionConstraint", + "FixedPointConstraint" + }, + abbreviations: new[] { + "C", + "LGC", + "LOC", + "RGC", + "ENC", + "LNC", + "REC", + "FPC" + }, + value: new SammElementRenderInfo() { + DisplayName = "Constraint", + Abbreviation = "C", + Foreground = 0xFF000000, + Background = 0xFF74AEAF + }); _renderInfo.Add(typeof(Trait), new SammElementRenderInfo() { diff --git a/src/AasxPackageLogic/DispEditHelperModules.cs b/src/AasxPackageLogic/DispEditHelperModules.cs index e57e80b78..d2d0f8b20 100644 --- a/src/AasxPackageLogic/DispEditHelperModules.cs +++ b/src/AasxPackageLogic/DispEditHelperModules.cs @@ -32,6 +32,8 @@ This source code may use other Open Source software components (see LICENSE.txt) using System.Runtime.Intrinsics.X86; using Lucene.Net.Tartarus.Snowball.Ext; using Lucene.Net.Util; +using System.Runtime.Serialization; +using J2N.Text; namespace AasxPackageLogic { @@ -732,18 +734,18 @@ public void DisplayOrEditEntityHasEmbeddedSpecification( // let the user control the number of references this.AddActionPanel( stack, "Spec. records:", repo: repo, - superMenu: superMenu, - ticketMenu: new AasxMenu() - .AddAction("add-record", "Add record", - "Adds a record for data specification reference and content.") - .AddAction("add-iec61360", "Add IEC61360", - "Adds a record initialized for IEC 61360 content.") - .AddAction("auto-detect", "Auto detect content", - "Auto dectects known data specification contents and sets valid references.") - .AddAction("delete-last", "Delete last record", - "Deletes last record (data specification reference and content)."), - ticketAction: (buttonNdx, ticket) => - { + superMenu: superMenu, + ticketMenu: new AasxMenu() + .AddAction("add-record", "Add record", + "Adds a record for data specification reference and content.") + .AddAction("add-iec61360", "Add IEC61360", + "Adds a record initialized for IEC 61360 content.") + .AddAction("auto-detect", "Auto detect content", + "Auto dectects known data specification contents and sets valid references.") + .AddAction("delete-last", "Delete last record", + "Deletes last record (data specification reference and content)."), + ticketAction: (buttonNdx, ticket) => + { if (buttonNdx == 0) hasDataSpecification.Add( new Aas.EmbeddedDataSpecification( @@ -2411,13 +2413,50 @@ public void DisplayOrEditEntityFileResource(AnyUiStackPanel stack, } - // - // - // SAMM - // - // + // + // + // SAMM + // + // - public Type SammExtensionHelperSelectSammType(Type[] addableElements) + public class EnumHelperMemberInfo + { + public string MemberValue = ""; + public object MemberInstance; + } + + public static IEnumerable EnumHelperGetMemberInfo(Type underlyingType) + { + foreach (var enumMemberInfo in underlyingType.GetFields(BindingFlags.Public | BindingFlags.Static)) + { + var enumInst = Activator.CreateInstance(underlyingType); + + var enumMemberStrValue = enumMemberInfo.GetCustomAttribute(); + if (enumMemberStrValue?.Value != null) + { + var ev = enumMemberInfo.GetValue(enumInst); + + yield return new EnumHelperMemberInfo() + { + MemberValue = enumMemberStrValue?.Value, + MemberInstance = ev + }; + + //// how to get the enum value? + //// (bad) solution is to iterate over values and compare types .. + //foreach (var ev in Enum.GetValues(underlyingType)) + // if (ev.GetType() == enumMemberInfo.FieldType) + // { + // yield return new EnumHelperMemberInfo() { + // MemberValue = enumMemberStrValue?.Value, + // MemberInstance = ev + // }; + // } + } + } + } + + public Type SammExtensionHelperSelectSammType(Type[] addableElements) { // create choices var fol = new List(); @@ -2475,7 +2514,8 @@ public AnyUiLambdaActionBase SammExtensionHelperSammReferenceAction( T sr, Action setValue, Func createInstance, - string[] presetList = null) where T : SammReference + string[] presetList = null, + Type[] addableElements = null) where T : SammReference { if (actionIndex == 0 && presetList != null && presetList.Length > 0) { @@ -2508,7 +2548,9 @@ public AnyUiLambdaActionBase SammExtensionHelperSammReferenceAction( if (actionIndex == 2) { // select type - var sammTypeToCreate = SammExtensionHelperSelectSammType(Samm.Constants.AddableElements); + var sammTypeToCreate = SammExtensionHelperSelectSammType( + addableElements: (addableElements != null) + ? addableElements : Samm.Constants.AddableElements); if (sammTypeToCreate == null) return new AnyUiLambdaActionNone(); @@ -2606,7 +2648,8 @@ public void SammExtensionHelperAddSammReference( bool noFirstColumnWidth = false, string[] presetList = null, bool showButtons = true, - bool editOptionalFlag = false) where T : SammReference + bool editOptionalFlag = false, + Type[] addableElements = null) where T : SammReference { var grid = AddSmallGrid(1, 2, colWidths: new[] { "*", "#" }); stack.Add(grid); @@ -2637,7 +2680,8 @@ public void SammExtensionHelperAddSammReference( sr: sr, setValue: setValue, createInstance: createInstance, - presetList: presetList); + presetList: presetList, + addableElements: addableElements); }); if (editOptionalFlag && sr is OptionalSammReference osr) @@ -2665,7 +2709,8 @@ public void SammExtensionHelperAddListOfSammReference( List value, Action> setValue, Func createInstance, - bool editOptionalFlag) where T : SammReference + bool editOptionalFlag, + Type[] addableElements = null) where T : SammReference { this.AddVerticalSpace(stack); @@ -2681,7 +2726,7 @@ public void SammExtensionHelperAddListOfSammReference( rows: 1 + value.Count, cols: 2, minWidthFirstCol: GetWidth(FirstColumnWidth.Standard), paddingCaption: new AnyUiThickness(5, 0, 0, 0), - colWidths: new[] { "*", "#" }); + colWidths: new[] { "*", "#" }); AnyUiUIElement.RegisterControl( AddSmallButtonTo(sg, 0, 1, @@ -2710,6 +2755,7 @@ public void SammExtensionHelperAddListOfSammReference( noFirstColumnWidth: true, showButtons: false, editOptionalFlag: editOptionalFlag, + addableElements: addableElements, setValue: (v) => { value[theLsri] = v; setValue?.Invoke(value); @@ -2797,6 +2843,390 @@ public void SammExtensionHelperAddListOfSammReference( } + public void SammExtensionHelperAddCompleteModelElement( + Aas.Environment env, AnyUiStackPanel stack, + Samm.ModelElement sammInst, + Aas.IReferable relatedReferable, + Action setValue) + { + // access + if (env == null || stack == null || sammInst == null) + return; + + // visually ease + this.AddVerticalSpace(stack); + + // okay, try to build up a edit field by reflection + var propInfo = sammInst.GetType().GetProperties(); + for (int pi = 0; pi < propInfo.Length; pi++) + { + // access + var pii = propInfo[pi]; + + // some type investigation + var propType = pii.PropertyType; + var underlyingType = Nullable.GetUnderlyingType(propType); + + // try to access flags + var propFlags = "" + pii.GetCustomAttribute()?.Flags; + var propFlagsLC = propFlags.ToLower(); + + // List of SammReference? + if (pii.PropertyType.IsAssignableTo(typeof(List))) + { + var addableElements = Samm.Constants.AddableElements; + if (propFlagsLC.Contains("contraints")) + addableElements = Samm.Constants.AddableConstraints; + + SammExtensionHelperAddListOfSammReference( + env, stack, caption: "" + pii.Name, + (ModelElement)sammInst, + relatedReferable, + editOptionalFlag: false, + value: (List)pii.GetValue(sammInst), + setValue: (v) => + { + pii.SetValue(sammInst, v); + setValue?.Invoke(sammInst); + }, + createInstance: (sr) => new SammReference(sr)); + } + + // 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); + setValue?.Invoke(sammInst); + }, + createInstance: (sr) => new OptionalSammReference(sr)); + } + + // NamespaceMap + if (pii.PropertyType.IsAssignableTo(typeof(Samm.NamespaceMap))) + { + this.AddVerticalSpace(stack); + + var lsr = (Samm.NamespaceMap)pii.GetValue(sammInst); + + Action lambdaSetValue = (v) => + { + pii.SetValue(sammInst, v); + setValue?.Invoke(sammInst); + }; + + if (this.SafeguardAccess(stack, repo, lsr, "" + pii.Name + ":", + "Create data element!", + v => + { + lambdaSetValue(new Samm.NamespaceMap()); + return new AnyUiLambdaActionRedrawEntity(); + })) + { + // Head + var sg = this.AddSubGrid(stack, "" + pii.Name + ":", + rows: 1 + lsr.Count(), cols: 3, + minWidthFirstCol: GetWidth(FirstColumnWidth.Standard), + paddingCaption: new AnyUiThickness(5, 0, 0, 0), + colWidths: new[] { "80:", "*", "#" }); + + AnyUiUIElement.RegisterControl( + AddSmallButtonTo(sg, 0, 2, + margin: new AnyUiThickness(2, 2, 2, 2), + padding: new AnyUiThickness(1, 0, 1, 0), + content: "\u2795"), + (v) => + { + lsr.AddOrIgnore(":", ""); + lambdaSetValue(lsr); + return new AnyUiLambdaActionRedrawEntity(); + }); + + // individual references + for (int lsri = 0; lsri < lsr.Count(); lsri++) + { + var theLsri = lsri; + + // prefix + AnyUiUIElement.RegisterControl( + AddSmallTextBoxTo(sg, 1 + theLsri, 0, + text: lsr[theLsri].Prefix, + margin: new AnyUiThickness(4, 2, 2, 2)), + (v) => + { + lsr[theLsri].Prefix = (string)v; + pii.SetValue(sammInst, lsr); + setValue?.Invoke(sammInst); + return new AnyUiLambdaActionNone(); + }); + + // uri + AnyUiUIElement.RegisterControl( + AddSmallTextBoxTo(sg, 1 + theLsri, 1, + text: lsr[theLsri].Uri, + margin: new AnyUiThickness(2, 2, 2, 2)), + (v) => + { + lsr[theLsri].Uri = (string)v; + pii.SetValue(sammInst, lsr); + setValue?.Invoke(sammInst); + return new AnyUiLambdaActionNone(); + }); + + // minus + AnyUiUIElement.RegisterControl( + AddSmallButtonTo(sg, 1 + theLsri, 2, + margin: new AnyUiThickness(2, 2, 2, 2), + padding: new AnyUiThickness(5, 0, 5, 0), + content: "-"), + (v) => + { + lsr.RemoveAt(theLsri); + pii.SetValue(sammInst, lsr); + setValue?.Invoke(sammInst); + return new AnyUiLambdaActionRedrawEntity(); + }); + } + } + } + + // List of Constraint? + if (pii.PropertyType.IsAssignableTo(typeof(List))) + { + ; + } + + // single SammReference? + if (pii.PropertyType.IsAssignableTo(typeof(Samm.SammReference))) + { + this.AddVerticalSpace(stack); + + var sr = (Samm.SammReference)pii.GetValue(sammInst); + + // preset attribute + string[] presetValues = null; + var x3 = pii.GetCustomAttribute(); + if (x3 != null) + { + presetValues = Samm.Constants.GetPresetsForListName(x3.PresetListName); + } + + SammExtensionHelperAddSammReference( + env, stack, "" + pii.Name, (Samm.ModelElement)sammInst, relatedReferable, + sr, + presetList: presetValues, + setValue: (v) => { + pii.SetValue(sammInst, v); + setValue?.Invoke(sammInst); + }, + createInstance: (sr) => new SammReference(sr)); + } + + // List of string? + if (pii.PropertyType.IsAssignableTo(typeof(List))) + { + this.AddVerticalSpace(stack); + + var ls = (List)pii.GetValue(sammInst); + if (ls == null) + { + // Log.Singleton.Error("Internal error in SAMM element. Aborting."); + continue; + } + + var sg = this.AddSubGrid(stack, "" + pii.Name + ":", + rows: 1 + ls.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(5, 0, 5, 0), + content: "Add blank"), + (v) => + { + ls.Add(""); + pii.SetValue(sammInst, ls); + setValue?.Invoke(sammInst); + return new AnyUiLambdaActionRedrawEntity(); + }); + + for (int lsi = 0; lsi < ls.Count; lsi++) + { + var theLsi = lsi; + var tb = AnyUiUIElement.RegisterControl( + AddSmallTextBoxTo(sg, 1 + lsi, 0, + text: ls[lsi], + margin: new AnyUiThickness(2, 2, 2, 2)), + (v) => + { + ls[theLsi] = (string)v; + pii.SetValue(sammInst, ls); + setValue?.Invoke(sammInst); + return new AnyUiLambdaActionRedrawEntity(); + }); + + AnyUiUIElement.RegisterControl( + AddSmallButtonTo(sg, 1 + lsi, 1, + margin: new AnyUiThickness(2, 2, 2, 2), + padding: new AnyUiThickness(5, 0, 5, 0), + content: "-"), + (v) => + { + ls.RemoveAt(theLsi); + pii.SetValue(sammInst, ls); + setValue?.Invoke(sammInst); + return new AnyUiLambdaActionRedrawEntity(); + }); + } + } + + // single string? + if (pii.PropertyType.IsAssignableTo(typeof(string))) + { + var isMultiLineAttr = pii.GetCustomAttribute(); + + Func setValueLambda = (v) => + { + pii.SetValue(sammInst, v); + setValue?.Invoke(sammInst); + return new AnyUiLambdaActionNone(); + }; + + if (isMultiLineAttr == null) + { + // 1 line + AddKeyValueExRef( + stack, "" + pii.Name, sammInst, (string)pii.GetValue(sammInst), null, repo, + setValue: setValueLambda); + } + 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) => + { + if (buttonNdx == 0) + { + var uc = new AnyUiDialogueDataTextEditor( + caption: $"Edit " + pii.Name, + mimeType: System.Net.Mime.MediaTypeNames.Text.Plain, + text: (string)pii.GetValue(sammInst)); + if (this.context.StartFlyoverModal(uc)) + { + pii.SetValue(sammInst, uc.Text); + setValue?.Invoke(sammInst); + return new AnyUiLambdaActionRedrawEntity(); + } + } + return new AnyUiLambdaActionNone(); + }); + } + } + + // single uint? + if (pii.PropertyType.IsAssignableTo(typeof(uint?))) + { + Func setValueLambda = (v) => + { + if (v == null || ((string)v).Trim().Length < 1) + pii.SetValue(sammInst, null); + else + if (uint.TryParse((string) v, out var result)) + pii.SetValue(sammInst, result); + setValue?.Invoke(sammInst); + return new AnyUiLambdaActionNone(); + }; + + var input = (uint?) pii.GetValue(sammInst); + string value = ""; + if (input.HasValue) + value = input.Value.ToString(); + + // 1 line + AddKeyValueExRef( + stack, "" + pii.Name, sammInst, + value, + null, repo, + setValue: setValueLambda, + maxLines: 1); + } + + // nullable enum? + if (underlyingType != null && underlyingType.IsEnum) + { + // a little space + AddVerticalSpace(stack); + + // current enum member + var currEM = pii.GetValue(sammInst); + + // generate a list for combo box + var eMems = EnumHelperGetMemberInfo(underlyingType).ToList(); + + // find selected index + int? selectedIndex = null; + for (int emi=0; emi < eMems.Count; emi++) + { + if (((int)eMems[emi].MemberInstance) == ((int)currEM)) + selectedIndex = emi; + } + + // add a container + var sg = this.AddSubGrid(stack, "" + pii.Name + ":", + rows: 1, cols: 2, + minWidthFirstCol: GetWidth(FirstColumnWidth.Standard), + paddingCaption: new AnyUiThickness(5, 0, 0, 0), + marginGrid: new AnyUiThickness(4, 0, 0, 0), + colWidths: new[] { "*", "#" }); + + // and combobox inside + AnyUiComboBox cb = null; + cb = AnyUiUIElement.RegisterControl( + AddSmallComboBoxTo( + sg, 0, 0, + minWidth: 120, + margin: NormalOrCapa( + new AnyUiThickness(4, 1, 2, 3), + AnyUiContextCapability.Blazor, new AnyUiThickness(4, 2, 2, 0)), + padding: NormalOrCapa( + new AnyUiThickness(2, 1, 2, 1), + AnyUiContextCapability.Blazor, new AnyUiThickness(0, 4, 0, 4)), + selectedIndex: selectedIndex, + items: eMems.Select((mi) => mi.MemberValue).ToArray()), + setValue: (o) => + { + if (cb.SelectedIndex.HasValue + && cb.SelectedIndex.Value >= 0 + && cb.SelectedIndex.Value < eMems.Count) + { + pii.SetValue(sammInst, eMems[cb.SelectedIndex.Value].MemberInstance); + setValue?.Invoke(sammInst); + } + return new AnyUiLambdaActionNone(); + }); + } + } + } + /// /// Shall provide rather quick access to information .. /// @@ -3041,11 +3471,11 @@ public void DisplayOrEditEntitySammExtensions( iconElement: iconElem); // get instance data - object sammInst = null; + Samm.ModelElement sammInst = null; if (false) { // Note: right now, create fresh instance - sammInst = Activator.CreateInstance(sammType, new object[] { }); + sammInst = Activator.CreateInstance(sammType, new object[] { }) as Samm.ModelElement; if (sammInst == null) { stack.Add(new AnyUiLabel() { Content = "(unable to create instance data)" }); @@ -3058,7 +3488,7 @@ public void DisplayOrEditEntitySammExtensions( try { if (se.Value != null) - sammInst = JsonConvert.DeserializeObject(se.Value, sammType); + sammInst = JsonConvert.DeserializeObject(se.Value, sammType) as Samm.ModelElement; } catch (Exception ex) { @@ -3068,294 +3498,19 @@ public void DisplayOrEditEntitySammExtensions( if (sammInst == null) { - sammInst = Activator.CreateInstance(sammType, new object[] { }); + sammInst = Activator.CreateInstance(sammType, new object[] { }) as Samm.ModelElement; } } - // editing actions need to asynchronously write back values - Action WriteSammInstBack = () => - { - SammExtensionHelperUpdateJson(se, sammType, sammInst as Samm.ModelElement); - }; - - // okay, try to build up a edit field by reflection - 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; - - var pii = propInfo[pi]; - - // List of SammReference? - if (pii.PropertyType.IsAssignableTo(typeof(List))) - { - SammExtensionHelperAddListOfSammReference( - env, stack, caption: "" + pii.Name, - (ModelElement)sammInst, - relatedReferable, - editOptionalFlag: false, - value: (List)pii.GetValue(sammInst), - setValue: (v) => - { - pii.SetValue(sammInst, v); - WriteSammInstBack(); - }, - createInstance: (sr) => new SammReference(sr)); - } - - // 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))) + SammExtensionHelperAddCompleteModelElement( + env, stack, + sammInst: sammInst, + relatedReferable: relatedReferable, + setValue: (si) => { - this.AddVerticalSpace(stack); - - var lsr = (Samm.NamespaceMap)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 Samm.NamespaceMap()); - return new AnyUiLambdaActionRedrawEntity(); - })) - { - // Head - var sg = this.AddSubGrid(stack, "" + pii.Name + ":", - rows: 1 + lsr.Count(), cols: 3, - minWidthFirstCol: GetWidth(FirstColumnWidth.Standard), - paddingCaption: new AnyUiThickness(5, 0, 0, 0), - colWidths: new[] { "80:", "*", "#" }); - - AnyUiUIElement.RegisterControl( - AddSmallButtonTo(sg, 0, 2, - margin: new AnyUiThickness(2, 2, 2, 2), - padding: new AnyUiThickness(1, 0, 1, 0), - content: "\u2795"), - (v) => - { - lsr.AddOrIgnore(":", ""); - lambdaSetValue(lsr); - return new AnyUiLambdaActionRedrawEntity(); - }); - - // individual references - for (int lsri = 0; lsri < lsr.Count(); lsri++) - { - var theLsri = lsri; - - // prefix - AnyUiUIElement.RegisterControl( - AddSmallTextBoxTo(sg, 1 + theLsri, 0, - text: lsr[theLsri].Prefix, - margin: new AnyUiThickness(4, 2, 2, 2)), - (v) => - { - lsr[theLsri].Prefix = (string)v; - pii.SetValue(sammInst, lsr); - WriteSammInstBack(); - return new AnyUiLambdaActionNone(); - }); - - // uri - AnyUiUIElement.RegisterControl( - AddSmallTextBoxTo(sg, 1 + theLsri, 1, - text: lsr[theLsri].Uri, - margin: new AnyUiThickness(2, 2, 2, 2)), - (v) => - { - lsr[theLsri].Uri = (string)v; - pii.SetValue(sammInst, lsr); - WriteSammInstBack(); - return new AnyUiLambdaActionNone(); - }); - - // minus - AnyUiUIElement.RegisterControl( - AddSmallButtonTo(sg, 1 + theLsri, 2, - margin: new AnyUiThickness(2, 2, 2, 2), - padding: new AnyUiThickness(5, 0, 5, 0), - content: "-"), - (v) => - { - lsr.RemoveAt(theLsri); - pii.SetValue(sammInst, lsr); - WriteSammInstBack(); - return new AnyUiLambdaActionRedrawEntity(); - }); - } - } - } - - // List of Constraint? - if (pii.PropertyType.IsAssignableTo(typeof(List))) - { - ; - } - - // single SammReference? - if (pii.PropertyType.IsAssignableTo(typeof(Samm.SammReference))) - { - this.AddVerticalSpace(stack); - - var sr = (Samm.SammReference)pii.GetValue(sammInst); - - // preset attribute - string[] presetValues = null; - var x3 = pii.GetCustomAttribute(); - if (x3 != null) - { - presetValues = Samm.Constants.GetPresetsForListName(x3.PresetListName); - } - - 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? - if (pii.PropertyType.IsAssignableTo(typeof(List))) - { - this.AddVerticalSpace(stack); - - var ls = (List)pii.GetValue(sammInst); - if (ls == null) - { - // Log.Singleton.Error("Internal error in SAMM element. Aborting."); - continue; - } - - var sg = this.AddSubGrid(stack, "" + pii.Name + ":", - rows: 1 + ls.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(5, 0, 5, 0), - content: "Add blank"), - (v) => - { - ls.Add(""); - pii.SetValue(sammInst, ls); - WriteSammInstBack(); - return new AnyUiLambdaActionRedrawEntity(); - }); - - for (int lsi=0; lsi - { - ls[theLsi] = (string)v; - pii.SetValue(sammInst, ls); - WriteSammInstBack(); - return new AnyUiLambdaActionRedrawEntity(); - }); - - AnyUiUIElement.RegisterControl( - AddSmallButtonTo(sg, 1 + lsi, 1, - margin: new AnyUiThickness(2, 2, 2, 2), - padding: new AnyUiThickness(5, 0, 5, 0), - content: "-"), - (v) => - { - ls.RemoveAt(theLsi); - pii.SetValue(sammInst, ls); - WriteSammInstBack(); - return new AnyUiLambdaActionRedrawEntity(); - }); - } - } - - // single string? - if (pii.PropertyType.IsAssignableTo(typeof(string))) - { - var isMultiLineAttr = pii.GetCustomAttribute(); - - Func setValueLambda = (v) => - { - pii.SetValue(sammInst, v); - WriteSammInstBack(); - return new AnyUiLambdaActionNone(); - }; + SammExtensionHelperUpdateJson(se, si.GetType(), si); + }); - if (isMultiLineAttr == null) - { - // 1 line - AddKeyValueExRef( - stack, "" + pii.Name, sammInst, (string)pii.GetValue(sammInst), null, repo, - setValue: setValueLambda); - } - 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) => - { - if (buttonNdx == 0) - { - var uc = new AnyUiDialogueDataTextEditor( - caption: $"Edit " + pii.Name, - mimeType: System.Net.Mime.MediaTypeNames.Text.Plain, - text: (string)pii.GetValue(sammInst)); - if (this.context.StartFlyoverModal(uc)) - { - pii.SetValue(sammInst, uc.Text); - WriteSammInstBack(); - return new AnyUiLambdaActionRedrawEntity(); - } - } - return new AnyUiLambdaActionNone(); - }); - } - } - } } } } @@ -3504,6 +3659,9 @@ public static void ImportSammModelToConceptDescriptions( // continue; 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; if (propSearchUri == null) @@ -3597,6 +3755,47 @@ public static void ImportSammModelToConceptDescriptions( // simply set the value pii.SetValue(sammInst, objStr); } + + // just int? + if (pii.PropertyType.IsAssignableTo(typeof(uint?))) + { + // simply set the value + if (uint.TryParse(objStr, out var result)) + { + uint? value = result; + pii.SetValue(sammInst, value); + } + } + + // first check: any kind of enum? + if (underlyingType != null && underlyingType.IsEnum) + { + + var eMems = EnumHelperGetMemberInfo(underlyingType); + foreach (var em in eMems) + if (objStr.Contains(em.MemberValue)) + { + // set the enum type, even if it is a Nullable enum type .. + pii.SetValue(sammInst, em.MemberInstance); + } + + // foreach (var enumMemberInfo in underlyingType.GetFields()) + // { + // var enumMemberValue = enumMemberInfo.GetCustomAttribute(); + // if (enumMemberValue?.Value != null + // && objStr.Contains(enumMemberValue?.Value)) + // { + // // how to get the enum value? + // // (bad) solution is to iterate over values and compare types .. + // foreach (var ev in Enum.GetValues(underlyingType)) + // if (ev.GetType() == enumMemberInfo.FieldType) + // { + // // set the enum type, even if it is a Nullable enum type .. + // pii.SetValue(sammInst, ev); + // } + // } + //} + } } }