
001package org.hl7.fhir.convertors.misc; 002 003import java.io.BufferedOutputStream; 004import java.io.ByteArrayOutputStream; 005import java.io.FileInputStream; 006import java.io.IOException; 007import java.io.InputStream; 008import java.nio.charset.StandardCharsets; 009import java.util.ArrayList; 010import java.util.HashMap; 011import java.util.List; 012import java.util.Map; 013import java.util.Map.Entry; 014 015import javax.annotation.Nonnull; 016 017import org.apache.commons.compress.archivers.tar.TarArchiveEntry; 018import org.apache.commons.compress.archivers.tar.TarArchiveInputStream; 019import org.apache.commons.compress.archivers.tar.TarArchiveOutputStream; 020import org.apache.commons.compress.compressors.gzip.GzipCompressorInputStream; 021import org.apache.commons.compress.compressors.gzip.GzipCompressorOutputStream; 022import org.hl7.fhir.convertors.advisors.impl.BaseAdvisor_30_40; 023import org.hl7.fhir.convertors.advisors.impl.BaseAdvisor_30_50; 024import org.hl7.fhir.convertors.factory.VersionConvertorFactory_10_30; 025import org.hl7.fhir.convertors.factory.VersionConvertorFactory_10_40; 026import org.hl7.fhir.convertors.factory.VersionConvertorFactory_10_50; 027import org.hl7.fhir.convertors.factory.VersionConvertorFactory_14_30; 028import org.hl7.fhir.convertors.factory.VersionConvertorFactory_14_40; 029import org.hl7.fhir.convertors.factory.VersionConvertorFactory_14_50; 030import org.hl7.fhir.convertors.factory.VersionConvertorFactory_30_40; 031import org.hl7.fhir.convertors.factory.VersionConvertorFactory_30_50; 032import org.hl7.fhir.convertors.factory.VersionConvertorFactory_40_50; 033import org.hl7.fhir.r5.model.Enumeration; 034import org.hl7.fhir.r5.model.Enumerations.FHIRVersionEnumFactory; 035import org.hl7.fhir.r5.model.ImplementationGuide; 036import org.hl7.fhir.r5.model.Resource; 037import org.hl7.fhir.utilities.TextFile; 038import org.hl7.fhir.utilities.VersionUtilities; 039import org.hl7.fhir.utilities.json.model.JsonArray; 040import org.hl7.fhir.utilities.json.model.JsonObject; 041import org.hl7.fhir.utilities.json.parser.JsonParser; 042import org.hl7.fhir.utilities.npm.NpmPackageIndexBuilder; 043 044public class NpmPackageVersionConverter { 045 046 private static final int BUFFER_SIZE = 1024; 047 048 private final String source; 049 private final String dest; 050 private final String version; 051 private final String vCode; 052 private final List<String> errors = new ArrayList<>(); 053 private String currentVersion; 054 055 private String packageId; 056 057 public NpmPackageVersionConverter(String source, String dest, String version, String packageId) { 058 super(); 059 this.source = source; 060 this.dest = dest; 061 this.vCode = version; 062 this.packageId = packageId; 063 this.version = VersionUtilities.versionFromCode(version); 064 } 065 066 public static void main(String[] args) throws IOException { 067 NpmPackageVersionConverter self = new NpmPackageVersionConverter(args[0], args[1], args[2], args[3]); 068 self.execute(); 069 System.out.println("Finished"); 070 for (String s : self.errors) { 071 System.out.println(s); 072 } 073 } 074 075 public List<String> getErrors() { 076 return errors; 077 } 078 079 public void execute() throws IOException { 080 Map<String, byte[]> content = loadContentMap(new FileInputStream(source)); 081 082 Map<String, byte[]> output = new HashMap<>(); 083 output.put("package/package.json", convertPackage(content.get("package/package.json"))); 084 output.put("package/other/spec.internals", convertSpec(content.get("package/other/spec.internals"))); 085 086 for (Entry<String, byte[]> e : content.entrySet()) { 087 if (!e.getKey().equals("package/package.json") && !e.getKey().equals("package/other/spec.internals") && !e.getKey().endsWith("ig-r4.json") && !e.getKey().endsWith("ig-r4.jsonX")) { 088 byte[] cnv = e.getValue(); 089 try { 090 JsonObject json = JsonParser.parseObject(e.getValue()); 091 if (json.has("resourceType")) { 092 cnv = convertResource(e.getKey(), e.getValue()); 093 } 094 } catch (Exception ex) { 095 } 096 if (cnv != null && cnv.length > 0) { 097 output.put(e.getKey(), cnv); 098 } 099 } 100 } 101 102 TarArchiveOutputStream tar; 103 ByteArrayOutputStream OutputStream; 104 BufferedOutputStream bufferedOutputStream; 105 GzipCompressorOutputStream gzipOutputStream; 106 107 OutputStream = new ByteArrayOutputStream(); 108 bufferedOutputStream = new BufferedOutputStream(OutputStream); 109 gzipOutputStream = new GzipCompressorOutputStream(bufferedOutputStream); 110 tar = new TarArchiveOutputStream(gzipOutputStream); 111 112 113 Map<String, NpmPackageIndexBuilder> indexers = new HashMap<>(); 114 for (Entry<String, byte[]> e : output.entrySet()) { 115 String n = e.getKey().substring(0, e.getKey().lastIndexOf("/")); 116 String s = e.getKey().substring(n.length() + 1); 117 byte[] b = e.getValue(); 118 NpmPackageIndexBuilder indexer = indexers.get(n); 119 if (indexer == null) { 120 indexer = new NpmPackageIndexBuilder(); 121 indexer.start(); 122 indexers.put(n, indexer); 123 } 124 indexer.seeFile(s, b); 125 if (!s.equals(".index.json") && !s.equals("package.json")) { 126 TarArchiveEntry entry = new TarArchiveEntry(e.getKey()); 127 entry.setSize(b.length); 128 tar.putArchiveEntry(entry); 129 tar.write(b); 130 tar.closeArchiveEntry(); 131 } 132 } 133 for (Entry<String, NpmPackageIndexBuilder> e : indexers.entrySet()) { 134 byte[] cnt = e.getValue().build().getBytes(StandardCharsets.UTF_8); 135 TarArchiveEntry entry = new TarArchiveEntry(e.getKey() + "/.index.json"); 136 entry.setSize(cnt.length); 137 tar.putArchiveEntry(entry); 138 tar.write(cnt); 139 tar.closeArchiveEntry(); 140 } 141 142 byte[] cnt = output.get("package/package.json"); 143 TarArchiveEntry entry = new TarArchiveEntry("package/package.json"); 144 entry.setSize(cnt.length); 145 tar.putArchiveEntry(entry); 146 tar.write(cnt); 147 tar.closeArchiveEntry(); 148 149 tar.finish(); 150 tar.close(); 151 gzipOutputStream.close(); 152 bufferedOutputStream.close(); 153 OutputStream.close(); 154 byte[] b = OutputStream.toByteArray(); 155 TextFile.bytesToFile(b, dest); 156 } 157 158 @Nonnull 159 protected Map<String, byte[]> loadContentMap(InputStream inputStream) throws IOException { 160 GzipCompressorInputStream gzipIn; 161 try { 162 gzipIn = new GzipCompressorInputStream(inputStream); 163 } catch (Exception e) { 164 throw new IOException("Error reading " + source + ": " + e.getMessage(), e); 165 } 166 Map<String, byte[]> content = new HashMap<>(); 167 168 try (TarArchiveInputStream tarIn = new TarArchiveInputStream(gzipIn)) { 169 TarArchiveEntry entry; 170 171 while ((entry = (TarArchiveEntry) tarIn.getNextEntry()) != null) { 172 String n = entry.getName(); 173 if (n.contains("..")) { 174 throw new RuntimeException("Entry with an illegal name: " + n); 175 } 176 if (!entry.isDirectory()) { 177 int count; 178 byte[] data = new byte[BUFFER_SIZE]; 179 ByteArrayOutputStream fos = new ByteArrayOutputStream(); 180 try (BufferedOutputStream dest = new BufferedOutputStream(fos, BUFFER_SIZE)) { 181 while ((count = tarIn.read(data, 0, BUFFER_SIZE)) != -1) { 182 dest.write(data, 0, count); 183 } 184 } 185 fos.close(); 186 content.put(n, fos.toByteArray()); 187 } 188 } 189 } 190 return content; 191 } 192 193 private byte[] convertPackage(byte[] cnt) throws IOException { 194 JsonObject json = JsonParser.parseObject(cnt); 195 currentVersion = json.getJsonArray("fhirVersions").get(0).asString(); 196 String name = json.asString("name"); 197 assert(packageId.equals(name + "." + vCode)); 198 json.remove("name"); 199 json.add("name", name + "." + vCode); 200 json.remove("fhirVersions"); 201 json.remove("dependencies"); 202 JsonArray fv = new JsonArray(); 203 json.add("fhirVersions", fv); 204 fv.add(version); 205 JsonObject dep = new JsonObject(); 206 json.add("dependencies", dep); 207 dep.add(VersionUtilities.packageForVersion(version), version); 208 return JsonParser.composeBytes(json); 209 } 210 211 private byte[] convertSpec(byte[] cnt) throws IOException { 212 JsonObject json = JsonParser.parseObject(cnt); 213 json.set("ig-version", version); 214 json.set("npm-name", packageId); 215 return JsonParser.composeBytes(json, true); 216 } 217 218 private byte[] convertResource(String n, byte[] cnt) { 219 try { 220 if (VersionUtilities.isR2Ver(currentVersion)) { 221 org.hl7.fhir.dstu2.model.Resource res = new org.hl7.fhir.dstu2.formats.JsonParser().parse(cnt); 222 convertResourceR2(res); 223 if (VersionUtilities.isR2Ver(version)) { 224 return new org.hl7.fhir.dstu2.formats.JsonParser().composeBytes(res); 225 } else if (VersionUtilities.isR2BVer(version)) { 226 return new org.hl7.fhir.dstu2016may.formats.JsonParser().composeBytes(VersionConvertorFactory_14_30.convertResource(VersionConvertorFactory_10_30.convertResource(res))); 227 } else if (VersionUtilities.isR3Ver(version)) { 228 return new org.hl7.fhir.dstu3.formats.JsonParser().composeBytes(VersionConvertorFactory_10_30.convertResource(res)); 229 } else if (VersionUtilities.isR4Ver(version)) { 230 return new org.hl7.fhir.r4.formats.JsonParser().composeBytes(VersionConvertorFactory_10_40.convertResource(res)); 231 } else if (VersionUtilities.isR5Plus(version)) { 232 return new org.hl7.fhir.r5.formats.JsonParser().composeBytes(VersionConvertorFactory_10_50.convertResource(res)); 233 } 234 } else if (VersionUtilities.isR2BVer(currentVersion)) { 235 org.hl7.fhir.dstu2016may.model.Resource res = new org.hl7.fhir.dstu2016may.formats.JsonParser().parse(cnt); 236 convertResourceR2B(res); 237 if (VersionUtilities.isR2Ver(version)) { 238 return new org.hl7.fhir.dstu2.formats.JsonParser().composeBytes(VersionConvertorFactory_10_30.convertResource(VersionConvertorFactory_14_30.convertResource(res))); 239 } else if (VersionUtilities.isR2BVer(version)) { 240 return new org.hl7.fhir.dstu2016may.formats.JsonParser().composeBytes(res); 241 } else if (VersionUtilities.isR3Ver(version)) { 242 return new org.hl7.fhir.dstu3.formats.JsonParser().composeBytes(VersionConvertorFactory_14_30.convertResource(res)); 243 } else if (VersionUtilities.isR4Ver(version)) { 244 return new org.hl7.fhir.r4.formats.JsonParser().composeBytes(VersionConvertorFactory_14_40.convertResource(res)); 245 } else if (VersionUtilities.isR5Plus(version)) { 246 return new org.hl7.fhir.r5.formats.JsonParser().composeBytes(VersionConvertorFactory_14_50.convertResource(res)); 247 } 248 } else if (VersionUtilities.isR3Ver(currentVersion)) { 249 org.hl7.fhir.dstu3.model.Resource res = new org.hl7.fhir.dstu3.formats.JsonParser().parse(cnt); 250 convertResourceR3(res); 251 if (VersionUtilities.isR2Ver(version)) { 252 return new org.hl7.fhir.dstu2.formats.JsonParser().composeBytes(VersionConvertorFactory_10_30.convertResource(res)); 253 } else if (VersionUtilities.isR2BVer(version)) { 254 return new org.hl7.fhir.dstu2016may.formats.JsonParser().composeBytes(VersionConvertorFactory_14_30.convertResource(res)); 255 } else if (VersionUtilities.isR3Ver(version)) { 256 return new org.hl7.fhir.dstu3.formats.JsonParser().composeBytes(res); 257 } else if (VersionUtilities.isR4Ver(version)) { 258 return new org.hl7.fhir.r4.formats.JsonParser().composeBytes(VersionConvertorFactory_30_40.convertResource(res)); 259 } else if (VersionUtilities.isR5Plus(version)) { 260 return new org.hl7.fhir.r5.formats.JsonParser().composeBytes(VersionConvertorFactory_30_50.convertResource(res)); 261 } 262 } else if (VersionUtilities.isR4Ver(currentVersion)) { 263 org.hl7.fhir.r4.model.Resource res = new org.hl7.fhir.r4.formats.JsonParser().parse(cnt); 264 convertResourceR4(res); 265 if (VersionUtilities.isR2Ver(version)) { 266 return new org.hl7.fhir.dstu2.formats.JsonParser().composeBytes(VersionConvertorFactory_10_40.convertResource(res, new PR2Handler())); 267 } else if (VersionUtilities.isR2BVer(version)) { 268 return new org.hl7.fhir.dstu2016may.formats.JsonParser().composeBytes(VersionConvertorFactory_14_40.convertResource(res)); 269 } else if (VersionUtilities.isR3Ver(version)) { 270 return new org.hl7.fhir.dstu3.formats.JsonParser().composeBytes(VersionConvertorFactory_30_40.convertResource(res, new BaseAdvisor_30_40(false))); 271 } else if (VersionUtilities.isR4Ver(version)) { 272 return new org.hl7.fhir.r4.formats.JsonParser().composeBytes(res); 273 } else if (VersionUtilities.isR5Plus(version)) { 274 return new org.hl7.fhir.r5.formats.JsonParser().composeBytes(VersionConvertorFactory_40_50.convertResource(res)); 275 } 276 } else if (VersionUtilities.isR5Plus(currentVersion)) { 277 org.hl7.fhir.r5.model.Resource res = new org.hl7.fhir.r5.formats.JsonParser().parse(cnt); 278 convertResourceR5(res); 279 if (VersionUtilities.isR2Ver(version)) { 280 return new org.hl7.fhir.dstu2.formats.JsonParser().composeBytes(VersionConvertorFactory_10_50.convertResource(res)); 281 } else if (VersionUtilities.isR2BVer(version)) { 282 return new org.hl7.fhir.dstu2016may.formats.JsonParser().composeBytes(VersionConvertorFactory_14_50.convertResource(res)); 283 } else if (VersionUtilities.isR3Ver(version)) { 284 return new org.hl7.fhir.dstu3.formats.JsonParser().composeBytes(VersionConvertorFactory_30_50.convertResource(res, new BaseAdvisor_30_50(false))); 285 } else if (VersionUtilities.isR4Ver(version)) { 286 return new org.hl7.fhir.r4.formats.JsonParser().composeBytes(VersionConvertorFactory_40_50.convertResource(res)); 287 } else if (VersionUtilities.isR5Plus(version)) { 288 return new org.hl7.fhir.r5.formats.JsonParser().composeBytes(res); 289 } 290 } 291 throw new Error("Unknown version " + currentVersion + " -> " + version); 292 } catch (Exception ex) { 293 ex.printStackTrace(); 294 errors.add("Error converting " + n + ": " + ex.getMessage()); 295 return null; 296 } 297 } 298 299 private void convertResourceR2(org.hl7.fhir.dstu2.model.Resource res) { 300 if (res instanceof org.hl7.fhir.dstu2.model.ImplementationGuide) { 301 org.hl7.fhir.dstu2.model.ImplementationGuide ig = (org.hl7.fhir.dstu2.model.ImplementationGuide) res; 302 ig.setFhirVersion(version); 303 } 304 } 305 306 private void convertResourceR2B(org.hl7.fhir.dstu2016may.model.Resource res) { 307 if (res instanceof org.hl7.fhir.dstu2016may.model.ImplementationGuide) { 308 org.hl7.fhir.dstu2016may.model.ImplementationGuide ig = (org.hl7.fhir.dstu2016may.model.ImplementationGuide) res; 309 ig.setFhirVersion(version); 310 } 311 } 312 313 private void convertResourceR3(org.hl7.fhir.dstu3.model.Resource res) { 314 if (res instanceof org.hl7.fhir.dstu3.model.ImplementationGuide) { 315 org.hl7.fhir.dstu3.model.ImplementationGuide ig = (org.hl7.fhir.dstu3.model.ImplementationGuide) res; 316 ig.setFhirVersion(version); 317 } 318 } 319 320 private void convertResourceR4(org.hl7.fhir.r4.model.Resource res) { 321 if (res instanceof org.hl7.fhir.r4.model.ImplementationGuide) { 322 org.hl7.fhir.r4.model.ImplementationGuide ig = (org.hl7.fhir.r4.model.ImplementationGuide) res; 323 ig.getFhirVersion().clear(); 324 ig.getFhirVersion().add(new org.hl7.fhir.r4.model.Enumeration<>(new org.hl7.fhir.r4.model.Enumerations.FHIRVersionEnumFactory(), version)); 325 ig.setPackageId(packageId); 326 } 327 } 328 329 private void convertResourceR5(Resource res) { 330 if (res instanceof ImplementationGuide) { 331 ImplementationGuide ig = (ImplementationGuide) res; 332 ig.getFhirVersion().clear(); 333 ig.getFhirVersion().add(new Enumeration<>(new FHIRVersionEnumFactory(), version)); 334 ig.setPackageId(packageId); 335 } 336 } 337 338}