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