001package org.hl7.fhir.r5.renderers;
002
003import java.io.IOException;
004import java.nio.charset.Charset;
005import java.nio.charset.StandardCharsets;
006import java.util.ArrayList;
007import java.util.List;
008
009import org.hl7.fhir.r5.model.Binary;
010import org.hl7.fhir.utilities.TextFile;
011import org.hl7.fhir.utilities.Utilities;
012import org.hl7.fhir.utilities.xhtml.NodeType;
013import org.hl7.fhir.utilities.xhtml.XhtmlComposer;
014import org.hl7.fhir.utilities.xhtml.XhtmlNode;
015
016public class BinaryRenderer {
017
018  private String folder;
019  private List<String> filenames = new ArrayList<String>();
020
021  public BinaryRenderer(String folder) {
022    super();
023    this.folder = folder;
024  }
025
026  public String getFolder() {
027    return folder;
028  }
029
030  public List<String> getFilenames() {
031    return filenames;
032  }
033
034  public static String getBinContentAsString(Binary bin) {
035    // for now, assume UTF8. To do: extract character encoding from mime type if possible (charset)
036    return new String(bin.getContent(), StandardCharsets.UTF_8);
037  }
038
039  public String display(Binary bin) throws IOException {
040    XhtmlNode div = new XhtmlNode(NodeType.Element, "div");
041    render(div, bin);
042    return new XhtmlComposer(false, true).compose(div);
043  }
044  
045  
046  public void render(XhtmlNode x, Binary bin) throws IOException {
047    filenames.clear();
048    if (!bin.hasContentType()) {
049      error(x, "No Content Type");
050    } else if (bin.getContentType().startsWith("image/")) {
051      image(x, bin);
052    } else if (isXml(bin.getContentType())) {
053      xml(x, bin);
054    } else if (isJson(bin.getContentType())) {
055      json(x, bin);      
056    } else if (isTtl(bin.getContentType())) {
057      ttl(x, bin);      
058    } else if (isText(bin.getContentType())) {
059      text(x, bin);      
060    } else {
061      error(x, "The Content Type '"+bin.getContentType()+"' is not rendered in this context");
062    }
063  }
064
065
066  private void image(XhtmlNode x, Binary bin) throws IOException {
067    String ext = null;
068    if (bin.getContentType().startsWith("image/png")) {
069      ext = ".png";
070    } else if (bin.getContentType().startsWith("image/jpeg")) {
071      ext = ".jpg";
072    } else if (bin.getContentType().startsWith("image/gif")) {
073      ext = ".gif";
074    } else if (bin.getContentType().startsWith("image/svg")) {
075      ext = ".svg";
076    }
077    
078    if (ext == null) {
079      error(x, "The Image Type '"+bin.getContentType()+"' is not rendered in this context");
080    } else {
081      String fn = "Binary-Native-"+bin.getId()+ext;
082      TextFile.bytesToFile(bin.getContent(), Utilities.path(folder, fn));
083      filenames.add(fn);
084      x.img("Binary-Native-"+bin.getId()+ext);
085    }
086  }
087
088  private void error(XhtmlNode x, String message) {
089    x.tx("["+message+"]");
090  }
091
092  private boolean isXml(String ct) {
093    return ct.startsWith("text/xml") || ct.startsWith("application/xml") || ct.contains("+xml");
094  }
095
096  private void xml(XhtmlNode x, Binary bin) {
097    String content = "\r\n"+getBinContentAsString(bin);
098    XhtmlNode pre = x.pre("xml");
099    pre.code(content);    
100  }
101  
102  private boolean isJson(String ct) {
103    return ct.startsWith("text/json") || ct.startsWith("application/json") || ct.contains("+json");
104  }
105  
106  private void json(XhtmlNode x, Binary bin) {
107    String content = "\r\n"+getBinContentAsString(bin);
108    XhtmlNode pre = x.pre("json");
109    pre.code(content);    
110  }
111  
112  private boolean isTtl(String ct) {
113    return ct.startsWith("text/rdf") || ct.contains("+turtle");
114  }
115  
116  private void ttl(XhtmlNode x, Binary bin) {
117    String content = "\r\n"+getBinContentAsString(bin);
118    XhtmlNode pre = x.pre("rdf language-turtle");
119    pre.code(content);    
120  }
121  
122
123  private boolean isText(String ct) {
124    return ct.startsWith("text/");
125  }
126  
127  private void text(XhtmlNode x, Binary bin) {
128    String content = "\r\n"+getBinContentAsString(bin);
129    XhtmlNode pre = x.pre();
130    pre.code(content);    
131  }
132  
133
134}