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);
        }
Esempio n. 2
0
        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);
        }