001package org.hl7.fhir.convertors;
002
003/*
004  Copyright (c) 2011+, HL7, Inc.
005  All rights reserved.
006  
007  Redistribution and use in source and binary forms, with or without modification, 
008  are permitted provided that the following conditions are met:
009    
010   * Redistributions of source code must retain the above copyright notice, this 
011     list of conditions and the following disclaimer.
012   * Redistributions in binary form must reproduce the above copyright notice, 
013     this list of conditions and the following disclaimer in the documentation 
014     and/or other materials provided with the distribution.
015   * Neither the name of HL7 nor the names of its contributors may be used to 
016     endorse or promote products derived from this software without specific 
017     prior written permission.
018  
019  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
020  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
021  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
022  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
023  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
024  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
025  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
026  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
027  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
028  POSSIBILITY OF SUCH DAMAGE.
029  
030 */
031
032
033import org.hl7.fhir.convertors.factory.*;
034import org.hl7.fhir.exceptions.FHIRException;
035import org.hl7.fhir.r4.elementmodel.Manager.FhirFormat;
036import org.hl7.fhir.r4.formats.IParser.OutputStyle;
037import org.hl7.fhir.r4.model.FhirPublication;
038
039import java.io.IOException;
040
041public class VersionConversionService {
042  /**
043   * use the package manager to load relevant conversion packages, and then initialise internally as required
044   * <p>
045   * not thread safe
046   *
047   * @param system   - true if the software is running in system context, not in a user context
048   * @param txServer - Address of the terminology server to use (null = use http://tx.fhir.org
049   */
050  public VersionConversionService(boolean system, String txServer) throws FHIRException {
051
052  }
053
054  /**
055   * convert from one version to another.
056   * <p>
057   * This routine is thread safe
058   *
059   * @param src        - the resource to convert
060   * @param srcVersion - the version of the resource to convert
061   * @param dstVersion - the target version to convert to
062   * @return the converted resource
063   * @throws FHIRException - if the source resource cannot be parsed, no single path exists from source to dest version, or the conversion process fails
064   * @throws IOException
065   */
066  public byte[] convert(byte[] src, FhirFormat srcFormat, FhirPublication srcVersion, FhirFormat dstFormat, FhirPublication dstVersion, boolean useJava, OutputStyle style) throws FHIRException, IOException {
067    if (src == null)
068      throw new FHIRException("No source specified");
069    if (srcVersion == null)
070      throw new FHIRException("No source version specified");
071    if (dstVersion == null)
072      throw new FHIRException("No destination version specified");
073    switch (srcVersion) {
074      case DSTU1:
075        throw new FHIRException("FHIR Version #1 is not supported by the inter-version convertor");
076      case DSTU2:
077        return convert10(parseResource10(src, srcFormat), dstFormat, dstVersion, useJava, style);
078      case DSTU2016May:
079        return convert14(parseResource14(src, srcFormat), dstFormat, dstVersion, useJava, style);
080      case R4:
081        return convert40(parseResource40(src, srcFormat), dstFormat, dstVersion, useJava, style);
082      case STU3:
083        return convert30(parseResource30(src, srcFormat), dstFormat, dstVersion, useJava, style);
084      default:
085        throw new FHIRException("FHIR Version 'unknown' is not supported by the inter-version convertor");
086    }
087  }
088
089  private org.hl7.fhir.dstu2.model.Resource parseResource10(byte[] src, FhirFormat srcFormat) throws FHIRException, IOException {
090    switch (srcFormat) {
091      case JSON:
092        return new org.hl7.fhir.dstu2.formats.JsonParser().parse(src);
093      case TEXT:
094        throw new FHIRException("Text format not supported for DSTU2");
095      case TURTLE:
096        throw new FHIRException("Turtle format not supported for DSTU2");
097      case VBAR:
098        throw new FHIRException("Vertical Bar format not supported for DSTU2");
099      case XML:
100        return new org.hl7.fhir.dstu2.formats.XmlParser().parse(src);
101      default:
102        throw new FHIRException("Unknown format not supported for DSTU2");
103    }
104  }
105
106  private org.hl7.fhir.dstu2016may.model.Resource parseResource14(byte[] src, FhirFormat srcFormat) throws FHIRException, IOException {
107    switch (srcFormat) {
108      case JSON:
109        return new org.hl7.fhir.dstu2016may.formats.JsonParser().parse(src);
110      case TEXT:
111        throw new FHIRException("Text format not supported for DSTU2");
112      case TURTLE:
113        throw new FHIRException("Turtle format not supported for DSTU2");
114      case VBAR:
115        throw new FHIRException("Vertical Bar format not supported for DSTU2");
116      case XML:
117        return new org.hl7.fhir.dstu2016may.formats.XmlParser().parse(src);
118      default:
119        throw new FHIRException("Unknown format not supported for DSTU2");
120    }
121  }
122
123  private org.hl7.fhir.dstu3.model.Resource parseResource30(byte[] src, FhirFormat srcFormat) throws FHIRException, IOException {
124    switch (srcFormat) {
125      case JSON:
126        return new org.hl7.fhir.dstu3.formats.JsonParser().parse(src);
127      case TEXT:
128        throw new FHIRException("Text format not supported for DSTU2");
129      case TURTLE:
130        return new org.hl7.fhir.dstu3.formats.RdfParser().parse(src);
131      case VBAR:
132        throw new FHIRException("Vertical Bar format not supported for DSTU2");
133      case XML:
134        return new org.hl7.fhir.dstu3.formats.XmlParser().parse(src);
135      default:
136        throw new FHIRException("Unknown format not supported for DSTU2");
137    }
138  }
139
140  private org.hl7.fhir.r4.model.Resource parseResource40(byte[] src, FhirFormat srcFormat) throws FHIRException, IOException {
141    switch (srcFormat) {
142      case JSON:
143        return new org.hl7.fhir.r4.formats.JsonParser().parse(src);
144      case TEXT:
145        throw new FHIRException("Text format not supported for DSTU2");
146      case TURTLE:
147        return new org.hl7.fhir.r4.formats.RdfParser().parse(src);
148      case VBAR:
149        throw new FHIRException("Vertical Bar format not supported for DSTU2");
150      case XML:
151        return new org.hl7.fhir.r4.formats.XmlParser().parse(src);
152      default:
153        throw new FHIRException("Unknown format not supported for DSTU2");
154    }
155  }
156
157  private org.hl7.fhir.dstu2.formats.IParser.OutputStyle style10(OutputStyle style) {
158    return style == OutputStyle.CANONICAL ? org.hl7.fhir.dstu2.formats.IParser.OutputStyle.CANONICAL : style == OutputStyle.NORMAL ? org.hl7.fhir.dstu2.formats.IParser.OutputStyle.NORMAL : org.hl7.fhir.dstu2.formats.IParser.OutputStyle.PRETTY;
159  }
160
161  private org.hl7.fhir.dstu2016may.formats.IParser.OutputStyle style14(OutputStyle style) {
162    return style == OutputStyle.CANONICAL ? org.hl7.fhir.dstu2016may.formats.IParser.OutputStyle.CANONICAL : style == OutputStyle.NORMAL ? org.hl7.fhir.dstu2016may.formats.IParser.OutputStyle.NORMAL : org.hl7.fhir.dstu2016may.formats.IParser.OutputStyle.PRETTY;
163  }
164
165  private org.hl7.fhir.dstu3.formats.IParser.OutputStyle style30(OutputStyle style) {
166    return style == OutputStyle.CANONICAL ? org.hl7.fhir.dstu3.formats.IParser.OutputStyle.CANONICAL : style == OutputStyle.NORMAL ? org.hl7.fhir.dstu3.formats.IParser.OutputStyle.NORMAL : org.hl7.fhir.dstu3.formats.IParser.OutputStyle.PRETTY;
167  }
168
169  private byte[] saveResource10(org.hl7.fhir.dstu2.model.Resource src, FhirFormat dstFormat, OutputStyle style) throws FHIRException, IOException {
170    switch (dstFormat) {
171      case JSON:
172        return new org.hl7.fhir.dstu2.formats.JsonParser().setOutputStyle(style10(style)).composeBytes(src);
173      case TEXT:
174        throw new FHIRException("Text format not supported for DSTU2");
175      case TURTLE:
176        throw new FHIRException("Turtle format not supported for DSTU2");
177      case VBAR:
178        throw new FHIRException("Vertical Bar format not supported for DSTU2");
179      case XML:
180        return new org.hl7.fhir.dstu2.formats.XmlParser().setOutputStyle(style10(style)).composeBytes(src);
181      default:
182        throw new FHIRException("Unknown format not supported for DSTU2");
183    }
184  }
185
186  private byte[] saveResource14(org.hl7.fhir.dstu2016may.model.Resource src, FhirFormat dstFormat, OutputStyle style) throws FHIRException, IOException {
187    switch (dstFormat) {
188      case JSON:
189        return new org.hl7.fhir.dstu2016may.formats.JsonParser().setOutputStyle(style14(style)).composeBytes(src);
190      case TEXT:
191        throw new FHIRException("Text format not supported for DSTU2");
192      case TURTLE:
193        throw new FHIRException("Turtle format not supported for DSTU2");
194      case VBAR:
195        throw new FHIRException("Vertical Bar format not supported for DSTU2");
196      case XML:
197        return new org.hl7.fhir.dstu2016may.formats.XmlParser().setOutputStyle(style14(style)).composeBytes(src);
198      default:
199        throw new FHIRException("Unknown format not supported for DSTU2");
200    }
201  }
202
203  private byte[] saveResource30(org.hl7.fhir.dstu3.model.Resource src, FhirFormat dstFormat, OutputStyle style) throws FHIRException, IOException {
204    switch (dstFormat) {
205      case JSON:
206        return new org.hl7.fhir.dstu3.formats.JsonParser().setOutputStyle(style30(style)).composeBytes(src);
207      case TEXT:
208        throw new FHIRException("Text format not supported for DSTU2");
209      case TURTLE:
210        return new org.hl7.fhir.dstu3.formats.RdfParser().setOutputStyle(style30(style)).composeBytes(src);
211      case VBAR:
212        throw new FHIRException("Vertical Bar format not supported for DSTU2");
213      case XML:
214        return new org.hl7.fhir.dstu3.formats.XmlParser().setOutputStyle(style30(style)).composeBytes(src);
215      default:
216        throw new FHIRException("Unknown format not supported for DSTU2");
217    }
218  }
219
220
221  private byte[] saveResource40(org.hl7.fhir.r4.model.Resource src, FhirFormat dstFormat, OutputStyle style) throws FHIRException, IOException {
222    switch (dstFormat) {
223      case JSON:
224        return new org.hl7.fhir.r4.formats.JsonParser().setOutputStyle(style).composeBytes(src);
225      case TEXT:
226        throw new FHIRException("Text format not supported for DSTU2");
227      case TURTLE:
228        return new org.hl7.fhir.r4.formats.RdfParser().setOutputStyle(style).composeBytes(src);
229      case VBAR:
230        throw new FHIRException("Vertical Bar format not supported for DSTU2");
231      case XML:
232        return new org.hl7.fhir.r4.formats.XmlParser().setOutputStyle(style).composeBytes(src);
233      default:
234        throw new FHIRException("Unknown format not supported for DSTU2");
235    }
236  }
237
238
239  private byte[] convert10(org.hl7.fhir.dstu2.model.Resource src, FhirFormat dstFormat, FhirPublication dstVersion, boolean useJava, OutputStyle style) throws FHIRException, IOException {
240    switch (dstVersion) {
241      case DSTU1:
242        throw new FHIRException("FHIR Version #1 is not supported by the inter-version convertor");
243      case DSTU2:
244        return saveResource10(src, dstFormat, style);
245      case DSTU2016May:
246        throw new FHIRException("Conversion from DSTU2 to 2016May version is not supported");
247      case R4:
248        if (useJava && VersionConvertorFactory_10_40.convertsResource(src.fhirType()))
249          return saveResource40(VersionConvertorFactory_10_40.convertResource(src), dstFormat, style); // todo: handle code system?
250        else
251          throw new FHIRException("Conversion from R4 to 2016May version is not supported for resources of type " + src.fhirType());
252      case STU3:
253        if (useJava && VersionConvertorFactory_10_30.convertsResource(src.fhirType()))
254          return saveResource30(VersionConvertorFactory_10_30.convertResource(src), dstFormat, style); // todo: handle code system?
255        else
256          throw new FHIRException("todo: use script based conversion....");
257      default:
258        throw new FHIRException("FHIR Version 'unknown' is not supported by the inter-version convertor");
259    }
260  }
261
262  private byte[] convert14(org.hl7.fhir.dstu2016may.model.Resource src, FhirFormat dstFormat, FhirPublication dstVersion, boolean useJava, OutputStyle style) throws FHIRException, IOException {
263    switch (dstVersion) {
264      case DSTU1:
265        throw new FHIRException("FHIR Version #1 is not supported by the inter-version convertor");
266      case DSTU2:
267        throw new FHIRException("Conversion from 2016May version to DSTU2 is not supported");
268      case DSTU2016May:
269        return saveResource14(src, dstFormat, style);
270      case R4:
271        if (useJava && VersionConvertorFactory_14_40.convertsResource(src.fhirType()))
272          return saveResource40(VersionConvertorFactory_14_40.convertResource(src), dstFormat, style);
273        else
274          throw new FHIRException("Conversion from 2016May version to R4 is not supported for resources of type " + src.fhirType());
275      case STU3:
276        if (useJava && VersionConvertorFactory_14_30.convertsResource(src.fhirType()))
277          return saveResource30(VersionConvertorFactory_14_30.convertResource(src), dstFormat, style);
278        else
279          throw new FHIRException("Conversion from 2016May version to STU3 is not supported for resources of type " + src.fhirType());
280      default:
281        throw new FHIRException("FHIR Version 'unknown' is not supported by the inter-version convertor");
282    }
283  }
284
285  private byte[] convert30(org.hl7.fhir.dstu3.model.Resource src, FhirFormat dstFormat, FhirPublication dstVersion, boolean useJava, OutputStyle style) throws FHIRException, IOException {
286    switch (dstVersion) {
287      case DSTU1:
288        throw new FHIRException("FHIR Version #1 is not supported by the inter-version convertor");
289      case DSTU2:
290        if (useJava && VersionConvertorFactory_10_30.convertsResource(src.fhirType()))
291          return saveResource10(VersionConvertorFactory_10_30.convertResource(src), dstFormat, style); // todo: handle code system?
292        else
293          throw new FHIRException("todo: use script based conversion....");
294      case DSTU2016May:
295        if (useJava && VersionConvertorFactory_14_30.convertsResource(src.fhirType()))
296          return saveResource14(VersionConvertorFactory_14_30.convertResource(src), dstFormat, style);
297        else
298          throw new FHIRException("Conversion from R3 to 2016May version is not supported for resources of type " + src.fhirType());
299      case R4:
300        if (useJava && VersionConvertorFactory_30_40.convertsResource(src.fhirType()))
301          return saveResource40(VersionConvertorFactory_30_40.convertResource(src), dstFormat, style);
302        else
303          throw new FHIRException("todo: use script based conversion....");
304      case STU3:
305        return saveResource30(src, dstFormat, style);
306      default:
307        throw new FHIRException("FHIR Version 'unknown' is not supported by the inter-version convertor");
308    }
309  }
310
311  private byte[] convert40(org.hl7.fhir.r4.model.Resource src, FhirFormat dstFormat, FhirPublication dstVersion, boolean useJava, OutputStyle style) throws FHIRException, IOException {
312    switch (dstVersion) {
313      case DSTU1:
314        throw new FHIRException("FHIR Version #1 is not supported by the inter-version convertor");
315      case DSTU2:
316        if (useJava && VersionConvertorFactory_10_40.convertsResource(src.fhirType()))
317          return saveResource10(VersionConvertorFactory_10_40.convertResource(src), dstFormat, style); // todo: handle code system?
318        else
319          throw new FHIRException("Conversion from R4 to DSTU2 version is not supported for resources of type " + src.fhirType());
320      case DSTU2016May:
321        if (useJava && VersionConvertorFactory_14_40.convertsResource(src.fhirType()))
322          return saveResource14(VersionConvertorFactory_14_40.convertResource(src), dstFormat, style);
323        else
324          throw new FHIRException("Conversion from DSTU2 to 2016May version is not supported for resources of type " + src.fhirType());
325      case R4:
326        return saveResource40(src, dstFormat, style);
327      case STU3:
328        if (useJava && VersionConvertorFactory_30_40.convertsResource(src.fhirType()))
329          return saveResource30(VersionConvertorFactory_30_40.convertResource(src), dstFormat, style);
330        else
331          throw new FHIRException("todo: use script based conversion....");
332      default:
333        throw new FHIRException("FHIR Version 'unknown' is not supported by the inter-version convertor");
334    }
335  }
336
337}