001package org.hl7.fhir.r5.renderers;
002
003import java.io.IOException;
004import java.io.UnsupportedEncodingException;
005import java.util.List;
006
007import org.hl7.fhir.exceptions.DefinitionException;
008import org.hl7.fhir.exceptions.FHIRException;
009import org.hl7.fhir.exceptions.FHIRFormatError;
010import org.hl7.fhir.r5.model.StructureDefinition;
011import org.hl7.fhir.r5.renderers.utils.RenderingContext;
012import org.hl7.fhir.r5.renderers.utils.ResourceWrapper;
013import org.hl7.fhir.r5.utils.EOperationOutcome;
014
015import org.hl7.fhir.utilities.MarkedToMoveToAdjunctPackage;
016import org.hl7.fhir.utilities.xhtml.HierarchicalTableGenerator;
017import org.hl7.fhir.utilities.xhtml.NodeType;
018import org.hl7.fhir.utilities.xhtml.XhtmlNode;
019import org.hl7.fhir.utilities.xhtml.HierarchicalTableGenerator.Cell;
020import org.hl7.fhir.utilities.xhtml.HierarchicalTableGenerator.Piece;
021import org.hl7.fhir.utilities.xhtml.HierarchicalTableGenerator.Row;
022
023@MarkedToMoveToAdjunctPackage
024public class FeatureDefinitionRenderer extends ResourceRenderer {
025  
026  public FeatureDefinitionRenderer(RenderingContext context) { 
027    super(context); 
028  } 
029
030  @Override
031  public boolean renderingUsesValidation() {
032    return true;
033  }
034  
035  @Override
036  public String buildSummary(ResourceWrapper r) throws UnsupportedEncodingException, IOException {
037    return canonicalTitle(r);
038  }
039
040  @Override
041  public void buildNarrative(RenderingStatus status, XhtmlNode x, ResourceWrapper fd) throws FHIRFormatError, DefinitionException, IOException, FHIRException, EOperationOutcome {
042    renderResourceTechDetails(fd, x);
043    genSummaryTable(status, x, fd);
044    
045    XhtmlNode tbl = x.table("grid", false).markGenerated(!context.forValidResource());
046    
047    XhtmlNode td = tbl.tr().td();
048    td.tx("Feature ");
049    td.code().tx(fd.primitiveValue("url"));
050    
051    addMarkdown(tbl.tr().td(), fd.primitiveValue("description"));
052
053    td = tbl.tr().td();
054    td.b().tx("Type: ");    
055    td.tx(fd.primitiveValue("valueType"));
056    
057    td = tbl.tr().td();
058    td.b().tx("Contexts");
059    XhtmlNode ul = td.ul();
060    for (ResourceWrapper c : fd.children("context")) {
061      String url = c.primitiveValue();
062      var li = ul.li();
063      if (url.contains("#")) {
064        String type = url.substring(0, url.indexOf("#"));
065        String id = url.substring(url.indexOf("#")+1);
066        StructureDefinition sd = context.getContext().fetchTypeDefinition(type);
067        if (sd != null && sd.hasWebPath()) {
068          li.ah(sd.getWebPath()).tx(sd.present());
069        } else {
070          li.tx(url);
071        }
072        if (id != null) {
073          li.tx(" element ");
074          li.code().tx(id);
075        }
076      } else {
077        li.tx(url);
078      }
079    }
080    td = tbl.tr().td();
081    if (fd.has("qualifier")) {
082      td.b().tx("Qualifiers");
083
084      XhtmlNode tbl2 = td.table("lines", false).markGenerated(!context.forValidResource());
085      XhtmlNode tr = tbl2.tr();
086      tr.td().b().tx("Name");
087      tr.td().b().tx("Type");
088      tr.td().b().tx("Optional");
089      tr.td().b().tx("Description");
090      for (ResourceWrapper q : fd.children("qualifier")) {
091        tr = tbl2.tr();
092        tr.td().tx(q.primitiveValue("name"));
093        tr.td().tx(q.primitiveValue("valueType"));
094        tr.td().tx(q.primitiveValue("optional"));
095        tr.td().tx(q.primitiveValue("description"));
096        
097      }
098    } else {
099      td.tx("This feature doesn't have any qualifiers");
100    }
101
102  }
103
104  private void renderSelect(RenderingStatus status, HierarchicalTableGenerator gen, List<Row> rows, ResourceWrapper vd, ResourceWrapper select) {
105    Row r = gen.new Row(); 
106    rows.add(r); 
107    
108    r.setIcon("icon_vd_select.png", "Select"); 
109    Cell c1 = gen.new Cell(null, null, "Select", null, null); 
110    r.getCells().add(c1); 
111    r.getCells().add(gen.new Cell(null, null, null, null, null)); 
112    r.getCells().add(gen.new Cell(null, null, null, null, null));
113    Cell cell = gen.new Cell(null, null, null, null, null);
114    if (select.has("forEach")) {
115      addFHIRPath(cell.getPieces().get(0), "for each ", select.primitiveValue("forEach"), null);     
116    } else if (select.has("forEachOrNull")) {
117      addFHIRPath(cell.getPieces().get(0), "for each ", select.primitiveValue("forEachOrNull"), ", or null");        
118    } else {
119    }
120    r.getCells().add(cell);
121
122    for (ResourceWrapper column : select.children("column")) { 
123      renderColumn(status, gen, r.getSubRows(), vd, select, column); 
124    }      
125
126    for (ResourceWrapper child : select.children("select")) { 
127      renderSelect(status, gen, r.getSubRows(), vd, child); 
128    }      
129
130  }
131
132  private void renderColumn(RenderingStatus status, HierarchicalTableGenerator gen, List<Row> rows, ResourceWrapper vd, ResourceWrapper select, ResourceWrapper column) {
133    Row r = gen.new Row(); 
134    rows.add(r); 
135    
136    r.setIcon("icon_vd_col.png", "Column"); 
137    Cell c1 = gen.new Cell(null, null, column.primitiveValue("name"), null, null); 
138    r.getCells().add(c1); 
139    String coll = column.has("collection") ? "true".equals(column.primitiveValue("collection")) ? "Y" : "N" : "";
140    r.getCells().add(gen.new Cell(null, null, coll, null, null)); 
141    r.getCells().add(gen.new Cell(null, null, column.primitiveValue("type"), null, null));
142    Cell cell = gen.new Cell(null, null, null, null, null);
143    addFHIRPath(cell.getPieces().get(0), null, column.primitiveValue("path"), null); 
144    if (column.has("description")) {
145      cell.addPiece(gen.new Piece("br")); 
146      cell.addPiece(gen.new Piece(null, column.primitiveValue("description"), null)); 
147    }
148    for (ResourceWrapper tag : column.children("tag")) {
149      cell.addPiece(gen.new Piece("br")); 
150      cell.addPiece(gen.new Piece(null, tag.primitiveValue("name")+"="+tag.primitiveValue("value"), null)); 
151    }
152    r.getCells().add(cell);  
153  }
154
155  private void addFHIRPath(Piece p, String pfx, String expr, String sfx) {
156    XhtmlNode x = new XhtmlNode(NodeType.Element, "span").style("font-size: 11px"); 
157    p.addHtml(x); 
158    if (pfx != null) {
159      x.tx(pfx);
160    }
161    x.code(expr); 
162    if (sfx != null) {
163      x.tx(sfx);
164    }
165  }
166
167  private Row addViewRoot(HierarchicalTableGenerator gen, List<Row> rows, ResourceWrapper vd) throws IOException { 
168    Row r = gen.new Row(); 
169    rows.add(r); 
170
171    r.setIcon("icon_vd_view.png", context.formatPhrase(RenderingContext.QUEST_ROOT)); 
172    r.getCells().add(gen.new Cell(null, null, vd.primitiveValue("name"), null, null)); 
173    r.getCells().add(gen.new Cell(null, null, "", null, null)); 
174    r.getCells().add(gen.new Cell(null, null, vd.primitiveValue("resource"), null, null)); 
175    r.getCells().add(gen.new Cell(null, null, vd.primitiveValue("description"), null, null)); 
176    return r;     
177  } 
178
179}