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