Exemple #1
0
        /// <summary>
        /// Send a Bundle to a path on the server
        /// </summary>
        /// <param name="bundle">The contents of the Bundle to be sent</param>
        /// <param name="path">A path on the server to send the Bundle to</param>
        /// <returns>True if the bundle was successfully delivered, false otherwise</returns>
        /// <remarks>This method differs from Batch, in that it can be used to deliver a Bundle
        /// at the endpoint for messages, documents or binaries, instead of the batched update
        /// REST endpoint.</remarks>
        public bool DeliverBundle(Bundle bundle, string path)
        {
            if (Endpoint == null)
            {
                throw new InvalidOperationException("Endpoint must be provided using either the Endpoint property or the FhirClient constructor");
            }

            byte[] data;
            string contentType = ContentType.BuildContentType(PreferredFormat, false);

            if (PreferredFormat == ContentType.ResourceFormat.Json)
            {
                data = FhirSerializer.SerializeBundleToJsonBytes(bundle);
            }
            else if (PreferredFormat == ContentType.ResourceFormat.Xml)
            {
                data = FhirSerializer.SerializeBundleToXmlBytes(bundle);
            }
            else
            {
                throw new ArgumentException("Cannot encode a batch into format " + PreferredFormat.ToString());
            }

            var req = createRequest(Endpoint, true);

            req.Method      = "POST";
            req.ContentType = contentType;
            prepareRequest(req, data);

            return(doRequest(req, HttpStatusCode.OK, () => 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}.")));
        }