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.OperationDefinition; 011import org.hl7.fhir.r5.model.Resource; 012import org.hl7.fhir.r5.model.SearchParameter; 013import org.hl7.fhir.r5.model.SearchParameter.SearchComparator; 014import org.hl7.fhir.r5.model.SearchParameter.SearchModifierCode; 015import org.hl7.fhir.r5.model.SearchParameter.SearchParameterComponentComponent; 016import org.hl7.fhir.r5.model.StringType; 017import org.hl7.fhir.r5.model.StructureDefinition; 018import org.hl7.fhir.r5.renderers.utils.RenderingContext; 019import org.hl7.fhir.r5.renderers.utils.RenderingContext.KnownLinkType; 020import org.hl7.fhir.r5.renderers.utils.Resolver.ResourceContext; 021import org.hl7.fhir.r5.utils.EOperationOutcome; 022import org.hl7.fhir.utilities.Utilities; 023import org.hl7.fhir.utilities.xhtml.XhtmlNode; 024 025public class SearchParameterRenderer extends TerminologyRenderer { 026 027 public SearchParameterRenderer(RenderingContext context) { 028 super(context); 029 } 030 031 public SearchParameterRenderer(RenderingContext context, ResourceContext rcontext) { 032 super(context, rcontext); 033 } 034 035 public boolean render(XhtmlNode x, Resource dr) throws IOException, FHIRException, EOperationOutcome { 036 return render(x, (SearchParameter) dr); 037 } 038 039 public boolean render(XhtmlNode x, SearchParameter spd) throws IOException, FHIRException, EOperationOutcome { 040 x.h2().addText(spd.getName()); 041 XhtmlNode p = x.para(); 042 p.tx("Parameter "); 043 p.code().tx(spd.getCode()); 044 p.tx(":"); 045 p.code().tx(spd.getType().toCode()); 046 addMarkdown(x, spd.getDescription()); 047 048 XhtmlNode tbl = x.table("grid"); 049 XhtmlNode tr = tbl.tr(); 050 tr.td().tx(Utilities.pluralize("Resource", spd.getBase().size())); 051 XhtmlNode td = tr.td(); 052 for (CodeType t : spd.getBase()) { 053 StructureDefinition sd = context.getWorker().fetchTypeDefinition(t.toString()); 054 if (sd != null && sd.hasUserData("path")) { 055 td.ah(sd.getUserString("path")).sep(", ").tx(t.getCode()); 056 } else { 057 td.sep(", ").tx(t.getCode()); 058 } 059 } 060 tr = tbl.tr(); 061 tr.td().tx("Expression"); 062 if (spd.hasExpression()) { 063 tr.td().code().tx(spd.getExpression()); 064 } else { 065 tr.td().tx("(none)"); 066 } 067 if (spd.hasProcessingMode()) { 068 tr = tbl.tr(); 069 tr.td().tx("Usage"); 070 tr.td().tx(spd.getProcessingMode().getDisplay()); 071 } 072 if (spd.hasTarget()) { 073 tr = tbl.tr(); 074 tr.td().tx(Utilities.pluralize("Target Resources", spd.getTarget().size())); 075 td = tr.td(); 076 if (isAllConcreteResources(spd.getTarget())) { 077 td.ah(Utilities.pathURL(context.getLink(KnownLinkType.SPEC), "resourcelist.html")).tx("All Resources"); 078 } else { 079 for (CodeType t : spd.getTarget()) { 080 StructureDefinition sd = context.getWorker().fetchTypeDefinition(t.toString()); 081 if (sd != null && sd.hasUserData("path")) { 082 td.sep(", "); 083 td.ah(sd.getUserString("path")).tx(t.getCode()); 084 } else { 085 td.sep(", "); 086 td.tx(t.getCode()); 087 } 088 } 089 } 090 } 091 tr = tbl.tr(); 092 tr.td().tx("Multiples"); 093 if (spd.getMultipleAnd() && spd.getMultipleOr()) { 094 tr.td().tx("The parameter can repeat (and) and can have repeating values (or)"); 095 } else if (spd.getMultipleOr()) { 096 tr.td().tx("The parameter can repeat (and) but each repeat can only have one value"); 097 } else if (spd.getMultipleAnd()) { 098 tr.td().tx("The parameter cannot repeat (and) but the single parameter can have multiple values (or)"); 099 } else { 100 tr.td().tx("The parameter cannot repeat or have multiple values"); 101 } 102 if (spd.hasComparator()) { 103 tr = tbl.tr(); 104 tr.td().tx("Comparators"); 105 td = tr.td(); 106 td.tx("Allowed: "); 107 for (Enumeration<SearchComparator> t : spd.getComparator()) { 108 td.sep(", "); 109 td.tx(t.asStringValue()); 110 } 111 } 112 if (spd.hasModifier()) { 113 tr = tbl.tr(); 114 tr.td().tx("Modifiers"); 115 td = tr.td(); 116 td.tx("Allowed: "); 117 for (Enumeration<SearchModifierCode> t : spd.getModifier()) { 118 td.sep(", "); 119 td.tx(t.asStringValue()); 120 } 121 } 122 if (spd.hasChain()) { 123 tr = tbl.tr(); 124 tr.td().tx("Chains"); 125 td = tr.td(); 126 td.tx("Allowed: "); 127 for (StringType t : spd.getChain()) { 128 td.sep(", "); 129 td.tx(t.asStringValue()); 130 } 131 } 132 133 if (spd.hasComponent()) { 134 x.para().b().tx("Components"); 135 tbl = x.table("grid"); 136 for (SearchParameterComponentComponent t : spd.getComponent()) { 137 tr = tbl.tr(); 138 SearchParameter tsp = context.getWorker().fetchResource(SearchParameter.class, t.getDefinition(), spd); 139 if (tsp != null && tsp.hasUserData("path")) { 140 tr.td().ah(tsp.getUserString("path")).tx(tsp.present()); 141 } else { 142 tr.td().tx(t.getDefinition()); 143 } 144 tr.td().code().tx(t.getExpression()); 145 } 146 } 147 return false; 148 } 149 150 private boolean isAllConcreteResources(List<CodeType> target) { 151 for (String s : context.getWorker().getResourceNames()) { 152 StructureDefinition sd = context.getWorker().fetchTypeDefinition(s); 153 if (!sd.getAbstract() && !Utilities.existsInList(sd.getType(), "Parameters")) { 154 boolean found = false; 155 for (CodeType c : target) { 156 found = found || sd.getName().equals(c.getValue()); 157 } 158 if (!found) { 159 return false; 160 } 161 } 162 } 163 return true; 164 } 165 166 public void describe(XhtmlNode x, OperationDefinition opd) { 167 x.tx(display(opd)); 168 } 169 170 public String display(OperationDefinition opd) { 171 return opd.present(); 172 } 173 174 @Override 175 public String display(Resource r) throws UnsupportedEncodingException, IOException { 176 return ((OperationDefinition) r).present(); 177 } 178 179}