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}