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