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