All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.hl7.fhir.r5.renderers.WebTemplateRenderer Maven / Gradle / Ivy

package org.hl7.fhir.r5.renderers;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.List;

import org.apache.commons.codec.binary.Base64;
import org.hl7.fhir.exceptions.DefinitionException;
import org.hl7.fhir.exceptions.FHIRException;
import org.hl7.fhir.exceptions.FHIRFormatError;
import org.hl7.fhir.r5.model.CanonicalResource;
import org.hl7.fhir.r5.model.Resource;
import org.hl7.fhir.r5.model.StructureDefinition;
import org.hl7.fhir.r5.model.ValueSet;
import org.hl7.fhir.r5.renderers.Renderer.RenderingStatus;
import org.hl7.fhir.r5.renderers.utils.RenderingContext;
import org.hl7.fhir.r5.renderers.utils.ResourceWrapper;
import org.hl7.fhir.r5.terminologies.utilities.ValidationResult;
import org.hl7.fhir.r5.renderers.utils.RenderingContext.GenerationRules;
import org.hl7.fhir.r5.renderers.utils.RenderingContext.KnownLinkType;
import org.hl7.fhir.r5.utils.EOperationOutcome;
import org.hl7.fhir.r5.utils.ToolingExtensions;
import org.hl7.fhir.r5.utils.UserDataNames;
import org.hl7.fhir.r5.utils.sql.Column;
import org.hl7.fhir.r5.utils.sql.ColumnKind;
import org.hl7.fhir.utilities.CommaSeparatedStringBuilder;
import org.hl7.fhir.utilities.MarkedToMoveToAdjunctPackage;
import org.hl7.fhir.utilities.Utilities;
import org.hl7.fhir.utilities.VersionUtilities;
import org.hl7.fhir.utilities.xhtml.HierarchicalTableGenerator;
import org.hl7.fhir.utilities.xhtml.NodeType;
import org.hl7.fhir.utilities.xhtml.XhtmlNode;
import org.hl7.fhir.utilities.xhtml.HierarchicalTableGenerator.Cell;
import org.hl7.fhir.utilities.xhtml.HierarchicalTableGenerator.Piece;
import org.hl7.fhir.utilities.xhtml.HierarchicalTableGenerator.Row;
import org.hl7.fhir.utilities.xhtml.HierarchicalTableGenerator.TableModel;
import org.hl7.fhir.utilities.xhtml.HierarchicalTableGenerator.Title;

@MarkedToMoveToAdjunctPackage
public class WebTemplateRenderer extends ResourceRenderer {
  
  public WebTemplateRenderer(RenderingContext context) { 
    super(context); 
  } 

  @Override
  public boolean renderingUsesValidation() {
    return true;
  }
  
  @Override
  public String buildSummary(ResourceWrapper r) throws UnsupportedEncodingException, IOException {
    return canonicalTitle(r);
  }

  @Override
  public void buildNarrative(RenderingStatus status, XhtmlNode x, ResourceWrapper wt) throws FHIRFormatError, DefinitionException, IOException, FHIRException, EOperationOutcome {
    renderResourceTechDetails(wt, x);

    HierarchicalTableGenerator gen = new HierarchicalTableGenerator(context, context.getDestDir(), context.isInlineGraphics(), true, ""); 
    TableModel model = gen.new TableModel("wt="+wt.getId(), context.getRules() == GenerationRules.IG_PUBLISHER);     
    model.setAlternating(true); 
    if (context.getRules() == GenerationRules.VALID_RESOURCE || context.isInlineGraphics()) { 
      model.setDocoImg(HierarchicalTableGenerator.help16AsData());     
    } else { 
      model.setDocoImg(Utilities.pathURL(context.getLink(KnownLinkType.SPEC), "help16.png")); 
    }  
    model.getTitles().add(gen.new Title(null, model.getDocoRef(), ("Name"), (context.formatPhrase(RenderingContext.QUEST_LINK)), null, 0)); 
    model.getTitles().add(gen.new Title(null, model.getDocoRef(), ("Card."), (context.formatPhrase(RenderingContext.QUEST_TEXTFOR)), null, 0)); 
    model.getTitles().add(gen.new Title(null, model.getDocoRef(), ("Definition"), (context.formatPhrase(RenderingContext.QUEST_TIMES)), null, 0)); 
    model.getTitles().add(gen.new Title(null, model.getDocoRef(), ("Type"), (context.formatPhrase(RenderingContext.QUEST_TIMES)), null, 0)); 
    model.getTitles().add(gen.new Title(null, model.getDocoRef(), ("Inputs"), (context.formatPhrase(RenderingContext.QUEST_TYPE_ITEM)), null, 0)); 
 
    // first we add a root for the WebTemplate itself 
    Row row = addItem(gen, model.getRows(), wt.child("tree")); 
//    for (ResourceWrapper select : vd.children("select")) { 
//      renderSelect(status, gen, row.getSubRows(), vd, select); 
//    } 
    XhtmlNode xn = gen.generate(model, context.getLocalPrefix(), 1, null); 
    x.addChildNode(xn); 
 
    
  } 

  private Row addItem(HierarchicalTableGenerator gen, List rows, ResourceWrapper item) {
    Row r = gen.new Row(); 
    rows.add(r); 

    r.setIcon("icon_vd_view.png", context.formatPhrase(RenderingContext.QUEST_ROOT)); 
    r.getCells().add(gen.new Cell(null, null, item.primitiveValue("name"), null, null)); 
    
    r.getCells().add(gen.new Cell(null, null, item.primitiveValue("min")+".."+("-1".equals(item.primitiveValue("max")) ? "*" : item.primitiveValue("max")), null, null));
    
    String def = (item.primitiveValue("archetype_id") != null ? item.primitiveValue("archetype_id")+"/" : "")+(item.primitiveValue("nodeId") != null ?item.primitiveValue("nodeId") : "");
    Cell cell = gen.new Cell(null, null, Utilities.noString(def) ? "--" : def, item.primitiveValue("aqlPath"), null);
    r.getCells().add(cell);
    addTermBindings(gen, cell, item);
    
    
    r.getCells().add(gen.new Cell(null, linkForType(item.primitiveValue("rmType")), item.primitiveValue("rmType"), null, null));
    
    cell = gen.new Cell(null, null, null, null, null);
    r.getCells().add(cell);
    boolean first = true;
    for (ResourceWrapper input : item.children("inputs")) {
      if (first) {
        first = false;
      } else {
        cell.getPieces().add(gen.new Piece("br"));
      }
      addInput(gen, cell, input);
    }
    
    
    for (ResourceWrapper child : item.children("children")) {
      addItem(gen, r.getSubRows(), child);
    }
    return r;     
  }

  private void addInput(HierarchicalTableGenerator gen, Cell cell, ResourceWrapper input) {
    if (input.has("suffix")) {
      cell.getPieces().add(gen.new Piece(null, input.primitiveValue("suffix"), null));
      cell.getPieces().add(gen.new Piece(null, " ", null));      
    }
    cell.getPieces().add(gen.new Piece(null, input.primitiveValue("type"), null).addStyle("font-weight: bold"));
    if (input.has("defaultValue")) {
      cell.getPieces().add(gen.new Piece(null, "(=", null));
      cell.getPieces().add(gen.new Piece(null, input.primitiveValue("defaultValue"), null));
      cell.getPieces().add(gen.new Piece(null, ")", null));
    }
    if (input.has("validation")) {
      addValidation(gen, cell, input.child("validation"));
    }
    if (input.has("list")) {
      addList(gen, cell, input.children("list"));
    }
  }

  private void addValidation(HierarchicalTableGenerator gen, Cell cell, ResourceWrapper validation) {
    cell.getPieces().add(gen.new Piece(null, ": ", null));
    
    if (validation.has("range") && !validation.has("precision")) {
      addRange(gen, cell, validation.child("range"));
    } else {
      boolean first = true;
      if (validation.has("range")) {
        cell.getPieces().add(gen.new Piece(null, "range: ", null));
        addRange(gen, cell, validation.child("range"));
        first = false;
      }        
      if (validation.has("precision")) {
        if (!first) {          
          cell.getPieces().add(gen.new Piece(null, "; ", null));
        }
        cell.getPieces().add(gen.new Piece(null, "precision: ", null));
        addRange(gen, cell, validation.child("precision"));
      }        
    }
  }

  private void addRange(HierarchicalTableGenerator gen, Cell cell, ResourceWrapper range) {
    String min = range.primitiveValue("min");
    String minOp = range.primitiveValue("minOp");
    String max = range.primitiveValue("max");
    String maxOp = range.primitiveValue("maxOp");
    String summ;
    if ("0".equals(min) && "0".equals(max)) {
      summ = "0";
    } else {
      summ = minOp+min;
      if (!Utilities.noString(max)) {
        summ = summ+","+maxOp+max;
      }
    } 
    cell.getPieces().add(gen.new Piece(null, summ, null));
    
  }

  private void addList(HierarchicalTableGenerator gen, Cell cell, List list) {
    for (ResourceWrapper item : list) {
      cell.getPieces().add(gen.new Piece("br"));
      cell.getPieces().add(gen.new Piece(null, "• ", null));
      cell.getPieces().add(gen.new Piece(null, item.primitiveValue("label"), item.primitiveValue("value")));      
    }
    
  }

  private void addTermBindings(HierarchicalTableGenerator gen, Cell cell, ResourceWrapper item) {
    for (ResourceWrapper tb : item.children("termBindings")) {
      String code = tb.primitiveValue("code");
      ResourceWrapper v = tb.child("value");
      String value = v.primitiveValue("value");
      if (value.contains("::")) {
        value = value.substring(value.indexOf("::")+2).replace("]", "");
      }
      String tid = v.primitiveValue("terminologyId");
      String pfx = "";
      String link = null;
      String hint = null;
      switch (code) {
      case "SNOMED-CT" : 
        pfx = "SCT:";
        link = getLinkForCode("http://snomed.info/sct", null, value);
        ValidationResult vr = context.getContext().validateCode(context.getTerminologyServiceOptions(), "http://snomed.info/sct", null, value, null);
        if (vr.isOk()) {
          hint = "SNOMED CT "+value+": "+vr.getDisplay();
        }
        break;
      case "LOINC" :
        pfx = "LN:";
        link = getLinkForCode("http://loinc.org", null, value);
        vr = context.getContext().validateCode(context.getTerminologyServiceOptions(), "http://loinc.org", null, value, null);
        if (vr.isOk()) {
          hint = "LOINC "+value+": "+vr.getDisplay();
        }
        break;
      case "LNC205" :
        // what is this?
        break;
      default: 
        System.out.println("?");
      }
      cell.addPiece(gen.new Piece(null, " ", null));
      cell.addPiece(gen.new Piece(link, pfx+value, hint));      
    }
  }

  private String linkForType(String t) {
    if (t == null) {
      return null;
    }
    StructureDefinition sd = context.getContext().fetchResource(StructureDefinition.class, "http://openehr.org/fhir/StructureDefinition/"+t);
    if (sd == null) {
      sd = context.getContext().fetchTypeDefinition(t);
    }
    if (sd != null) {
      return sd.getWebPath();
    }
    return null;
  }

  protected XhtmlNode renderResourceTechDetails(ResourceWrapper r, XhtmlNode x) throws UnsupportedEncodingException, FHIRException, IOException {
    return renderResourceTechDetails(r, x, (context.isContained() && r.getId() != null ? "#"+r.getId() : r.getId()));
  }
  
  protected XhtmlNode renderResourceTechDetails(ResourceWrapper r, XhtmlNode x, String desc) throws UnsupportedEncodingException, FHIRException, IOException {
    XhtmlNode p = x.para().attribute("class", "res-header-id");
    if (desc == null) { 
      p.b().tx(context.formatPhrase(context.isTechnicalMode() && !isInner() ? RenderingContext.PROF_DRIV_GEN_NARR_TECH : RenderingContext.PROF_DRIV_GEN_NARR, "WebTemplate", ""));      
    } else {
      p.b().tx(context.formatPhrase(context.isTechnicalMode() && !isInner() ? RenderingContext.PROF_DRIV_GEN_NARR_TECH : RenderingContext.PROF_DRIV_GEN_NARR, "WebTemplate", desc));
    }

    // first thing we do is lay down the resource anchors. 
    String tid = r.primitiveValue("templateId");
    if (!Utilities.noString(tid)) {
      String sid = "hc"+tid;
      if (!context.hasAnchor(sid)) {
        context.addAnchor(sid);
        x.an(context.prefixAnchor(sid));
      }
    }

    if (context.isTechnicalMode()) {
      RenderingStatus status = new RenderingStatus();

      String lang = r.primitiveValue("defaultLanguage"); 
      ResourceWrapper versionId = r.child("semver");

      if (lang != null || versionId != null) {
        XhtmlNode div = x.div().style("display: inline-block").style("background-color: #d9e0e7").style("padding: 6px")
            .style("margin: 4px").style("border: 1px solid #8da1b4")
            .style("border-radius: 5px").style("line-height: 60%");

        boolean sfirst = true;
        p = plateStyle(div.para());
        if (tid != null) {
          p.tx(context.formatPhrase(RenderingContext.RES_REND_TEMPLATE_ID, tid));
          sfirst = false;
        }
        if (versionId != null) {
          p.tx(context.formatPhrase(RenderingContext.RES_REND_VER, versionId.primitiveValue()));
          sfirst = false;
        }
        if (lang != null) {
          if (!sfirst) {
            p.tx("; ");
          }
          p.tx(context.formatPhrase(RenderingContext.RES_REND_LANGUAGE, lang));
          sfirst = false;
        }
      }
    }
    return null;
  }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy