001package org.hl7.fhir.r5.terminologies.client;
002
003import java.net.URISyntaxException;
004import java.util.EnumSet;
005import java.util.Map;
006
007/*
008  Copyright (c) 2011+, HL7, Inc.
009  All rights reserved.
010  
011  Redistribution and use in source and binary forms, with or without modification, 
012  are permitted provided that the following conditions are met:
013    
014   * Redistributions of source code must retain the above copyright notice, this 
015     list of conditions and the following disclaimer.
016   * Redistributions in binary form must reproduce the above copyright notice, 
017     this list of conditions and the following disclaimer in the documentation 
018     and/or other materials provided with the distribution.
019   * Neither the name of HL7 nor the names of its contributors may be used to 
020     endorse or promote products derived from this software without specific 
021     prior written permission.
022  
023  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
024  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
025  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
026  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
027  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
028  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
029  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
030  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
031  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
032  POSSIBILITY OF SUCH DAMAGE.
033  
034 */
035
036
037import org.hl7.fhir.exceptions.FHIRException;
038import org.hl7.fhir.r5.model.Bundle;
039import org.hl7.fhir.r5.model.CanonicalResource;
040import org.hl7.fhir.r5.model.CapabilityStatement;
041import org.hl7.fhir.r5.model.CodeSystem;
042import org.hl7.fhir.r5.model.OperationOutcome;
043import org.hl7.fhir.r5.model.Parameters;
044import org.hl7.fhir.r5.model.Resource;
045import org.hl7.fhir.r5.model.TerminologyCapabilities;
046import org.hl7.fhir.r5.model.ValueSet;
047import org.hl7.fhir.r5.terminologies.client.TerminologyClientManager.ITerminologyClientFactory;
048import org.hl7.fhir.r5.utils.client.FHIRToolingClient;
049import org.hl7.fhir.r5.utils.client.network.ClientHeaders;
050import org.hl7.fhir.utilities.FhirPublication;
051import org.hl7.fhir.utilities.ToolingClientLogger;
052import org.hl7.fhir.utilities.Utilities;
053import org.hl7.fhir.utilities.http.HTTPHeader;
054
055public class TerminologyClientR5 implements ITerminologyClient {
056
057  public static class TerminologyClientR5Factory implements ITerminologyClientFactory {
058
059    @Override
060    public ITerminologyClient makeClient(String id, String url, String userAgent, ToolingClientLogger logger) throws URISyntaxException {
061      return new TerminologyClientR5(id, checkEndsWith("/r5", url), userAgent);
062    }
063
064    private String checkEndsWith(String term, String url) {
065      if (url.endsWith(term))
066        return url;
067      if (Utilities.isTxFhirOrgServer(url)) {
068        return Utilities.pathURL(url, term);
069      }
070      return url;
071    }
072
073    @Override
074    public String getVersion() {
075      return "5.0.0";
076    }
077  }
078
079  private final FHIRToolingClient client;
080  private ClientHeaders clientHeaders;
081  private String id;
082
083  public TerminologyClientR5(String id, String address, String userAgent) throws URISyntaxException {
084    this.client = new FHIRToolingClient(address, userAgent);
085    setClientHeaders(new ClientHeaders());
086    this.id = id;
087  }
088
089  @Override
090  public String getId() {
091    return id;
092  }
093
094  public TerminologyClientR5(String id, String address, String userAgent, ClientHeaders clientHeaders) throws URISyntaxException {
095    this.client = new FHIRToolingClient(address, userAgent);
096    setClientHeaders(clientHeaders);
097    this.id = id;
098  }
099
100  public EnumSet<FhirPublication> supportableVersions() {
101    // todo
102    return EnumSet.range(FhirPublication.STU3, FhirPublication.R5);
103  }
104  
105  public void setAllowedVersions(EnumSet<FhirPublication> versions) {
106    // todo
107  }
108  
109  public EnumSet<FhirPublication> getAllowedVersions() {
110    return null; // todo
111  }
112  
113  public FhirPublication getActualVersion() {
114    return FhirPublication.R5;
115  }
116  
117  
118  @Override
119  public TerminologyCapabilities getTerminologyCapabilities() {
120    return client.getTerminologyCapabilities();
121  }
122
123  @Override
124  public String getAddress() {
125    return client.getAddress();
126  }
127
128  @Override
129  public ValueSet expandValueset(ValueSet vs, Parameters p) {
130    return client.expandValueset(vs, p);
131  }
132
133  @Override
134  public Parameters validateCS(Parameters pin) {
135    return client.operateType(CodeSystem.class, "validate-code", pin);
136  }
137
138  @Override
139  public Parameters batchValidateCS(Parameters pin) {
140    return client.operateType(CodeSystem.class, "batch-validate-code", pin);
141  }
142
143  @Override
144  public Parameters subsumes(Parameters pin) {
145    return client.operateType(CodeSystem.class, "subsumes", pin);
146  }
147
148  @Override
149  public Parameters validateVS(Parameters pin) {
150    return client.operateType(ValueSet.class, "validate-code", pin);
151  }
152
153  @Override
154  public Parameters batchValidateVS(Parameters pin) {
155    return client.operateType(ValueSet.class, "batch-validate-code", pin);
156  }
157
158  @Override
159  public ITerminologyClient setTimeoutFactor(int i) {
160    client.setTimeoutFactor(i);
161    return this;
162  }
163
164  @Override
165  public ToolingClientLogger getLogger() {
166    return client.getLogger();
167  }
168  
169  @Override
170  public ITerminologyClient setLogger(ToolingClientLogger txLog) {
171    client.setLogger(txLog);
172    return this;
173  }
174
175  @Override
176  public CapabilityStatement getCapabilitiesStatementQuick() {
177    return client.getCapabilitiesStatementQuick();
178  }
179
180  @Override
181  public CapabilityStatement getCapabilitiesStatement() {
182    return client.getCapabilitiesStatement();
183  }
184
185  @Override
186  public Parameters lookupCode(Map<String, String> params) {
187    return client.lookupCode(params);
188  }
189
190  @Override
191  public Parameters lookupCode(Parameters params) {
192    return client.lookupCode(params);
193  }
194
195  @Override
196  public ITerminologyClient setRetryCount(int retryCount) throws FHIRException {
197    client.setRetryCount(retryCount);
198    return this;
199  }
200
201  @Override
202  public int getRetryCount() throws FHIRException {
203    return client.getRetryCount();
204  }
205
206  @Override
207  public Bundle batch(Bundle batch) {
208    return client.transaction(batch);
209  }
210
211  @Override
212  public CanonicalResource read(String type, String id) {
213    Class<Resource> t;
214    try {
215      t = (Class<Resource>) Class.forName("org.hl7.fhir.r5.model." + type);// todo: do we have to deal with any resource renaming? Use cases are limited...
216    } catch (ClassNotFoundException e) {
217      throw new FHIRException("Unable to fetch resources of type " + type + " in R5");
218    }
219    org.hl7.fhir.r5.model.Resource r5 = client.read(t, id);
220    if (r5 == null) {
221      throw new FHIRException("Unable to convert resource " + Utilities.pathURL(getAddress(), type, id) + " to R5 (internal representation)");
222    }
223    if (!(r5 instanceof CanonicalResource)) {
224      throw new FHIRException("Unable to convert resource " + Utilities.pathURL(getAddress(), type, id) + " to R5 canonical resource (internal representation)");
225    }
226    return (CanonicalResource) r5;
227  }
228
229  @Override
230  public Iterable<HTTPHeader> getClientHeaders() {
231    return clientHeaders.headers();
232  }
233
234  @Override
235  public ITerminologyClient setClientHeaders(ClientHeaders clientHeaders) {
236    this.clientHeaders = clientHeaders;
237    this.client.setClientHeaders(this.clientHeaders.headers());
238    this.client.setVersionInMimeTypes(true);
239    return this;
240  }
241
242  @Override
243  public ITerminologyClient setUserAgent(String userAgent) {
244    client.setUserAgent(userAgent);
245    return this;
246  }
247
248  @Override
249  public String getUserAgent() {
250    return client.getUserAgent();
251  }
252
253  @Override
254  public String getServerVersion() {
255    return client.getServerVersion();
256  }
257
258  @Override
259  public ITerminologyClient setAcceptLanguage(String lang) {
260    client.setAcceptLanguage(lang);
261    return this;
262  }
263  
264  @Override
265  public ITerminologyClient setContentLanguage(String lang) {
266    client.setContentLanguage(lang);
267    return this;
268  }
269  
270  @Override
271  public int getUseCount() {
272    return client.getUseCount();
273  }
274
275  public static ITerminologyClientFactory factory() {
276    return new TerminologyClientR5Factory();
277  }
278
279  @Override
280  public Bundle search(String type, String criteria) {
281    return client.search(type, criteria);
282  }
283
284  @Override
285  public Parameters translate(Parameters params) throws FHIRException {
286    return client.translate(params);
287  }
288
289  @Override
290  public void setConversionLogger(ITerminologyConversionLogger logger) {
291    // TODO Auto-generated method stub
292    
293  }
294
295  public OperationOutcome validateResource(Resource res) {
296    return client.validate(res, res.getId());
297  }
298}