public bool LoadFromAasEnvString(string content) { try { using (var file = new StringReader(content)) { // TODO (Michael Hoffmeister, 2020-08-01): use a unified function to create a serializer JsonSerializer serializer = new JsonSerializer(); serializer.Converters.Add(new AdminShellConverters.JsonAasxConverter("modelType", "name")); this.aasenv = (AdminShell.AdministrationShellEnv)serializer.Deserialize( file, typeof(AdminShell.AdministrationShellEnv)); } } catch (Exception ex) { throw (new Exception( string.Format("While reading AASENV string {0} gave: {1}", AdminShellUtil.ShortLocation(ex), ex.Message))); } return(true); }
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}."))); }
public bool Load(string fn, bool indirectLoadSave = false) { this.fn = fn; if (this.openPackage != null) { this.openPackage.Close(); } this.openPackage = null; if (fn.ToLower().EndsWith(".xml")) { // load only XML try { var reader = new StreamReader(fn); // TODO: use aasenv serialzers here! this.aasenv = AdminShellSerializationHelper.DeserializeXmlFromStreamWithCompat(reader.BaseStream); if (this.aasenv == null) { throw (new Exception("Type error for XML file!")); } reader.Close(); } catch (Exception ex) { throw (new Exception(string.Format("While reading AAS {0} at {1} gave: {2}", fn, AdminShellUtil.ShortLocation(ex), ex.Message))); } return(true); } if (fn.ToLower().EndsWith(".json")) { // load only JSON try { using (StreamReader file = System.IO.File.OpenText(fn)) { // TODO: use aasenv serialzers here! JsonSerializer serializer = new JsonSerializer(); serializer.Converters.Add(new AdminShellConverters.JsonAasxConverter("modelType", "name")); this.aasenv = (AdminShell.AdministrationShellEnv)serializer.Deserialize(file, typeof(AdminShell.AdministrationShellEnv)); } } catch (Exception ex) { throw (new Exception(string.Format("While reading AAS {0} at {1} gave: {2}", fn, AdminShellUtil.ShortLocation(ex), ex.Message))); } return(true); } if (fn.ToLower().EndsWith(".aasx")) { var fnToLoad = fn; this.tempFn = null; if (indirectLoadSave) { try { this.tempFn = System.IO.Path.GetTempFileName().Replace(".tmp", ".aasx"); System.IO.File.Copy(fn, this.tempFn); fnToLoad = this.tempFn; } catch (Exception ex) { throw (new Exception(string.Format("While copying AASX {0} for indirect load at {1} gave: {2}", fn, AdminShellUtil.ShortLocation(ex), ex.Message))); } } string nsuri = ""; // for (int loop = 0; loop < 2; loop++) for (int loop = 1; loop < 2; loop++) { // load package AASX try { Package package = null; switch (loop) { case 0: package = Package.Open(fnToLoad, FileMode.Open); break; case 1: package = Package.Open(fnToLoad, FileMode.Open, FileAccess.Read, FileShare.Read); break; } // 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) { throw (new Exception("Unable to find AASX origin. Aborting!")); } // get the specs from the package PackagePart specPart = null; xs = originPart.GetRelationshipsByType("http://www.admin-shell.io/aasx/relationships/aas-spec"); foreach (var x in xs) { specPart = package.GetPart(x.TargetUri); break; } if (specPart == null) { throw (new Exception("Unable to find AASX spec(s). Aborting!")); } // open spec part to read try { if (specPart.Uri.ToString().ToLower().Trim().EndsWith("json")) { using (var s = specPart.GetStream(FileMode.Open)) { using (StreamReader file = new StreamReader(s)) { JsonSerializer serializer = new JsonSerializer(); serializer.Converters.Add(new AdminShellConverters.JsonAasxConverter("modelType", "name")); this.aasenv = (AdminShell.AdministrationShellEnv)serializer.Deserialize(file, typeof(AdminShell.AdministrationShellEnv)); file.Close(); } s.Close(); } loop = 2; } else { // using (var s = specPart.GetStream(FileMode.Open)) var s = specPart.GetStream(FileMode.Open); { // own catch loop to be more specific if (loop == 0) { nsuri = AdminShellSerializationHelper.TryReadXmlFirstElementNamespaceURI(s); s.Close(); package.Close(); continue; } // neu nsuri = AdminShellSerializationHelper.TryReadXmlFirstElementNamespaceURI(s); s.Close(); s = specPart.GetStream(FileMode.Open, FileAccess.Read); // read V1.0? if (nsuri != null && nsuri.Trim() == "http://www.admin-shell.io/aas/1/0") { #if UseAasxCompatibilityModels XmlSerializer serializer = new XmlSerializer(typeof(AasxCompatibilityModels.AdminShellV10.AdministrationShellEnv), "http://www.admin-shell.io/aas/1/0"); var v10 = serializer.Deserialize(s) as AasxCompatibilityModels.AdminShellV10.AdministrationShellEnv; this.aasenv = new AdminShellV20.AdministrationShellEnv(v10); #else throw (new Exception("Cannot handle AAS file format http://www.admin-shell.io/aas/1/0 !")); #endif } // read V2.0? if (nsuri != null && nsuri.Trim() == "http://www.admin-shell.io/aas/2/0") { XmlSerializer serializer = new XmlSerializer(typeof(AdminShell.AdministrationShellEnv), "http://www.admin-shell.io/aas/2/0"); this.aasenv = serializer.Deserialize(s) as AdminShell.AdministrationShellEnv; } this.openPackage = package; if (this.aasenv == null) { throw (new Exception("Type error for XML file!")); } s.Close(); } } } catch (Exception ex) { throw (new Exception(string.Format("While reading AAS {0} spec at {1} gave: {2}", fn, AdminShellUtil.ShortLocation(ex), ex.Message))); } // Package must not close to read e.g. thumbnails //// package.Close(); } catch (Exception ex) { throw (new Exception(string.Format("While reading 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}."))); }
public bool Load(string fn, bool indirectLoadSave = false) { this.fn = fn; if (this.openPackage != null) { this.openPackage.Close(); } this.openPackage = null; if (fn.ToLower().EndsWith(".xml")) { // load only XML try { var reader = new StreamReader(fn); this.aasenv = AdminShellSerializationHelper.DeserializeXmlFromStreamWithCompat(reader.BaseStream); if (this.aasenv == null) { throw (new Exception("Type error for XML file!")); } reader.Close(); } catch (Exception ex) { throw (new Exception( string.Format("While reading AAS {0} at {1} gave: {2}", fn, AdminShellUtil.ShortLocation(ex), ex.Message))); } return(true); } if (fn.ToLower().EndsWith(".json")) { // load only JSON try { using (StreamReader file = System.IO.File.OpenText(fn)) { // TODO (Michael Hoffmeister, 2020-08-01): use a unified function to create a serializer JsonSerializer serializer = new JsonSerializer(); serializer.Converters.Add(new AdminShellConverters.JsonAasxConverter("modelType", "name")); this.aasenv = (AdminShell.AdministrationShellEnv)serializer.Deserialize( file, typeof(AdminShell.AdministrationShellEnv)); } } catch (Exception ex) { throw (new Exception( string.Format("While reading AAS {0} at {1} gave: {2}", fn, AdminShellUtil.ShortLocation(ex), ex.Message))); } return(true); } if (fn.ToLower().EndsWith(".aasx")) { var fnToLoad = fn; this.tempFn = null; if (indirectLoadSave) { try { this.tempFn = System.IO.Path.GetTempFileName().Replace(".tmp", ".aasx"); System.IO.File.Copy(fn, this.tempFn); fnToLoad = this.tempFn; } catch (Exception ex) { throw (new Exception( string.Format("While copying AASX {0} for indirect load at {1} gave: {2}", fn, AdminShellUtil.ShortLocation(ex), ex.Message))); } } // load package AASX try { var package = Package.Open(fnToLoad, FileMode.Open); // 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) { throw (new Exception("Unable to find AASX origin. Aborting!")); } // get the specs from the package PackagePart specPart = null; xs = originPart.GetRelationshipsByType("http://www.admin-shell.io/aasx/relationships/aas-spec"); foreach (var x in xs) { specPart = package.GetPart(x.TargetUri); break; } if (specPart == null) { throw (new Exception("Unable to find AASX spec(s). Aborting!")); } // open spec part to read try { if (specPart.Uri.ToString().ToLower().Trim().EndsWith("json")) { using (var s = specPart.GetStream(FileMode.Open)) { using (StreamReader file = new StreamReader(s)) { JsonSerializer serializer = new JsonSerializer(); serializer.Converters.Add( new AdminShellConverters.JsonAasxConverter("modelType", "name")); this.aasenv = (AdminShell.AdministrationShellEnv)serializer.Deserialize( file, typeof(AdminShell.AdministrationShellEnv)); } } } else { using (var s = specPart.GetStream(FileMode.Open)) { // own catch loop to be more specific this.aasenv = AdminShellSerializationHelper.DeserializeXmlFromStreamWithCompat(s); this.openPackage = package; if (this.aasenv == null) { throw (new Exception("Type error for XML file!")); } s.Close(); } } } catch (Exception ex) { throw (new Exception( string.Format("While reading AAS {0} spec at {1} gave: {2}", fn, AdminShellUtil.ShortLocation(ex), ex.Message))); } } catch (Exception ex) { throw (new Exception( string.Format("While reading 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}."))); }