001package org.hl7.fhir.r4.utils.client; 002 003 004/* 005 Copyright (c) 2011+, HL7, Inc. 006 All rights reserved. 007 008 Redistribution and use in source and binary forms, with or without modification, 009 are permitted provided that the following conditions are met: 010 011 * Redistributions of source code must retain the above copyright notice, this 012 list of conditions and the following disclaimer. 013 * Redistributions in binary form must reproduce the above copyright notice, 014 this list of conditions and the following disclaimer in the documentation 015 and/or other materials provided with the distribution. 016 * Neither the name of HL7 nor the names of its contributors may be used to 017 endorse or promote products derived from this software without specific 018 prior written permission. 019 020 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 021 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 022 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 023 IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 024 INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 025 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 026 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 027 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 028 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 029 POSSIBILITY OF SUCH DAMAGE. 030 031*/ 032 033import java.net.URI; 034import java.net.URISyntaxException; 035import java.util.HashMap; 036import java.util.List; 037import java.util.Map; 038 039import org.apache.http.Header; 040import org.apache.http.HttpHost; 041import org.hl7.fhir.r4.model.Bundle; 042import org.hl7.fhir.r4.model.CapabilityStatement; 043import org.hl7.fhir.r4.model.CodeSystem; 044import org.hl7.fhir.r4.model.Coding; 045import org.hl7.fhir.r4.model.ConceptMap; 046import org.hl7.fhir.r4.model.OperationOutcome; 047import org.hl7.fhir.r4.model.Parameters; 048import org.hl7.fhir.r4.model.Parameters.ParametersParameterComponent; 049import org.hl7.fhir.r4.model.PrimitiveType; 050import org.hl7.fhir.r4.model.Resource; 051import org.hl7.fhir.r4.model.StringType; 052import org.hl7.fhir.r4.model.ValueSet; 053import org.hl7.fhir.utilities.Utilities; 054 055/** 056 * Very Simple RESTful client. This is purely for use in the standalone 057 * tools jar packages. It doesn't support many features, only what the tools 058 * need. 059 * 060 * To use, initialize class and set base service URI as follows: 061 * 062 * <pre><code> 063 * FHIRSimpleClient fhirClient = new FHIRSimpleClient(); 064 * fhirClient.initialize("http://my.fhir.domain/myServiceRoot"); 065 * </code></pre> 066 * 067 * Default Accept and Content-Type headers are application/fhir+xml and application/fhir+json. 068 * 069 * These can be changed by invoking the following setter functions: 070 * 071 * <pre><code> 072 * setPreferredResourceFormat() 073 * setPreferredFeedFormat() 074 * </code></pre> 075 * 076 * TODO Review all sad paths. 077 * 078 * @author Claude Nanjo 079 * 080 */ 081public class FHIRToolingClient { 082 083 public static final String DATETIME_FORMAT = "yyyy-MM-dd'T'HH:mm:ssK"; 084 public static final String DATE_FORMAT = "yyyy-MM-dd"; 085 public static final String hostKey = "http.proxyHost"; 086 public static final String portKey = "http.proxyPort"; 087 088 private String base; 089 private ResourceAddress resourceAddress; 090 private ResourceFormat preferredResourceFormat; 091 private int maxResultSetSize = -1;//_count 092 private CapabilityStatement capabilities; 093 094 private ClientUtils utils = new ClientUtils(); 095 096 //Pass enpoint for client - URI 097 public FHIRToolingClient(String baseServiceUrl) throws URISyntaxException { 098 preferredResourceFormat = ResourceFormat.RESOURCE_XML; 099 detectProxy(); 100 initialize(baseServiceUrl); 101 } 102 103 public FHIRToolingClient(String baseServiceUrl, String username, String password) throws URISyntaxException { 104 preferredResourceFormat = ResourceFormat.RESOURCE_XML; 105 utils.setUsername(username); 106 utils.setPassword(password); 107 detectProxy(); 108 initialize(baseServiceUrl); 109 } 110 111 public void configureProxy(String proxyHost, int proxyPort) { 112 utils.setProxy(new HttpHost(proxyHost, proxyPort)); 113 } 114 115 public void detectProxy() { 116 String host = System.getenv(hostKey); 117 String port = System.getenv(portKey); 118 119 if(host==null) { 120 host = System.getProperty(hostKey); 121 } 122 123 if(port==null) { 124 port = System.getProperty(portKey); 125 } 126 127 if(host!=null && port!=null) { 128 this.configureProxy(host, Integer.parseInt(port)); 129 } 130 } 131 132 public void initialize(String baseServiceUrl) throws URISyntaxException { 133 base = baseServiceUrl; 134 resourceAddress = new ResourceAddress(baseServiceUrl); 135 this.maxResultSetSize = -1; 136 checkCapabilities(); 137 } 138 139 private void checkCapabilities() { 140 try { 141 capabilities = getCapabilitiesStatementQuick(); 142 } catch (Throwable e) { 143 } 144 } 145 146 public String getPreferredResourceFormat() { 147 return preferredResourceFormat.getHeader(); 148 } 149 150 public void setPreferredResourceFormat(ResourceFormat resourceFormat) { 151 preferredResourceFormat = resourceFormat; 152 } 153 154 public int getMaximumRecordCount() { 155 return maxResultSetSize; 156 } 157 158 public void setMaximumRecordCount(int maxResultSetSize) { 159 this.maxResultSetSize = maxResultSetSize; 160 } 161 162 public CapabilityStatement getCapabilitiesStatement() { 163 CapabilityStatement conformance = null; 164 try { 165 conformance = (CapabilityStatement)utils.issueGetResourceRequest(resourceAddress.resolveMetadataUri(false), getPreferredResourceFormat()).getReference(); 166 } catch(Exception e) { 167 handleException("An error has occurred while trying to fetch the server's conformance statement", e); 168 } 169 return conformance; 170 } 171 172 public CapabilityStatement getCapabilitiesStatementQuick() throws EFhirClientException { 173 if (capabilities != null) 174 return capabilities; 175 try { 176 capabilities = (CapabilityStatement)utils.issueGetResourceRequest(resourceAddress.resolveMetadataUri(true), getPreferredResourceFormat()).getReference(); 177 } catch(Exception e) { 178 handleException("An error has occurred while trying to fetch the server's conformance statement", e); 179 } 180 return capabilities; 181 } 182 183 public <T extends Resource> T read(Class<T> resourceClass, String id) {//TODO Change this to AddressableResource 184 ResourceRequest<T> result = null; 185 try { 186 result = utils.issueGetResourceRequest(resourceAddress.resolveGetUriFromResourceClassAndId(resourceClass, id), getPreferredResourceFormat()); 187 result.addErrorStatus(410);//gone 188 result.addErrorStatus(404);//unknown 189 result.addSuccessStatus(200);//Only one for now 190 if(result.isUnsuccessfulRequest()) { 191 throw new EFhirClientException("Server returned error code " + result.getHttpStatus(), (OperationOutcome)result.getPayload()); 192 } 193 } catch (Exception e) { 194 handleException("An error has occurred while trying to read this resource", e); 195 } 196 return result.getPayload(); 197 } 198 199 public <T extends Resource> T vread(Class<T> resourceClass, String id, String version) { 200 ResourceRequest<T> result = null; 201 try { 202 result = utils.issueGetResourceRequest(resourceAddress.resolveGetUriFromResourceClassAndIdAndVersion(resourceClass, id, version), getPreferredResourceFormat()); 203 result.addErrorStatus(410);//gone 204 result.addErrorStatus(404);//unknown 205 result.addErrorStatus(405);//unknown 206 result.addSuccessStatus(200);//Only one for now 207 if(result.isUnsuccessfulRequest()) { 208 throw new EFhirClientException("Server returned error code " + result.getHttpStatus(), (OperationOutcome)result.getPayload()); 209 } 210 } catch (Exception e) { 211 handleException("An error has occurred while trying to read this version of the resource", e); 212 } 213 return result.getPayload(); 214 } 215 216 // GET fhir/ValueSet?url=http://hl7.org/fhir/ValueSet/clinical-findings&version=0.8 217 218 public <T extends Resource> T getCanonical(Class<T> resourceClass, String canonicalURL) { 219 ResourceRequest<T> result = null; 220 try { 221 result = utils.issueGetResourceRequest(resourceAddress.resolveGetUriFromResourceClassAndCanonical(resourceClass, canonicalURL), getPreferredResourceFormat()); 222 result.addErrorStatus(410);//gone 223 result.addErrorStatus(404);//unknown 224 result.addErrorStatus(405);//unknown 225 result.addSuccessStatus(200);//Only one for now 226 if(result.isUnsuccessfulRequest()) { 227 throw new EFhirClientException("Server returned error code " + result.getHttpStatus(), (OperationOutcome)result.getPayload()); 228 } 229 } catch (Exception e) { 230 handleException("An error has occurred while trying to read this version of the resource", e); 231 } 232 Bundle bnd = (Bundle) result.getPayload(); 233 if (bnd.getEntry().size() == 0) 234 throw new EFhirClientException("No matching resource found for canonical URL '"+canonicalURL+"'"); 235 if (bnd.getEntry().size() > 1) 236 throw new EFhirClientException("Multiple matching resources found for canonical URL '"+canonicalURL+"'"); 237 return (T) bnd.getEntry().get(0).getResource(); 238 } 239 240// 241// public <T extends Resource> T update(Class<T> resourceClass, T resource, String id) { 242// ResourceRequest<T> result = null; 243// try { 244// List<Header> headers = null; 245// result = utils.issuePutRequest(resourceAddress.resolveGetUriFromResourceClassAndId(resourceClass, id),utils.getResourceAsByteArray(resource, false, isJson(getPreferredResourceFormat())), getPreferredResourceFormat(), headers, proxy); 246// result.addErrorStatus(410);//gone 247// result.addErrorStatus(404);//unknown 248// result.addErrorStatus(405); 249// result.addErrorStatus(422);//Unprocessable Entity 250// result.addSuccessStatus(200); 251// result.addSuccessStatus(201); 252// if(result.isUnsuccessfulRequest()) { 253// throw new EFhirClientException("Server returned error code " + result.getHttpStatus(), (OperationOutcome)result.getPayload()); 254// } 255// } catch(Exception e) { 256// throw new EFhirClientException("An error has occurred while trying to update this resource", e); 257// } 258// // TODO oe 26.1.2015 could be made nicer if only OperationOutcome locationheader is returned with an operationOutcome would be returned (and not the resource also) we make another read 259// try { 260// OperationOutcome operationOutcome = (OperationOutcome)result.getPayload(); 261// ResourceAddress.ResourceVersionedIdentifier resVersionedIdentifier = ResourceAddress.parseCreateLocation(result.getLocation()); 262// return this.vread(resourceClass, resVersionedIdentifier.getId(),resVersionedIdentifier.getVersionId()); 263// } catch(ClassCastException e) { 264// // if we fall throught we have the correct type already in the create 265// } 266// 267// return result.getPayload(); 268// } 269 270// 271// public <T extends Resource> boolean delete(Class<T> resourceClass, String id) { 272// try { 273// return utils.issueDeleteRequest(resourceAddress.resolveGetUriFromResourceClassAndId(resourceClass, id), proxy); 274// } catch(Exception e) { 275// throw new EFhirClientException("An error has occurred while trying to delete this resource", e); 276// } 277// 278// } 279 280// 281// public <T extends Resource> OperationOutcome create(Class<T> resourceClass, T resource) { 282// ResourceRequest<T> resourceRequest = null; 283// try { 284// List<Header> headers = null; 285// resourceRequest = utils.issuePostRequest(resourceAddress.resolveGetUriFromResourceClass(resourceClass),utils.getResourceAsByteArray(resource, false, isJson(getPreferredResourceFormat())), getPreferredResourceFormat(), headers, proxy); 286// resourceRequest.addSuccessStatus(201); 287// if(resourceRequest.isUnsuccessfulRequest()) { 288// throw new EFhirClientException("Server responded with HTTP error code " + resourceRequest.getHttpStatus(), (OperationOutcome)resourceRequest.getPayload()); 289// } 290// } catch(Exception e) { 291// handleException("An error has occurred while trying to create this resource", e); 292// } 293// OperationOutcome operationOutcome = null;; 294// try { 295// operationOutcome = (OperationOutcome)resourceRequest.getPayload(); 296// ResourceAddress.ResourceVersionedIdentifier resVersionedIdentifier = 297// ResourceAddress.parseCreateLocation(resourceRequest.getLocation()); 298// OperationOutcomeIssueComponent issue = operationOutcome.addIssue(); 299// issue.setSeverity(IssueSeverity.INFORMATION); 300// issue.setUserData(ResourceAddress.ResourceVersionedIdentifier.class.toString(), 301// resVersionedIdentifier); 302// return operationOutcome; 303// } catch(ClassCastException e) { 304// // some server (e.g. grahams) returns the resource directly 305// operationOutcome = new OperationOutcome(); 306// OperationOutcomeIssueComponent issue = operationOutcome.addIssue(); 307// issue.setSeverity(IssueSeverity.INFORMATION); 308// issue.setUserData(ResourceRequest.class.toString(), 309// resourceRequest.getPayload()); 310// return operationOutcome; 311// } 312// } 313 314// 315// public <T extends Resource> Bundle history(Calendar lastUpdate, Class<T> resourceClass, String id) { 316// Bundle history = null; 317// try { 318// history = utils.issueGetFeedRequest(resourceAddress.resolveGetHistoryForResourceId(resourceClass, id, lastUpdate, maxResultSetSize), getPreferredResourceFormat(), proxy); 319// } catch (Exception e) { 320// handleException("An error has occurred while trying to retrieve history information for this resource", e); 321// } 322// return history; 323// } 324 325// 326// public <T extends Resource> Bundle history(Date lastUpdate, Class<T> resourceClass, String id) { 327// Bundle history = null; 328// try { 329// history = utils.issueGetFeedRequest(resourceAddress.resolveGetHistoryForResourceId(resourceClass, id, lastUpdate, maxResultSetSize), getPreferredResourceFormat(), proxy); 330// } catch (Exception e) { 331// handleException("An error has occurred while trying to retrieve history information for this resource", e); 332// } 333// return history; 334// } 335// 336// 337// public <T extends Resource> Bundle history(Calendar lastUpdate, Class<T> resourceClass) { 338// Bundle history = null; 339// try { 340// history = utils.issueGetFeedRequest(resourceAddress.resolveGetHistoryForResourceType(resourceClass, lastUpdate, maxResultSetSize), getPreferredResourceFormat(), proxy); 341// } catch (Exception e) { 342// handleException("An error has occurred while trying to retrieve history information for this resource type", e); 343// } 344// return history; 345// } 346// 347// 348// public <T extends Resource> Bundle history(Date lastUpdate, Class<T> resourceClass) { 349// Bundle history = null; 350// try { 351// history = utils.issueGetFeedRequest(resourceAddress.resolveGetHistoryForResourceType(resourceClass, lastUpdate, maxResultSetSize), getPreferredResourceFormat(), proxy); 352// } catch (Exception e) { 353// handleException("An error has occurred while trying to retrieve history information for this resource type", e); 354// } 355// return history; 356// } 357// 358// 359// public <T extends Resource> Bundle history(Class<T> resourceClass) { 360// Bundle history = null; 361// try { 362// history = utils.issueGetFeedRequest(resourceAddress.resolveGetHistoryForResourceType(resourceClass, maxResultSetSize), getPreferredResourceFormat(), proxy); 363// } catch (Exception e) { 364// handleException("An error has occurred while trying to retrieve history information for this resource type", e); 365// } 366// return history; 367// } 368// 369// 370// public <T extends Resource> Bundle history(Class<T> resourceClass, String id) { 371// Bundle history = null; 372// try { 373// history = utils.issueGetFeedRequest(resourceAddress.resolveGetHistoryForResourceId(resourceClass, id, maxResultSetSize), getPreferredResourceFormat(), proxy); 374// } catch (Exception e) { 375// handleException("An error has occurred while trying to retrieve history information for this resource", e); 376// } 377// return history; 378// } 379// 380// 381// public <T extends Resource> Bundle history(Date lastUpdate) { 382// Bundle history = null; 383// try { 384// history = utils.issueGetFeedRequest(resourceAddress.resolveGetHistoryForAllResources(lastUpdate, maxResultSetSize), getPreferredResourceFormat(), proxy); 385// } catch (Exception e) { 386// handleException("An error has occurred while trying to retrieve history since last update",e); 387// } 388// return history; 389// } 390// 391// 392// public <T extends Resource> Bundle history(Calendar lastUpdate) { 393// Bundle history = null; 394// try { 395// history = utils.issueGetFeedRequest(resourceAddress.resolveGetHistoryForAllResources(lastUpdate, maxResultSetSize), getPreferredResourceFormat(), proxy); 396// } catch (Exception e) { 397// handleException("An error has occurred while trying to retrieve history since last update",e); 398// } 399// return history; 400// } 401// 402// 403// public <T extends Resource> Bundle history() { 404// Bundle history = null; 405// try { 406// history = utils.issueGetFeedRequest(resourceAddress.resolveGetHistoryForAllResources(maxResultSetSize), getPreferredResourceFormat(), proxy); 407// } catch (Exception e) { 408// handleException("An error has occurred while trying to retrieve history since last update",e); 409// } 410// return history; 411// } 412// 413// 414// public <T extends Resource> Bundle search(Class<T> resourceClass, Map<String, String> parameters) { 415// Bundle searchResults = null; 416// try { 417// searchResults = utils.issueGetFeedRequest(resourceAddress.resolveSearchUri(resourceClass, parameters), getPreferredResourceFormat(), proxy); 418// } catch (Exception e) { 419// handleException("Error performing search with parameters " + parameters, e); 420// } 421// return searchResults; 422// } 423// 424// 425// public <T extends Resource> Bundle searchPost(Class<T> resourceClass, T resource, Map<String, String> parameters) { 426// Bundle searchResults = null; 427// try { 428// searchResults = utils.issuePostFeedRequest(resourceAddress.resolveSearchUri(resourceClass, new HashMap<String, String>()), parameters, "src", resource, getPreferredResourceFormat()); 429// } catch (Exception e) { 430// handleException("Error performing search with parameters " + parameters, e); 431// } 432// return searchResults; 433// } 434 435 436 public <T extends Resource> Parameters operateType(Class<T> resourceClass, String name, Parameters params) { 437 boolean complex = false; 438 for (ParametersParameterComponent p : params.getParameter()) 439 complex = complex || !(p.getValue() instanceof PrimitiveType); 440 Parameters searchResults = null; 441 String ps = ""; 442 try { 443 if (!complex) 444 for (ParametersParameterComponent p : params.getParameter()) 445 if (p.getValue() instanceof PrimitiveType) 446 ps += p.getName() + "=" + Utilities.encodeUri(((PrimitiveType) p.getValue()).asStringValue())+"&"; 447 ResourceRequest<T> result; 448 if (complex) 449 result = utils.issuePostRequest(resourceAddress.resolveOperationURLFromClass(resourceClass, name, ps), utils.getResourceAsByteArray(params, false, isJson(getPreferredResourceFormat())), getPreferredResourceFormat()); 450 else 451 result = utils.issueGetResourceRequest(resourceAddress.resolveOperationURLFromClass(resourceClass, name, ps), getPreferredResourceFormat()); 452 result.addErrorStatus(410);//gone 453 result.addErrorStatus(404);//unknown 454 result.addSuccessStatus(200);//Only one for now 455 if(result.isUnsuccessfulRequest()) 456 throw new EFhirClientException("Server returned error code " + result.getHttpStatus(), (OperationOutcome)result.getPayload()); 457 if (result.getPayload() instanceof Parameters) 458 return (Parameters) result.getPayload(); 459 else { 460 Parameters p_out = new Parameters(); 461 p_out.addParameter().setName("return").setResource(result.getPayload()); 462 return p_out; 463 } 464 } catch (Exception e) { 465 handleException("Error performing operation '"+name+"' with parameters " + ps, e); 466 } 467 return null; 468 } 469 470 471 public Bundle transaction(Bundle batch) { 472 Bundle transactionResult = null; 473 try { 474 transactionResult = utils.postBatchRequest(resourceAddress.getBaseServiceUri(), utils.getFeedAsByteArray(batch, false, isJson(getPreferredResourceFormat())), getPreferredResourceFormat()); 475 } catch (Exception e) { 476 handleException("An error occurred trying to process this transaction request", e); 477 } 478 return transactionResult; 479 } 480 481 @SuppressWarnings("unchecked") 482 483 public <T extends Resource> OperationOutcome validate(Class<T> resourceClass, T resource, String id) { 484 ResourceRequest<T> result = null; 485 try { 486 result = utils.issuePostRequest(resourceAddress.resolveValidateUri(resourceClass, id), utils.getResourceAsByteArray(resource, false, isJson(getPreferredResourceFormat())), getPreferredResourceFormat()); 487 result.addErrorStatus(400);//gone 488 result.addErrorStatus(422);//Unprocessable Entity 489 result.addSuccessStatus(200);//OK 490 if(result.isUnsuccessfulRequest()) { 491 throw new EFhirClientException("Server returned error code " + result.getHttpStatus(), (OperationOutcome)result.getPayload()); 492 } 493 } catch(Exception e) { 494 handleException("An error has occurred while trying to validate this resource", e); 495 } 496 return (OperationOutcome)result.getPayload(); 497 } 498 499 /* change to meta operations 500 501 public List<Coding> getAllTags() { 502 TagListRequest result = null; 503 try { 504 result = utils.issueGetRequestForTagList(resourceAddress.resolveGetAllTags(), getPreferredResourceFormat(), null, proxy); 505 } catch (Exception e) { 506 handleException("An error has occurred while trying to retrieve all tags", e); 507 } 508 return result.getPayload(); 509 } 510 511 512 public <T extends Resource> List<Coding> getAllTagsForResourceType(Class<T> resourceClass) { 513 TagListRequest result = null; 514 try { 515 result = utils.issueGetRequestForTagList(resourceAddress.resolveGetAllTagsForResourceType(resourceClass), getPreferredResourceFormat(), null, proxy); 516 } catch (Exception e) { 517 handleException("An error has occurred while trying to retrieve tags for this resource type", e); 518 } 519 return result.getPayload(); 520 } 521 522 523 public <T extends Resource> List<Coding> getTagsForReference(Class<T> resource, String id) { 524 TagListRequest result = null; 525 try { 526 result = utils.issueGetRequestForTagList(resourceAddress.resolveGetTagsForReference(resource, id), getPreferredResourceFormat(), null, proxy); 527 } catch (Exception e) { 528 handleException("An error has occurred while trying to retrieve tags for this resource", e); 529 } 530 return result.getPayload(); 531 } 532 533 534 public <T extends Resource> List<Coding> getTagsForResourceVersion(Class<T> resource, String id, String versionId) { 535 TagListRequest result = null; 536 try { 537 result = utils.issueGetRequestForTagList(resourceAddress.resolveGetTagsForResourceVersion(resource, id, versionId), getPreferredResourceFormat(), null, proxy); 538 } catch (Exception e) { 539 handleException("An error has occurred while trying to retrieve tags for this resource version", e); 540 } 541 return result.getPayload(); 542 } 543 544// 545// public <T extends Resource> boolean deleteTagsForReference(Class<T> resourceClass, String id) { 546// try { 547// return utils.issueDeleteRequest(resourceAddress.resolveGetTagsForReference(resourceClass, id), proxy); 548// } catch(Exception e) { 549// handleException("An error has occurred while trying to retrieve tags for this resource version", e); 550// throw new EFhirClientException("An error has occurred while trying to delete this resource", e); 551// } 552// 553// } 554// 555// 556// public <T extends Resource> boolean deleteTagsForResourceVersion(Class<T> resourceClass, String id, List<Coding> tags, String version) { 557// try { 558// return utils.issueDeleteRequest(resourceAddress.resolveGetTagsForResourceVersion(resourceClass, id, version), proxy); 559// } catch(Exception e) { 560// handleException("An error has occurred while trying to retrieve tags for this resource version", e); 561// throw new EFhirClientException("An error has occurred while trying to delete this resource", e); 562// } 563// } 564 565 566 public <T extends Resource> List<Coding> createTags(List<Coding> tags, Class<T> resourceClass, String id) { 567 TagListRequest request = null; 568 try { 569 request = utils.issuePostRequestForTagList(resourceAddress.resolveGetTagsForReference(resourceClass, id),utils.getTagListAsByteArray(tags, false, isJson(getPreferredResourceFormat())), getPreferredResourceFormat(), null, proxy); 570 request.addSuccessStatus(201); 571 request.addSuccessStatus(200); 572 if(request.isUnsuccessfulRequest()) { 573 throw new EFhirClientException("Server responded with HTTP error code " + request.getHttpStatus()); 574 } 575 } catch(Exception e) { 576 handleException("An error has occurred while trying to set tags for this resource", e); 577 } 578 return request.getPayload(); 579 } 580 581 582 public <T extends Resource> List<Coding> createTags(List<Coding> tags, Class<T> resourceClass, String id, String version) { 583 TagListRequest request = null; 584 try { 585 request = utils.issuePostRequestForTagList(resourceAddress.resolveGetTagsForResourceVersion(resourceClass, id, version),utils.getTagListAsByteArray(tags, false, isJson(getPreferredResourceFormat())), getPreferredResourceFormat(), null, proxy); 586 request.addSuccessStatus(201); 587 request.addSuccessStatus(200); 588 if(request.isUnsuccessfulRequest()) { 589 throw new EFhirClientException("Server responded with HTTP error code " + request.getHttpStatus()); 590 } 591 } catch(Exception e) { 592 handleException("An error has occurred while trying to set the tags for this resource version", e); 593 } 594 return request.getPayload(); 595 } 596 597 598 public <T extends Resource> List<Coding> deleteTags(List<Coding> tags, Class<T> resourceClass, String id, String version) { 599 TagListRequest request = null; 600 try { 601 request = utils.issuePostRequestForTagList(resourceAddress.resolveDeleteTagsForResourceVersion(resourceClass, id, version),utils.getTagListAsByteArray(tags, false, isJson(getPreferredResourceFormat())), getPreferredResourceFormat(), null, proxy); 602 request.addSuccessStatus(201); 603 request.addSuccessStatus(200); 604 if(request.isUnsuccessfulRequest()) { 605 throw new EFhirClientException("Server responded with HTTP error code " + request.getHttpStatus()); 606 } 607 } catch(Exception e) { 608 handleException("An error has occurred while trying to delete the tags for this resource version", e); 609 } 610 return request.getPayload(); 611 } 612 */ 613 614 /** 615 * Helper method to prevent nesting of previously thrown EFhirClientExceptions 616 * 617 * @param e 618 * @throws EFhirClientException 619 */ 620 protected void handleException(String message, Exception e) throws EFhirClientException { 621 if(e instanceof EFhirClientException) { 622 throw (EFhirClientException)e; 623 } else { 624 throw new EFhirClientException(message, e); 625 } 626 } 627 628 /** 629 * Helper method to determine whether desired resource representation 630 * is Json or XML. 631 * 632 * @param format 633 * @return 634 */ 635 protected boolean isJson(String format) { 636 boolean isJson = false; 637 if(format.toLowerCase().contains("json")) { 638 isJson = true; 639 } 640 return isJson; 641 } 642 643 public Bundle fetchFeed(String url) { 644 Bundle feed = null; 645 try { 646 feed = utils.issueGetFeedRequest(new URI(url), getPreferredResourceFormat()); 647 } catch (Exception e) { 648 handleException("An error has occurred while trying to retrieve history since last update",e); 649 } 650 return feed; 651 } 652 653 public ValueSet expandValueset(ValueSet source, Parameters expParams) { 654 List<Header> headers = null; 655 Parameters p = expParams == null ? new Parameters() : expParams.copy(); 656 p.addParameter().setName("valueSet").setResource(source); 657 ResourceRequest<Resource> result = utils.issuePostRequest(resourceAddress.resolveOperationUri(ValueSet.class, "expand"), 658 utils.getResourceAsByteArray(p, false, isJson(getPreferredResourceFormat())), getPreferredResourceFormat(), headers); 659 result.addErrorStatus(410);//gone 660 result.addErrorStatus(404);//unknown 661 result.addErrorStatus(405); 662 result.addErrorStatus(422);//Unprocessable Entity 663 result.addSuccessStatus(200); 664 result.addSuccessStatus(201); 665 if(result.isUnsuccessfulRequest()) { 666 throw new EFhirClientException("Server returned error code " + result.getHttpStatus(), (OperationOutcome)result.getPayload()); 667 } 668 return (ValueSet) result.getPayload(); 669 } 670 671 672 public Parameters lookupCode(Map<String, String> params) { 673 ResourceRequest<Resource> result = utils.issueGetResourceRequest(resourceAddress.resolveOperationUri(CodeSystem.class, "lookup", params), getPreferredResourceFormat()); 674 result.addErrorStatus(410);//gone 675 result.addErrorStatus(404);//unknown 676 result.addErrorStatus(405); 677 result.addErrorStatus(422);//Unprocessable Entity 678 result.addSuccessStatus(200); 679 result.addSuccessStatus(201); 680 if(result.isUnsuccessfulRequest()) { 681 throw new EFhirClientException("Server returned error code " + result.getHttpStatus(), (OperationOutcome)result.getPayload()); 682 } 683 return (Parameters) result.getPayload(); 684 } 685 public ValueSet expandValueset(ValueSet source, Parameters expParams, Map<String, String> params) { 686 List<Header> headers = null; 687 Parameters p = expParams == null ? new Parameters() : expParams.copy(); 688 p.addParameter().setName("valueSet").setResource(source); 689 for (String n : params.keySet()) 690 p.addParameter().setName(n).setValue(new StringType(params.get(n))); 691 ResourceRequest<Resource> result = utils.issuePostRequest(resourceAddress.resolveOperationUri(ValueSet.class, "expand", params), 692 utils.getResourceAsByteArray(p, false, isJson(getPreferredResourceFormat())), getPreferredResourceFormat(), headers); 693 result.addErrorStatus(410);//gone 694 result.addErrorStatus(404);//unknown 695 result.addErrorStatus(405); 696 result.addErrorStatus(422);//Unprocessable Entity 697 result.addSuccessStatus(200); 698 result.addSuccessStatus(201); 699 if(result.isUnsuccessfulRequest()) { 700 throw new EFhirClientException("Server returned error code " + result.getHttpStatus(), (OperationOutcome)result.getPayload()); 701 } 702 return (ValueSet) result.getPayload(); 703 } 704 705// public ValueSet expandValueset(ValueSet source, ExpansionProfile profile, Map<String, String> params) { 706// List<Header> headers = null; 707// ResourceRequest<Resource> result = utils.issuePostRequest(resourceAddress.resolveOperationUri(ValueSet.class, "expand", params), 708// utils.getResourceAsByteArray(source, false, isJson(getPreferredResourceFormat())), getPreferredResourceFormat(), headers, proxy); 709// result.addErrorStatus(410);//gone 710// result.addErrorStatus(404);//unknown 711// result.addErrorStatus(405); 712// result.addErrorStatus(422);//Unprocessable Entity 713// result.addSuccessStatus(200); 714// result.addSuccessStatus(201); 715// if(result.isUnsuccessfulRequest()) { 716// throw new EFhirClientException("Server returned error code " + result.getHttpStatus(), (OperationOutcome)result.getPayload()); 717// } 718// return (ValueSet) result.getPayload(); 719// } 720 721 722 public String getAddress() { 723 return base; 724 } 725 726 public ConceptMap initializeClosure(String name) { 727 Parameters params = new Parameters(); 728 params.addParameter().setName("name").setValue(new StringType(name)); 729 List<Header> headers = null; 730 ResourceRequest<Resource> result = utils.issuePostRequest(resourceAddress.resolveOperationUri(null, "closure", new HashMap<String, String>()), 731 utils.getResourceAsByteArray(params, false, isJson(getPreferredResourceFormat())), getPreferredResourceFormat(), headers); 732 result.addErrorStatus(410);//gone 733 result.addErrorStatus(404);//unknown 734 result.addErrorStatus(405); 735 result.addErrorStatus(422);//Unprocessable Entity 736 result.addSuccessStatus(200); 737 result.addSuccessStatus(201); 738 if(result.isUnsuccessfulRequest()) { 739 throw new EFhirClientException("Server returned error code " + result.getHttpStatus(), (OperationOutcome)result.getPayload()); 740 } 741 return (ConceptMap) result.getPayload(); 742 } 743 744 public ConceptMap updateClosure(String name, Coding coding) { 745 Parameters params = new Parameters(); 746 params.addParameter().setName("name").setValue(new StringType(name)); 747 params.addParameter().setName("concept").setValue(coding); 748 List<Header> headers = null; 749 ResourceRequest<Resource> result = utils.issuePostRequest(resourceAddress.resolveOperationUri(null, "closure", new HashMap<String, String>()), 750 utils.getResourceAsByteArray(params, false, isJson(getPreferredResourceFormat())), getPreferredResourceFormat(), headers); 751 result.addErrorStatus(410);//gone 752 result.addErrorStatus(404);//unknown 753 result.addErrorStatus(405); 754 result.addErrorStatus(422);//Unprocessable Entity 755 result.addSuccessStatus(200); 756 result.addSuccessStatus(201); 757 if(result.isUnsuccessfulRequest()) { 758 throw new EFhirClientException("Server returned error code " + result.getHttpStatus(), (OperationOutcome)result.getPayload()); 759 } 760 return (ConceptMap) result.getPayload(); 761 } 762 763 public int getTimeout() { 764 return utils.getTimeout(); 765 } 766 767 public void setTimeout(int timeout) { 768 utils.setTimeout(timeout); 769 } 770 771 public String getUsername() { 772 return utils.getUsername(); 773 } 774 775 public void setUsername(String username) { 776 utils.setUsername(username); 777 } 778 779 public String getPassword() { 780 return utils.getPassword(); 781 } 782 783 public void setPassword(String password) { 784 utils.setPassword(password); 785 } 786 787}