001package org.hl7.fhir.convertors.loaders.loaderR5;
002
003import java.io.IOException;
004import java.io.InputStream;
005import java.util.ArrayList;
006import java.util.HashSet;
007import java.util.List;
008import java.util.Set;
009import java.util.UUID;
010
011import org.hl7.fhir.convertors.advisors.impl.BaseAdvisor_43_50;
012import org.hl7.fhir.convertors.factory.VersionConvertorFactory_40_50;
013import org.hl7.fhir.convertors.factory.VersionConvertorFactory_43_50;
014import org.hl7.fhir.convertors.txClient.TerminologyClientFactory;
015import org.hl7.fhir.exceptions.FHIRException;
016import org.hl7.fhir.r4b.model.Basic;
017import org.hl7.fhir.r4b.formats.JsonParser;
018import org.hl7.fhir.r4b.formats.XmlParser;
019import org.hl7.fhir.r4b.model.Resource;
020import org.hl7.fhir.r5.conformance.StructureDefinitionHacker;
021import org.hl7.fhir.r5.context.IContextResourceLoader;
022import org.hl7.fhir.r5.context.SimpleWorkerContext.PackageResourceLoader;
023import org.hl7.fhir.r5.model.Bundle;
024import org.hl7.fhir.r5.model.Bundle.BundleEntryComponent;
025import org.hl7.fhir.r5.model.Bundle.BundleType;
026import org.hl7.fhir.r5.model.CanonicalResource;
027import org.hl7.fhir.r5.model.CodeSystem;
028import org.hl7.fhir.r5.model.StructureDefinition;
029import org.hl7.fhir.r5.model.StructureDefinition.StructureDefinitionKind;
030import org.hl7.fhir.r5.terminologies.client.TerminologyClientManager.ITerminologyClientFactory;
031import org.hl7.fhir.utilities.Utilities;
032
033public class R4BToR5Loader extends BaseLoaderR5 implements IContextResourceLoader {
034
035  private final BaseAdvisor_43_50 advisor = new BaseAdvisor_43_50();
036  private String version;
037
038  public R4BToR5Loader(Set<String> types, ILoaderKnowledgeProviderR5 lkp, String version) { // might be 4B
039    super(types, lkp);
040    this.version = version;
041  }
042
043  @Override
044  public Bundle loadBundle(InputStream stream, boolean isJson) throws FHIRException, IOException {
045    Resource r4 = null;
046    if (isJson)
047      r4 = new JsonParser().parse(stream);
048    else
049      r4 = new XmlParser().parse(stream);
050    org.hl7.fhir.r5.model.Resource r5 = VersionConvertorFactory_43_50.convertResource(r4, advisor);
051
052    Bundle b;
053    if (r5 instanceof Bundle)
054      b = (Bundle) r5;
055    else {
056      b = new Bundle();
057      b.setId(UUID.randomUUID().toString().toLowerCase());
058      b.setType(BundleType.COLLECTION);
059      b.addEntry().setResource(r5).setFullUrl(r5 instanceof CanonicalResource ? ((CanonicalResource) r5).getUrl() : null);
060    }
061    for (CodeSystem cs : advisor.getCslist()) {
062      BundleEntryComponent be = b.addEntry();
063      be.setFullUrl(cs.getUrl());
064      be.setResource(cs);
065    }
066    if (killPrimitives) {
067      List<BundleEntryComponent> remove = new ArrayList<BundleEntryComponent>();
068      for (BundleEntryComponent be : b.getEntry()) {
069        if (be.hasResource() && be.getResource() instanceof StructureDefinition) {
070          StructureDefinition sd = (StructureDefinition) be.getResource();
071          if (sd.getKind() == StructureDefinitionKind.PRIMITIVETYPE)
072            remove.add(be);
073        }
074      }
075      b.getEntry().removeAll(remove);
076    }
077    if (patchUrls) {
078      for (BundleEntryComponent be : b.getEntry()) {
079        if (be.hasResource()) {
080          doPatchUrls(be.getResource());
081        }
082      }
083    }
084    return b;
085  }
086
087  @Override
088  public org.hl7.fhir.r5.model.Resource loadResource(InputStream stream, boolean isJson) throws FHIRException, IOException {
089    Resource r4 = null;
090    if (isJson)
091      r4 = new JsonParser().parse(stream);
092    else
093      r4 = new XmlParser().parse(stream);
094    org.hl7.fhir.r5.model.Resource r5 = VersionConvertorFactory_43_50.convertResource(r4);
095    setPath(r5);
096
097    if (!advisor.getCslist().isEmpty()) {
098      throw new FHIRException("Error: Cannot have included code systems");
099    }
100    if (killPrimitives) {
101      throw new FHIRException("Cannot kill primitives when using deferred loading");
102    }
103    if (r5 instanceof StructureDefinition) {
104      r5 = new StructureDefinitionHacker(version).fixSD((StructureDefinition) r5);
105    }
106    if (patchUrls) {
107      doPatchUrls(r5);
108    }
109    return r5;
110  }
111  
112  @Override
113  public List<CodeSystem> getCodeSystems() {
114    return new ArrayList<>();
115  }
116
117  @Override
118  protected String versionString() {
119    return "4.3";
120  }
121
122
123  @Override
124  public ITerminologyClientFactory txFactory() {
125    return new TerminologyClientFactory(versionString());
126  }
127
128  @Override  
129  public Set<String> reviewActualTypes(Set<String> types) {
130    Set<String> set = new HashSet<String>();
131    for (String t : types) {
132      if (Utilities.existsInList(t, "ActorDefinition", "Requirements", "TestPlan")) {
133        set.add("Basic");
134      } else {
135        set.add(t);
136      }      
137    }    
138    return set;
139  }
140
141  @Override
142  public PackageResourceLoader editInfo(PackageResourceLoader pri) {
143
144    if (pri.getType().equals("Basic")) {
145      try {
146        InputStream f = pri.getStream();
147        try {
148          Basic b = (Basic) new JsonParser().parse(f);
149          org.hl7.fhir.r5.model.Resource r5 = VersionConvertorFactory_43_50.convertResource(b);
150          if (r5 instanceof CanonicalResource) {
151            pri.setResource((CanonicalResource) r5);
152            pri.updateInfo();
153            setPath(r5);
154          } else {
155            return null;
156          }
157        } finally {
158          f.close();
159        }
160      } catch (Exception e) {
161        throw new FHIRException("Error loading Resource Basic/"+pri.getId()+": "+e.getMessage(), e);
162      }
163    }
164    return pri;
165  }
166}