public override List <ConvertOfferBase> CheckForOffers(AdminShell.Referable currentReferable) { // collectResults var res = new List <ConvertOfferBase>(); // use pre-definitions var defs = new AasxPredefinedConcepts.DefinitionsZveiDigitalTypeplate.SetOfNameplate( new AasxPredefinedConcepts.DefinitionsZveiDigitalTypeplate()); var sm = currentReferable as AdminShell.Submodel; if (sm != null && true == sm.GetSemanticKey()?.Matches(defs.SM_Nameplate.GetSemanticKey(), AdminShellV20.Key.MatchMode.Relaxed)) { res.Add(new ConvertOfferNameplateHsuToZveiV10(this, $"Convert Submodel '{"" + sm.idShort}' for Digital Nameplate HSU to ZVEI V1.0")); } return(res); }
public static int Execute(IReadOnlyList <Instruction.IInstruction> instructions) { // # Context AdminShellPackageEnv package = null; // # Execution loop foreach (var instruction in instructions) { // The instruction dispatch is intentionally implemented as a switch statement and case blocks // instead of encapsulating the individual blocks in separate methods or classes. The shared context // is clearly signaled, while we do not gain much in clarity with separate functions and classes. // // Moreover, the pre-emptive stops in the execution logic were much more difficult to get right with the // methods than with this fairly simple construct. switch (instruction) { case Instruction.Generate generate: { try { package = AasxToolkit.Generate.GeneratePackage(generate.JsonInitFile); } catch (Exception ex) { Console.Error.WriteLine( "Failed to generate the package: {0} at {1}", ex.Message, ex.StackTrace); return(-1); } Console.Out.WriteLine("Package generated."); break; } case Instruction.Load load: { Console.Out.WriteLine("Loading package {0} ..", load.Path); try { if (load.Path.EndsWith(".aml")) { package = new AdminShellPackageEnv(); AmlImport.ImportInto(package, load.Path); } else { package = new AdminShellPackageEnv(load.Path); } } catch (Exception ex) { Console.Error.WriteLine( "While loading package {0}: {1} at {2}", load.Path, ex.Message, ex.StackTrace); return(-1); } Console.Out.WriteLine($"Loaded package: {load.Path}"); break; } case Instruction.Save save: { if (package == null) { Console.Error.WriteLine( "You must either generate a package (`gen`) or " + "load a package (`load`) before you can save it."); return(-1); } Console.Out.WriteLine("Writing package {0} ..", save.Path); try { if (Path.GetExtension(save.Path).ToLower() == ".aml") { AmlExport.ExportTo( package, save.Path, tryUseCompactProperties: false); } else { package.SaveAs(save.Path, writeFreshly: true); package.Close(); } } catch (Exception ex) { Console.Error.WriteLine( "While saving package {0}: {1} at {2}", save.Path, ex.Message, ex.StackTrace); return(-1); } break; } case Instruction.Validate validate: { try { var recs = new AasValidationRecordList(); string extension = Path.GetExtension(validate.Path).ToLower(); if (extension == ".xml") { Console.Out.WriteLine($"Validating file {validate.Path} against XSD .."); using (var stream = File.Open(validate.Path, FileMode.Open, FileAccess.Read)) { AasSchemaValidation.ValidateXML(recs, stream); } } else if (extension == ".json") { Console.Out.WriteLine($"Validating file {validate.Path} against JSON .."); using (var stream = File.Open(validate.Path, FileMode.Open, FileAccess.Read)) { AasSchemaValidation.ValidateJSONAlternative(recs, stream); } } else { throw new System.InvalidOperationException( $"Validation of the file with the extension {extension} " + $"is not supported: {validate.Path}"); } if (recs.Count > 0) { Console.Out.WriteLine($"Found {recs.Count} issue(s):"); foreach (var r in recs) { Console.Out.WriteLine(r.ToString()); } } else { Console.Out.WriteLine($"Found no issues."); } } catch (Exception ex) { Console.Error.WriteLine( $"While validating the package {validate.Path}: " + $"{ex.Message} at {ex.StackTrace}"); return(-1); } break; } case Instruction.ExportTemplate exportTemplate: { if (package == null) { Console.Error.WriteLine( "You must either generate a package (`gen`) or " + "load a package (`load`) before you can export it as a template."); return(-1); } Console.Out.WriteLine("Exporting to file {0} ..", exportTemplate.Path); try { AasFormUtils.ExportAsTemplate(package, exportTemplate.Path); } catch (Exception ex) { Console.Error.WriteLine( "While exporting package {0}: {1} at {2}", exportTemplate.Path, ex.Message, ex.StackTrace); return(-1); } Console.Out.WriteLine("Package {0} written.", exportTemplate.Path); break; } case Instruction.ExportCst ecst: { if (package == null) { Console.Error.WriteLine( "You must either generate a package (`gen`) or " + "load a package (`load`) before you can export it as a template."); return(-1); } Console.Out.WriteLine("Exporting to file {0} ..", ecst.Path); try { var ei = new AasxFormatCst.AasxToCst(jsonKnownIds: "cst-default-id-map.json"); var dnp = new AasxPredefinedConcepts.DefinitionsZveiDigitalTypeplate.SetOfNameplate( new AasxPredefinedConcepts.DefinitionsZveiDigitalTypeplate()); ei.DoNotAddMultipleBlockRecordsWithSameIds = true; // requested by Siemens ei.ExportSingleSubmodel( package, ecst.Path, dnp.SM_Nameplate.GetSemanticKey(), dnp.GetAllReferables(), firstNodeId: new AasxFormatCst.CstIdObjectBase() { Namespace = "IDTA", ID = "FESTOAAS", Revision = "001", Name = "Festo" }, secondNodeId: new AasxFormatCst.CstIdObjectBase() { Namespace = "IDTA", ID = "FESTOSM", Revision = "001", Name = "Submodel Nameplate" }, appClassId: new AasxFormatCst.CstIdObjectBase() { Namespace = "IDTA", ObjectType = "01", ID = "SMNP001", Revision = "001", Name = "Submodel Nameplate" }); AasFormUtils.ExportAsTemplate(package, ecst.Path); } catch (Exception ex) { Console.Error.WriteLine( "While exporting CST {0}: {1} at {2}", ecst.Path, ex.Message, ex.StackTrace); return(-1); } Console.Out.WriteLine("File {0} written.", ecst.Path); break; } case Instruction.CheckAndFix checkAndFix: { try { if (package == null) { Console.Error.WriteLine( "You must either generate a package (`gen`) or " + "load a package (`load`) before you can check it."); return(-1); } // validate var recs = package?.AasEnv?.ValidateAll(); if (recs == null) { throw new InvalidOperationException( "Validation returned null -- we do not know how to handle this situation."); } if (recs.Count > 0) { Console.Out.WriteLine($"Found {recs.Count} issue(s):"); foreach (var rec in recs) { Console.Out.WriteLine(rec.ToString()); } if (checkAndFix.ShouldFix) { Console.Out.WriteLine($"Fixing all records.."); var i = package.AasEnv.AutoFix(recs); Console.Out.WriteLine($".. gave result {i}."); } } else { Console.Out.WriteLine($"Found no issues."); } } catch (Exception ex) { Console.Error.WriteLine( "While checking the package in RAM: {0} at {1}", ex.Message, ex.StackTrace); return(-1); } break; } case Instruction.Test _: { try { if (package == null) { Console.Error.WriteLine( "You must either generate a package (`gen`) or " + "load a package (`load`) before you can test it."); return(-1); } var prop = AdminShellV20.Property.CreateNew("test", "cat01"); prop.semanticId = new AdminShellV20.SemanticId( AdminShellV20.Reference.CreateNew( "GlobalReference", false, "IRI", "www.admin-shell.io/nonsense")); var fil = AdminShellV20.File.CreateNew("test", "cat01"); fil.semanticId = new AdminShellV20.SemanticId( AdminShellV20.Reference.CreateNew( "GlobalReference", false, "IRI", "www.admin-shell.io/nonsense")); fil.parent = fil; var so = new AdminShellUtil.SearchOptions(); so.allowedAssemblies = new[] { typeof(AdminShell).Assembly }; var sr = new AdminShellUtil.SearchResults(); AdminShellUtil.EnumerateSearchable( sr, package.AasEnv, "", 0, so); // test debug foreach (var fr in sr.foundResults) { Console.Out.WriteLine( "{0}|{1} = {2}", fr.qualifiedNameHead, fr.metaModelName, fr.foundText); } } catch (Exception ex) { Console.Error.WriteLine( "While testing the package in RAM: {0} at {1}", ex.Message, ex.StackTrace); return(-1); } break; } default: throw ExhaustiveMatching.ExhaustiveMatch.Failed(instruction); } } return(0); }
public override bool ExecuteOffer(AdminShellPackageEnv package, AdminShell.Referable currentReferable, ConvertOfferBase offerBase, bool deleteOldCDs, bool addNewCDs) { // access var offer = offerBase as ConvertOfferNameplateHsuToZveiV10; if (package == null || package.AasEnv == null || currentReferable == null || offer == null) { return(false); } // use pre-definitions var defsHSU = new AasxPredefinedConcepts.DefinitionsZveiDigitalTypeplate.SetOfNameplate( new AasxPredefinedConcepts.DefinitionsZveiDigitalTypeplate()); var defsV10 = AasxPredefinedConcepts.ZveiNameplateV10.Static; // access Submodel (again) var sm = currentReferable as AdminShell.Submodel; if (sm == null || sm.submodelElements == null || true != sm.GetSemanticKey()?.Matches(defsHSU.SM_Nameplate.GetSemanticKey())) { /* disable line above to allow more models, such as MCAD/ECAD */ return(false); } // convert in place: detach old SMEs, change semanticId var smHSU = sm.submodelElements; sm.submodelElements = new AdminShell.SubmodelElementWrapperCollection(); sm.semanticId = new AdminShell.SemanticId(defsV10.SM_Nameplate.GetSemanticKey()); // delete (old) CDs if (deleteOldCDs) { sm.RecurseOnSubmodelElements(null, (state, parents, current) => { var sme = current; if (sme != null && sme.semanticId != null) { var cd = package.AasEnv.FindConceptDescription(sme.semanticId); if (cd != null) { if (package.AasEnv.ConceptDescriptions.Contains(cd)) { package.AasEnv.ConceptDescriptions.Remove(cd); } } } // recurse return(true); }); } // add (all) new CDs? if (addNewCDs) { foreach (var rf in defsV10.GetAllReferables()) { if (rf is AdminShell.ConceptDescription) { package.AasEnv.ConceptDescriptions.AddIfNew(new AdminShell.ConceptDescription( rf as AdminShell.ConceptDescription)); } } } // Submodel level sm.submodelElements.CopyOneSMEbyCopy <AdminShell.Property>(defsV10.CD_ManNam, smHSU, defsHSU.CD_ManufacturerName, createDefault: true, addSme: true, idShort: "ManufacturerName"); sm.submodelElements.CopyOneSMEbyCopy <AdminShell.Property>(defsV10.CD_ManProDes, smHSU, defsHSU.CD_ManufacturerProductDesignation, createDefault: true, addSme: true, idShort: "ManufacturerProductDesignation"); // Address (target cardinality: 1) foreach (var smcHSUadd in smHSU.FindAllSemanticIdAs <AdminShell.SubmodelElementCollection>( defsHSU.CD_PhysicalAddress.GetSingleKey())) { // make a new one var smcV10add = sm.submodelElements.CreateSMEForCD <AdminShell.SubmodelElementCollection>( defsV10.CD_Add, idShort: "Address", addSme: true); // SME smcV10add.value.CopyOneSMEbyCopy <AdminShell.Property>(defsV10.CD_Str, smcHSUadd.value, new[] { defsHSU.CD_Street.GetSingleKey(), new AdminShell.Key(AdminShell.Key.ConceptDescription, true, AdminShell.Identification.IRI, "https://www.hsu-hh.de/aut/aas/street") }, createDefault: true, addSme: true, idShort: "Street"); smcV10add.value.CopyOneSMEbyCopy <AdminShell.Property>(defsV10.CD_ZipCod, smcHSUadd.value, new[] { defsHSU.CD_Zip.GetSingleKey(), new AdminShell.Key(AdminShell.Key.ConceptDescription, true, AdminShell.Identification.IRI, "https://www.hsu-hh.de/aut/aas/postalcode") }, createDefault: true, addSme: true, idShort: "Zipcode"); smcV10add.value.CopyOneSMEbyCopy <AdminShell.Property>(defsV10.CD_CitTow, smcHSUadd.value, new[] { defsHSU.CD_CityTown.GetSingleKey(), new AdminShell.Key(AdminShell.Key.ConceptDescription, true, AdminShell.Identification.IRI, "https://www.hsu-hh.de/aut/aas/city") }, createDefault: true, addSme: true, idShort: "CityTown"); smcV10add.value.CopyOneSMEbyCopy <AdminShell.Property>(defsV10.CD_StaCou, smcHSUadd.value, new[] { defsHSU.CD_StateCounty.GetSingleKey(), new AdminShell.Key(AdminShell.Key.ConceptDescription, true, AdminShell.Identification.IRI, "https://www.hsu-hh.de/aut/aas/statecounty") }, createDefault: true, addSme: true, idShort: "StateCounty"); smcV10add.value.CopyOneSMEbyCopy <AdminShell.Property>(defsV10.CD_NatCod, smcHSUadd.value, defsHSU.CD_CountryCode, createDefault: true, addSme: true, idShort: "NationalCode"); } // Submodel level - continued sm.submodelElements.CopyOneSMEbyCopy <AdminShell.Property>(defsV10.CD_ManProFam, smHSU, defsHSU.CD_ManufacturerProductFamily, createDefault: true, addSme: true, idShort: "ManufacturerProductFamily"); sm.submodelElements.CopyOneSMEbyCopy <AdminShell.Property>(defsV10.CD_SerNum, smHSU, defsHSU.CD_SerialNumber, createDefault: true, addSme: true, idShort: "SerialNumber"); sm.submodelElements.CopyOneSMEbyCopy <AdminShell.Property>(defsV10.CD_YeaOfCon, smHSU, defsHSU.CD_YearOfConstruction, createDefault: true, addSme: true, idShort: "YearOfConstruction"); // Markings var smcV10mks = sm.submodelElements.CreateSMEForCD <AdminShell.SubmodelElementCollection>( defsV10.CD_Markings, idShort: "Markings", addSme: true); // each Marking foreach (var smcHSUmk in smHSU.FindAllSemanticIdAs <AdminShell.SubmodelElementCollection>( defsHSU.CD_ProductMarking.GetSingleKey())) { // make a new one var smcV10mk = smcV10mks.value.CreateSMEForCD <AdminShell.SubmodelElementCollection>( defsV10.CD_Marking, idShort: "" + smcHSUmk.idShort, addSme: true); // take over the name of the old collection in the distinct Property var mkName = "" + smcHSUmk.idShort; if (mkName.StartsWith("Marking_")) { mkName = mkName.Substring(8); } var mkNameProp = smcV10mk.value.CreateSMEForCD <AdminShell.Property>( defsV10.CD_MarkingName, idShort: "MarkingName", addSme: true)? .Set(AdminShell.DataElement.ValueType_STRING, "" + mkName); // file smcV10mk.value.CopyOneSMEbyCopy <AdminShell.File>(defsV10.CD_MarkingFile, smcHSUmk.value, defsHSU.CD_File, createDefault: true, addSme: true, idShort: "ManufacturerName"); // if there a other Property inside, assume, that their semantic ids shall // go into the valueId of the Name foreach (var other in smcHSUmk.value.FindAll((smw) => smw?.submodelElement is AdminShell.Property)) { if (mkNameProp != null && other?.submodelElement?.semanticId != null && !other.submodelElement.semanticId.IsEmpty && other.submodelElement.semanticId[0].IsIdType(AdminShell.Identification.IRDI)) { mkNameProp.valueId = other.submodelElement.semanticId; } } } // obviously well return(true); }