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