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