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