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.Enumeration;
011import org.hl7.fhir.r5.model.Enumerations.SearchComparator;
012import org.hl7.fhir.r5.model.Enumerations.SearchModifierCode;
013import org.hl7.fhir.r5.model.Enumerations.VersionIndependentResourceTypesAll;
014import org.hl7.fhir.r5.model.OperationDefinition;
015import org.hl7.fhir.r5.model.Resource;
016import org.hl7.fhir.r5.model.SearchParameter;
017import org.hl7.fhir.r5.model.SearchParameter.SearchParameterComponentComponent;
018import org.hl7.fhir.r5.model.StringType;
019import org.hl7.fhir.r5.model.StructureDefinition;
020import org.hl7.fhir.r5.renderers.utils.RenderingContext;
021import org.hl7.fhir.r5.renderers.utils.RenderingContext.KnownLinkType;
022import org.hl7.fhir.r5.renderers.utils.ResourceWrapper;
023import org.hl7.fhir.r5.utils.EOperationOutcome;
024import org.hl7.fhir.r5.utils.ToolingExtensions;
025import org.hl7.fhir.utilities.StandardsStatus;
026import org.hl7.fhir.utilities.Utilities;
027import org.hl7.fhir.utilities.xhtml.XhtmlNode;
028
029public class SearchParameterRenderer extends TerminologyRenderer {
030
031
032  public SearchParameterRenderer(RenderingContext context) { 
033    super(context); 
034  } 
035 
036  @Override
037  public void buildNarrative(RenderingStatus status, XhtmlNode x, ResourceWrapper r) throws FHIRFormatError, DefinitionException, IOException, FHIRException, EOperationOutcome {
038    if (r.isDirect()) {
039      renderResourceTechDetails(r, x);
040      genSummaryTable(status, x, (SearchParameter) r.getBase());
041
042      render(status, x, (SearchParameter) r.getBase());      
043    } else {
044      // the intention is to change this in the future
045      x.para().tx("SearchParameterRenderer only renders native resources directly");
046    }
047  }
048  
049  
050  @Override
051  public String buildSummary(ResourceWrapper r) throws UnsupportedEncodingException, IOException {
052    return canonicalTitle(r);
053  }
054
055  public void render(RenderingStatus status, XhtmlNode x, SearchParameter spd) throws IOException, FHIRException, EOperationOutcome {
056    XhtmlNode h2 = x.h2();
057    h2.addText(spd.getName());
058    StandardsStatus ss = ToolingExtensions.getStandardsStatus(spd);
059    if (ss != context.getDefaultStandardsStatus()) {
060      genStandardsStatus(h2, ss);
061    }
062    XhtmlNode p =  x.para();
063    p.tx(context.formatPhrase(RenderingContext.GENERAL_PAR)+" ");
064    p.code().tx(spd.getCode());
065    p.tx(":");
066    p.code().tx(spd.getType().toCode());
067    addMarkdown(x, spd.getDescription());
068
069    XhtmlNode tbl = x.table("grid");
070    XhtmlNode tr = tbl.tr();
071    tr.td().tx(Utilities.pluralize(context.formatPhrase(RenderingContext.GENERAL_RESOURCE), spd.getBase().size()));
072    XhtmlNode td = tr.td();
073    for (Enumeration<VersionIndependentResourceTypesAll> t : spd.getBase()) {
074      StructureDefinition sd = context.getWorker().fetchTypeDefinition(t.getCode());
075      if (sd != null && sd.hasWebPath()) {
076        td.sep(", ");
077        td.ah(context.prefixLocalHref(context.prefixLocalHref(sd.getWebPath()))).tx(t.getCode());
078      } else {
079        td.sep(", ");
080        td.tx(t.getCode());
081      }
082    }
083    tr = tbl.tr();
084    tr.td().tx(context.formatPhrase(RenderingContext.SEARCH_PAR_EXP));
085    if (spd.hasExpression()) {
086      tr.td().code().tx(spd.getExpression());
087    } else {
088      tr.td().tx(context.formatPhrase(RenderingContext.SEARCH_PAR_NONE));
089    }
090    if (spd.hasProcessingMode()) {
091      tr = tbl.tr();
092      tr.td().tx(context.formatPhrase(RenderingContext.SEARCH_PAR_PROC));
093      tr.td().tx(spd.getProcessingMode().getDisplay());      
094    }
095    if (spd.hasTarget()) {
096      tr = tbl.tr();
097      tr.td().tx(Utilities.pluralize(context.formatPhrase(RenderingContext.SEARCH_PAR_REND_TARGET), spd.getTarget().size()));
098      td = tr.td();
099      if (isAllConcreteResources(spd.getTarget())) {
100        td.ah(context.prefixLocalHref(Utilities.pathURL(context.getLink(KnownLinkType.SPEC), "resourcelist.html"))).tx(context.formatPhrase(RenderingContext.SEARCH_PAR_RES));
101      } else {
102        for (Enumeration<VersionIndependentResourceTypesAll> t : spd.getTarget()) {
103          StructureDefinition sd = context.getWorker().fetchTypeDefinition(t.getCode());
104          if (sd != null && sd.hasWebPath()) {
105            td.sep(", ");
106            td.ah(context.prefixLocalHref(sd.getWebPath())).tx(t.getCode());
107          } else {
108            td.sep(", ");
109            td.tx(t.getCode());
110          }
111        }
112      }
113    }
114    tr = tbl.tr();    
115    tr.td().tx(context.formatPhrase(RenderingContext.SEARCH_PAR_MULTIPLES));
116    XhtmlNode ul = tr.td().ul();
117    if (!spd.hasMultipleAnd()) {
118      ul.li().tx(context.formatPhrase(RenderingContext.SEARCH_PAR_MULTIPLE_AND_SERVER));
119    } else if (spd.getMultipleAnd()) {
120      ul.li().tx(context.formatPhrase(RenderingContext.SEARCH_PAR_MULTIPLE_AND_REPEAT));
121    } else {
122      ul.li().tx(context.formatPhrase(RenderingContext.SEARCH_PAR_MULTIPLE_AND_APPEAR));
123    }
124    if (!spd.hasMultipleOr()) {
125      ul.li().tx(context.formatPhrase(RenderingContext.SEARCH_PAR_MULTIPLE_OR_SERVER));
126    } else if (spd.getMultipleOr()) {
127      ul.li().tx(context.formatPhrase(RenderingContext.SEARCH_PAR_MULTIPLE_OR_MULTIPLE));
128    } else {
129      ul.li().tx(context.formatPhrase(RenderingContext.SEARCH_PAR_MULTIPLE_OR_ONE));
130    }
131
132    if (spd.hasComparator()) {
133      tr = tbl.tr();
134      tr.td().tx(context.formatPhrase(RenderingContext.GENERAL_COMPARATORS));
135      td = tr.td();
136      td.tx(context.formatPhrase(RenderingContext.SEARCH_PAR_ALLOWED)+" ");
137      for (Enumeration<SearchComparator> t : spd.getComparator()) {
138        td.sep(", ");
139        td.tx(t.asStringValue());
140      }      
141    }
142    if (spd.hasModifier()) {
143      tr = tbl.tr();
144      tr.td().tx(context.formatPhrase(RenderingContext.GENERAL_MODIFIERS));
145      td = tr.td();
146      td.tx(context.formatPhrase(RenderingContext.SEARCH_PAR_ALLOWED)+" ");
147      for (Enumeration<SearchModifierCode> t : spd.getModifier()) {
148        td.sep(", ");
149        td.tx(t.asStringValue());
150      }      
151    }
152    if (spd.hasChain()) {
153      tr = tbl.tr();
154      tr.td().tx(context.formatPhrase(RenderingContext.SEARCH_PAR_CHAIN));
155      td = tr.td();
156      td.tx(context.formatPhrase(RenderingContext.SEARCH_PAR_ALLOWED)+" ");
157      for (StringType t : spd.getChain()) {
158        td.sep(", ");
159        td.tx(t.asStringValue());
160      }      
161    }
162    
163    if (spd.hasComponent()) {
164      x.para().b().tx(context.formatPhrase(RenderingContext.GENERAL_COMPARATORS));
165      tbl = x.table("grid");
166      for (SearchParameterComponentComponent t : spd.getComponent()) {
167        tr = tbl.tr();
168        SearchParameter tsp = context.getWorker().fetchResource(SearchParameter.class, t.getDefinition(), spd);
169        if (tsp != null && tsp.hasWebPath()) {
170          tr.td().ah(context.prefixLocalHref(tsp.getWebPath())).tx(tsp.present());          
171        } else {
172          tr.td().tx(t.getDefinition());
173        }
174        tr.td().code().tx(t.getExpression());
175      }
176    }
177  }
178
179  private boolean isAllConcreteResources(List<Enumeration<VersionIndependentResourceTypesAll>> list) {
180    for (String s : context.getWorker().getResourceNames()) {
181      StructureDefinition sd = context.getWorker().fetchTypeDefinition(s);
182      if (!sd.getAbstract() && !Utilities.existsInList(sd.getType(), context.formatPhrase(RenderingContext.GENERAL_PAR))) {
183        boolean found = false;
184        for (Enumeration<VersionIndependentResourceTypesAll> c : list) {
185          found = found || sd.getName().equals(c.getCode());
186        }
187        if (!found) {
188          return false;
189        }
190      }
191    }
192    return true;
193  }
194
195  public void describe(XhtmlNode x, OperationDefinition opd) {
196    x.tx(display(opd));
197  }
198
199  public String display(OperationDefinition opd) {
200    return opd.present();
201  }
202
203  @Override
204  public String display(Resource r) throws UnsupportedEncodingException, IOException {
205    return ((SearchParameter) r).present();
206  }
207
208}