From e1a5c44a6702cd839608bff0966580aa225a2e4d Mon Sep 17 00:00:00 2001 From: Michael Hoffmeister Date: Sat, 29 Jul 2023 08:23:55 +0200 Subject: [PATCH] * add missing CDs from pool --- .../Extensions/ExtendEnvironment.cs | 32 +++--- .../Extensions/ExtendIReferable.cs | 17 ++- .../options-debug.MIHO.json | 4 +- src/AasxPackageLogic/ExplorerMenuFactory.cs | 5 +- .../MainWindowAnyUiDialogs.cs | 19 ++++ src/AasxPackageLogic/MainWindowHeadless.cs | 100 ++++++++++++++++++ .../AasxPluginExportTable.options.json | 28 +++++ .../Table/AnyUiDialogueTable.cs | 3 +- src/AasxPredefinedConcepts/DefinitionsPool.cs | 14 +++ src/Notes_V3.md | 1 + 10 files changed, 200 insertions(+), 23 deletions(-) diff --git a/src/AasxCsharpLibrary/Extensions/ExtendEnvironment.cs b/src/AasxCsharpLibrary/Extensions/ExtendEnvironment.cs index 9fc7a1009..a2bd20a39 100644 --- a/src/AasxCsharpLibrary/Extensions/ExtendEnvironment.cs +++ b/src/AasxCsharpLibrary/Extensions/ExtendEnvironment.cs @@ -539,22 +539,22 @@ public static ISubmodel FindSubmodelById(this AasCore.Aas3_0.Environment environ return null; } - public static IEnumerable FindAllSubmodelsGroupedByAAS(this AasCore.Aas3_0.Environment environment, Func p = null) - { - if (environment.AssetAdministrationShells == null || environment.Submodels == null) - yield break; - foreach (var aas in environment.AssetAdministrationShells) - { - if (aas?.Submodels == null) - continue; - foreach (var submodelReference in aas.Submodels) - { - var submodel = environment.FindSubmodel(submodelReference); - if (submodel != null && (p == null || p(aas, submodel))) - yield return submodel; - } - } - } + //public static IEnumerable FindAllSubmodelsGroupedByAAS(this AasCore.Aas3_0.Environment environment, Func p = null) + //{ + // if (environment.AssetAdministrationShells == null || environment.Submodels == null) + // yield break; + // foreach (var aas in environment.AssetAdministrationShells) + // { + // if (aas?.Submodels == null) + // continue; + // foreach (var submodelReference in aas.Submodels) + // { + // var submodel = environment.FindSubmodel(submodelReference); + // if (submodel != null && (p == null || p(aas, submodel))) + // yield return submodel; + // } + // } + //} public static IEnumerable FindAllSubmodelBySemanticId(this AasCore.Aas3_0.Environment environment, string semanticId) { diff --git a/src/AasxCsharpLibrary/Extensions/ExtendIReferable.cs b/src/AasxCsharpLibrary/Extensions/ExtendIReferable.cs index b92b37c1a..250af331f 100644 --- a/src/AasxCsharpLibrary/Extensions/ExtendIReferable.cs +++ b/src/AasxCsharpLibrary/Extensions/ExtendIReferable.cs @@ -16,12 +16,23 @@ namespace Extensions { public static class ExtendIReferable { - #region AasxPackageExplorer - - public static void RecurseOnReferables(this IReferable referable, + #region AasxPackageExplorer + + /// + /// Recurses on all Submodel elements of a Submodel or SME, which allows children. + /// The state object will be passed to the lambda function in order to provide + /// stateful approaches. Include this element, as well. + /// + /// State object to be provided to lambda. Could be null. + /// The lambda function as (state, parents, SME) + /// The lambda shall return TRUE in order to deep into recursion. + /// Include this element as well. parents will then + /// include this element as well! + public static void RecurseOnReferables(this IReferable referable, object state, Func, IReferable, bool> lambda, bool includeThis = false) { + // TODO (MIHO, 2023-07-28): not all elements are covered if (referable is Submodel submodel) { submodel.RecurseOnReferables(state, lambda, includeThis); diff --git a/src/AasxPackageExplorer/options-debug.MIHO.json b/src/AasxPackageExplorer/options-debug.MIHO.json index 2a53a4257..0e36e419d 100644 --- a/src/AasxPackageExplorer/options-debug.MIHO.json +++ b/src/AasxPackageExplorer/options-debug.MIHO.json @@ -16,8 +16,8 @@ /* "AasxToLoad": "C:\\MIHO\\Develop\\Aasx\\AasxFesto\\AasxFesto\\AasxFctTool\\bin\\Debug\\net472\\test.aasx", */ /* "AasxToLoad": "C:\\Users\\miho\\Desktop\\Festo_SPAU_VR3_UA.aasx", */ /* "AasxToLoad": "C:\\MIHO\\Develop\\Aasx\\repo\\Festo_SPAU_VR3.aasx", */ - "AasxToLoad": "C:\\HOMI\\Develop\\Aasx\\repo\\PxC_aasT_2900542_ELR_H3_I_SC__24DC_500AC_0_6.aasx", - // "AasxToLoad": "C:\\HOMI\\Develop\\Aasx\\repo\\Festo_SPAU-B2R-H-G18FD-L-PNLK-PNVBA-M8U_V3a.aasx", + // "AasxToLoad": "C:\\HOMI\\Develop\\Aasx\\repo\\PxC_aasT_2900542_ELR_H3_I_SC__24DC_500AC_0_6.aasx", + "AasxToLoad": "C:\\HOMI\\Develop\\Aasx\\repo\\Festo_SPAU-B2R-H-G18FD-L-PNLK-PNVBA-M8U_V3a.aasx", // "AasxToLoad": "C:\\HOMI\\Develop\\Aasx\\repo\\01_Festo_SPAU_VR3_DPPV2.aasx", // "AasxToLoad": "C:\\HOMI\\Develop\\Aasx\\repo\\bomtest1.aasx", // "AasxToLoad": "C:\\HOMI\\Develop\\Aasx\\repo\\IDTA 02006-2-1_Template_Digital Nameplate_V3_lang.aasx", diff --git a/src/AasxPackageLogic/ExplorerMenuFactory.cs b/src/AasxPackageLogic/ExplorerMenuFactory.cs index 1aae4fad8..209f0faea 100644 --- a/src/AasxPackageLogic/ExplorerMenuFactory.cs +++ b/src/AasxPackageLogic/ExplorerMenuFactory.cs @@ -285,7 +285,10 @@ public static AasxMenu CreateMainMenu() help: "Creates a new Submodel based on defintions provided by a pool of known definitions.", args: new AasxMenuListOfArgDefs() .Add("Domain", "Domain of knowledge/ name of the Submodel (partially)") - .Add("SmRef", "Return: Submodel generated", hidden: true))) + .Add("SmRef", "Return: Submodel generated", hidden: true)) + .AddWpfBlazor(name: "MissingCdsFromKnown", header: "Missing ConceptDescriptions from pool of known", + help: "For the selected element: checks which SME refer to missing " + + "ConceptDescriptions, which can be created from pool of known definitions.")) .AddMenu(header: "Visualize …", attachPoint: "Visualize") .AddSeparator() .AddWpfBlazor(name: "ConvertElement", header: "Convert …", diff --git a/src/AasxPackageLogic/MainWindowAnyUiDialogs.cs b/src/AasxPackageLogic/MainWindowAnyUiDialogs.cs index baf947091..07d853dd3 100644 --- a/src/AasxPackageLogic/MainWindowAnyUiDialogs.cs +++ b/src/AasxPackageLogic/MainWindowAnyUiDialogs.cs @@ -1429,6 +1429,25 @@ await DisplayContextPlus.CheckIfDownloadAndStart( MainWindow.RedrawAllElementsAndFocus(nextFocus: ticket["SmRef"]); } + if (cmd == "missingcdsfromknown") + { + // simply pass on + try + { + // delegate futher + await CommandBinding_GeneralDispatchHeadless(cmd, menuItem, ticket); + } + catch (Exception ex) + { + LogErrorToTicket(ticket, ex, + $"When executing command {cmd}, an error occurred"); + } + + // redisplay + if (ticket.Success) + MainWindow.RedrawAllElementsAndFocus(); + } + if (cmd == "convertelement") { // check diff --git a/src/AasxPackageLogic/MainWindowHeadless.cs b/src/AasxPackageLogic/MainWindowHeadless.cs index 1efe10fa4..df09149d2 100644 --- a/src/AasxPackageLogic/MainWindowHeadless.cs +++ b/src/AasxPackageLogic/MainWindowHeadless.cs @@ -26,6 +26,7 @@ This source code may use other Open Source software components (see LICENSE.txt) using System.IO; using System.Linq; using System.Threading.Tasks; +using System.Windows; using Aas = AasCore.Aas3_0; // ReSharper disable MethodHasAsyncOverload @@ -1099,6 +1100,105 @@ record = rec; #endif } + if (cmd == "missingcdsfromknown") + { + // + // Step 1: analyze selected entity + // + + var rfToCheck = new List(); + if (ticket.SelectedDereferencedMainDataObjects != null) + foreach (var mdo in ticket.SelectedDereferencedMainDataObjects) + if (mdo is Aas.AssetAdministrationShell mdoAas) + foreach (var sm in ticket.Env.FindAllSubmodelGroupedByAAS((aas, sm) => aas == mdoAas)) + rfToCheck.Add(sm); + else if (mdo is Aas.Submodel mdoSm) + rfToCheck.Add(mdoSm); + else if (mdo is Aas.ISubmodelElement mdoSme) + rfToCheck.Add(mdoSme); + + if (rfToCheck.Count < 1) + { + LogErrorToTicket(ticket, "No valid element selected to be checked for missing CDs."); + return; + } + + // + // Step 2: collect missing CDs + // + + var cdsMissing = new List(); + foreach (var rf in rfToCheck) + foreach (var x in rf.Descend()) + if (x is Aas.ISubmodelElement sme && sme.SemanticId != null + && ticket.Env.FindConceptDescriptionByReference(sme.SemanticId) == null + && sme.SemanticId.IsValid() && sme.SemanticId.Count() == 1 + && !cdsMissing.Contains(sme.SemanticId.Keys[0].Value)) + cdsMissing.Add(sme.SemanticId.Keys[0].Value); + + if (cdsMissing.Count < 1) + { + LogErrorToTicket(ticket, "No missing CDs could be found for selected element. Aborting!"); + return; + } + + // + // Step 3: check, which CDs could be provided by pool + // + + var cdsAvail = new List(); + var duplicates = false; + foreach (var cdm in cdsMissing) + { + int count = 0; + foreach (var frf in AasxPredefinedConcepts.DefinitionsPool.Static + .FindReferableByReference(cdm)) + if (frf is Aas.ConceptDescription fcd) + { + var cpy = fcd.Copy(); + count++; + if (count > 1) + { + cpy.Id += $"__{count:000}"; + Log.Singleton.Error( + $"Multiple CDs found for Id={cdm}. CD added with altered Id={cpy.Id}."); + duplicates = true; + } + cdsAvail.Add(cpy); + } + } + + if (cdsAvail.Count < 1) + { + LogErrorToTicket(ticket, "No missing CDs could be found in pool of known. Aborting!"); + return; + } + + // + // Step 4: Ask + // + + if (AnyUiMessageBoxResult.Yes != await DisplayContext.MessageBoxFlyoutShowAsync( + $"{cdsMissing.Count} CDs missing. {cdsAvail.Count} CDs available in pool of knonw. " + + "Add these available CDs to Environment?", + "Add CDs from pool of known", + AnyUiMessageBoxButton.YesNo, AnyUiMessageBoxImage.Question)) + return; + + // + // Step 5: Go, add + // + + foreach (var cd in cdsAvail) + ticket.Env.Add(cd); + + Log.Singleton.Info($"Added {cdsAvail.Count} missing CDs from pool of known."); + if (duplicates) + Log.Singleton.Error("Duplicated CDs found while adding missing CDs from pool of known. " + + "See log."); + ticket.Success = true; + } + if (cmd == "convertelement") { // arguments diff --git a/src/AasxPluginExportTable/AasxPluginExportTable.options.json b/src/AasxPluginExportTable/AasxPluginExportTable.options.json index ae898014e..0b8e70102 100644 --- a/src/AasxPluginExportTable/AasxPluginExportTable.options.json +++ b/src/AasxPluginExportTable/AasxPluginExportTable.options.json @@ -635,6 +635,34 @@ "null", "%SME.multiplicity%" ] + }, + { + "Name": "Export scratch info", + "Format": 2, + "RowsTop": 1, + "RowsBody": 1, + "RowsGap": 2, + "Cols": 2, + "ReplaceFailedMatches": true, + "FailText": "-", + "ActInHierarchy": true, + "NoHeadings": false, + "Top": [ + "", + "", + "", + "", + "", + "" + ], + "Body": [ + "", + "", + "", + "", + "[%SME.elementShort%]\r\n%SME.idShort%", + "idShort: %SME.idShort%\r\nsemanticId: %SME.semanticId[0].value%" + ] } ] } diff --git a/src/AasxPluginExportTable/Table/AnyUiDialogueTable.cs b/src/AasxPluginExportTable/Table/AnyUiDialogueTable.cs index 3c7717f16..b891d9055 100644 --- a/src/AasxPluginExportTable/Table/AnyUiDialogueTable.cs +++ b/src/AasxPluginExportTable/Table/AnyUiDialogueTable.cs @@ -420,7 +420,8 @@ record = newRec; verticalAlignment: AnyUiVerticalAlignment.Stretch, verticalContentAlignment: AnyUiVerticalAlignment.Top, textWrap: AnyUiTextWrapping.Wrap, - fontSize: 0.7, multiLine: true), + fontSize: 0.7, + multiLine: true), minWidth: 100, minHeight: 60, horizontalAlignment: AnyUiHorizontalAlignment.Stretch), diff --git a/src/AasxPredefinedConcepts/DefinitionsPool.cs b/src/AasxPredefinedConcepts/DefinitionsPool.cs index 564529622..175ea9780 100644 --- a/src/AasxPredefinedConcepts/DefinitionsPool.cs +++ b/src/AasxPredefinedConcepts/DefinitionsPool.cs @@ -187,5 +187,19 @@ public void IndexDefinitions(AasxDefinitionBase bs) return; IndexReferables(bs.DomainInfo, bs.GetAllReferables()); } + + public IEnumerable FindReferableByReference(string id) + { + if (id?.HasContent() != true) + yield break; + + foreach (var ldp in pool.Values) + foreach (var dpeb in ldp) + if (dpeb is DefinitionsPoolReferableEntity dpre + && dpre.Ref is Aas.IIdentifiable dpreid + && dpreid.Id == id) + yield return dpre.Ref; + + } } } diff --git a/src/Notes_V3.md b/src/Notes_V3.md index 88bd819c4..becac3486 100644 --- a/src/Notes_V3.md +++ b/src/Notes_V3.md @@ -66,6 +66,7 @@ if (reference.Keys == null || reference.Keys.Count == 0 || otherReference?.Keys Soll ich den Bug im Repository eintragen bzw. ein PullRequest starten? Oder pflegst du so etwas „auf dem kurzen Dienstweg“ ein? +* Export table / cells / allow return ## Done (w.r.t. recently V3.0)