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.ActorDefinition; 011import org.hl7.fhir.r5.model.CanonicalResource; 012import org.hl7.fhir.r5.model.CodeSystem; 013import org.hl7.fhir.r5.model.Library; 014import org.hl7.fhir.r5.model.Requirements; 015import org.hl7.fhir.r5.model.Requirements.RequirementsStatementComponent; 016import org.hl7.fhir.r5.model.Resource; 017import org.hl7.fhir.r5.renderers.utils.RenderingContext; 018import org.hl7.fhir.r5.renderers.utils.Resolver.ResourceWithReference; 019import org.hl7.fhir.r5.renderers.utils.ResourceWrapper; 020import org.hl7.fhir.r5.utils.EOperationOutcome; 021import org.hl7.fhir.utilities.Utilities; 022import org.hl7.fhir.utilities.xhtml.XhtmlNode; 023 024public class RequirementsRenderer extends ResourceRenderer { 025 026 public RequirementsRenderer(RenderingContext context) { 027 super(context); 028 } 029 030 @Override 031 public String buildSummary(ResourceWrapper r) throws UnsupportedEncodingException, IOException { 032 return canonicalTitle(r); 033 } 034 035 @Override 036 public void buildNarrative(RenderingStatus status, XhtmlNode x, ResourceWrapper req) throws FHIRFormatError, DefinitionException, IOException, FHIRException, EOperationOutcome { 037 renderResourceTechDetails(req, x); 038 genSummaryTable(status, x, (CanonicalResource) req.getResourceNative()); 039 040 if (req.has("actor")) { 041 List<ResourceWrapper> actors = req.children("actor"); 042 if (actors.size() == 1) { 043 ActorDefinition acd = context.getWorker().fetchResource(ActorDefinition.class, actors.get(0).primitiveValue(), req.getResourceNative()); 044 XhtmlNode p = x.para(); 045 p.tx(context.formatPhrase(RenderingContext.REQ_ACTOR)+" "); 046 renderCanonical(status, p, ActorDefinition.class, actors.get(0)); 047 } else { 048 x.para().tx(context.formatPhrase(RenderingContext.REQ_FOLLOWING_ACTOR)+" "); 049 XhtmlNode ul = x.ul(); 050 for (ResourceWrapper a : actors) { 051 renderCanonical(status, ul.li(), ActorDefinition.class, a); 052 } 053 } 054 } 055 if (req.has("derivedFrom")) { 056 List<ResourceWrapper> list = req.children("derivedFrom"); 057 if (list.size() == 1) { 058 XhtmlNode p = x.para(); 059 p.tx(context.formatPhrase(RenderingContext.REQ_DERIVE)+" "); 060 renderCanonical(status, p, Requirements.class, list.get(0)); 061 } else { 062 x.para().tx(context.formatPhrase(RenderingContext.REQ_FOLLOWING_REQ)+" "); 063 XhtmlNode ul = x.ul(); 064 for (ResourceWrapper a : list) { 065 renderCanonical(status, ul.li(), Requirements.class, a); 066 } 067 } 068 } 069 if (req.has("reference")) { 070 XhtmlNode p = x.para(); 071 p.tx(context.formatPhrase(RenderingContext.GENERAL_REFS)+" "); 072 int i = 0; 073 for (ResourceWrapper c : req.children("reference")) { 074 i++; 075 if (i>1) p.tx(", "); 076 String url = c.primitiveValue(); 077 if (url.contains("#")) { 078 url = url.substring(0, url.indexOf("#")); 079 } 080 p.ah(context.prefixLocalHref(c.primitiveValue())).tx(url); 081 } 082 } 083 XhtmlNode tbl = x.table("grid"); 084 085 for (ResourceWrapper stmt : req.children("statement")) { 086 XhtmlNode tr = tbl.tr(); 087 String lbl = stmt.has("label") ? stmt.primitiveValue("label") : stmt.primitiveValue("key"); 088 XhtmlNode td = tr.td(); 089 td.b().an(context.prefixAnchor(stmt.primitiveValue("key"))); 090 td.tx(lbl); 091 td = tr.td(); 092 boolean first = true; 093 CodeSystem cs = context.getWorker().fetchCodeSystem("http://hl7.org/fhir/conformance-expectation"); 094 for (ResourceWrapper t : stmt.children("conformance")) { 095 if (first) first = false; else td.tx(", "); 096 if (cs != null) { 097 td.ah(context.prefixLocalHref(cs.getWebPath()+"#conformance-expectation-"+t.primitiveValue())).tx(t.primitiveValue().toUpperCase()); 098 } else { 099 td.tx(t.primitiveValue().toUpperCase()); 100 } 101 } 102 td = tr.td(); 103 addMarkdown(td, stmt.primitiveValue("requirement")); 104 if (stmt.has("derivedFrom") || stmt.has("satisfiedBy") || stmt.has("reference") || stmt.has("source")) { 105 td.para().tx(context.formatPhrase(RenderingContext.REQ_LINKS)+" "); 106 XhtmlNode ul = td.ul(); 107 if (stmt.has("derivedFrom")) { 108 XhtmlNode li = ul.li(); 109 li.tx(context.formatPhrase(RenderingContext.REQ_DERIVED)+" "); 110 String url = stmt.primitiveValue("derivedFrom"); 111 String key = url.contains("#") ? url.substring(url.indexOf("#")+1) : ""; 112 if (url.contains("#")) { url = url.substring(0, url.indexOf("#")); }; 113 Requirements reqr = context.getWorker().fetchResource(Requirements.class, url, req.getResourceNative()); 114 if (reqr != null) { 115 RequirementsStatementComponent stmtr = reqr.findStatement(key); 116 if (stmtr != null) { 117 li.ah(context.prefixLocalHref(reqr.getWebPath()+"#"+key)).tx(reqr.present() + " # " +(stmt.has("label") ? stmt.primitiveValue("label") : stmt.primitiveValue("key"))); 118 } else { 119 li.ah(context.prefixLocalHref(reqr.getWebPath()+"#"+key)).tx(reqr.present()+" # "+key); 120 } 121 } else { 122 li.code(stmt.primitiveValue("derivedFrom")); 123 } 124 } 125 if (stmt.has("satisfiedBy")) { 126 XhtmlNode li = ul.li(); 127 li.tx(context.formatPhrase(RenderingContext.REQ_SATISFIED)+" "); 128 first = true; 129 for (ResourceWrapper c : stmt.children("satisfiedBy")) { 130 if (first) first = false; else li.tx(", "); 131 String url = c.primitiveValue(); 132 if (url.contains("#")) { 133 url = url.substring(0, url.indexOf("#")); 134 } 135 Resource r = context.getWorker().fetchResource(Resource.class, url, req.getResourceNative()); 136 if (r != null) { 137 String desc = getResourceDescription(r, null); 138 li.ah(context.prefixLocalHref(c.primitiveValue())).tx(desc); 139 } else { 140 li.ah(context.prefixLocalHref(c.primitiveValue())).tx(url); 141 } 142 } 143 } 144 if (stmt.has("reference")) { 145 XhtmlNode li = ul.li(); 146 li.tx(context.formatPhrase(RenderingContext.GENERAL_REFS)+" "); 147 int i = 0; 148 for (ResourceWrapper c : stmt.children("reference")) { 149 i++; 150 if (i>1) li.tx(", "); 151 String url = c.primitiveValue(); 152 if (url.contains("#")) { 153 url = url.substring(0, url.indexOf("#")); 154 } 155 li.ah(context.prefixLocalHref(c.primitiveValue())).tx(url); 156 } 157 } 158 if (stmt.has("source")) { 159 XhtmlNode li = ul.li(); 160 li.tx(context.formatPhrase(RenderingContext.GENERAL_SRC)+" "); 161 first = true; 162 for (ResourceWrapper c : stmt.children("source")) { 163 if (first) first = false; else li.tx(", "); 164 if (c.has("reference")) { 165 String url = c.primitiveValue("reference"); 166 if (url.contains("#")) { 167 url = url.substring(0, url.indexOf("#")); 168 } 169 Resource r = context.getWorker().fetchResource(Resource.class, url, req.getResourceNative()); 170 ResourceWithReference t = null; 171 if (r == null && context.getResolver() != null) { 172 t = context.getResolver().resolve(context, url, null); 173 } 174 if (r != null) { 175 String desc = getResourceDescription(r, c.primitiveValue("display")); 176 li.ah(context.prefixLocalHref(c.primitiveValue("reference"))).tx(desc); 177 } else if (t != null) { 178 String desc = getResourceDescription(t, c.primitiveValue("display")); 179 li.ah(context.prefixLocalHref(t.getWebPath())).tx(desc); 180 } else { 181 li.ah(context.prefixLocalHref(c.primitiveValue("reference"))).tx(url); 182 } 183 } else if (c.has("display")) { 184 li.tx(c.primitiveValue("display")); 185 } else { 186 li.tx("??"); 187 } 188 } 189 } 190 } 191 } 192 } 193 194 private String getResourceDescription(ResourceWithReference res, String display) throws UnsupportedEncodingException, IOException { 195 if (!Utilities.noString(display)) { 196 return display; 197 } 198 return RendererFactory.factory(res.getResource(), context.forContained()).buildSummary(res.getResource()); 199 } 200 201 private String getResourceDescription(Resource res, String display) throws UnsupportedEncodingException, IOException { 202 if (!Utilities.noString(display)) { 203 return display; 204 } 205 if (res instanceof CanonicalResource) { 206 return ((CanonicalResource) res).present(); 207 } 208 return RendererFactory.factory(res, context.forContained()).buildSummary(wrap(res)); 209 } 210 211 public void describe(XhtmlNode x, Library lib) { 212 x.tx(display(lib)); 213 } 214 215 public String display(Library lib) { 216 return lib.present(); 217 } 218 219}