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.FHIRException;
008import org.hl7.fhir.exceptions.FHIRFormatError;
009import org.hl7.fhir.r5.model.CodeType;
010import org.hl7.fhir.r5.model.DomainResource;
011import org.hl7.fhir.r5.model.Enumeration;
012import org.hl7.fhir.r5.model.Extension;
013import org.hl7.fhir.r5.model.OperationDefinition;
014import org.hl7.fhir.r5.model.OperationDefinition.OperationDefinitionParameterComponent;
015import org.hl7.fhir.r5.model.Resource;
016import org.hl7.fhir.r5.model.SearchParameter;
017import org.hl7.fhir.r5.model.SearchParameter.SearchComparator;
018import org.hl7.fhir.r5.model.SearchParameter.SearchModifierCode;
019import org.hl7.fhir.r5.model.SearchParameter.SearchParameterComponentComponent;
020import org.hl7.fhir.r5.model.StringType;
021import org.hl7.fhir.r5.model.StructureDefinition;
022import org.hl7.fhir.r5.renderers.utils.RenderingContext;
023import org.hl7.fhir.r5.renderers.utils.Resolver.ResourceContext;
024import org.hl7.fhir.r5.utils.EOperationOutcome;
025import org.hl7.fhir.r5.utils.ToolingExtensions;
026import org.hl7.fhir.utilities.Utilities;
027import org.hl7.fhir.utilities.xhtml.XhtmlNode;
028
029public class SearchParameterRenderer extends TerminologyRenderer {
030
031  public SearchParameterRenderer(RenderingContext context) {
032    super(context);
033  }
034
035  public SearchParameterRenderer(RenderingContext context, ResourceContext rcontext) {
036    super(context, rcontext);
037  }
038  
039  public boolean render(XhtmlNode x, Resource dr) throws IOException, FHIRException, EOperationOutcome {
040    return render(x, (OperationDefinition) dr);
041  }
042
043  public boolean render(XhtmlNode x, SearchParameter spd) throws IOException, FHIRException, EOperationOutcome {
044    x.h2().addText(spd.getName());
045    XhtmlNode p =  x.para();
046    p.tx("Parameter ");
047    p.code().tx(spd.getCode());
048    p.tx(":");
049    p.code().tx(spd.getType().toCode());
050    addMarkdown(x, spd.getDescription());
051
052    XhtmlNode tbl = x.table("grid");
053    XhtmlNode tr = tbl.tr();
054    tr.td().tx(Utilities.pluralize("Resource", spd.getBase().size()));
055    XhtmlNode td = tr.td();
056    for (CodeType t : spd.getBase()) {
057      StructureDefinition sd = context.getWorker().fetchTypeDefinition(t.toString());
058      if (sd != null && sd.hasUserData("path")) {
059        td.sep(", ").ah(sd.getUserString("path")).tx(t.getCode());
060      } else {
061        td.sep(", ").tx(t.getCode());
062      }
063    }
064    tr = tbl.tr();
065    tr.td().tx("Expression");
066    if (spd.hasExpression()) {
067      tr.td().code().tx(spd.getExpression());
068    } else {
069      tr.td().tx("(none)");
070    }
071    if (spd.hasXpathUsage()) {
072      tr = tbl.tr();
073      tr.td().tx("Usage");
074      tr.td().tx(spd.getXpathUsage().getDisplay());      
075    }
076    if (spd.hasXpath()) {
077      tr = tbl.tr();
078      tr.td().tx("XPath");
079      tr.td().code().tx(spd.getXpath());      
080    }
081    if (spd.hasTarget()) {
082      tr = tbl.tr();
083      tr.td().tx(Utilities.pluralize("Target Resources", spd.getTarget().size()));
084      td = tr.td();
085      for (CodeType t : spd.getTarget()) {
086        StructureDefinition sd = context.getWorker().fetchTypeDefinition(t.toString());
087        if (sd != null && sd.hasUserData("path")) {
088          td.sep(", ").ah(sd.getUserString("path")).tx(t.getCode());
089        } else {
090          td.sep(", ").tx(t.getCode());
091        }
092      }
093    }
094    tr = tbl.tr();
095    tr.td().tx("Multiples");
096    if (spd.getMultipleAnd() && spd.getMultipleOr()) {
097      tr.td().tx("The parameter can repeat (and) and can have repeating values (or)");      
098    } else if (spd.getMultipleOr()) {
099      tr.td().tx("The parameter can repeat (and) but each repeat can only have one value");      
100    } else if (spd.getMultipleAnd()) {
101      tr.td().tx("The parameter cannot repeat (and) but the single parameter can have multiple values (or)");      
102    } else { 
103      tr.td().tx("The parameter cannot repeat or have multiple values");
104    }
105    if (spd.hasComparator()) {
106      tr = tbl.tr();
107      tr.td().tx("Comparators");
108      td = tr.td().tx("Allowed: ");
109      for (Enumeration<SearchComparator> t : spd.getComparator()) {
110        td.sep(", ").tx(t.asStringValue());
111      }      
112    }
113    if (spd.hasModifier()) {
114      tr = tbl.tr();
115      tr.td().tx("Modifiers");
116      td = tr.td().tx("Allowed: ");
117      for (Enumeration<SearchModifierCode> t : spd.getModifier()) {
118        td.sep(", ").tx(t.asStringValue());
119      }      
120    }
121    if (spd.hasChain()) {
122      tr = tbl.tr();
123      tr.td().tx("Chains");
124      td = tr.td().tx("Allowed: ");
125      for (StringType t : spd.getChain()) {
126        td.sep(", ").tx(t.asStringValue());
127      }      
128    }
129    
130    if (spd.hasComponent()) {
131      x.para().b().tx("Components");
132      tbl = x.table("grid");
133      for (SearchParameterComponentComponent t : spd.getComponent()) {
134        tr = tbl.tr();
135        SearchParameter tsp = context.getWorker().fetchResource(SearchParameter.class, t.getDefinition());
136        if (tsp != null && tsp.hasUserData("path")) {
137          tr.td().ah(tsp.getUserString("path")).tx(tsp.present());          
138        } else {
139          tr.td().tx(t.getDefinition());
140        }
141        tr.td().code().tx(t.getExpression());
142      }
143    }
144    return false;
145  }
146
147  public void describe(XhtmlNode x, OperationDefinition opd) {
148    x.tx(display(opd));
149  }
150
151  public String display(OperationDefinition opd) {
152    return opd.present();
153  }
154
155  @Override
156  public String display(Resource r) throws UnsupportedEncodingException, IOException {
157    return ((OperationDefinition) r).present();
158  }
159
160}