/// <summary> /// Checks, if the <c>sourceElements</c> can be used to pre-set instances for the rendering of /// the description/ form. /// If not, the display functionality will finally care about creating them. /// </summary> public void PresetInstancesBasedOnSource(AdminShell.SubmodelElementWrapperCollection sourceElements = null) { // access var desc = this.workingDesc as FormDescSubmodelElement; if (desc == null || desc.KeySemanticId == null || sourceElements == null) { return; } // Instances ready? if (this.SubInstances == null) { this.SubInstances = new List <FormInstanceBase>(); } // maximum == 1? if (desc.Multiplicity == FormMultiplicity.ZeroToOne || desc.Multiplicity == FormMultiplicity.One) { var smw = sourceElements.FindFirstSemanticId(desc.KeySemanticId); if (smw != null && smw.submodelElement != null) { var y = desc.CreateInstance(this, smw.submodelElement); if (y != null) { this.SubInstances.Add(y); } } } // maximum > 1? if (desc.Multiplicity == FormMultiplicity.ZeroToMany || desc.Multiplicity == FormMultiplicity.OneToMany) { foreach (var smw in sourceElements.FindAllSemanticId(desc.KeySemanticId)) { if (smw != null && smw.submodelElement != null) { var y = desc.CreateInstance(this, smw.submodelElement); if (y != null) { this.SubInstances.Add(y); } } } } // prepare list of original source elements if (this.InitialSourceElements == null) { this.InitialSourceElements = new List <AdminShellV20.SubmodelElement>(); } foreach (var inst in this.SubInstances) { if (inst != null && inst is FormInstanceSubmodelElement && (inst as FormInstanceSubmodelElement).sourceSme != null) { this.InitialSourceElements.Add((inst as FormInstanceSubmodelElement).sourceSme); } } }
/// <summary> /// Render the instance into a list (right now, exactly one!) of SubmodelElements. /// Might be overridden in subclasses. /// </summary> public virtual AdminShell.SubmodelElementWrapperCollection AddOrUpdateSmeToCollection( AdminShell.SubmodelElementWrapperCollection collectionNewElements, AdminShellPackageEnv packageEnv = null, bool addFilesToPackage = false) { // typically, there will be only one SME var res = new AdminShell.SubmodelElementWrapperCollection(); // SME present? if (sme != null) { // process (will update existing elements) var doAdd = ProcessSmeForRender(packageEnv, addFilesToPackage, editSource: true); // still add? if (doAdd) { // add to elements (this is the real transaction) collectionNewElements.Add(AdminShell.SubmodelElementWrapper.CreateFor(sme)); // add to the tracing information for new elements res.Add(AdminShell.SubmodelElementWrapper.CreateFor(sme)); } } // OK return(res); }
/// <summary> /// Render the list of form elements into a list of SubmodelElements. /// </summary> public AdminShell.SubmodelElementWrapperCollection AddOrUpdateDifferentElementsToCollection( AdminShell.SubmodelElementWrapperCollection elements, AdminShellPackageEnv packageEnv = null, bool addFilesToPackage = false) { // will be a list of newly added elements (for tracing) var res = new AdminShell.SubmodelElementWrapperCollection(); // each description / instance pair foreach (var pair in this) { // ok, perform the actual add or update procedure var lst = pair.instances.AddOrUpdateSameElementsToCollection(elements, packageEnv, addFilesToPackage); // for newly added elements, shaping of idSHort might be required if (lst != null) { foreach (var smw in lst) { // access if (smw?.submodelElement?.idShort == null) { continue; } // check, if to make idShort unique? FormInstanceHelper.MakeIdShortUnique(elements, smw.submodelElement); // add to tracing res.Add(smw); } } } return(res); }
/// <summary> /// Render the list of form elements into a list of SubmodelElements. /// </summary> public AdminShell.SubmodelElementWrapperCollection AddOrUpdateDifferentElementsToCollection( AdminShell.SubmodelElementWrapperCollection elements, AdminShellPackageEnv packageEnv = null, bool addFilesToPackage = false, bool editSource = false) { // SM itself? if (this.sm != null && Touched && this.sourceSM != null && editSource) { if (this.sm.idShort != null) { this.sourceSM.idShort = "" + this.sm.idShort; } if (this.sm.description != null) { this.sourceSM.description = new AdminShell.Description(this.sm.description); } } // SM as a set of elements if (this.PairInstances != null) { return(this.PairInstances.AddOrUpdateDifferentElementsToCollection( elements, packageEnv, addFilesToPackage)); } return(null); }
// // V11 // private static void SearchForRelations( AdminShell.SubmodelElementWrapperCollection smwc, DocumentEntity.DocRelationType drt, AdminShell.Reference semId, DocumentEntity intoDoc) { // access if (smwc == null || semId == null || intoDoc == null) { return; } foreach (var re in smwc.FindAllSemanticIdAs <AdminShell.ReferenceElement>(semId, AdminShellV20.Key.MatchMode.Relaxed)) { // access if (re.value == null || re.value.Count < 1) { continue; } // be a bit picky if (re.value.Last.type.ToLower().Trim() != AdminShell.Key.Entity.ToLower()) { continue; } // add intoDoc.Relations.Add(new Tuple <DocumentEntity.DocRelationType, AdminShellV20.Reference>( drt, re.value)); } }
/// <summary> /// Checks, if the <c>sourceElements</c> can be used to pre-set instances for the rendering /// of the description/ form. /// If not, the display functionality will finally care about creating them. /// </summary> public void PresetInstancesBasedOnSource(AdminShell.SubmodelElementWrapperCollection sourceElements = null) { if (this.PairInstances != null) { foreach (var pair in this.PairInstances) { pair?.instances?.PresetInstancesBasedOnSource(sourceElements); } } }
/// <summary> /// Render the list of form elements into a list of SubmodelElements. /// </summary> public AdminShell.SubmodelElementWrapperCollection AddOrUpdateDifferentElementsToCollection( AdminShell.SubmodelElementWrapperCollection elements, AdminShellPackageEnv packageEnv = null, bool addFilesToPackage = false) { if (this.PairInstances != null) { return(this.PairInstances.AddOrUpdateDifferentElementsToCollection( elements, packageEnv, addFilesToPackage)); } return(null); }
/// <summary> /// Build a new instance, based on the description data /// </summary> public override AdminShell.SubmodelElementWrapperCollection AddOrUpdateSmeToCollection( AdminShell.SubmodelElementWrapperCollection elements, AdminShellPackageEnv packageEnv = null, bool addFilesToPackage = false) { // SMEC as Refrable this.ProcessSmeForRender(packageEnv: null, addFilesToPackage: false, editSource: true); // SMEC as list of items if (this.PairInstances != null) { return(this.PairInstances.AddOrUpdateDifferentElementsToCollection( elements, packageEnv, addFilesToPackage)); } return(null); }
private void DisplaySubmodel() { // show the edit panel OuterTabControl.SelectedItem = TabPanelEdit; // clear first ScrollViewerForm.Content = null; // test trivial access if (theOptions == null || theSubmodel == null) { return; } // identify the record // check for a record in options, that matches Submodel currentFormRecord = theOptions.MatchRecordsForSemanticId(theSubmodel.semanticId); if (currentFormRecord == null) { return; } // check form if (currentFormRecord.FormSubmodel == null || currentFormRecord.FormSubmodel.SubmodelElements == null) { return; } // initialize form formInUpdateMode = true; updateSourceElements = theSubmodel.submodelElements; // take over existing data this.currentFormInst = new FormInstanceSubmodel(currentFormRecord.FormSubmodel); this.currentFormInst.InitReferable(currentFormRecord.FormSubmodel, theSubmodel); this.currentFormInst.PresetInstancesBasedOnSource(updateSourceElements); this.currentFormInst.outerEventStack = theEventStack; // bring it to the panel var elementsCntl = new FormListOfDifferentControl(); elementsCntl.DataContext = this.currentFormInst; ScrollViewerForm.Content = elementsCntl; }
/// <summary> /// Check if <c>smw.idShort</c>c> contains something like "{0:00}" and iterate index to make it unique /// </summary> public static void MakeIdShortUnique( AdminShell.SubmodelElementWrapperCollection collection, AdminShell.SubmodelElement sme) { // access if (collection == null || sme == null) { return; } // check, if to make idShort unique? if (sme.idShort.Contains("{0")) { var newIdShort = collection.IterateIdShortTemplateToBeUnique(sme.idShort, 999); if (newIdShort != null) { sme.idShort = newIdShort; } } }
public void CreateEmptyItemsFromSMEs( AdminShell.SubmodelElementWrapperCollection smwc, bool omitIecEclass = false) { if (smwc == null) { return; } foreach (var smw in smwc) { var sme = smw?.submodelElement; if (sme == null) { continue; } // any var si = sme.semanticId?.GetAsExactlyOneKey()?.value; if (si != null) { if (omitIecEclass && (si.StartsWith("0173") || si.StartsWith("0112"))) { continue; } var item = new CstIdDictionaryItem() { semId = si, cstRef = "" }; this.Add(item); } if (sme is AdminShell.SubmodelElementCollection smc) { // SMC ? recurse! CreateEmptyItemsFromSMEs(smc.value, omitIecEclass); } } }
public AdminShell.SubmodelElementWrapperCollection GenerateDefault() { var res = new AdminShell.SubmodelElementWrapperCollection(); foreach (var desc in this) { AdminShell.SubmodelElement sme = null; // generate element if (desc is FormDescProperty) { sme = (desc as FormDescProperty).GenerateDefault(); } if (desc is FormDescMultiLangProp) { sme = (desc as FormDescMultiLangProp).GenerateDefault(); } if (desc is FormDescFile) { sme = (desc as FormDescFile).GenerateDefault(); } if (desc is FormDescSubmodelElementCollection) { sme = (desc as FormDescSubmodelElementCollection).GenerateDefault(); } // multiplicity -> enumerate correctly FormInstanceHelper.MakeIdShortUnique(res, sme); if (sme != null) { res.Add(sme); } } return(res); }
private void ButtonTabPanels_Click(object sender, RoutedEventArgs e) { if (sender == ButtonCreateDoc) { // show the edit panel OuterTabControl.SelectedItem = TabPanelEdit; ButtonAddUpdateDoc.Content = "Add"; //// TODO (MIHO, 2020-09-29): if the V1.1 template works and is adopted, the old //// V1.0 shall be removed completely (over complicated) */ //// make a template description for the content (remeber it) var desc = theOptions.FormVdi2770; if (desc == null) { desc = DocumentShelfOptions.CreateVdi2770TemplateDesc(theOptions); } // latest version (from resources) if (this.CheckBoxLatestVersion.IsChecked == true) { desc = DocumentShelfOptions.CreateVdi2770v11TemplateDesc(); } this.currentFormDescription = desc; formInUpdateMode = false; updateSourceElements = null; // take over existing data this.currentFormInst = new FormInstanceSubmodelElementCollection(null, currentFormDescription); this.currentFormInst.PresetInstancesBasedOnSource(updateSourceElements); this.currentFormInst.outerEventStack = theEventStack; // bring it to the panel var elementsCntl = new FormListOfDifferentControl(); elementsCntl.ShowHeader = false; elementsCntl.DataContext = this.currentFormInst; ScrollViewerForm.Content = elementsCntl; } if (sender == ButtonAddUpdateDoc) { // add if (this.currentFormInst != null && this.currentFormDescription != null && thePackage != null && theOptions != null && theOptions.SemIdDocument != null && theSubmodel != null) { // on this level of the hierarchy, shall a new SMEC be created or shall // the existing source of elements be used? AdminShell.SubmodelElementWrapperCollection currentElements = null; if (formInUpdateMode && updateSourceElements != null) { currentElements = updateSourceElements; } else { currentElements = new AdminShell.SubmodelElementWrapperCollection(); } // create a sequence of SMEs try { this.currentFormInst.AddOrUpdateDifferentElementsToCollection( currentElements, thePackage, addFilesToPackage: true); } catch (Exception ex) { Log.Error(ex, "when adding Document"); } // the InstSubmodel, which started the process, should have a "fresh" SMEC available // make it unique in the Documentens Submodel var newSmc = this.currentFormInst?.sme as AdminShell.SubmodelElementCollection; // if not update, put them into the Document's Submodel if (!formInUpdateMode && currentElements != null && newSmc != null) { // make newSmc unique in the cotext of the Submodel FormInstanceHelper.MakeIdShortUnique(theSubmodel.submodelElements, newSmc); // add the elements newSmc.value = currentElements; // add the whole SMC theSubmodel.Add(newSmc); } #if __may_be_not__ // save directly to ensure consistency try { if (thePackage.Filename != null) { thePackage.SaveAs(thePackage.Filename); } } catch (Exception ex) { if (theLogger != null) { theLogger.Log( $"Saving package {thePackage.Filename} failed for adding Document " + $"and gave: {ex.Message}"); } } #endif } else { Log.Error("Preconditions for adding Document not met."); } // change back OuterTabControl.SelectedItem = TabPanelList; // re-display ParseSubmodelToListItems( this.theSubmodel, this.theOptions, theViewModel.TheSelectedDocClass, theViewModel.TheSelectedLanguage, theViewModel.TheSelectedListType); // re-display also in Explorer var evt = new AasxPluginResultEventRedrawAllElements(); if (theEventStack != null) { theEventStack.PushEvent(evt); } } if (sender == ButtonCancel) { OuterTabControl.SelectedItem = TabPanelList; } if (sender == ButtonFixCDs) { // check if CDs are present var theDefs = new AasxPredefinedConcepts.DefinitionsVDI2770.SetOfDefsVDI2770( new AasxPredefinedConcepts.DefinitionsVDI2770()); var theCds = theDefs.GetAllReferables().Where( (rf) => { return(rf is AdminShell.ConceptDescription); }).ToList(); // v11 if (CheckBoxLatestVersion.IsChecked == true) { theCds = AasxPredefinedConcepts.VDI2770v11.Static.GetAllReferables().Where( (rf) => { return(rf is AdminShell.ConceptDescription); }).ToList(); } if (theCds.Count < 1) { Log.Error( "Not able to find appropriate ConceptDescriptions in pre-definitions. " + "Aborting."); return; } // check for Environment var env = this.thePackage?.AasEnv; if (env == null) { Log.Error( "Not able to access AAS environment for set of Submodel's ConceptDescriptions. Aborting."); return; } // be safe? if (MessageBoxResult.Yes != MessageBox.Show( "Add missing ConceptDescriptions to the AAS?", "Question", MessageBoxButton.YesNo, MessageBoxImage.Warning)) { return; } // ok, check int nr = 0; foreach (var x in theCds) { var cd = x as AdminShell.ConceptDescription; if (cd == null || cd.identification == null) { continue; } var cdFound = env.FindConceptDescription(cd.identification); if (cdFound != null) { continue; } // ok, add var newCd = new AdminShell.ConceptDescription(cd); env.ConceptDescriptions.Add(newCd); nr++; } // ok Log.Info("In total, {0} ConceptDescriptions were added to the AAS environment.", nr); } if (sender == ButtonCreateEntity) { // show the edit panel OuterTabControl.SelectedItem = TabPanelEntity; } if (sender == ButtonCancelEntity) { OuterTabControl.SelectedItem = TabPanelList; } if (sender == ButtonAddEntity && this.theSubmodel != null && TextBoxEntityIdShort.Text.Trim().HasContent()) { // add entity this.theSubmodel.SmeForWrite.CreateSMEForCD <AdminShell.Entity>( AasxPredefinedConcepts.VDI2770v11.Static.CD_DocumentedEntity, idShort: "" + TextBoxEntityIdShort.Text.Trim(), addSme: true); // switch back OuterTabControl.SelectedItem = TabPanelList; // re-display also in Explorer var evt = new AasxPluginResultEventRedrawAllElements(); if (theEventStack != null) { theEventStack.PushEvent(evt); } } }
private void ButtonTabPanels_Click(object sender, RoutedEventArgs e) { if (sender == ButtonCreateDoc) { // show the edit panel OuterTabControl.SelectedItem = TabPanelEdit; ButtonAddUpdateDoc.Content = "Add"; // make a template description for the content (remeber it) var desc = theOptions.FormVdi2770; if (desc == null) { desc = DocumentShelfOptions.CreateVdi2770TemplateDesc(theOptions); } this.currentFormDescription = desc; formInUpdateMode = false; updateSourceElements = null; // take over existing data this.currentFormInst = new FormInstanceSubmodelElementCollection(null, currentFormDescription); this.currentFormInst.PresetInstancesBasedOnSource(updateSourceElements); // bring it to the panel var elementsCntl = new FormListOfDifferentControl(); elementsCntl.ShowHeader = false; elementsCntl.DataContext = this.currentFormInst; ScrollViewerForm.Content = elementsCntl; } if (sender == ButtonAddUpdateDoc) { // add if (this.currentFormInst != null && this.currentFormDescription != null && thePackage != null && theOptions != null && theOptions.SemIdDocument != null && theSubmodel != null) { // on this level of the hierarchy, shall a new SMEC be created or shall // the existing source of elements be used? AdminShell.SubmodelElementWrapperCollection currentElements = null; if (formInUpdateMode && updateSourceElements != null) { currentElements = updateSourceElements; } else { currentElements = new AdminShell.SubmodelElementWrapperCollection(); } // create a sequence of SMEs try { this.currentFormInst.AddOrUpdateDifferentElementsToCollection( currentElements, thePackage, addFilesToPackage: true); } catch (Exception ex) { Log.Error(ex, "when adding Document"); } // the InstSubmodel, which started the process, should have a "fresh" SMEC available // make it unique in the Documentens Submodel var newSmc = this.currentFormInst?.sme as AdminShell.SubmodelElementCollection; // if not update, put them into the Document's Submodel if (!formInUpdateMode && currentElements != null && newSmc != null) { // make newSmc unique in the cotext of the Submodel FormInstanceHelper.MakeIdShortUnique(theSubmodel.submodelElements, newSmc); // add the elements newSmc.value = currentElements; // add the whole SMC theSubmodel.Add(newSmc); } #if __may_be_not__ // save directly to ensure consistency try { if (thePackage.Filename != null) { thePackage.SaveAs(thePackage.Filename); } } catch (Exception ex) { if (theLogger != null) { theLogger.Log( $"Saving package {thePackage.Filename} failed for adding Document " + $"and gave: {ex.Message}"); } } #endif } else { Log.Error("Preconditions for adding Document not met."); } // change back OuterTabControl.SelectedItem = TabPanelList; // re-display ParseSubmodelToListItems( this.theSubmodel, this.theOptions, theViewModel.TheSelectedDocClass, theViewModel.TheSelectedLanguage, theViewModel.TheSelectedListType); // re-display also in Explorer var evt = new AasxPluginResultEventRedrawAllElements(); if (theEventStack != null) { theEventStack.PushEvent(evt); } } if (sender == ButtonCancel) { OuterTabControl.SelectedItem = TabPanelList; } }
public void TableAddPropertyRows_Recurse( ConceptModelZveiTechnicalData theDefs, string defaultLang, AdminShellPackageEnv package, Table table, AdminShell.SubmodelElementWrapperCollection smwc, int depth = 0) { // access if (table == null || smwc == null) { return; } // make a RowGroup var currentRowGroup = new TableRowGroup(); table.RowGroups.Add(currentRowGroup); // go element by element foreach (var smw in smwc) { // access if (smw?.submodelElement == null) { continue; } var sme = smw.submodelElement; // prepare information about displayName, semantics unit var semantics = "-"; var unit = ""; // make up property name (1) var dispName = "" + sme.idShort; var dispNameWithCD = dispName; // make up semantics if (sme.semanticId != null) { if (sme.semanticId.Matches(theDefs.CD_SemanticIdNotAvailable.GetSingleKey())) { semantics = "(not available)"; } else { // the semantics display semantics = "" + sme.semanticId.ToString(2); // find better property name (2) var cd = package?.AasEnv?.FindConceptDescription(sme.semanticId); if (cd != null) { // unit? unit = "" + cd.GetIEC61360()?.unit; // names var dsn = cd.GetDefaultShortName(defaultLang); if (dsn != "") { dispNameWithCD = dsn; } var dpn = cd.GetDefaultPreferredName(defaultLang); if (dpn != "") { dispNameWithCD = dpn; } } } } // make up even better better property name (3) var descDef = "" + sme.description?.langString?.GetDefaultStr(defaultLang); if (descDef.HasContent()) { dispName = descDef; dispNameWithCD = dispName; } // special function? if (sme is AdminShell.SubmodelElementCollection && true == sme.semanticId?.Matches(theDefs.CD_MainSection.GetSingleKey())) { // finalize current row group?? ; // Main Section var cell = NewTableCellPara("" + dispName, null, "ParaStyleSectionMain", columnSpan: 3, padding: new Thickness(5 * depth, 0, 0, 0)); // add cell (to a new row group) currentRowGroup = new TableRowGroup(); table.RowGroups.Add(currentRowGroup); var tr = new TableRow(); currentRowGroup.Rows.Add(tr); tr.Cells.Add(cell); // recurse into that (again, new group) TableAddPropertyRows_Recurse( theDefs, defaultLang, package, table, (sme as AdminShell.SubmodelElementCollection).value, depth + 1); // start new group currentRowGroup = new TableRowGroup(); table.RowGroups.Add(currentRowGroup); } else if (sme is AdminShell.SubmodelElementCollection && true == sme.semanticId?.Matches(theDefs.CD_SubSection.GetSingleKey())) { // finalize current row group?? ; // Sub Section var cell = NewTableCellPara("" + dispName, null, "ParaStyleSectionSub", columnSpan: 3, padding: new Thickness(5 * depth, 0, 0, 0)); // add cell (to a new row group) currentRowGroup = new TableRowGroup(); table.RowGroups.Add(currentRowGroup); var tr = new TableRow(); currentRowGroup.Rows.Add(tr); tr.Cells.Add(cell); // recurse into that TableAddPropertyRows_Recurse( theDefs, defaultLang, package, table, (sme as AdminShell.SubmodelElementCollection).value, depth + 1); // start new group currentRowGroup = new TableRowGroup(); table.RowGroups.Add(currentRowGroup); } else if (sme is AdminShell.Property || sme is AdminShell.MultiLanguageProperty || sme is AdminShell.Range) { // make a row (in current group) var tr = new TableRow(); currentRowGroup.Rows.Add(tr); // add cells tr.Cells.Add(NewTableCellPara(dispNameWithCD, "CellStylePropertyLeftmost", "ParaStyleProperty", padding: new Thickness(5 * depth, 0, 0, 0))); tr.Cells.Add(NewTableCellPara(semantics, "CellStylePropertyOther", "ParaStyleProperty")); tr.Cells.Add(NewTableCellPara("" + sme.ValueAsText(defaultLang) + " " + unit, "CellStylePropertyOther", "ParaStyleProperty")); } } // finalize current row group?? ; }
private void ButtonTabPanels_Click(object sender, RoutedEventArgs e) { if (sender == ButtonUpdate) { // add if (this.currentFormInst != null && thePackage != null && theOptions != null && theSubmodel != null) { // on this level of the hierarchy, shall a new SMEC be created or shall // the existing source of elements be used? AdminShell.SubmodelElementWrapperCollection currentElements = null; if (formInUpdateMode && updateSourceElements != null) { currentElements = updateSourceElements; } else { } // create a sequence of SMEs try { this.currentFormInst.AddOrUpdateDifferentElementsToCollection( currentElements, thePackage, addFilesToPackage: true, editSource: true); } catch (Exception ex) { Log.Error(ex, "when adding Document"); } #if __may_be_not__ // save directly to ensure consistency try { if (thePackage.Filename != null) { thePackage.SaveAs(thePackage.Filename); } } catch (Exception ex) { if (theLogger != null) { theLogger.Log( $"Saving package {thePackage.Filename} failed for adding Document " + $"and gave: {ex.Message}"); } } #endif } else { Log.Error("Preconditions for adding entities from GenericForm not met."); } // re-display DisplaySubmodel(); // re-display also in Explorer var evt = new AasxPluginResultEventRedrawAllElements(); if (theEventStack != null) { theEventStack.PushEvent(evt); } } if (sender == ButtonFixCDs) { // check if CDs are present if (currentFormRecord == null || currentFormRecord.ConceptDescriptions == null || currentFormRecord.ConceptDescriptions.Count < 1) { Log.Error( "Not able to find appropriate ConceptDescriptions in the GeneralForm option records. " + "Aborting."); return; } // check for Environment var env = this.thePackage?.AasEnv; if (env == null) { Log.Error( "Not able to access AAS environment for set of Submodel's ConceptDescriptions. Aborting."); return; } // be safe? if (MessageBoxResult.Yes != MessageBox.Show( "Add missing ConceptDescriptions to the AAS?", "Question", MessageBoxButton.YesNo, MessageBoxImage.Warning)) { return; } // ok, check int nr = 0; foreach (var cd in currentFormRecord.ConceptDescriptions) { if (cd == null || cd.identification == null) { continue; } var cdFound = env.FindConceptDescription(cd.identification); if (cdFound != null) { continue; } // ok, add var newCd = new AdminShell.ConceptDescription(cd); env.ConceptDescriptions.Add(newCd); nr++; } // ok Log.Info("In total, {0} ConceptDescriptions were added to the AAS environment.", nr); } }
private void PublishSingleValues_ChangeItem( AasEventMsgEnvelope ev, AdminShell.ReferableRootInfo ri, AdminShell.KeyList startPath, AasPayloadStructuralChangeItem ci) { // trivial if (ev == null || ci == null || startPath == null) { return; } // only specific reasons if (!(ci.Reason == AasPayloadStructuralChangeItem.ChangeReason.Create || ci.Reason == AasPayloadStructuralChangeItem.ChangeReason.Modify)) { return; } // need a payload if (ci.Path == null || ci.Data == null) { return; } var dataRef = ci.GetDataAsReferable(); // give this to (recursive) function var messages = new List <MqttApplicationMessage>(); if (dataRef is AdminShell.SubmodelElement dataSme) { var smwc = new AdminShell.SubmodelElementWrapperCollection(dataSme); smwc.RecurseOnSubmodelElements(null, null, (o, parents, sme) => { // assumption is, the sme is now "leaf" of a SME-hierarchy if (sme is AdminShell.IEnumerateChildren) { return; } // value of the leaf var valStr = sme.ValueAsText(); // build a complete path of keys var path = startPath + ci.Path + parents.ToKeyList() + sme?.ToKey(); var pathStr = path.BuildIdShortPath(); // publish if (_diaData.LogDebug) { _logger?.Info("Publish single value (create/ update)"); } messages.Add( new MqttApplicationMessageBuilder() .WithTopic(GenerateTopic( _diaData.EventTopic, defaultIfNull: "SingleValue", aasIdShort: ri?.AAS?.idShort, aasId: ri?.AAS?.identification, smIdShort: ri?.Submodel?.idShort, smId: ri?.Submodel?.identification, path: pathStr)) .WithPayload(valStr) .WithExactlyOnceQoS() .WithRetainFlag(_diaData.MqttRetain) .Build()); }); } // publish these // convert to synchronous behaviour int count = 0; foreach (var msg in messages) { count++; _mqttClient.PublishAsync(msg).GetAwaiter().GetResult(); } LogStatus(incSingleValue: count); }
private static void RecurseExportAsTemplate( AdminShell.SubmodelElementWrapperCollection smwc, FormDescListOfElement tels, AdminShell.AdministrationShellEnv env = null, AdminShell.ListOfConceptDescriptions cds = null) { // access if (smwc == null || tels == null) { return; } // over all elems foreach (var smw in smwc) { if (smw != null && smw.submodelElement != null) { FormDescSubmodelElement tsme = null; if (smw.submodelElement is AdminShell.Property p) { tsme = new FormDescProperty( "" + p.idShort, FormMultiplicity.One, p.semanticId?.GetAsExactlyOneKey(), "" + p.idShort, valueType: p.valueType); } if (smw.submodelElement is AdminShell.MultiLanguageProperty mlp) { tsme = new FormDescMultiLangProp( "" + mlp.idShort, FormMultiplicity.One, mlp.semanticId?.GetAsExactlyOneKey(), "" + mlp.idShort); } if (smw.submodelElement is AdminShell.File fl) { tsme = new FormDescFile( "" + fl.idShort, FormMultiplicity.One, fl.semanticId?.GetAsExactlyOneKey(), "" + fl.idShort); } if (smw.submodelElement is AdminShell.ReferenceElement rf) { tsme = new FormDescReferenceElement( "" + rf.idShort, FormMultiplicity.One, rf.semanticId?.GetAsExactlyOneKey(), "" + rf.idShort); } if (smw.submodelElement is AdminShell.SubmodelElementCollection smec) { tsme = new FormDescSubmodelElementCollection( "" + smec.idShort, FormMultiplicity.One, smec.semanticId?.GetAsExactlyOneKey(), "" + smec.idShort); } if (tsme != null) { // take over directly tsme.PresetCategory = smw.submodelElement.category; // Qualifers var qs = smw.submodelElement.qualifiers; var q = qs?.FindType("FormTitle"); if (q != null) { tsme.FormTitle = "" + q.value; } q = qs?.FindType("FormInfo"); if (q != null) { tsme.FormInfo = "" + q.value; } q = qs?.FindType("EditIdShort"); if (q != null) { tsme.FormEditIdShort = q.value.Trim().ToLower() == "true"; } q = qs?.FindType("EditDescription"); if (q != null) { tsme.FormEditDescription = q.value.Trim().ToLower() == "true"; } q = qs?.FindType("Multiplicity"); if (q != null) { foreach (var m in (FormMultiplicity[])Enum.GetValues(typeof(FormMultiplicity))) { if (("" + q.value) == Enum.GetName(typeof(FormMultiplicity), m)) { tsme.Multiplicity = m; } } } q = qs?.FindType("PresetValue"); if (q != null && tsme is FormDescProperty) { (tsme as FormDescProperty).presetValue = "" + q.value; } q = qs?.FindType("PresetMimeType"); if (q != null && tsme is FormDescFile) { (tsme as FormDescFile).presetMimeType = "" + q.value; } q = qs?.FindType("FormChoices"); if (q != null && q.value.HasContent() && tsme is FormDescProperty fdprop) { var choices = q.value.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries); if (choices != null && choices.Length > 0) { fdprop.comboBoxChoices = choices; } } // adopt presetIdShort if (tsme.Multiplicity == FormMultiplicity.ZeroToMany || tsme.Multiplicity == FormMultiplicity.OneToMany) { tsme.PresetIdShort += "{0:00}"; } // Ignore this element q = qs?.FindType("FormIgnore"); if (q != null) { continue; } } if (tsme != null) { tels.Add(tsme); } // in any case, check for CD if (env != null && cds != null && smw?.submodelElement?.semanticId?.Keys != null) { var masterCd = env.FindConceptDescription(smw?.submodelElement?.semanticId?.Keys); if (masterCd != null && masterCd.identification != null) { // already in cds? var copyCd = cds.Find(masterCd.identification); if (copyCd == null) { // add clone cds.Add(new AdminShell.ConceptDescription(masterCd)); } } } // recurse if (smw.submodelElement is AdminShell.SubmodelElementCollection) { RecurseExportAsTemplate( (smw.submodelElement as AdminShell.SubmodelElementCollection).value, (tsme as FormDescSubmodelElementCollection).value, env, cds); } } } }
private void RecurseOnSme( AdminShell.SubmodelElementWrapperCollection smwc, CstIdObjectBase presetId, string presetClassType, CstPropertyRecord.ListOfProperty propRecs) { // access if (smwc == null) { return; } // create a class def CstClassDef.ClassDefinition clsdef; if (presetId != null) { clsdef = new CstClassDef.ClassDefinition(presetId); } else { clsdef = new CstClassDef.ClassDefinition(GenerateCustomId("CLS")); } clsdef.ClassType = presetClassType; // add the class def (to have the following classes below) ClassDefs.AddIfUnique(clsdef); // values for (int smcMode = 0; smcMode < 2; smcMode++) { foreach (var smw in smwc) { // trivial var sme = smw?.submodelElement; if (sme == null) { continue; } // is SMC? .. ugly contraption to have first all Properties, then all SMCs var smc = sme as AdminShell.SubmodelElementCollection; if ((smcMode == 0 && smc != null) || (smcMode == 1 && smc == null)) { continue; } // check, if ConceptDescription exists .. var cd = _env?.AasEnv.FindConceptDescription(sme.semanticId); // try to take over as much information from the pure SME as possible var semid = sme.semanticId.GetAsExactlyOneKey()?.value; string refStr = null; string refName = null; if (semid != null) { // standardized ID? if (semid.StartsWith("0173") || semid.StartsWith("0112")) { refStr = semid; } // already known, fixed id? var it = _knownIdStore?.FindStringSemId(semid); if (it != null) { if (it.cstRef != null) { refStr = it.cstRef; } if (it.cstId != null) { refStr = it.cstId.ToRef(); } if (it.preferredName != null) { refName = it.preferredName; } } } // prepare a prop def & data type CstPropertyDef.PropertyDefinition tmpPd = null; string tmpDt = null; if (refStr != null) { // make it var bo = CstIdObjectBase.Parse(refStr); tmpPd = new CstPropertyDef.PropertyDefinition(bo); // more info tmpPd.Name = "" + sme.idShort; if (sme.description != null) { tmpPd.Remark = sme.description.GetDefaultStr("en"); } if (sme is AdminShell.Property prop) { tmpDt = prop.valueType; } // more info if (cd != null) { var ds61360 = cd.IEC61360Content; if (ds61360 != null) { if (ds61360.definition != null) { tmpPd.Definition = ds61360.definition.GetDefaultStr("en"); } var dst = ds61360.dataType?.Trim().ToUpper(); if (ds61360 == null && dst != null) { tmpDt = dst; } } } // default if (!tmpDt.HasContent()) { tmpDt = "STRING"; } } if (smc != null) { // SMC // make a reference property def // the property itself needs to have an ALTERED ID, to be not ídentical with if (tmpPd != null) { // class id tmpPd.ID = "BLPRP_" + tmpPd.ID; // will be a reference to the intended class tmpPd.DataType = new CstPropertyDef.DataType() { Type = "Reference", BlockReference = "" + refStr }; // rest of attributes tmpPd.ObjectType = "02"; tmpPd.Status = "Released"; // add PropertyDefs.AddIfUnique(tmpPd); } // create a new class attribute (with reference to ALTERED ID!) var attr = new CstClassDef.ClassAttribute() { Type = "Property", Reference = tmpPd?.ToRef() ?? "NULL" }; clsdef.ClassAttributes.AddIfUnique(attr); // start new list of property values, embedded in a PropertyRecord var rec = new CstPropertyRecord.PropertyRecord(); var lop = new CstPropertyRecord.ListOfProperty(); rec.ClassDefinition = refStr; rec.Properties = lop; var pr = new CstPropertyRecord.Property() { ID = tmpPd.ToRef(), Name = "" + smc.idShort, ValueProps = rec }; // execute the following, only if twice the same ID in proprety records // (for blocks are allowed) var addBlockRec = true; if (DoNotAddMultipleBlockRecordsWithSameIds && propRecs.FindExisting(pr) != null) { addBlockRec = false; } // ok? if (addBlockRec) { if (propRecs != null) { propRecs.Add(pr); } // recursion, but as Block // TODO (MIHO, 2021-05-28): extend Parse() to parse also ECLASS, IEC CDD var blockId = CstIdObjectBase.Parse(refStr); blockId.Name = refName; RecurseOnSme(smc.value, blockId, "Block", lop); } } else { // normal case .. Property or so // create a new class attribute var attr = new CstClassDef.ClassAttribute() { Type = "Property", Reference = refStr }; clsdef.ClassAttributes.AddIfUnique(attr); // make a "normal" property definition if (tmpPd != null) { // use data type? if (tmpDt != null) { tmpPd.DataType = new CstPropertyDef.DataType() { Type = AasxCstUtils.ToPascalCase(tmpDt) } } ; tmpPd.ObjectType = "02"; tmpPd.Status = "Released"; PropertyDefs.AddIfUnique(tmpPd); } // make a prop rec var pr = new CstPropertyRecord.Property() { ValueStr = sme.ValueAsText(), ID = refStr, Name = "" + sme.idShort }; if (propRecs != null) { propRecs.Add(pr); } } } } }
/// <summary> /// Render the form description and adds or updates its instances into a list of SubmodelElements. /// </summary> public AdminShell.SubmodelElementWrapperCollection AddOrUpdateSameElementsToCollection( AdminShell.SubmodelElementWrapperCollection elements, AdminShellPackageEnv packageEnv = null, bool addFilesToPackage = false) { // access var res = new AdminShell.SubmodelElementWrapperCollection(); if (this.SubInstances == null || this.workingDesc == null) { return(null); } // over all instances foreach (var ins in this.SubInstances) { // access if (!(ins is FormInstanceSubmodelElement)) { continue; } // only touched? if (!(ins is FormInstanceSubmodelElementCollection) && !ins.Touched) { continue; } // this is not very nice: distinguish between SMECs und SMEs if (!(this.workingDesc is FormDescSubmodelElementCollection)) { var lst1 = (ins as FormInstanceSubmodelElement).AddOrUpdateSmeToCollection( elements, packageEnv, addFilesToPackage); // for monitoring purpose res.AddRange(lst1); } else { // Special case: SMEC // the Same-Instance was already prepared, however it needs to be eventually // filled with the new elements var smecInst = ins as FormInstanceSubmodelElementCollection; var sourceSmec = smecInst?.sourceSme as AdminShell.SubmodelElementCollection; AdminShell.SubmodelElementWrapperCollection newElems = null; bool addMode = false; if (sourceSmec == null) { // will become a NEW SMEC ! newElems = new AdminShell.SubmodelElementWrapperCollection(); addMode = true; } else { // will be added to an existing SMEC newElems = sourceSmec.value; addMode = false; } var lst = (ins as FormInstanceSubmodelElement).AddOrUpdateSmeToCollection( newElems, packageEnv, addFilesToPackage); if (newElems != null && newElems.Count > 0) { var smec = smecInst?.sme as AdminShell.SubmodelElementCollection; // really add a new instances of the SMEC if (addMode && smecInst != null && smec != null) { // add if (smec.value == null) { smec.value = new AdminShellV20.SubmodelElementWrapperCollection(); } smec.value.AddRange(newElems); // make smec unique FormInstanceHelper.MakeIdShortUnique(elements, smec); // to (outer) elements elements.Add(smec); } // for monitoring purpose res.AddRange(lst); } } } // now, check if original SMEs are missing in the Instances and have therefore be removed // (kind of post-mortem analysis) if (this.InitialSourceElements != null) { foreach (var ise in this.InitialSourceElements) { // exclude trivial cases if (ise == null) { continue; } // manually search var found = false; foreach (var ins in this.SubInstances) { if (ins != null && ins is FormInstanceSubmodelElement && (ins as FormInstanceSubmodelElement).sourceSme == ise) { found = true; } } // if not foudnd, DELETE original element if (!found) { elements.Remove(ise); } } } // ok return(res); }