001package org.hl7.fhir.r4.utils;
002
003import java.io.File;
004import java.io.FileInputStream;
005import java.io.IOException;
006import java.net.URISyntaxException;
007import java.util.UUID;
008import java.util.zip.ZipEntry;
009import java.util.zip.ZipInputStream;
010
011import org.hl7.fhir.r4.formats.IParser;
012import org.hl7.fhir.r4.formats.JsonParser;
013import org.hl7.fhir.r4.model.Bundle;
014import org.hl7.fhir.r4.model.Bundle.BundleEntryComponent;
015import org.hl7.fhir.r4.model.Bundle.BundleType;
016import org.hl7.fhir.r4.model.Bundle.HTTPVerb;
017import org.hl7.fhir.r4.model.Resource;
018import org.hl7.fhir.r4.utils.client.FHIRToolingClient;
019import org.hl7.fhir.exceptions.FHIRException;
020import org.hl7.fhir.utilities.Utilities;
021
022public class BatchLoader {
023
024        public static void main(String[] args) throws IOException, Exception {
025          if (args.length < 4) {
026                System.out.println("Batch uploader takes 4 parameters in order: server base url, file/folder to upload, xml/json, and batch size");
027          } else {
028                String server = args[0];
029                String file = args[1];
030                IParser p = new JsonParser(); // args[2].equals("json") ? new JsonParser() : new XmlParser();
031                int size = Integer.parseInt(args[3]);
032                size = 500;
033                if (file.endsWith(".xml")) {
034                        throw new FHIRException("Unimplemented file type "+file);
035                } else if (file.endsWith(".json")) {
036                        throw new FHIRException("Unimplemented file type "+file);
037                } else if (file.endsWith(".zip")) {
038                        LoadZipFile(server, file, p, size, 0, -1);
039                } else if (new File(file).isDirectory()) {
040                  LoadDirectory(server, file, p, size);
041                } else 
042                        throw new FHIRException("Unknown file type "+file);
043          }
044        }
045
046        private static void LoadDirectory(String server, String file, IParser p, int size) throws IOException, Exception {
047//    LoadZipFile(server, Utilities.path(file, "Patient.json.zip"), p, size, 1000, -1);
048//    LoadZipFile(server, Utilities.path(file, "Binary.json.zip"), p, size, 0, -1);
049//        LoadZipFile(server, Utilities.path(file, "DocumentReference.json.zip"), p, size, 0, -1);
050//        LoadZipFile(server, Utilities.path(file, "Encounter.json.zip"), p, size, 0, -1);
051//        LoadZipFile(server, Utilities.path(file, "Organization.json.zip"), p, size, 0, -1);
052//          LoadZipFile(server, Utilities.path(file, "Procedure.json.zip"), p, size, 0, -1);
053//        LoadZipFile(server, Utilities.path(file, "AllergyIntolerance.json.zip"), p, size, 1500, -1);
054//          LoadZipFile(server, Utilities.path(file, "Condition.json.zip"), p, size, 0, -1);
055            LoadZipFile(server, Utilities.path(file, "Immunization.json.zip"), p, size, 0, -1);
056//        LoadZipFile(server, Utilities.path(file, "MedicationStatement.json.zip"), p, size, 0, -1);
057//        LoadZipFile(server, Utilities.path(file, "Observation-res.json.zip"), p, size, 0, -1);
058//        LoadZipFile(server, Utilities.path(file, "Observation-sh.json.zip"), p, size, 0, -1);
059//        LoadZipFile(server, Utilities.path(file, "Observation-vs.json.zip"), p, size, 0, -1);
060//        LoadZipFile(server, Utilities.path(file, "Observation-gen.json.zip"), p, size, 0, -1);
061//        LoadZipFile(server, Utilities.path(file, "List.json.zip"), p, size, 6500, -1);
062//        LoadZipFile(server, Utilities.path(file, "List-res.json.zip"), p, size, 0, -1);
063//        LoadZipFile(server, Utilities.path(file, "List-vs.json.zip"), p, size, 0, -1);
064  }
065
066        
067  private static void LoadZipFile(String server, String file, IParser p, int size, int start, int end) throws IOException, Exception {
068                System.out.println("Load Zip file "+file);
069                Bundle b = new Bundle();
070                b.setType(BundleType.COLLECTION);
071                b.setId(UUID.randomUUID().toString().toLowerCase());
072                ZipInputStream zip = new ZipInputStream(new FileInputStream(file));
073                ZipEntry entry;
074    while((entry = zip.getNextEntry())!=null)
075    {
076        try {
077          Resource r = p.parse(zip);
078          b.addEntry().setResource(r);
079        } catch (Exception e) {
080                throw new Exception("Error parsing "+entry.getName()+": "+e.getMessage(), e);
081        }
082    }
083                loadBundle(server, b, size, start, end);
084        }
085
086  
087        private static int loadBundle(String server, Bundle b, int size, int start, int end) throws URISyntaxException {
088                System.out.println("Post to "+server+". size = "+Integer.toString(size)+", start = "+Integer.toString(start)+", total = "+Integer.toString(b.getEntry().size()));
089                FHIRToolingClient client = new FHIRToolingClient(server);
090          int c = start;
091          if (end == -1)
092            end = b.getEntry().size();
093          while (c < end) {
094                        Bundle bt = new Bundle();
095                        bt.setType(BundleType.BATCH);                   
096                        bt.setId(UUID.randomUUID().toString().toLowerCase());
097                        for (int i = c; i < Math.min(b.getEntry().size(), c+size); i++) {
098                                BundleEntryComponent be = bt.addEntry();
099                                be.setResource(b.getEntry().get(i).getResource());
100                                be.getRequest().setMethod(HTTPVerb.PUT);
101                                be.getRequest().setUrl(be.getResource().getResourceType().toString()+"/"+be.getResource().getId());
102                        }
103                        System.out.print("  posting..");
104                        long ms = System.currentTimeMillis();
105                        Bundle resp = client.transaction(bt);
106                        
107                        for (int i = 0; i < resp.getEntry().size(); i++) {
108                          BundleEntryComponent t = resp.getEntry().get(i);
109                          if (!t.getResponse().getStatus().startsWith("2")) { 
110                            System.out.println("failed status at "+Integer.toString(i)+": "+t.getResponse().getStatus());
111                            return c+i;
112                          }
113                        }
114                        c = c + size;
115      System.out.println("  ..done: "+Integer.toString(c)+". ("+Long.toString(System.currentTimeMillis()-ms)+" ms)");
116          }
117                System.out.println(" done");
118                return c;
119        }
120
121}