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          inspectResource(be.getResource());
081          doPatchUrls(be.getResource());
082        }
083      }
084    }
085    return b;
086  }
087
088  @Override
089  public org.hl7.fhir.r5.model.Resource loadResource(InputStream stream, boolean isJson) throws FHIRException, IOException {
090    Resource r4 = null;
091    if (isJson)
092      r4 = new JsonParser().parse(stream);
093    else
094      r4 = new XmlParser().parse(stream);
095    org.hl7.fhir.r5.model.Resource r5 = VersionConvertorFactory_43_50.convertResource(r4);
096    setPath(r5);
097
098    if (!advisor.getCslist().isEmpty()) {
099      throw new FHIRException("Error: Cannot have included code systems");
100    }
101    if (killPrimitives) {
102      throw new FHIRException("Cannot kill primitives when using deferred loading");
103    }
104    if (r5 instanceof StructureDefinition) {
105      r5 = new StructureDefinitionHacker(version).fixSD((StructureDefinition) r5);
106    }
107    inspectResource(r5);
108    if (patchUrls) {
109      doPatchUrls(r5);
110    }
111    return r5;
112  }
113  
114  @Override
115  public List<CodeSystem> getCodeSystems() {
116    return new ArrayList<>();
117  }
118
119  @Override
120  protected String versionString() {
121    return "4.3";
122  }
123
124
125  @Override
126  public ITerminologyClientFactory txFactory() {
127    return new TerminologyClientFactory(versionString());
128  }
129
130  @Override  
131  public Set<String> reviewActualTypes(Set<String> types) {
132    Set<String> set = new HashSet<String>();
133    for (String t : types) {
134      if (Utilities.existsInList(t, "ActorDefinition", "Requirements", "TestPlan")) {
135        set.add("Basic");
136      } else {
137        set.add(t);
138      }      
139    }    
140    return set;
141  }
142
143  @Override
144  public PackageResourceLoader editInfo(PackageResourceLoader pri) {
145
146    if (pri.getType().equals("Basic")) {
147      try {
148        InputStream f = pri.getStream();
149        try {
150          Basic b = (Basic) new JsonParser().parse(f);
151          org.hl7.fhir.r5.model.Resource r5 = VersionConvertorFactory_43_50.convertResource(b);
152          if (r5 instanceof CanonicalResource) {
153            pri.setResource((CanonicalResource) r5);
154            pri.updateInfo();
155            setPath(r5);
156          } else {
157            return null;
158          }
159        } finally {
160          f.close();
161        }
162      } catch (Exception e) {
163        throw new FHIRException("Error loading Resource Basic/"+pri.getId()+": "+e.getMessage(), e);
164      }
165    }
166    return pri;
167  }
168}