001package org.hl7.fhir.r5.renderers; 002 003import java.io.IOException; 004import java.io.UnsupportedEncodingException; 005 006import org.hl7.fhir.exceptions.DefinitionException; 007import org.hl7.fhir.exceptions.FHIRFormatError; 008import org.hl7.fhir.r5.model.ActorDefinition; 009import org.hl7.fhir.r5.model.CanonicalResource; 010import org.hl7.fhir.r5.model.CanonicalType; 011import org.hl7.fhir.r5.model.CodeSystem; 012import org.hl7.fhir.r5.model.Enumeration; 013import org.hl7.fhir.r5.model.Library; 014import org.hl7.fhir.r5.model.Reference; 015import org.hl7.fhir.r5.model.Requirements; 016import org.hl7.fhir.r5.model.Requirements.ConformanceExpectation; 017import org.hl7.fhir.r5.model.Requirements.RequirementsStatementComponent; 018import org.hl7.fhir.r5.model.Resource; 019import org.hl7.fhir.r5.model.UrlType; 020import org.hl7.fhir.r5.renderers.utils.BaseWrappers.ResourceWrapper; 021import org.hl7.fhir.r5.renderers.utils.RenderingContext; 022import org.hl7.fhir.r5.renderers.utils.Resolver.ResourceContext; 023import org.hl7.fhir.r5.renderers.utils.Resolver.ResourceWithReference; 024import org.hl7.fhir.utilities.Utilities; 025import org.hl7.fhir.utilities.xhtml.XhtmlNode; 026 027public class RequirementsRenderer extends ResourceRenderer { 028 029 public RequirementsRenderer(RenderingContext context) { 030 super(context); 031 } 032 033 public RequirementsRenderer(RenderingContext context, ResourceContext rcontext) { 034 super(context, rcontext); 035 } 036 037 public boolean render(XhtmlNode x, Resource dr) throws FHIRFormatError, DefinitionException, IOException { 038 return render(x, (Requirements) dr); 039 } 040 041 public boolean render(XhtmlNode x, Requirements req) throws FHIRFormatError, DefinitionException, IOException { 042 if (req.hasActor()) { 043 if (req.getActor().size() == 1) { 044 ActorDefinition acd = context.getWorker().fetchResource(ActorDefinition.class, req.getActor().get(0).getValue(), req); 045 XhtmlNode p = x.para(); 046 p.tx("These requirements apply to the actor "); 047 if (acd == null) { 048 p.code(req.getActor().get(0).getValue()); 049 } else { 050 p.ah(acd.getWebPath()).tx(acd.present()); 051 } 052 } else { 053 x.para().tx("These requirements apply to the following actors:"); 054 XhtmlNode ul = x.ul(); 055 for (CanonicalType a : req.getActor()) { 056 ActorDefinition acd = context.getWorker().fetchResource(ActorDefinition.class, a.getValue(), req); 057 if (acd == null) { 058 ul.li().code(a.getValue()); 059 } else { 060 ul.li().ah(acd.getWebPath()).tx(acd.present()); 061 } 062 } 063 } 064 } 065 if (req.hasDerivedFrom()) { 066 if (req.getDerivedFrom().size() == 1) { 067 Requirements reqd = context.getWorker().fetchResource(Requirements.class, req.getDerivedFrom().get(0).getValue(), req); 068 XhtmlNode p = x.para(); 069 p.tx("These requirements derive from "); 070 if (reqd == null) { 071 p.code(req.getDerivedFrom().get(0).getValue()); 072 } else { 073 p.ah(reqd.getWebPath()).tx(reqd.present()); 074 } 075 } else { 076 x.para().tx("These requirements are derived from the following requirements:"); 077 XhtmlNode ul = x.ul(); 078 for (CanonicalType a : req.getDerivedFrom()) { 079 Requirements reqd = context.getWorker().fetchResource(Requirements.class, a.getValue(), req); 080 if (reqd == null) { 081 ul.li().code(a.getValue()); 082 } else { 083 ul.li().ah(reqd.getWebPath()).tx(reqd.present()); 084 } 085 } 086 } 087 } 088 089 XhtmlNode tbl = x.table("grid"); 090 091 for (RequirementsStatementComponent stmt : req.getStatement()) { 092 XhtmlNode tr = tbl.tr(); 093 String lbl = stmt.hasLabel() ? stmt.getLabel() : stmt.getKey(); 094 XhtmlNode td = tr.td(); 095 td.b().an(stmt.getKey()); 096 td.tx(lbl); 097 td = tr.td(); 098 boolean first = true; 099 CodeSystem cs = context.getWorker().fetchCodeSystem("http://hl7.org/fhir/conformance-expectation"); 100 for (Enumeration<ConformanceExpectation> t : stmt.getConformance()) { 101 if (first) first = false; else td.tx(", "); 102 if (cs != null) { 103 td.ah(cs.getWebPath()+"#conformance-expectation-"+t.asStringValue()).tx(t.asStringValue().toUpperCase()); 104 } else { 105 td.tx(t.asStringValue().toUpperCase()); 106 } 107 } 108 td = tr.td(); 109 addMarkdown(td, stmt.getRequirement()); 110 if (stmt.hasDerivedFrom() || stmt.hasSatisfiedBy() || stmt.hasReference() || stmt.hasSource()) { 111 td.para().tx("Links:"); 112 XhtmlNode ul = td.ul(); 113 if (stmt.hasDerivedFrom()) { 114 XhtmlNode li = ul.li(); 115 li.tx("Derived From: "); 116 String url = stmt.getDerivedFrom(); 117 String key = url.contains("#") ? url.substring(url.indexOf("#")+1) : ""; 118 if (url.contains("#")) { url = url.substring(0, url.indexOf("#")); }; 119 Requirements reqr = context.getWorker().fetchResource(Requirements.class, url, req); 120 if (reqr != null) { 121 RequirementsStatementComponent stmtr = reqr.findStatement(key); 122 if (stmtr != null) { 123 li.ah(reqr.getWebPath()+"#"+key).tx(reqr.present() + " # " +(stmt.hasLabel() ? stmt.getLabel() : stmt.getKey())); 124 } else { 125 li.ah(reqr.getWebPath()+"#"+key).tx(reqr.present()+" # "+key); 126 } 127 } else { 128 li.code(stmt.getDerivedFrom()); 129 } 130 } 131 if (stmt.hasSatisfiedBy()) { 132 XhtmlNode li = ul.li(); 133 li.tx("Satisfied By: "); 134 first = true; 135 for (UrlType c : stmt.getSatisfiedBy()) { 136 if (first) first = false; else li.tx(", "); 137 String url = c.getValue(); 138 if (url.contains("#")) { 139 url = url.substring(0, url.indexOf("#")); 140 } 141 Resource r = context.getWorker().fetchResource(Resource.class, url, req); 142 if (r != null) { 143 String desc = getResourceDescription(r, null); 144 li.ah(c.getValue()).tx(desc); 145 } else { 146 li.ah(c.getValue()).tx(url); 147 } 148 } 149 } 150 if (stmt.hasReference()) { 151 XhtmlNode li = ul.li(); 152 li.tx("References: "); 153 int i = 0; 154 for (UrlType c : stmt.getSatisfiedBy()) { 155 i++; 156 if (i>1) li.tx(", "); 157 String url = c.getValue(); 158 if (url.contains("#")) { 159 url = url.substring(0, url.indexOf("#")); 160 } 161 li.ah(c.getValue()).tx(url); 162 } 163 } 164 if (stmt.hasSource()) { 165 XhtmlNode li = ul.li(); 166 li.tx("Source: "); 167 first = true; 168 for (Reference c : stmt.getSource()) { 169 if (first) first = false; else li.tx(", "); 170 if (c.hasReference()) { 171 String url = c.getReference(); 172 if (url.contains("#")) { 173 url = url.substring(0, url.indexOf("#")); 174 } 175 Resource r = context.getWorker().fetchResource(Resource.class, url, req); 176 ResourceWithReference t = null; 177 if (r == null && context.getResolver() != null) { 178 t = context.getResolver().resolve(context, url); 179 } 180 if (r != null) { 181 String desc = getResourceDescription(r, c.getDisplay()); 182 li.ah(c.getReference()).tx(desc); 183 } else if (t != null) { 184 String desc = getResourceDescription(t, c.getDisplay()); 185 li.ah(t.getReference()).tx(desc); 186 } else { 187 li.ah(c.getReference()).tx(url); 188 } 189 } else if (c.hasDisplay()) { 190 li.tx(c.getDisplay()); 191 } else { 192 li.tx("??"); 193 } 194 } 195 } 196 } 197 } 198 return false; 199 } 200 201 private String getResourceDescription(ResourceWithReference res, String display) throws UnsupportedEncodingException, IOException { 202 if (!Utilities.noString(display)) { 203 return display; 204 } 205 return RendererFactory.factory(res.getResource(), context).display(res.getResource()); 206 } 207 208 private String getResourceDescription(Resource res, String display) throws UnsupportedEncodingException, IOException { 209 if (!Utilities.noString(display)) { 210 return display; 211 } 212 if (res instanceof CanonicalResource) { 213 return ((CanonicalResource) res).present(); 214 } 215 return RendererFactory.factory(res, context).display(res); 216 } 217 218 public void describe(XhtmlNode x, Library lib) { 219 x.tx(display(lib)); 220 } 221 222 public String display(Library lib) { 223 return lib.present(); 224 } 225 226 @Override 227 public String display(Resource r) throws UnsupportedEncodingException, IOException { 228 return ((Library) r).present(); 229 } 230 231 @Override 232 public String display(ResourceWrapper r) throws UnsupportedEncodingException, IOException { 233 if (r.has("title")) { 234 return r.children("title").get(0).getBase().primitiveValue(); 235 } 236 return "??"; 237 } 238 239}