
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 @Override 145 public Parameters batchValidateCS(Parameters pin) throws FHIRException { 146 try { 147 org.hl7.fhir.r4.model.Parameters p2 = (org.hl7.fhir.r4.model.Parameters) convertResource("validateCS.request", pin); 148 p2 = client.operateType(org.hl7.fhir.r4.model.CodeSystem.class, "batch-validate-code", p2); 149 return (Parameters) convertResource("validateCS.response", p2); 150 } catch (EFhirClientException e) { 151 if (e.getServerErrors().size() == 1) { 152 OperationOutcome op = (OperationOutcome) convertResource("validateCS.error", e.getServerErrors().get(0)); 153 throw new org.hl7.fhir.r5.utils.client.EFhirClientException(e.getCode(), e.getMessage(), op, e); 154 } else { 155 throw new org.hl7.fhir.r5.utils.client.EFhirClientException(e.getCode(), e.getMessage(), e); 156 } 157 } catch (IOException e) { 158 throw new FHIRException(e); 159 } 160 } 161 162 163 164 @Override 165 public Parameters subsumes(Parameters pin) throws FHIRException { 166 try { 167 org.hl7.fhir.r4.model.Parameters p2 = (org.hl7.fhir.r4.model.Parameters) convertResource("subsumes.request", pin); 168 p2 = client.operateType(org.hl7.fhir.r4.model.CodeSystem.class, "subsumes", p2); 169 return (Parameters) convertResource("subsumes.response", p2); 170 } catch (EFhirClientException e) { 171 if (e.getServerErrors().size() == 1) { 172 OperationOutcome op = (OperationOutcome) convertResource("subsumes.error", e.getServerErrors().get(0)); 173 throw new org.hl7.fhir.r5.utils.client.EFhirClientException(e.getCode(), e.getMessage(), op, e); 174 } else { 175 throw new org.hl7.fhir.r5.utils.client.EFhirClientException(e.getCode(), e.getMessage(), e); 176 } 177 } catch (IOException e) { 178 throw new FHIRException(e); 179 } 180 } 181 182 @Override 183 public Parameters validateVS(Parameters pin) throws FHIRException { 184 try { 185 org.hl7.fhir.r4.model.Parameters p2 = (org.hl7.fhir.r4.model.Parameters) convertResource("validateVS.request", pin); 186 p2 = client.operateType(org.hl7.fhir.r4.model.ValueSet.class, "validate-code", p2); 187 return (Parameters) convertResource("validateVS.response", p2); 188 } catch (EFhirClientException e) { 189 if (e.getServerErrors().size() == 1) { 190 OperationOutcome op = (OperationOutcome) convertResource("validateVS.error", e.getServerErrors().get(0)); 191 throw new org.hl7.fhir.r5.utils.client.EFhirClientException(e.getCode(), e.getMessage(), op, e); 192 } else { 193 throw new org.hl7.fhir.r5.utils.client.EFhirClientException(e.getCode(), e.getMessage(), e); 194 } 195 } catch (IOException e) { 196 throw new FHIRException(e); 197 } 198 } 199 200 @Override 201 public Parameters batchValidateVS(Parameters pin) throws FHIRException { 202 try { 203 org.hl7.fhir.r4.model.Parameters p2 = (org.hl7.fhir.r4.model.Parameters) convertResource("validateVS.request", pin); 204 p2 = client.operateType(org.hl7.fhir.r4.model.ValueSet.class, "batch-validate-code", p2); 205 return (Parameters) convertResource("validateVS.response", p2); 206 } catch (EFhirClientException e) { 207 if (e.getServerErrors().size() == 1) { 208 OperationOutcome op = (OperationOutcome) convertResource("validateVS.error", e.getServerErrors().get(0)); 209 throw new org.hl7.fhir.r5.utils.client.EFhirClientException(e.getCode(), e.getMessage(), op, e); 210 } else { 211 throw new org.hl7.fhir.r5.utils.client.EFhirClientException(e.getCode(), e.getMessage(), e); 212 } 213 } catch (IOException e) { 214 throw new FHIRException(e); 215 } 216 } 217 218 @Override 219 public ITerminologyClient setTimeoutFactor(int i) { 220 client.setTimeoutFactor(i); 221 return this; 222 } 223 224 @Override 225 public ToolingClientLogger getLogger() { 226 return client.getLogger(); 227 } 228 229 @Override 230 public ITerminologyClient setLogger(ToolingClientLogger txLog) { 231 client.setLogger(txLog); 232 return this; 233 } 234 235 @Override 236 public ITerminologyClient setRetryCount(int retryCount) throws FHIRException { 237 client.setRetryCount(retryCount); 238 return this; 239 } 240 241 @Override 242 public CapabilityStatement getCapabilitiesStatementQuick() throws FHIRException { 243 return (CapabilityStatement) convertResource("getCapabilitiesStatementQuick.response", client.getCapabilitiesStatementQuick()); 244 } 245 246 @Override 247 public CapabilityStatement getCapabilitiesStatement() throws FHIRException { 248 return (CapabilityStatement) convertResource("getCapabilitiesStatement.response", client.getCapabilitiesStatement()); 249 } 250 251 @Override 252 public Parameters lookupCode(Map<String, String> params) throws FHIRException { 253 return (Parameters) convertResource("lookupCode.response", client.lookupCode(params)); 254 } 255 256 @Override 257 public Parameters lookupCode(Parameters params) throws FHIRException { 258 return (Parameters) convertResource("lookupCode.response", client.lookupCode((org.hl7.fhir.r4.model.Parameters) convertResource("lookupCode.request", params))); 259 } 260 261 @Override 262 public int getRetryCount() throws FHIRException { 263 return client.getRetryCount(); 264 } 265 266 @Override 267 public Bundle batch(Bundle batch) { 268 org.hl7.fhir.r4.model.Bundle result = client.transaction((org.hl7.fhir.r4.model.Bundle) convertResource("validateBatch.request", batch)); 269 return result == null ? null : (Bundle) convertResource("validateBatch.response", result); 270 } 271 272 @Override 273 public CanonicalResource read(String type, String id) { 274 Class<Resource> t; 275 try { 276 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... 277 } catch (ClassNotFoundException e) { 278 throw new FHIRException("Unable to fetch resources of type " + type + " in R2"); 279 } 280 org.hl7.fhir.r4.model.Resource r4 = client.read(t, id); 281 if (r4 == null) { 282 throw new FHIRException("Unable to fetch resource " + Utilities.pathURL(getAddress(), type, id)); 283 } 284 org.hl7.fhir.r5.model.Resource r5 = convertResource("read.result", r4); 285 if (r5 == null) { 286 throw new FHIRException("Unable to convert resource " + Utilities.pathURL(getAddress(), type, id) + " to R5 (internal representation)"); 287 } 288 if (!(r5 instanceof CanonicalResource)) { 289 throw new FHIRException("Unable to convert resource " + Utilities.pathURL(getAddress(), type, id) + " to R5 canonical resource (internal representation)"); 290 } 291 return (CanonicalResource) r5; 292 } 293 294 @Override 295 public Iterable<HTTPHeader> getClientHeaders() { 296 return clientHeaders.headers(); 297 } 298 299 @Override 300 public ITerminologyClient setClientHeaders(ClientHeaders clientHeaders) { 301 this.clientHeaders = clientHeaders; 302 if (this.clientHeaders != null) { 303 this.client.setClientHeaders(this.clientHeaders.headers()); 304 } 305 this.client.setVersionInMimeTypes(true); 306 return this; 307 } 308 309 @Override 310 public ITerminologyClient setUserAgent(String userAgent) { 311 client.setUserAgent(userAgent); 312 return this; 313 } 314 315 @Override 316 public String getUserAgent() { 317 return client.getUserAgent(); 318 } 319 320 @Override 321 public String getServerVersion() { 322 return client.getServerVersion(); 323 } 324 325 326 @Override 327 public ITerminologyClient setAcceptLanguage(String lang) { 328 client.setAcceptLanguage(lang); 329 return this; 330 } 331 332 @Override 333 public ITerminologyClient setContentLanguage(String lang) { 334 client.setContentLanguage(lang); 335 return this; 336 } 337 338 @Override 339 public int getUseCount() { 340 return client.getUseCount(); 341 } 342 343 @Override 344 public Bundle search(String type, String criteria) { 345 org.hl7.fhir.r4.model.Bundle result = client.search(type, criteria); 346 return result == null ? null : (Bundle) convertResource("search.result", result); 347 } 348 349 @Override 350 public Parameters translate(Parameters params) throws FHIRException { 351 return (Parameters) convertResource("translate.response", client.translate((org.hl7.fhir.r4.model.Parameters) convertResource("translate.request", params))); 352 } 353 354 private org.hl7.fhir.r4.model.Resource convertResource(String name, org.hl7.fhir.r5.model.Resource resource) { 355 if (logger != null) { 356 try { 357 logger.log(name, resource.fhirType(), "r5", new org.hl7.fhir.r5.formats.JsonParser().setOutputStyle(OutputStyle.PRETTY).composeBytes(resource)); 358 } catch (IOException e) { 359 throw new FHIRException(e); 360 } 361 } 362 org.hl7.fhir.r4.model.Resource res = VersionConvertorFactory_40_50.convertResource(resource); 363 if (logger != null) { 364 try { 365 logger.log(name, resource.fhirType(), "r4", new org.hl7.fhir.r4.formats.JsonParser().setOutputStyle(org.hl7.fhir.r4.formats.IParser.OutputStyle.PRETTY).composeBytes(res)); 366 } catch (IOException e) { 367 throw new FHIRException(e); 368 } 369 } 370 return res; 371 } 372 373 private org.hl7.fhir.r5.model.Resource convertResource(String name, org.hl7.fhir.r4.model.Resource resource) { 374 if (logger != null && name != null) { 375 try { 376 logger.log(name, resource.fhirType(), "r4", new org.hl7.fhir.r4.formats.JsonParser().setOutputStyle(org.hl7.fhir.r4.formats.IParser.OutputStyle.PRETTY).composeBytes(resource)); 377 } catch (IOException e) { 378 throw new FHIRException(e); 379 } 380 } 381 org.hl7.fhir.r5.model.Resource res = VersionConvertorFactory_40_50.convertResource(resource); 382 if (logger != null && name != null) { 383 try { 384 logger.log(name, resource.fhirType(), "r5", new org.hl7.fhir.r5.formats.JsonParser().setOutputStyle(OutputStyle.PRETTY).composeBytes(res)); 385 } catch (IOException e) { 386 throw new FHIRException(e); 387 } 388 } 389 return res; 390 } 391 392 @Override 393 public void setConversionLogger(ITerminologyConversionLogger logger) { 394 this.logger = logger; 395 } 396 397 @Override 398 public OperationOutcome validateResource(org.hl7.fhir.r5.model.Resource res) { 399 try { 400 org.hl7.fhir.r4.model.Resource r2 = convertResource("validate.request", res); 401 Resource p2 = client.validate(r2, null); 402 return (OperationOutcome) convertResource("validateVS.response", p2); 403 } catch (EFhirClientException e) { 404 if (e.getServerErrors().size() == 1) { 405 OperationOutcome op = (OperationOutcome) convertResource("validateVS.error", e.getServerErrors().get(0)); 406 throw new org.hl7.fhir.r5.utils.client.EFhirClientException(e.getCode(), e.getMessage(), op, e); 407 } else { 408 throw new org.hl7.fhir.r5.utils.client.EFhirClientException(e.getCode(), e.getMessage(), e); 409 } 410 } 411 } 412 413}