001package org.hl7.fhir.r5.renderers;
002
003import java.io.IOException;
004import java.io.UnsupportedEncodingException;
005
006import org.hl7.fhir.exceptions.FHIRException;
007import org.hl7.fhir.r5.model.CodeType;
008import org.hl7.fhir.r5.model.Extension;
009import org.hl7.fhir.r5.model.OperationDefinition;
010import org.hl7.fhir.r5.model.OperationDefinition.OperationDefinitionParameterComponent;
011import org.hl7.fhir.r5.model.Resource;
012import org.hl7.fhir.r5.model.StructureDefinition;
013import org.hl7.fhir.r5.renderers.utils.RenderingContext;
014import org.hl7.fhir.r5.renderers.utils.RenderingContext.KnownLinkType;
015import org.hl7.fhir.r5.renderers.utils.Resolver.ResourceContext;
016import org.hl7.fhir.r5.utils.EOperationOutcome;
017import org.hl7.fhir.r5.utils.ToolingExtensions;
018import org.hl7.fhir.utilities.Utilities;
019import org.hl7.fhir.utilities.xhtml.XhtmlNode;
020
021public class OperationDefinitionRenderer extends TerminologyRenderer {
022
023  public OperationDefinitionRenderer(RenderingContext context) {
024    super(context);
025  }
026
027  public OperationDefinitionRenderer(RenderingContext context, ResourceContext rcontext) {
028    super(context, rcontext);
029  }
030  
031  public boolean render(XhtmlNode x, Resource dr) throws IOException, FHIRException, EOperationOutcome {
032    return render(x, (OperationDefinition) dr);
033  }
034
035  public boolean render(XhtmlNode x, OperationDefinition opd) throws IOException, FHIRException, EOperationOutcome {
036    if (context.isHeader()) {
037      x.h2().addText(opd.getName());
038      x.para().addText(Utilities.capitalize(opd.getKind().toString())+": "+opd.getName());    
039      x.para().tx("The official URL for this operation definition is: ");
040      x.pre().tx(opd.getUrl());
041      addMarkdown(x, opd.getDescription());}
042
043    if (opd.getSystem())
044      x.para().tx("URL: [base]/$"+opd.getCode());
045    for (CodeType c : opd.getResource()) {
046      if (opd.getType())
047        x.para().tx("URL: [base]/"+c.getValue()+"/$"+opd.getCode());
048      if (opd.getInstance())
049        x.para().tx("URL: [base]/"+c.getValue()+"/[id]/$"+opd.getCode());
050    }
051
052    if (opd.hasInputProfile()) {
053      XhtmlNode p = x.para();
054      p.tx("Input parameters Profile: ");
055      StructureDefinition sd = context.getContext().fetchResource(StructureDefinition.class, opd.getInputProfile(), opd);
056      if (sd == null) {
057        p.pre().tx(opd.getInputProfile());        
058      } else {
059        p.ah(sd.getUserString("path")).tx(sd.present());                 
060      }      
061    }
062    if (opd.hasOutputProfile()) {
063      XhtmlNode p = x.para();
064      p.tx("Output parameters Profile: ");
065      StructureDefinition sd = context.getContext().fetchResource(StructureDefinition.class, opd.getOutputProfile(), opd);
066      if (sd == null) {
067        p.pre().tx(opd.getOutputProfile());        
068      } else {
069        p.ah(sd.getUserString("path")).tx(sd.present());                 
070      }      
071    }
072    x.para().tx("Parameters");
073    XhtmlNode tbl = x.table( "grid");
074    XhtmlNode tr = tbl.tr();
075    tr.td().b().tx("Use");
076    tr.td().b().tx("Name");
077    tr.td().b().tx("Cardinality");
078    tr.td().b().tx("Type");
079    tr.td().b().tx("Binding");
080    tr.td().b().tx("Documentation");
081    for (OperationDefinitionParameterComponent p : opd.getParameter()) {
082      genOpParam(tbl, "", p, opd);
083    }
084    addMarkdown(x, opd.getComment());
085    return true;
086  }
087
088  public void describe(XhtmlNode x, OperationDefinition opd) {
089    x.tx(display(opd));
090  }
091
092  public String display(OperationDefinition opd) {
093    return opd.present();
094  }
095
096  @Override
097  public String display(Resource r) throws UnsupportedEncodingException, IOException {
098    return ((OperationDefinition) r).present();
099  }
100
101  private void genOpParam(XhtmlNode tbl, String path, OperationDefinitionParameterComponent p, Resource opd) throws EOperationOutcome, FHIRException, IOException {
102    XhtmlNode tr;
103    tr = tbl.tr();
104    tr.td().addText(p.getUse().toString());
105    tr.td().addText(path+p.getName());
106    tr.td().addText(Integer.toString(p.getMin())+".."+p.getMax());
107    XhtmlNode td = tr.td();
108    StructureDefinition sd = p.getType() != null ? context.getWorker().fetchTypeDefinition(p.getType().toCode()) : null;
109    if (sd == null)
110      td.tx(p.hasType() ? p.getType().toCode() : "");
111    else if (sd.getAbstract() && p.hasExtension(ToolingExtensions.EXT_ALLOWED_TYPE)) {
112      boolean first = true;
113      for (Extension ex : p.getExtensionsByUrl(ToolingExtensions.EXT_ALLOWED_TYPE)) {
114        if (first) first = false; else td.tx(" | ");
115        String s = ex.getValue().primitiveValue();
116        StructureDefinition sdt = context.getWorker().fetchTypeDefinition(s);
117        if (sdt == null)
118          td.tx(p.hasType() ? p.getType().toCode() : "");
119        else
120          td.ah(sdt.getUserString("path")).tx(s);         
121      }
122    } else
123      td.ah(sd.getUserString("path")).tx(p.hasType() ? p.getType().toCode() : "");
124    if (p.hasSearchType()) {
125      td.br();
126      td.tx("(");
127      td.ah( context.getLink(KnownLinkType.SPEC) == null ? "search.html#"+p.getSearchType().toCode() : Utilities.pathURL(context.getLink(KnownLinkType.SPEC), "search.html#"+p.getSearchType().toCode())).tx(p.getSearchType().toCode());       
128      td.tx(")");
129    }
130    td = tr.td();
131    if (p.hasBinding() && p.getBinding().hasValueSet()) {
132      AddVsRef(p.getBinding().getValueSet(), td, opd);
133      td.tx(" ("+p.getBinding().getStrength().getDisplay()+")");
134    }
135    addMarkdown(tr.td(), p.getDocumentation());
136    if (!p.hasType()) {
137      for (OperationDefinitionParameterComponent pp : p.getPart()) {
138        genOpParam(tbl, path+p.getName()+".", pp, opd);
139      }
140    }
141  }
142
143}