001package org.hl7.fhir.convertors.loaders.loaderR5; 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.advisors.impl.BaseAdvisor_40_50; 034import org.hl7.fhir.convertors.factory.VersionConvertorFactory_40_50; 035import org.hl7.fhir.exceptions.FHIRException; 036import org.hl7.fhir.r4.formats.JsonParser; 037import org.hl7.fhir.r4.formats.XmlParser; 038import org.hl7.fhir.r4.model.Resource; 039import org.hl7.fhir.r5.conformance.StructureDefinitionHacker; 040import org.hl7.fhir.r5.context.IWorkerContext.IContextResourceLoader; 041import org.hl7.fhir.r5.model.*; 042import org.hl7.fhir.r5.model.Bundle.BundleEntryComponent; 043import org.hl7.fhir.r5.model.Bundle.BundleType; 044import org.hl7.fhir.r5.model.ElementDefinition.TypeRefComponent; 045import org.hl7.fhir.r5.model.StructureDefinition.StructureDefinitionKind; 046import org.hl7.fhir.utilities.VersionUtilities; 047 048import java.io.IOException; 049import java.io.InputStream; 050import java.util.ArrayList; 051import java.util.List; 052import java.util.UUID; 053 054public class R4BToR5Loader extends BaseLoaderR5 implements IContextResourceLoader { 055 056 private final BaseAdvisor_40_50 advisor = new BaseAdvisor_40_50(); 057 private String version; 058 059 public R4BToR5Loader(String[] types, ILoaderKnowledgeProviderR5 lkp, String version) { // might be 4B 060 super(types, lkp); 061 this.version = version; 062 } 063 064 @Override 065 public Bundle loadBundle(InputStream stream, boolean isJson) throws FHIRException, IOException { 066 Resource r4 = null; 067 if (isJson) 068 r4 = new JsonParser().parse(stream); 069 else 070 r4 = new XmlParser().parse(stream); 071 org.hl7.fhir.r5.model.Resource r5 = VersionConvertorFactory_40_50.convertResource(r4, advisor); 072 073 Bundle b; 074 if (r5 instanceof Bundle) 075 b = (Bundle) r5; 076 else { 077 b = new Bundle(); 078 b.setId(UUID.randomUUID().toString().toLowerCase()); 079 b.setType(BundleType.COLLECTION); 080 b.addEntry().setResource(r5).setFullUrl(r5 instanceof CanonicalResource ? ((CanonicalResource) r5).getUrl() : null); 081 } 082 for (CodeSystem cs : advisor.getCslist()) { 083 BundleEntryComponent be = b.addEntry(); 084 be.setFullUrl(cs.getUrl()); 085 be.setResource(cs); 086 } 087 if (killPrimitives) { 088 List<BundleEntryComponent> remove = new ArrayList<BundleEntryComponent>(); 089 for (BundleEntryComponent be : b.getEntry()) { 090 if (be.hasResource() && be.getResource() instanceof StructureDefinition) { 091 StructureDefinition sd = (StructureDefinition) be.getResource(); 092 if (sd.getKind() == StructureDefinitionKind.PRIMITIVETYPE) 093 remove.add(be); 094 } 095 } 096 b.getEntry().removeAll(remove); 097 } 098 if (patchUrls) { 099 for (BundleEntryComponent be : b.getEntry()) { 100 if (be.hasResource() && be.getResource() instanceof StructureDefinition) { 101 StructureDefinition sd = (StructureDefinition) be.getResource(); 102 sd.setUrl(sd.getUrl().replace(URL_BASE, URL_R4)); 103 sd.addExtension().setUrl(URL_ELEMENT_DEF_NAMESPACE).setValue(new UriType(URL_BASE)); 104 for (ElementDefinition ed : sd.getSnapshot().getElement()) 105 patchUrl(ed); 106 for (ElementDefinition ed : sd.getDifferential().getElement()) 107 patchUrl(ed); 108 } 109 } 110 } 111 return b; 112 } 113 114 @Override 115 public org.hl7.fhir.r5.model.Resource loadResource(InputStream stream, boolean isJson) throws FHIRException, IOException { 116 Resource r4 = null; 117 if (isJson) 118 r4 = new JsonParser().parse(stream); 119 else 120 r4 = new XmlParser().parse(stream); 121 org.hl7.fhir.r5.model.Resource r5 = VersionConvertorFactory_40_50.convertResource(r4); 122 setPath(r5); 123 124 if (!advisor.getCslist().isEmpty()) { 125 throw new FHIRException("Error: Cannot have included code systems"); 126 } 127 if (killPrimitives) { 128 throw new FHIRException("Cannot kill primitives when using deferred loading"); 129 } 130 if (r5 instanceof StructureDefinition && VersionUtilities.isR4BVer(version)) { 131 r5 = new StructureDefinitionHacker(version).fixSD((StructureDefinition) r5); 132 } 133 if (patchUrls) { 134 if (r5 instanceof StructureDefinition) { 135 StructureDefinition sd = (StructureDefinition) r5; 136 sd.setUrl(sd.getUrl().replace(URL_BASE, "http://hl7.org/fhir/4.0/")); 137 sd.addExtension().setUrl(URL_ELEMENT_DEF_NAMESPACE).setValue(new UriType("http://hl7.org/fhir")); 138 for (ElementDefinition ed : sd.getSnapshot().getElement()) 139 patchUrl(ed); 140 for (ElementDefinition ed : sd.getDifferential().getElement()) 141 patchUrl(ed); 142 } 143 } 144 return r5; 145 } 146 147 private void patchUrl(ElementDefinition ed) { 148 for (TypeRefComponent tr : ed.getType()) { 149 for (CanonicalType s : tr.getTargetProfile()) { 150 s.setValue(s.getValue().replace(URL_BASE, "http://hl7.org/fhir/4.0/")); 151 } 152 for (CanonicalType s : tr.getProfile()) { 153 s.setValue(s.getValue().replace(URL_BASE, "http://hl7.org/fhir/4.0/")); 154 } 155 } 156 } 157}