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(context.formatPhrase(RenderingContext.REQ_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(context.formatPhrase(RenderingContext.REQ_FOLLOWING_ACTOR)+" ");
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(context.formatPhrase(RenderingContext.REQ_DERIVE)+" ");
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(context.formatPhrase(RenderingContext.REQ_FOLLOWING_REQ)+" ");
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    if (req.hasReference()) {
089      XhtmlNode p = x.para();
090      p.tx(context.formatPhrase(RenderingContext.GENERAL_REFS)+" ");
091      int i = 0;
092      for (UrlType c : req.getReference()) {
093        i++;
094        if (i>1) p.tx(", ");
095        String url = c.getValue();
096        if (url.contains("#")) {
097          url = url.substring(0, url.indexOf("#"));
098        }
099        p.ah(c.getValue()).tx(url);
100      }
101    }
102    XhtmlNode tbl = x.table("grid");
103    
104    for (RequirementsStatementComponent stmt : req.getStatement()) {
105      XhtmlNode tr = tbl.tr();
106      String lbl = stmt.hasLabel() ? stmt.getLabel() : stmt.getKey();
107      XhtmlNode td = tr.td();
108      td.b().an(stmt.getKey());
109      td.tx(lbl);
110      td = tr.td();
111      boolean first = true;
112      CodeSystem cs = context.getWorker().fetchCodeSystem("http://hl7.org/fhir/conformance-expectation");
113      for (Enumeration<ConformanceExpectation> t : stmt.getConformance()) {
114        if (first) first = false; else td.tx(", ");
115        if (cs != null) {
116          td.ah(cs.getWebPath()+"#conformance-expectation-"+t.asStringValue()).tx(t.asStringValue().toUpperCase());          
117        } else {
118          td.tx(t.asStringValue().toUpperCase());
119        }
120      }
121      td = tr.td();
122      addMarkdown(td, stmt.getRequirement());
123      if (stmt.hasDerivedFrom() || stmt.hasSatisfiedBy() || stmt.hasReference() || stmt.hasSource()) {
124        td.para().tx(context.formatPhrase(RenderingContext.REQ_LINKS)+" ");
125        XhtmlNode ul = td.ul();
126        if (stmt.hasDerivedFrom()) {
127          XhtmlNode li = ul.li();
128          li.tx(context.formatPhrase(RenderingContext.REQ_DERIVED)+" ");
129          String url = stmt.getDerivedFrom();
130          String key = url.contains("#") ? url.substring(url.indexOf("#")+1) : "";
131          if (url.contains("#")) { url = url.substring(0, url.indexOf("#")); };
132          Requirements reqr = context.getWorker().fetchResource(Requirements.class, url, req);
133          if (reqr != null) {
134            RequirementsStatementComponent stmtr = reqr.findStatement(key);
135            if (stmtr != null) {
136              li.ah(reqr.getWebPath()+"#"+key).tx(reqr.present() + " # " +(stmt.hasLabel() ? stmt.getLabel() : stmt.getKey()));
137            } else {
138              li.ah(reqr.getWebPath()+"#"+key).tx(reqr.present()+" # "+key);              
139            }
140          } else {
141            li.code(stmt.getDerivedFrom());
142          }
143        }
144        if (stmt.hasSatisfiedBy()) {
145          XhtmlNode li = ul.li();
146          li.tx(context.formatPhrase(RenderingContext.REQ_SATISFIED)+" ");
147          first = true;
148          for (UrlType c : stmt.getSatisfiedBy()) {
149            if (first) first = false; else li.tx(", ");
150            String url = c.getValue();
151            if (url.contains("#")) {
152              url = url.substring(0, url.indexOf("#"));
153            }
154            Resource r = context.getWorker().fetchResource(Resource.class, url, req);
155            if (r != null) {
156              String desc = getResourceDescription(r, null);
157              li.ah(c.getValue()).tx(desc);
158            } else {
159              li.ah(c.getValue()).tx(url);
160            }
161          }
162        }
163        if (stmt.hasReference()) {
164          XhtmlNode li = ul.li();
165          li.tx(context.formatPhrase(RenderingContext.GENERAL_REFS)+" ");
166          int i = 0;
167          for (UrlType c : stmt.getReference()) {
168            i++;
169            if (i>1) li.tx(", ");
170            String url = c.getValue();
171            if (url.contains("#")) {
172              url = url.substring(0, url.indexOf("#"));
173            }
174            li.ah(c.getValue()).tx(url);
175          }
176        }
177        if (stmt.hasSource()) {
178          XhtmlNode li = ul.li();
179          li.tx(context.formatPhrase(RenderingContext.GENERAL_SRC)+" ");
180          first = true;
181          for (Reference c : stmt.getSource()) {
182            if (first) first = false; else li.tx(", ");
183            if (c.hasReference()) {
184              String url = c.getReference();
185              if (url.contains("#")) {
186                url = url.substring(0, url.indexOf("#"));
187              }
188              Resource r = context.getWorker().fetchResource(Resource.class, url, req);
189              ResourceWithReference t = null;
190              if (r == null && context.getResolver() != null) {
191                t = context.getResolver().resolve(context, url);                
192              }
193              if (r != null) {
194                String desc = getResourceDescription(r, c.getDisplay());
195                li.ah(c.getReference()).tx(desc);
196              } else if (t != null) {
197                String desc = getResourceDescription(t, c.getDisplay());
198                li.ah(t.getReference()).tx(desc);
199              } else {
200                li.ah(c.getReference()).tx(url);
201              }
202            } else if (c.hasDisplay()) {
203              li.tx(c.getDisplay());
204            } else {
205              li.tx("??");
206            }
207          }
208        }
209      }
210    }
211    return false;
212  }
213  
214  private String getResourceDescription(ResourceWithReference res, String display) throws UnsupportedEncodingException, IOException {
215    if (!Utilities.noString(display)) {
216      return display;
217    }
218    return RendererFactory.factory(res.getResource(), context).display(res.getResource());
219  }
220
221  private String getResourceDescription(Resource res, String display) throws UnsupportedEncodingException, IOException {
222    if (!Utilities.noString(display)) {
223      return display;
224    }
225    if (res instanceof CanonicalResource) {
226      return ((CanonicalResource) res).present();
227    }
228    return RendererFactory.factory(res, context).display(res);
229  }
230
231  public void describe(XhtmlNode x, Library lib) {
232    x.tx(display(lib));
233  }
234
235  public String display(Library lib) {
236    return lib.present();
237  }
238
239  @Override
240  public String display(Resource r) throws UnsupportedEncodingException, IOException {
241    return ((Library) r).present();
242  }
243
244  @Override
245  public String display(ResourceWrapper r) throws UnsupportedEncodingException, IOException {
246    if (r.has("title")) {
247      return r.children("title").get(0).getBase().primitiveValue();
248    }
249    return "??";
250  }
251  
252}