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