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}