001package org.hl7.fhir.convertors.misc;
002
003import java.io.FileOutputStream;
004import java.io.IOException;
005import java.util.Arrays;
006import java.util.List;
007
008import org.hl7.fhir.convertors.factory.VersionConvertorFactory_10_50;
009import org.hl7.fhir.convertors.factory.VersionConvertorFactory_30_50;
010import org.hl7.fhir.convertors.factory.VersionConvertorFactory_40_50;
011import org.hl7.fhir.convertors.loaders.loaderR5.NullLoaderKnowledgeProviderR5;
012import org.hl7.fhir.convertors.loaders.loaderR5.R2ToR5Loader;
013import org.hl7.fhir.convertors.loaders.loaderR5.R3ToR5Loader;
014import org.hl7.fhir.convertors.loaders.loaderR5.R4ToR5Loader;
015import org.hl7.fhir.convertors.loaders.loaderR5.R5ToR5Loader;
016import org.hl7.fhir.exceptions.FHIRException;
017import org.hl7.fhir.r5.context.IContextResourceLoader;
018import org.hl7.fhir.r5.context.SimpleWorkerContext;
019import org.hl7.fhir.r5.context.SimpleWorkerContext.SimpleWorkerContextBuilder;
020import org.hl7.fhir.r5.model.CapabilityStatement;
021import org.hl7.fhir.r5.model.Resource;
022import org.hl7.fhir.r5.utils.ResourceDependencyWalker;
023import org.hl7.fhir.r5.utils.ResourceDependencyWalker.IResourceDependencyNotifier;
024import org.hl7.fhir.r5.utils.ResourceMinifier;
025import org.hl7.fhir.utilities.VersionUtilities;
026import org.hl7.fhir.utilities.filesystem.ManagedFileAccess;
027import org.hl7.fhir.utilities.json.JsonException;
028import org.hl7.fhir.utilities.json.parser.JsonParser;
029import org.hl7.fhir.utilities.npm.FilesystemPackageCacheManager;
030import org.hl7.fhir.utilities.npm.NpmPackage;
031
032public class ResourceDependencyPackageBuilder {
033
034  private static final List<String> LOADED_TYPES =
035      Arrays.asList("StructureDefinition", "CodeSystem", "ValueSet", "CapabilityStatement", "ConceptMap", "NamingSystem", "OperationDefinition", "SearchParameter", "Questionnaire");
036  
037  public static void main(String[] args) throws IOException {
038
039    FilesystemPackageCacheManager pcm = new FilesystemPackageCacheManager.Builder().build();
040    System.out.println("Load Core");
041    NpmPackage src = pcm.loadPackage(VersionUtilities.packageForVersion(args[0]));
042    SimpleWorkerContext ctxt = new SimpleWorkerContextBuilder().withAllowLoadingDuplicates(true).fromPackage(src);
043    loadFromPackage(args[0], ctxt, pcm, args[1]);
044    
045    NpmResourceDependencyCollector pckBuilder = new NpmResourceDependencyCollector();
046    pckBuilder.npm = makeNpm(args[3], ctxt.getVersion());
047    pckBuilder.minify = "true".equals(args[5]);
048    
049    new ResourceDependencyWalker(ctxt, pckBuilder).walk(ctxt.fetchResource(CapabilityStatement.class, args[2]));
050    
051    pckBuilder.npm.save(ManagedFileAccess.outStream(args[4]));
052  }
053
054  private static NpmPackage makeNpm(String vid, String version) throws JsonException, IOException {
055    NpmPackage res = NpmPackage.empty();
056    String name = vid.substring(0, vid.indexOf('#')); 
057    String ver = vid.substring(vid.indexOf("#")+1); 
058    res.setNpm(JsonParser.parseObject("{\"name\": \""+name+"\", \"version\": \""+ver+"\",\"fhirVersions\": [\""+version+"\"],\"type\": \"fhir.ig\",\"tools-version\": 3}"));
059    return res;
060  }
061
062
063  public static class NpmResourceDependencyCollector implements IResourceDependencyNotifier {
064
065    private NpmPackage npm;
066    private boolean minify;
067    
068    private byte[] toBytes(Resource resource) throws IOException {
069      if (VersionUtilities.isR5Ver(npm.fhirVersion())) {
070        return new org.hl7.fhir.r5.formats.JsonParser().composeBytes(resource);
071      }
072      if (VersionUtilities.isR4Plus(npm.fhirVersion())) {
073        org.hl7.fhir.r4.model.Resource r4 = VersionConvertorFactory_40_50.convertResource(resource);
074        return new org.hl7.fhir.r4.formats.JsonParser().composeBytes(r4);
075      }
076      if (VersionUtilities.isR3Ver(npm.fhirVersion())) {
077        org.hl7.fhir.dstu3.model.Resource r3 = VersionConvertorFactory_30_50.convertResource(resource);
078        return new org.hl7.fhir.dstu3.formats.JsonParser().composeBytes(r3);
079      }
080      if (VersionUtilities.isR2Ver(npm.fhirVersion())) {
081        org.hl7.fhir.dstu2.model.Resource r2 = VersionConvertorFactory_10_50.convertResource(resource);
082        return new org.hl7.fhir.dstu2.formats.JsonParser().composeBytes(r2);
083      }
084      throw new Error("Unsupported version");
085    }
086    
087    @Override
088    public void seeResource(Resource resource, String summaryId) {
089      if (minify) {
090        ResourceMinifier min = new ResourceMinifier();
091        if (min.isMinified(resource.fhirType())) {
092          resource = resource.copy();
093          if (!min.minify(resource)) {
094            return;
095          }
096        } else {
097          return;
098        }
099      }
100      try {
101        npm.addFile("package", resource.fhirType()+"-"+resource.getIdPart()+".json", toBytes(resource), null);
102      } catch (IOException e) {
103        e.printStackTrace();
104      }
105    }
106
107    @Override
108    public void brokenLink(String link) {
109      System.err.println("Broken Link: " +link);      
110    }
111  }
112  
113  private static void loadFromPackage(String version, SimpleWorkerContext ctxt, FilesystemPackageCacheManager pcm, String pid) throws FHIRException, IOException {
114    NpmPackage npm = pcm.loadPackage(pid);
115    for (String dep : npm.dependencies()) {
116      if (!VersionUtilities.isCorePackage(dep)) {
117        loadFromPackage(version, ctxt, pcm, dep);
118      }
119    }
120    System.out.println("Load "+pid);
121    ctxt.loadFromPackage(npm, getLoader(version));
122  }
123
124  private static IContextResourceLoader getLoader(String version) {
125    if (VersionUtilities.isR2Ver(version)) {
126      return new R2ToR5Loader(LOADED_TYPES, new NullLoaderKnowledgeProviderR5());
127    }
128    if (VersionUtilities.isR3Ver(version)) {
129      return new R3ToR5Loader(LOADED_TYPES, new NullLoaderKnowledgeProviderR5());
130    }
131    if (VersionUtilities.isR4Ver(version)) {
132      return new R4ToR5Loader(LOADED_TYPES, new NullLoaderKnowledgeProviderR5(), version);
133    }
134    if (VersionUtilities.isR5Ver(version)) {
135      return new R5ToR5Loader(LOADED_TYPES, new NullLoaderKnowledgeProviderR5());
136    }
137    return null;
138  }
139
140
141}