public bool SaveAs(string fn, bool writeFreshly = false, PreferredFormat prefFmt = PreferredFormat.None, MemoryStream useMemoryStream = null)
        {
            Console.WriteLine("SaveAs: " + fn);
            if (fn.ToLower().EndsWith(".xml"))
            {
                // save only XML
                this.fn = fn;
                try
                {
                    using (var s = new StreamWriter(this.fn))
                    {
                        // TODO: use aasenv serialzers here!
                        var serializer = new XmlSerializer(typeof(AdminShell.AdministrationShellEnv));
                        var nss        = new XmlSerializerNamespaces();
                        nss.Add("xsi", System.Xml.Schema.XmlSchema.InstanceNamespace);
                        nss.Add("aas", "http://www.admin-shell.io/aas/2/0");
                        nss.Add("IEC61360", "http://www.admin-shell.io/IEC61360/2/0");
                        serializer.Serialize(s, this.aasenv, nss);
                    }
                }
                catch (Exception ex)
                {
                    throw (new Exception(string.Format("While writing AAS {0} at {1} gave: {2}", fn, AdminShellUtil.ShortLocation(ex), ex.Message)));
                }
                return(true);
            }

            if (fn.ToLower().EndsWith(".json"))
            {
                // save only JSON
                // this funcitonality is a initial test
                this.fn = fn;
                try
                {
                    using (var sw = new StreamWriter(fn))
                    {
                        // TODO: use aasenv serialzers here!

                        sw.AutoFlush = true;

                        JsonSerializer serializer = new JsonSerializer()
                        {
                            NullValueHandling     = NullValueHandling.Ignore,
                            ReferenceLoopHandling = ReferenceLoopHandling.Serialize,
                            Formatting            = Newtonsoft.Json.Formatting.Indented
                        };
                        using (JsonWriter writer = new JsonTextWriter(sw))
                        {
                            serializer.Serialize(writer, this.aasenv);
                        }
                    }
                }
                catch (Exception ex)
                {
                    throw (new Exception(string.Format("While writing AAS {0} at {1} gave: {2}", fn, AdminShellUtil.ShortLocation(ex), ex.Message)));
                }
                return(true);
            }

            if (fn.ToLower().EndsWith(".aasx"))
            {
                // save package AASX
                try
                {
                    // we want existing contents to be preserved, but no possiblity to change file name
                    // therefore: copy file to new name, re-open!
                    // fn could be changed, therefore close "old" package first
                    if (this.openPackage != null)
                    {
                        // ReSharper disable EmptyGeneralCatchClause
                        try
                        {
                            this.openPackage.Close();
                            if (!writeFreshly)
                            {
                                if (this.tempFn != null)
                                {
                                    System.IO.File.Copy(this.tempFn, fn);
                                }
                                else
                                {
                                    System.IO.File.Copy(this.fn, fn);
                                }
                            }
                        }
                        catch { }
                        // ReSharper enable EmptyGeneralCatchClause
                        this.openPackage = null;
                    }

                    // approach is to utilize the existing package, if possible. If not, create from scratch
                    Package package = null;
                    if (useMemoryStream != null)
                    {
                        package = Package.Open(useMemoryStream, (writeFreshly) ? FileMode.Create : FileMode.OpenOrCreate);
                    }
                    else
                    {
                        package = Package.Open((this.tempFn != null) ? this.tempFn : fn, (writeFreshly) ? FileMode.Create : FileMode.OpenOrCreate);
                    }
                    this.fn = fn;

                    // get the origin from the package
                    PackagePart originPart = null;
                    var         xs         = package.GetRelationshipsByType("http://www.admin-shell.io/aasx/relationships/aasx-origin");
                    foreach (var x in xs)
                    {
                        if (x.SourceUri.ToString() == "/")
                        {
                            originPart = package.GetPart(x.TargetUri);
                            break;
                        }
                    }
                    if (originPart == null)
                    {
                        // create, as not existing
                        originPart = package.CreatePart(new Uri("/aasx/aasx-origin", UriKind.RelativeOrAbsolute), System.Net.Mime.MediaTypeNames.Text.Plain, CompressionOption.Maximum);
                        using (var s = originPart.GetStream(FileMode.Create))
                        {
                            var bytes = System.Text.Encoding.ASCII.GetBytes("Intentionally empty.");
                            s.Write(bytes, 0, bytes.Length);
                        }
                        package.CreateRelationship(originPart.Uri, TargetMode.Internal, "http://www.admin-shell.io/aasx/relationships/aasx-origin");
                    }

                    // get the specs from the package
                    PackagePart         specPart = null;
                    PackageRelationship specRel  = null;
                    xs = originPart.GetRelationshipsByType("http://www.admin-shell.io/aasx/relationships/aas-spec");
                    foreach (var x in xs)
                    {
                        specRel  = x;
                        specPart = package.GetPart(x.TargetUri);
                        break;
                    }

                    // check, if we have to change the spec part
                    if (specPart != null && specRel != null)
                    {
                        var name = System.IO.Path.GetFileNameWithoutExtension(specPart.Uri.ToString()).ToLower().Trim();
                        var ext  = System.IO.Path.GetExtension(specPart.Uri.ToString()).ToLower().Trim();
                        if ((ext == ".json" && prefFmt == PreferredFormat.Xml) ||
                            (ext == ".xml" && prefFmt == PreferredFormat.Json) ||
                            (name.StartsWith("aasenv-with-no-id")))
                        {
                            // try kill specpart
                            // ReSharper disable EmptyGeneralCatchClause
                            try
                            {
                                originPart.DeleteRelationship(specRel.Id);
                                package.DeletePart(specPart.Uri);
                            }
                            catch { }
                            finally { specPart = null; specRel = null; }
                            // ReSharper enable EmptyGeneralCatchClause
                        }
                    }

                    if (specPart == null)
                    {
                        // create, as not existing
                        var frn = "aasenv-with-no-id";
                        if (this.aasenv.AdministrationShells.Count > 0)
                        {
                            frn = this.aasenv.AdministrationShells[0].GetFriendlyName() ?? frn;
                        }
                        var aas_spec_fn = "/aasx/#/#.aas";
                        if (prefFmt == PreferredFormat.Json)
                        {
                            aas_spec_fn += ".json";
                        }
                        else
                        {
                            aas_spec_fn += ".xml";
                        }
                        aas_spec_fn = aas_spec_fn.Replace("#", "" + frn);
                        specPart    = package.CreatePart(new Uri(aas_spec_fn, UriKind.RelativeOrAbsolute), System.Net.Mime.MediaTypeNames.Text.Xml, CompressionOption.Maximum);
                        originPart.CreateRelationship(specPart.Uri, TargetMode.Internal, "http://www.admin-shell.io/aasx/relationships/aas-spec");
                    }

                    // now, specPart shall be != null!
                    if (specPart.Uri.ToString().ToLower().Trim().EndsWith("json"))
                    {
                        using (var s = specPart.GetStream(FileMode.Create))
                        {
                            JsonSerializer serializer = new JsonSerializer();
                            serializer.NullValueHandling     = NullValueHandling.Ignore;
                            serializer.ReferenceLoopHandling = ReferenceLoopHandling.Serialize;
                            serializer.Formatting            = Newtonsoft.Json.Formatting.Indented;
                            using (var sw = new StreamWriter(s))
                            {
                                using (JsonWriter writer = new JsonTextWriter(sw))
                                {
                                    serializer.Serialize(writer, this.aasenv);
                                }
                            }
                        }
                    }
                    else
                    {
                        using (var s = specPart.GetStream(FileMode.Create))
                        {
                            var serializer = new XmlSerializer(typeof(AdminShell.AdministrationShellEnv));
                            var nss        = new XmlSerializerNamespaces();
                            nss.Add("xsi", System.Xml.Schema.XmlSchema.InstanceNamespace);
                            nss.Add("aas", "http://www.admin-shell.io/aas/2/0");
                            nss.Add("IEC61360", "http://www.admin-shell.io/IEC61360/2/0");
                            serializer.Serialize(s, this.aasenv, nss);
                        }
                    }

                    // there might be pending files to be deleted (first delete, then add, in case of identical files in both categories)
                    foreach (var psfDel in pendingFilesToDelete)
                    {
                        // try find an existing part for that file ..
                        var found = false;

                        // normal files
                        xs = specPart.GetRelationshipsByType("http://www.admin-shell.io/aasx/relationships/aas-suppl");
                        foreach (var x in xs)
                        {
                            if (x.TargetUri == psfDel.uri)
                            {
                                // try to delete
                                specPart.DeleteRelationship(x.Id);
                                package.DeletePart(psfDel.uri);
                                found = true;
                                break;
                            }
                        }

                        // thumbnails
                        xs = package.GetRelationshipsByType("http://schemas.openxmlformats.org/package/2006/relationships/metadata/thumbnail");
                        foreach (var x in xs)
                        {
                            if (x.TargetUri == psfDel.uri)
                            {
                                // try to delete
                                package.DeleteRelationship(x.Id);
                                package.DeletePart(psfDel.uri);
                                found = true;
                                break;
                            }
                        }

                        if (!found)
                        {
                            throw (new Exception($"Not able to delete pending file {psfDel.uri} in saving package {fn}"));
                        }
                    }

                    // after this, there are no more pending for delete files
                    pendingFilesToDelete.Clear();

                    // write pending supplementary files
                    foreach (var psfAdd in pendingFilesToAdd)
                    {
                        // make sure ..
                        if ((psfAdd.sourceLocalPath == null && psfAdd.sourceGetBytesDel == null) || psfAdd.location != AdminShellPackageSupplementaryFile.LocationType.AddPending)
                        {
                            continue;
                        }

                        // normal file?
                        if (psfAdd.specialHandling == AdminShellPackageSupplementaryFile.SpecialHandlingType.None ||
                            psfAdd.specialHandling == AdminShellPackageSupplementaryFile.SpecialHandlingType.EmbedAsThumbnail)
                        {
                            // try find an existing part for that file ..
                            PackagePart filePart = null;
                            if (psfAdd.specialHandling == AdminShellPackageSupplementaryFile.SpecialHandlingType.None)
                            {
                                xs = specPart.GetRelationshipsByType("http://www.admin-shell.io/aasx/relationships/aas-suppl");
                                foreach (var x in xs)
                                {
                                    if (x.TargetUri == psfAdd.uri)
                                    {
                                        filePart = package.GetPart(x.TargetUri);
                                        break;
                                    }
                                }
                            }
                            if (psfAdd.specialHandling == AdminShellPackageSupplementaryFile.SpecialHandlingType.EmbedAsThumbnail)
                            {
                                xs = package.GetRelationshipsByType("http://schemas.openxmlformats.org/package/2006/relationships/metadata/thumbnail");
                                foreach (var x in xs)
                                {
                                    if (x.SourceUri.ToString() == "/" && x.TargetUri == psfAdd.uri)
                                    {
                                        filePart = package.GetPart(x.TargetUri);
                                        break;
                                    }
                                }
                            }

                            if (filePart == null)
                            {
                                // determine mimeType
                                var mimeType = psfAdd.useMimeType;
                                // reconcile mime
                                if (mimeType == null && psfAdd.sourceLocalPath != null)
                                {
                                    mimeType = AdminShellPackageEnv.GuessMimeType(psfAdd.sourceLocalPath);
                                }
                                // still null?
                                if (mimeType == null)
                                {
                                    // see: https://stackoverflow.com/questions/6783921/which-mime-type-to-use-for-a-binary-file-thats-specific-to-my-program
                                    mimeType = "application/octet-stream";
                                }

                                // create new part and link
                                filePart = package.CreatePart(psfAdd.uri, mimeType, CompressionOption.Maximum);
                                if (psfAdd.specialHandling == AdminShellPackageSupplementaryFile.SpecialHandlingType.None)
                                {
                                    specPart.CreateRelationship(filePart.Uri, TargetMode.Internal, "http://www.admin-shell.io/aasx/relationships/aas-suppl");
                                }
                                if (psfAdd.specialHandling == AdminShellPackageSupplementaryFile.SpecialHandlingType.EmbedAsThumbnail)
                                {
                                    package.CreateRelationship(filePart.Uri, TargetMode.Internal, "http://schemas.openxmlformats.org/package/2006/relationships/metadata/thumbnail");
                                }
                            }

                            // now should be able to write
                            using (var s = filePart.GetStream(FileMode.Create))
                            {
                                if (psfAdd.sourceLocalPath != null)
                                {
                                    var bytes = System.IO.File.ReadAllBytes(psfAdd.sourceLocalPath);
                                    s.Write(bytes, 0, bytes.Length);
                                }

                                if (psfAdd.sourceGetBytesDel != null)
                                {
                                    var bytes = psfAdd.sourceGetBytesDel();
                                    if (bytes != null)
                                    {
                                        s.Write(bytes, 0, bytes.Length);
                                    }
                                }
                            }
                        }
                    }

                    // after this, there are no more pending for add files
                    pendingFilesToAdd.Clear();

                    // flush and close
                    package.Flush();
                    this.openPackage = null;
                    package.Close();

                    // if in temp fn, close the package, copy to original fn, re-open the package
                    if (this.tempFn != null)
                    {
                        try
                        {
                            package.Close();
                            System.IO.File.Copy(this.tempFn, this.fn, overwrite: true);
                            this.openPackage = Package.Open(this.tempFn, FileMode.OpenOrCreate);
                        }
                        catch (Exception ex)
                        {
                            throw (new Exception(string.Format("While write AASX {0} indirectly at {1} gave: {2}", fn, AdminShellUtil.ShortLocation(ex), ex.Message)));
                        }
                    }
                }
                catch (Exception ex)
                {
                    throw (new Exception(string.Format("While write AASX {0} at {1} gave: {2}", fn, AdminShellUtil.ShortLocation(ex), ex.Message)));
                }
                return(true);
            }

            // Don't know to handle
            throw (new Exception(string.Format($"Not able to handle {fn}.")));
        }
        //Annotations
        //  Procedure:
        //  1. find submodel node
        //  2. create submodel node as submodel
        //  3. find children of submodel node
        //  4. create children of submodel node -> a (SubmodelElement)
        //      4.1. find children of a
        //      4.2. create children of a -> b (SubmodelElement)
        //          4.2.1. find children of b
        //          ...
        //      4.3. set a as SubmodelElement of submodel
        //  5. add Submodel
        //
        //
        //  most Methods are built the same way:
        //  1. iterate through all References of the node
        //  2. check that the ReferenceType is not HasTypeDefinition
        //  3. check for the Type or BrowseName

        public static AdminShellNS.AdminShellPackageEnv Import(UANodeSet model)
        {
            thePackageEnv    = new AdminShellNS.AdminShellPackageEnv();
            InformationModel = model;

            //Initialize everything needed
            AdminShell.AdministrationShellEnv env = thePackageEnv.AasEnv;
            var aas = new AdminShell.AdministrationShell();

            aas.views       = new Views();
            aas.views.views = new List <View>();
            env.AdministrationShells.Add(aas);

            //search for the root Node
            var root = getRoot();

            //see Annotations
            if (root != null)
            {
                foreach (Reference _ref in root.References)
                {
                    if (_ref.ReferenceType == "HasComponent")
                    {
                        var node = findNode(_ref.Value);
                        //create Submodel
                        if (getTypeDefinition(node) == "1:AASSubmodelType")
                        {
                            var submodel = createSubmodel((UAObject)node);

                            if (submodel != null)
                            {
                                //add Submodel and its SubmodelRef
                                env.Submodels.Add(submodel);
                                var smr = new AdminShell.SubmodelRef();
                                smr.Keys.Add(
                                    new AdminShell.Key(
                                        "Submodel", true, submodel.identification.idType, submodel.identification.id));
                                aas.submodelRefs.Add(smr);
                            }
                        }
                        //create ConceptDictionary
                        else if (getTypeDefinition(node) == "1:AASConceptDictionaryType")
                        {
                            createConceptDictionary((UAObject)node);
                        }
                        //create Asset
                        else if (getTypeDefinition(node) == "1:AASAssetType")
                        {
                            Asset ass = createAsset(node);
                            thePackageEnv.AasEnv.Assets.Add(ass);
                        }
                        //create Views
                        else if (getTypeDefinition(node) == "1:AASViewType")
                        {
                            aas.views.views.Add(createView(node));
                        }
                        //set DerivedFrom
                        else if (node.BrowseName == "1:DerivedFrom")
                        {
                            List <Key> keys = addSemanticID(node);
                            if (keys.Count > 0)
                            {
                                aas.derivedFrom = new AssetAdministrationShellRef(keys[0]);
                            }
                        }
                        //create HasDataSpecification
                        else if (node.BrowseName == "1:DataSpecification")
                        {
                            aas.hasDataSpecification = CreateHasDataSpecification(node);
                        }
                        //create AssetRef
                        else if (node.BrowseName == "1:AssetRef")
                        {
                            aas.assetRef = createAssetRef(node);
                        }
                        else if (node.BrowseName == "1:Identification" &&
                                 getTypeDefinition(node) == "1:AASIdentifierType")
                        {
                            aas.identification = createIdentification(node);
                        }
                    }
                    else if (_ref.ReferenceType == "HasProperty")
                    {
                        var node = findNode(_ref.Value);
                        if (node.BrowseName == "1:idShort")
                        {
                            var vari = (UAVariable)node;
                            aas.idShort = vari.Value.InnerText;
                        }
                    }
                }
            }

            return(thePackageEnv);
        }