CernerFhirController.cs 18 KB

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Web.Http;
using System.Xml;
using ADAM.CernerFHIR.Client;
using ADAM.CernerFHIR.Helper;
using ADAM.CernerFHIR.Model;
using AIAHTML5.API.Models;
using HtmlAgilityPack;
using Newtonsoft.Json.Linq;

namespace AIAHTML5.API.Controllers
{
    public class CernerFhirController : ApiController
    {
        // GET api/<controller>
        public IEnumerable<string> Get()
        {
            return new string[] { "value1", "value2" };
        }

        // GET api/<controller>/5
        public string Get(int id)
        {
            return "value";
        }

        // POST api/<controller>
        public HttpResponseMessage Post([FromBody]JObject cernerimageAIA)
        {
            HttpResponseMessage response = null;

            string json = Newtonsoft.Json.JsonConvert.SerializeObject(cernerimageAIA);

            var Base64ImageData = cernerimageAIA["data"].Value<string>();
            var Base64ImageName = cernerimageAIA["name"].Value<string>();
            var Base64ImageBlob = cernerimageAIA["blob"].Value<object>();
            var Base64ImageInfo = cernerimageAIA["imageInfo"].Value<object>();
            var Base64ImageInfoJson = cernerimageAIA["imageInfoJson"].Value<object>();
            var CernerUserSessionId = cernerimageAIA["CernerUserSessionId"].Value<string>();

            dynamic CernerAIAImageInfo = new {
                Data = Base64ImageData,
                Name = Base64ImageName,
                Blob = Base64ImageBlob,
                Info = Base64ImageInfo,
                infoJson = Base64ImageInfoJson,
                SessionId = CernerUserSessionId
            };
            
            // Upload data to cerner Fhir resource server
            UploadDocumentToCerner(CernerAIAImageInfo);

            response = new HttpResponseMessage { StatusCode = HttpStatusCode.OK, Content = null };
            return response;
        }

        // PUT api/<controller>/5
        public void Put(int id, [FromBody]string value)
        {
        }

        // DELETE api/<controller>/5
        public void Delete(int id)
        {
        }


        #region Cerner fhir resource call

        [NonAction]
        public void UploadDocumentToCerner(dynamic CernerAIAImageInfo)
        {
            var ImageHtmlTag = ConvertToImageHtmlTag(CernerAIAImageInfo.Data);
            var ImageName = CernerAIAImageInfo.Name.Split('.')[0];
            var finalHtml = CreateXHtml(ImageHtmlTag, ImageName);

            finalHtml = AddSelfClosingTags(finalHtml);

            //... Convert to rtf document.(Only applying inline styles to html, not really converting to rtf)
            //finalHtml = ConvertHtmlToText(finalHtml);// ConvertToRtfDocument(finalHtml);

            var base64EncodeHtmlData = Base64Encode(finalHtml);
            string[] PidGids = {"","", ImageName };
            //var VocabCode = new List<MedicalVocabulary>();
            var db = new DBModel();
            var CernerFhirSessionInfo = db.GetCernerFhirSessionInfo(CernerAIAImageInfo.SessionId);
            var loginResult = (LoginResult)CernerFhirSessionInfo.LoginResult;
            var cernerInfoJWT = (CernerInfoJWT)CernerFhirSessionInfo.CernerInfoJWT;

            var documentPath = Path.Combine(System.Web.Hosting.HostingEnvironment.ApplicationPhysicalPath, "Content", "DocumentReference.txt");
            string documentFormat = File.ReadAllText(documentPath);
            
            var AsyncTask = AsyncToSyncTaskHelper.AsyncHelpers.RunSync<string>(() => ADAM.CernerFHIR.Client.DocumentReferenceResource.PostDocumentReferenceAsync(base64EncodeHtmlData, PidGids, null, loginResult, cernerInfoJWT, documentFormat));
            var DocumentId = AsyncTask.Split(',')[1];
            
            var AIAImageInfo = new CernerUserImageAIA
            {
                DocumentId = DocumentId,
                JsonData = CernerAIAImageInfo.infoJson.ToString(),
                PatientId = cernerInfoJWT.PatientId,
                Encounter = cernerInfoJWT.Encounter,
                Code = CernerFhirSessionInfo.CernerCode
            };
            // save this DocumentId with the Json data to AIA database.
            //Create a object.
            db.SaveAIAImageIdWithJsondataForCerner(AIAImageInfo);
            
        }

        private string ConvertToImageHtmlTag(string AIAImageDataURL)
        {
            return $"<div><img src=\"{AIAImageDataURL}\"/></div>";
        }

        private string CreateXHtml(string rawhtml, string title)
        {
            var meta = "<meta http-equiv=\"x-ua-compatible\" content=\"IE=edge\"/>";

            StringWriter s = new StringWriter();
            s.WriteLine("{0}", "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">");
            s.WriteLine("{0}", "<html lang=\"en\" xmlns:adam=\"urn:DataProcessor\" xmlns:ax=\"http://www.adam.com\" xmlns:exsl=\"http://exslt.org/common\">");
            s.WriteLine("{0}", meta);
            s.WriteLine("{0}", "<head>");
            s.WriteLine("<title>{0}</title>", title);
            s.WriteLine("{0}", "</head>");
            s.WriteLine("{0}", "<body>");
            s.WriteLine("{0}", rawhtml);
            s.WriteLine("{0}", "</body>");
            s.WriteLine("{0}", "</html>");

            return s.ToString();
        }

        private string AddSelfClosingTags(string html)
        {
            string res = string.Empty;

            HtmlDocument doc = new HtmlDocument();
            doc.LoadHtml(html);
            doc.DocumentNode.Descendants("script").ToList().ForEach(x => { x.Remove(); });

            //Change all img instance src to Base64.
            doc.DocumentNode.Descendants("img")
                                        .Where(e =>
                                        {
                                            string src = e.GetAttributeValue("src", null) ?? "";
                                            return !string.IsNullOrEmpty(src);
                                        })
                                        .ToList()
                                        .ForEach(x =>
                                        {
                                            //if (!(x.OuterHtml.Contains("ftradamlogo")))
                                            x.SetAttributeValue("style", "max-width:800px;");

                                            //string currentSrcValue = x.GetAttributeValue("src", null);
                                            //currentSrcValue = currentSrcValue.Replace("../..", baseUrl);
                                            //var imageBase64Data = ConvertImageURLToBase64(currentSrcValue);

                                            //x.SetAttributeValue("src", "data:image/jpeg;base64," + imageBase64Data);
                                        });

            StringWriter sw = new StringWriter();
            XmlTextWriter xw = new XmlTextWriter(sw);
            doc.Save(xw);

            return res = sw.ToString();
        }

        private static string ConvertHtmlToText(string source)
        {

            string result;

            // Remove HTML Development formatting
            // Replace line breaks with space
            // because browsers inserts space
            result = source.Replace("\r", " ");
            // Replace line breaks with space
            // because browsers inserts space
            result = result.Replace("\n", " ");
            // Remove step-formatting
            result = result.Replace("\t", string.Empty);
            // Remove repeating speces becuase browsers ignore them
            result = System.Text.RegularExpressions.Regex.Replace(result,
                                                                  @"( )+", " ");

            // Remove the header (prepare first by clearing attributes)
            result = System.Text.RegularExpressions.Regex.Replace(result,
                     @"<( )*head([^>])*>", "<head>",
                     System.Text.RegularExpressions.RegexOptions.IgnoreCase);
            result = System.Text.RegularExpressions.Regex.Replace(result,
                     @"(<( )*(/)( )*head( )*>)", "</head>",
                     System.Text.RegularExpressions.RegexOptions.IgnoreCase);
            result = System.Text.RegularExpressions.Regex.Replace(result,
                     "(<head>).*(</head>)", string.Empty,
                     System.Text.RegularExpressions.RegexOptions.IgnoreCase);

            // remove all scripts (prepare first by clearing attributes)
            result = System.Text.RegularExpressions.Regex.Replace(result,
                     @"<( )*script([^>])*>", "<script>",
                     System.Text.RegularExpressions.RegexOptions.IgnoreCase);
            result = System.Text.RegularExpressions.Regex.Replace(result,
                     @"(<( )*(/)( )*script( )*>)", "</script>",
                     System.Text.RegularExpressions.RegexOptions.IgnoreCase);
            //result = System.Text.RegularExpressions.Regex.Replace(result, 
            //         @"(<script>)([^(<script>\.</script>)])*(</script>)",
            //         string.Empty, 
            //         System.Text.RegularExpressions.RegexOptions.IgnoreCase);
            result = System.Text.RegularExpressions.Regex.Replace(result,
                     @"(<script>).*(</script>)", string.Empty,
                     System.Text.RegularExpressions.RegexOptions.IgnoreCase);

            // remove all styles (prepare first by clearing attributes)
            result = System.Text.RegularExpressions.Regex.Replace(result,
                     @"<( )*style([^>])*>", "<style>",
                     System.Text.RegularExpressions.RegexOptions.IgnoreCase);
            result = System.Text.RegularExpressions.Regex.Replace(result,
                     @"(<( )*(/)( )*style( )*>)", "</style>",
                     System.Text.RegularExpressions.RegexOptions.IgnoreCase);
            result = System.Text.RegularExpressions.Regex.Replace(result,
                     "(<style>).*(</style>)", string.Empty,
                     System.Text.RegularExpressions.RegexOptions.IgnoreCase);

            // insert tabs in spaces of <td> tags
            result = System.Text.RegularExpressions.Regex.Replace(result,
                     @"<( )*td([^>])*>", "\t",
                     System.Text.RegularExpressions.RegexOptions.IgnoreCase);

            // insert line breaks in places of <BR> and <LI> tags
            result = System.Text.RegularExpressions.Regex.Replace(result,
                     @"<( )*br( )*>", "\r",
                     System.Text.RegularExpressions.RegexOptions.IgnoreCase);
            result = System.Text.RegularExpressions.Regex.Replace(result,
                     @"<( )*li( )*>", "\r",
                     System.Text.RegularExpressions.RegexOptions.IgnoreCase);

            // insert line paragraphs (double line breaks) in place
            // if <P>, <DIV> and <TR> tags
            result = System.Text.RegularExpressions.Regex.Replace(result,
                     @"<( )*div([^>])*>", "\r\r",
                     System.Text.RegularExpressions.RegexOptions.IgnoreCase);
            result = System.Text.RegularExpressions.Regex.Replace(result,
                     @"<( )*tr([^>])*>", "\r\r",
                     System.Text.RegularExpressions.RegexOptions.IgnoreCase);
            result = System.Text.RegularExpressions.Regex.Replace(result,
                     @"<( )*p([^>])*>", "\r\r",
                     System.Text.RegularExpressions.RegexOptions.IgnoreCase);

            // Remove remaining tags like <a>, links, images,
            // comments etc - anything thats enclosed inside < >
            result = System.Text.RegularExpressions.Regex.Replace(result,
                     @"<[^>]*>", string.Empty,
                     System.Text.RegularExpressions.RegexOptions.IgnoreCase);

            // replace special characters:
            result = System.Text.RegularExpressions.Regex.Replace(result,
                     @"&nbsp;", " ",
                     System.Text.RegularExpressions.RegexOptions.IgnoreCase);

            result = System.Text.RegularExpressions.Regex.Replace(result,
                     @"&bull;", " * ",
                     System.Text.RegularExpressions.RegexOptions.IgnoreCase);
            result = System.Text.RegularExpressions.Regex.Replace(result,
                     @"&lsaquo;", "<",
                     System.Text.RegularExpressions.RegexOptions.IgnoreCase);
            result = System.Text.RegularExpressions.Regex.Replace(result,
                     @"&rsaquo;", ">",
                     System.Text.RegularExpressions.RegexOptions.IgnoreCase);
            result = System.Text.RegularExpressions.Regex.Replace(result,
                     @"&trade;", "(tm)",
                     System.Text.RegularExpressions.RegexOptions.IgnoreCase);
            result = System.Text.RegularExpressions.Regex.Replace(result,
                     @"&frasl;", "/",
                     System.Text.RegularExpressions.RegexOptions.IgnoreCase);
            result = System.Text.RegularExpressions.Regex.Replace(result,
                     @"<", "<",
                     System.Text.RegularExpressions.RegexOptions.IgnoreCase);
            result = System.Text.RegularExpressions.Regex.Replace(result,
                     @">", ">",
                     System.Text.RegularExpressions.RegexOptions.IgnoreCase);
            result = System.Text.RegularExpressions.Regex.Replace(result,
                     @"&copy;", "(c)",
                     System.Text.RegularExpressions.RegexOptions.IgnoreCase);
            result = System.Text.RegularExpressions.Regex.Replace(result,
                     @"&reg;", "(r)",
                     System.Text.RegularExpressions.RegexOptions.IgnoreCase);
            // Remove all others. More can be added, see
            // http://hotwired.lycos.com/webmonkey/reference/special_characters/
            result = System.Text.RegularExpressions.Regex.Replace(result,
                     @"&(.{2,6});", string.Empty,
                     System.Text.RegularExpressions.RegexOptions.IgnoreCase);


            // make line breaking consistent
            result = result.Replace("\n", "\r");

            // Remove extra line breaks and tabs:
            // replace over 2 breaks with 2 and over 4 tabs with 4. 
            // Prepare first to remove any whitespaces inbetween
            // the escaped characters and remove redundant tabs inbetween linebreaks
            result = System.Text.RegularExpressions.Regex.Replace(result,
                     "(\r)( )+(\r)", "\r\r",
                     System.Text.RegularExpressions.RegexOptions.IgnoreCase);
            result = System.Text.RegularExpressions.Regex.Replace(result,
                     "(\t)( )+(\t)", "\t\t",
                     System.Text.RegularExpressions.RegexOptions.IgnoreCase);
            result = System.Text.RegularExpressions.Regex.Replace(result,
                     "(\t)( )+(\r)", "\t\r",
                     System.Text.RegularExpressions.RegexOptions.IgnoreCase);
            result = System.Text.RegularExpressions.Regex.Replace(result,
                     "(\r)( )+(\t)", "\r\t",
                     System.Text.RegularExpressions.RegexOptions.IgnoreCase);
            // Remove redundant tabs
            result = System.Text.RegularExpressions.Regex.Replace(result,
                     "(\r)(\t)+(\r)", "\r\r",
                     System.Text.RegularExpressions.RegexOptions.IgnoreCase);
            // Remove multible tabs followind a linebreak with just one tab
            result = System.Text.RegularExpressions.Regex.Replace(result,
                     "(\r)(\t)+", "\r\t",
                     System.Text.RegularExpressions.RegexOptions.IgnoreCase);
            // Initial replacement target string for linebreaks
            string breaks = "\r\r\r";
            // Initial replacement target string for tabs
            string tabs = "\t\t\t\t\t";
            for (int index = 0; index < result.Length; index++)
            {
                result = result.Replace(breaks, "\r\r");
                result = result.Replace(tabs, "\t\t\t\t");
                breaks = breaks + "\r";
                tabs = tabs + "\t";
            }

            // Thats it.
            return result;

        }

        private string Base64Encode(string plainText)
        {
            byte[] bytTemp = System.Text.Encoding.UTF8.GetBytes(plainText.ToString());
            return Convert.ToBase64String(bytTemp);
        }

        //private string ConvertImageURLToBase64(string url)
        //{
        //    StringBuilder _sb = new StringBuilder();

        //    Byte[] _byte = GetImage(url);

        //    if (_byte != null)
        //        _sb.Append(Convert.ToBase64String(_byte, 0, _byte.Length));

        //    return _sb.ToString();
        //}

        //private byte[] GetImage(string imageUrl)
        //{
        //    Stream stream = null;
        //    byte[] buf;

        //    try
        //    {
        //        System.Net.WebRequest req = System.Net.WebRequest.Create(imageUrl);
        //        System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls
        //                                                | (SecurityProtocolType)768
        //                                                | (SecurityProtocolType)3072
        //                                                | SecurityProtocolType.Ssl3;
        //        WebResponse webResponse = req.GetResponse();
        //        stream = webResponse.GetResponseStream();
        //        Encoding encode = Encoding.GetEncoding("utf-8");

        //        using (BinaryReader br = new BinaryReader(stream))
        //        {
        //            int len = (int)(webResponse.ContentLength);
        //            buf = br.ReadBytes(len);
        //            br.Close();
        //        }

        //        stream.Close();
        //        webResponse.Close();
        //    }
        //    catch (Exception exp)
        //    {
        //        buf = null;
        //    }

        //    return (buf);
        //}

        #endregion
    }
}