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.DomainResource;
009import org.hl7.fhir.r5.model.Resource;
010import org.hl7.fhir.r5.model.CapabilityStatement;
011import org.hl7.fhir.r5.model.CapabilityStatement.CapabilityStatementRestComponent;
012import org.hl7.fhir.r5.model.CapabilityStatement.CapabilityStatementRestResourceComponent;
013import org.hl7.fhir.r5.model.CapabilityStatement.ResourceInteractionComponent;
014import org.hl7.fhir.r5.model.CapabilityStatement.SystemInteractionComponent;
015import org.hl7.fhir.r5.model.CapabilityStatement.SystemRestfulInteraction;
016import org.hl7.fhir.r5.model.CapabilityStatement.TypeRestfulInteraction;
017import org.hl7.fhir.r5.model.CanonicalType;
018import org.hl7.fhir.r5.renderers.utils.RenderingContext;
019import org.hl7.fhir.r5.renderers.utils.BaseWrappers.ResourceWrapper;
020import org.hl7.fhir.r5.renderers.utils.Resolver.ResourceContext;
021import org.hl7.fhir.utilities.xhtml.NodeType;
022import org.hl7.fhir.utilities.xhtml.XhtmlNode;
023
024public class CapabilityStatementRenderer extends ResourceRenderer {
025
026  public CapabilityStatementRenderer(RenderingContext context) {
027    super(context);
028  }
029
030  public CapabilityStatementRenderer(RenderingContext context, ResourceContext rcontext) {
031    super(context, rcontext);
032  }
033  
034  public boolean render(XhtmlNode x, Resource dr) throws FHIRFormatError, DefinitionException, IOException {
035    return render(x, (CapabilityStatement) dr);
036  }
037
038  public boolean render(XhtmlNode x, CapabilityStatement conf) throws FHIRFormatError, DefinitionException, IOException {
039    x.h2().addText(conf.getName());
040    addMarkdown(x, conf.getDescription());
041    if (conf.getRest().size() > 0) {
042      CapabilityStatementRestComponent rest = conf.getRest().get(0);
043      XhtmlNode t = x.table(null);
044      addTableRow(t, "Mode", rest.getMode().toString());
045      addMarkdown(addTableRow(t, "Description"), rest.getDocumentation());
046
047      addTableRow(t, "Transaction", showOp(rest, SystemRestfulInteraction.TRANSACTION));
048      addTableRow(t, "System History", showOp(rest, SystemRestfulInteraction.HISTORYSYSTEM));
049      addTableRow(t, "System Search", showOp(rest, SystemRestfulInteraction.SEARCHSYSTEM));
050
051      boolean hasVRead = false;
052      boolean hasPatch = false;
053      boolean hasDelete = false;
054      boolean hasHistory = false;
055      boolean hasUpdates = false;
056      for (CapabilityStatementRestResourceComponent r : rest.getResource()) {
057        hasVRead = hasVRead || hasOp(r, TypeRestfulInteraction.VREAD);
058        hasPatch = hasPatch || hasOp(r, TypeRestfulInteraction.PATCH);
059        hasDelete = hasDelete || hasOp(r, TypeRestfulInteraction.DELETE);
060        hasHistory = hasHistory || hasOp(r, TypeRestfulInteraction.HISTORYTYPE);
061        hasUpdates = hasUpdates || hasOp(r, TypeRestfulInteraction.HISTORYINSTANCE);
062      }
063
064      t = x.table(null);
065      XhtmlNode tr = t.tr();
066      tr.th().b().tx("Resource Type");
067      tr.th().b().tx("Profile");
068      tr.th().b().attribute("title", "GET a resource (read interaction)").tx("Read");
069      if (hasVRead)
070        tr.th().b().attribute("title", "GET past versions of resources (vread interaction)").tx("V-Read");
071      tr.th().b().attribute("title", "GET all set of resources of the type (search interaction)").tx("Search");
072      tr.th().b().attribute("title", "PUT a new resource version (update interaction)").tx("Update");
073      if (hasPatch)
074        tr.th().b().attribute("title", "PATCH a new resource version (patch interaction)").tx("Patch");
075      tr.th().b().attribute("title", "POST a new resource (create interaction)").tx("Create");
076      if (hasDelete)
077        tr.th().b().attribute("title", "DELETE a resource (delete interaction)").tx("Delete");
078      if (hasUpdates)
079        tr.th().b().attribute("title", "GET changes to a resource (history interaction on instance)").tx("Updates");
080      if (hasHistory)
081        tr.th().b().attribute("title", "GET changes for all resources of the type (history interaction on type)").tx("History");
082
083      XhtmlNode profCell = null;
084      boolean hasProf = false;
085      boolean hasSupProf = false;
086      for (CapabilityStatementRestResourceComponent r : rest.getResource()) {
087        tr = t.tr();
088        tr.td().addText(r.getType());
089
090        //Show profiles
091        profCell = tr.td();
092        hasProf = r.hasProfile();
093        hasSupProf = r.hasSupportedProfile();
094        if ((!hasProf) && (!hasSupProf)) {
095          profCell.nbsp();
096        }
097        else if (hasProf) {
098          profCell.ah(r.getProfile()).addText(r.getProfile());
099          if (hasSupProf) {
100            profCell.br();
101            profCell.addText("Additional supported profiles:");
102            for (CanonicalType sp: r.getSupportedProfile()) { 
103              profCell.br();
104              profCell.nbsp().nbsp();
105              profCell.ah(sp.getValue()).addText(sp.getValue());   
106            }
107          }
108        }
109        else {    //Case of only supported profiles
110          profCell.addText("Supported profiles:");
111          for (CanonicalType sp: r.getSupportedProfile()) { 
112            profCell.br();
113            profCell.nbsp().nbsp();
114            profCell.ah(sp.getValue()).addText(sp.getValue());   
115          }
116        }
117        //Show capabilities
118        tr.td().addText(showOp(r, TypeRestfulInteraction.READ));
119        if (hasVRead)
120          tr.td().addText(showOp(r, TypeRestfulInteraction.VREAD));
121        tr.td().addText(showOp(r, TypeRestfulInteraction.SEARCHTYPE));
122        tr.td().addText(showOp(r, TypeRestfulInteraction.UPDATE));
123        if (hasPatch)
124          tr.td().addText(showOp(r, TypeRestfulInteraction.PATCH));
125        tr.td().addText(showOp(r, TypeRestfulInteraction.CREATE));
126        if (hasDelete)
127          tr.td().addText(showOp(r, TypeRestfulInteraction.DELETE));
128        if (hasUpdates)
129          tr.td().addText(showOp(r, TypeRestfulInteraction.HISTORYINSTANCE));
130        if (hasHistory)
131          tr.td().addText(showOp(r, TypeRestfulInteraction.HISTORYTYPE));
132      }
133    }
134
135    return true;
136  }
137
138  public void describe(XhtmlNode x, CapabilityStatement cs) {
139    x.tx(display(cs));
140  }
141
142  public String display(CapabilityStatement cs) {
143    return cs.present();
144  }
145
146  @Override
147  public String display(Resource r) throws UnsupportedEncodingException, IOException {
148    return ((CapabilityStatement) r).present();
149  }
150
151
152  private boolean hasOp(CapabilityStatementRestResourceComponent r, TypeRestfulInteraction on) {
153    for (ResourceInteractionComponent op : r.getInteraction()) {
154      if (op.getCode() == on)
155        return true;
156    }
157    return false;
158  }
159
160  private String showOp(CapabilityStatementRestResourceComponent r, TypeRestfulInteraction on) {
161    for (ResourceInteractionComponent op : r.getInteraction()) {
162      if (op.getCode() == on)
163        return "y";
164    }
165    return "";
166  }
167
168  private String showOp(CapabilityStatementRestComponent r, SystemRestfulInteraction on) {
169    for (SystemInteractionComponent op : r.getInteraction()) {
170      if (op.getCode() == on)
171        return "y";
172    }
173    return "";
174  }
175
176  private XhtmlNode addTableRow(XhtmlNode t, String name) {
177    XhtmlNode tr = t.tr();
178    tr.td().addText(name);
179    return tr.td();
180  }
181  
182  private void addTableRow(XhtmlNode t, String name, String value) {
183    XhtmlNode tr = t.tr();
184    tr.td().addText(name);
185    tr.td().addText(value);
186  }
187
188  public String display(ResourceWrapper r) throws UnsupportedEncodingException, IOException {
189    if (r.has("title")) {
190      return r.children("title").get(0).getBase().primitiveValue();
191    }
192    if (r.has("name")) {
193      return r.children("name").get(0).getBase().primitiveValue();
194    }
195    return "??";
196  }
197
198}