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