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