
001package org.hl7.fhir.convertors.txClient; 002 003import java.io.IOException; 004import java.net.URISyntaxException; 005import java.util.EnumSet; 006import java.util.HashMap; 007import java.util.Map; 008 009import org.hl7.fhir.convertors.factory.VersionConvertorFactory_40_50; 010import org.hl7.fhir.exceptions.FHIRException; 011import org.hl7.fhir.r4.model.Resource; 012import org.hl7.fhir.r4.utils.client.EFhirClientException; 013import org.hl7.fhir.r4.utils.client.FHIRToolingClient; 014import org.hl7.fhir.r5.formats.IParser.OutputStyle; 015import org.hl7.fhir.r5.formats.JsonParser; 016import org.hl7.fhir.r5.model.Bundle; 017import org.hl7.fhir.r5.model.CanonicalResource; 018import org.hl7.fhir.r5.model.CapabilityStatement; 019import org.hl7.fhir.r5.model.OperationOutcome; 020import org.hl7.fhir.r5.model.Parameters; 021import org.hl7.fhir.r5.model.TerminologyCapabilities; 022import org.hl7.fhir.r5.model.ValueSet; 023import org.hl7.fhir.r5.model.Parameters.ParametersParameterComponent; 024import org.hl7.fhir.r5.terminologies.client.ITerminologyClient; 025import org.hl7.fhir.r5.terminologies.client.TerminologyClientManager.ITerminologyClientFactory; 026import org.hl7.fhir.r5.utils.client.network.ClientHeaders; 027import org.hl7.fhir.utilities.FhirPublication; 028import org.hl7.fhir.utilities.ToolingClientLogger; 029import org.hl7.fhir.utilities.Utilities; 030import org.hl7.fhir.utilities.http.HTTPHeader; 031 032public class TerminologyClientR4 implements ITerminologyClient { 033 034 035 public static class TerminologyClientR4Factory implements ITerminologyClientFactory { 036 037 @Override 038 public ITerminologyClient makeClient(String id, String url, String userAgent, ToolingClientLogger logger) throws URISyntaxException { 039 return new TerminologyClientR4(id, checkEndsWith("/r4", url), userAgent); 040 } 041 042 private String checkEndsWith(String term, String url) { 043 if (url.endsWith(term)) 044 return url; 045 if (Utilities.isTxFhirOrgServer(url)) { 046 return Utilities.pathURL(url, term); 047 } 048 return url; 049 } 050 051 @Override 052 public String getVersion() { 053 return "4.0.1"; 054 } 055 } 056 057 private final FHIRToolingClient client; 058 private ClientHeaders clientHeaders; 059 private String id; 060 private ITerminologyConversionLogger logger; 061 062 public TerminologyClientR4(String id, String address, String userAgent) throws URISyntaxException { 063 this.client = new FHIRToolingClient(address, userAgent); 064 setClientHeaders(new ClientHeaders()); 065 this.id = id; 066 } 067 068 public TerminologyClientR4(String id, String address, String userAgent, ClientHeaders clientHeaders) throws URISyntaxException { 069 this.client = new FHIRToolingClient(address, userAgent); 070 setClientHeaders(clientHeaders); 071 this.id = id; 072 } 073 074 @Override 075 public String getId() { 076 return id; 077 } 078 079 080 081 public EnumSet<FhirPublication> supportableVersions() { 082 // todo 083 return EnumSet.range(FhirPublication.STU3, FhirPublication.R5); 084 } 085 086 public void setAllowedVersions(EnumSet<FhirPublication> versions) { 087 // todo 088 } 089 090 public EnumSet<FhirPublication> getAllowedVersions() { 091 return null; // todo 092 } 093 094 public FhirPublication getActualVersion() { 095 return FhirPublication.R4; 096 } 097 098 099 @Override 100 public TerminologyCapabilities getTerminologyCapabilities() throws FHIRException { 101 return (TerminologyCapabilities) convertResource("getTerminologyCapabilities.response", client.getTerminologyCapabilities()); 102 } 103 104 @Override 105 public String getAddress() { 106 return client.getAddress(); 107 } 108 109 @Override 110 public ValueSet expandValueset(ValueSet vs, Parameters p) throws FHIRException { 111 org.hl7.fhir.r4.model.ValueSet vs2 = vs == null ? null : (org.hl7.fhir.r4.model.ValueSet) convertResource("expandValueset.valueset", vs); 112 org.hl7.fhir.r4.model.Parameters p2 = p == null ? null : (org.hl7.fhir.r4.model.Parameters) convertResource("expandValueset.parameters", p); 113 try { 114 vs2 = client.expandValueset(vs2, p2); // todo: second parameter 115 return (ValueSet) convertResource("expandValueset.response", vs2); 116 } catch (org.hl7.fhir.r4.utils.client.EFhirClientException e) { 117 if (e.getServerErrors().size() > 0) { 118 throw new org.hl7.fhir.r5.utils.client.EFhirClientException(e.getCode(), e.getMessage(), (org.hl7.fhir.r5.model.OperationOutcome) convertResource("expandValueset.error", e.getServerErrors().get(0))); 119 } else { 120 throw new org.hl7.fhir.r5.utils.client.EFhirClientException(e.getCode(), e.getMessage()); 121 } 122 } 123 } 124 125 126 @Override 127 public Parameters validateCS(Parameters pin) throws FHIRException { 128 try { 129 org.hl7.fhir.r4.model.Parameters p2 = (org.hl7.fhir.r4.model.Parameters) convertResource("validateCS.request", pin); 130 p2 = client.operateType(org.hl7.fhir.r4.model.CodeSystem.class, "validate-code", p2); 131 return (Parameters) convertResource("validateCS.response", p2); 132 } catch (EFhirClientException e) { 133 if (e.getServerErrors().size() == 1) { 134 OperationOutcome op = (OperationOutcome) convertResource("validateCS.error", e.getServerErrors().get(0)); 135 throw new org.hl7.fhir.r5.utils.client.EFhirClientException(e.getCode(), e.getMessage(), op, e); 136 } else { 137 throw new org.hl7.fhir.r5.utils.client.EFhirClientException(e.getCode(), e.getMessage(), e); 138 } 139 } catch (IOException e) { 140 throw new FHIRException(e); 141 } 142 } 143 144 145 @Override 146 public Parameters subsumes(Parameters pin) throws FHIRException { 147 try { 148 org.hl7.fhir.r4.model.Parameters p2 = (org.hl7.fhir.r4.model.Parameters) convertResource("subsumes.request", pin); 149 p2 = client.operateType(org.hl7.fhir.r4.model.CodeSystem.class, "subsumes", p2); 150 return (Parameters) convertResource("subsumes.response", p2); 151 } catch (EFhirClientException e) { 152 if (e.getServerErrors().size() == 1) { 153 OperationOutcome op = (OperationOutcome) convertResource("subsumes.error", e.getServerErrors().get(0)); 154 throw new org.hl7.fhir.r5.utils.client.EFhirClientException(e.getCode(), e.getMessage(), op, e); 155 } else { 156 throw new org.hl7.fhir.r5.utils.client.EFhirClientException(e.getCode(), e.getMessage(), e); 157 } 158 } catch (IOException e) { 159 throw new FHIRException(e); 160 } 161 } 162 163 @Override 164 public Parameters validateVS(Parameters pin) throws FHIRException { 165 try { 166 org.hl7.fhir.r4.model.Parameters p2 = (org.hl7.fhir.r4.model.Parameters) convertResource("validateVS.request", pin); 167 p2 = client.operateType(org.hl7.fhir.r4.model.ValueSet.class, "validate-code", p2); 168 return (Parameters) convertResource("validateVS.response", p2); 169 } catch (EFhirClientException e) { 170 if (e.getServerErrors().size() == 1) { 171 OperationOutcome op = (OperationOutcome) convertResource("validateVS.error", e.getServerErrors().get(0)); 172 throw new org.hl7.fhir.r5.utils.client.EFhirClientException(e.getCode(), e.getMessage(), op, e); 173 } else { 174 throw new org.hl7.fhir.r5.utils.client.EFhirClientException(e.getCode(), e.getMessage(), e); 175 } 176 } catch (IOException e) { 177 throw new FHIRException(e); 178 } 179 } 180 181 @Override 182 public ITerminologyClient setTimeoutFactor(int i) { 183 client.setTimeoutFactor(i); 184 return this; 185 } 186 187 @Override 188 public ToolingClientLogger getLogger() { 189 return client.getLogger(); 190 } 191 192 @Override 193 public ITerminologyClient setLogger(ToolingClientLogger txLog) { 194 client.setLogger(txLog); 195 return this; 196 } 197 198 @Override 199 public ITerminologyClient setRetryCount(int retryCount) throws FHIRException { 200 client.setRetryCount(retryCount); 201 return this; 202 } 203 204 @Override 205 public CapabilityStatement getCapabilitiesStatementQuick() throws FHIRException { 206 return (CapabilityStatement) convertResource("getCapabilitiesStatementQuick.response", client.getCapabilitiesStatementQuick()); 207 } 208 209 @Override 210 public CapabilityStatement getCapabilitiesStatement() throws FHIRException { 211 return (CapabilityStatement) convertResource("getCapabilitiesStatement.response", client.getCapabilitiesStatement()); 212 } 213 214 @Override 215 public Parameters lookupCode(Map<String, String> params) throws FHIRException { 216 return (Parameters) convertResource("lookupCode.response", client.lookupCode(params)); 217 } 218 219 @Override 220 public Parameters lookupCode(Parameters params) throws FHIRException { 221 return (Parameters) convertResource("lookupCode.response", client.lookupCode((org.hl7.fhir.r4.model.Parameters) convertResource("lookupCode.request", params))); 222 } 223 224 @Override 225 public int getRetryCount() throws FHIRException { 226 return client.getRetryCount(); 227 } 228 229 @Override 230 public Bundle validateBatch(Bundle batch) { 231 org.hl7.fhir.r4.model.Bundle result = client.transaction((org.hl7.fhir.r4.model.Bundle) convertResource("validateBatch.request", batch)); 232 return result == null ? null : (Bundle) convertResource("validateBatch.response", result); 233 } 234 235 @Override 236 public CanonicalResource read(String type, String id) { 237 Class<Resource> t; 238 try { 239 t = (Class<Resource>) Class.forName("org.hl7.fhir.r4.model." + type);// todo: do we have to deal with any resource renaming? Use cases are limited... 240 } catch (ClassNotFoundException e) { 241 throw new FHIRException("Unable to fetch resources of type " + type + " in R2"); 242 } 243 org.hl7.fhir.r4.model.Resource r4 = client.read(t, id); 244 if (r4 == null) { 245 throw new FHIRException("Unable to fetch resource " + Utilities.pathURL(getAddress(), type, id)); 246 } 247 org.hl7.fhir.r5.model.Resource r5 = convertResource("read.result", r4); 248 if (r5 == null) { 249 throw new FHIRException("Unable to convert resource " + Utilities.pathURL(getAddress(), type, id) + " to R5 (internal representation)"); 250 } 251 if (!(r5 instanceof CanonicalResource)) { 252 throw new FHIRException("Unable to convert resource " + Utilities.pathURL(getAddress(), type, id) + " to R5 canonical resource (internal representation)"); 253 } 254 return (CanonicalResource) r5; 255 } 256 257 @Override 258 public Iterable<HTTPHeader> getClientHeaders() { 259 return clientHeaders.headers(); 260 } 261 262 @Override 263 public ITerminologyClient setClientHeaders(ClientHeaders clientHeaders) { 264 this.clientHeaders = clientHeaders; 265 if (this.clientHeaders != null) { 266 this.client.setClientHeaders(this.clientHeaders.headers()); 267 } 268 this.client.setVersionInMimeTypes(true); 269 return this; 270 } 271 272 @Override 273 public ITerminologyClient setUserAgent(String userAgent) { 274 client.setUserAgent(userAgent); 275 return this; 276 } 277 278 @Override 279 public String getUserAgent() { 280 return client.getUserAgent(); 281 } 282 283 @Override 284 public String getServerVersion() { 285 return client.getServerVersion(); 286 } 287 288 289 @Override 290 public ITerminologyClient setAcceptLanguage(String lang) { 291 client.setAcceptLanguage(lang); 292 return this; 293 } 294 295 @Override 296 public ITerminologyClient setContentLanguage(String lang) { 297 client.setContentLanguage(lang); 298 return this; 299 } 300 301 @Override 302 public int getUseCount() { 303 return client.getUseCount(); 304 } 305 306 @Override 307 public Bundle search(String type, String criteria) { 308 org.hl7.fhir.r4.model.Bundle result = client.search(type, criteria); 309 return result == null ? null : (Bundle) convertResource("search.result", result); 310 } 311 312 @Override 313 public Parameters translate(Parameters params) throws FHIRException { 314 return (Parameters) convertResource("translate.response", client.translate((org.hl7.fhir.r4.model.Parameters) convertResource("translate.request", params))); 315 } 316 317 private org.hl7.fhir.r4.model.Resource convertResource(String name, org.hl7.fhir.r5.model.Resource resource) { 318 if (logger != null) { 319 try { 320 logger.log(name, resource.fhirType(), "r5", new org.hl7.fhir.r5.formats.JsonParser().setOutputStyle(OutputStyle.PRETTY).composeBytes(resource)); 321 } catch (IOException e) { 322 throw new FHIRException(e); 323 } 324 } 325 org.hl7.fhir.r4.model.Resource res = VersionConvertorFactory_40_50.convertResource(resource); 326 if (logger != null) { 327 try { 328 logger.log(name, resource.fhirType(), "r4", new org.hl7.fhir.r4.formats.JsonParser().setOutputStyle(org.hl7.fhir.r4.formats.IParser.OutputStyle.PRETTY).composeBytes(res)); 329 } catch (IOException e) { 330 throw new FHIRException(e); 331 } 332 } 333 return res; 334 } 335 336 private org.hl7.fhir.r5.model.Resource convertResource(String name, org.hl7.fhir.r4.model.Resource resource) { 337 if (logger != null && name != null) { 338 try { 339 logger.log(name, resource.fhirType(), "r4", new org.hl7.fhir.r4.formats.JsonParser().setOutputStyle(org.hl7.fhir.r4.formats.IParser.OutputStyle.PRETTY).composeBytes(resource)); 340 } catch (IOException e) { 341 throw new FHIRException(e); 342 } 343 } 344 org.hl7.fhir.r5.model.Resource res = VersionConvertorFactory_40_50.convertResource(resource); 345 if (logger != null && name != null) { 346 try { 347 logger.log(name, resource.fhirType(), "r5", new org.hl7.fhir.r5.formats.JsonParser().setOutputStyle(OutputStyle.PRETTY).composeBytes(res)); 348 } catch (IOException e) { 349 throw new FHIRException(e); 350 } 351 } 352 return res; 353 } 354 355 @Override 356 public void setConversionLogger(ITerminologyConversionLogger logger) { 357 this.logger = logger; 358 } 359 360}