001package org.hl7.fhir.dstu2.utils;
002
003/*-
004 * #%L
005 * org.hl7.fhir.dstu2
006 * %%
007 * Copyright (C) 2014 - 2019 Health Level 7
008 * %%
009 * Licensed under the Apache License, Version 2.0 (the "License");
010 * you may not use this file except in compliance with the License.
011 * You may obtain a copy of the License at
012 * 
013 *      http://www.apache.org/licenses/LICENSE-2.0
014 * 
015 * Unless required by applicable law or agreed to in writing, software
016 * distributed under the License is distributed on an "AS IS" BASIS,
017 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
018 * See the License for the specific language governing permissions and
019 * limitations under the License.
020 * #L%
021 */
022
023
024import java.io.File;
025import java.io.FileInputStream;
026import java.io.IOException;
027import java.net.URISyntaxException;
028import java.util.UUID;
029import java.util.zip.ZipEntry;
030import java.util.zip.ZipInputStream;
031
032import org.hl7.fhir.dstu2.formats.IParser;
033import org.hl7.fhir.dstu2.formats.JsonParser;
034import org.hl7.fhir.dstu2.model.Bundle;
035import org.hl7.fhir.dstu2.model.Bundle.BundleEntryComponent;
036import org.hl7.fhir.dstu2.model.Bundle.BundleType;
037import org.hl7.fhir.dstu2.model.Bundle.HTTPVerb;
038import org.hl7.fhir.dstu2.model.Resource;
039import org.hl7.fhir.dstu2.utils.client.FHIRToolingClient;
040import org.hl7.fhir.exceptions.FHIRException;
041import org.hl7.fhir.utilities.Utilities;
042
043public class BatchLoader {
044
045        public static void main(String[] args) throws IOException, Exception {
046          if (args.length < 4) {
047                System.out.println("Batch uploader takes 4 parameters in order: server base url, file/folder to upload, xml/json, and batch size");
048          } else {
049                String server = args[0];
050                String file = args[1];
051                IParser p = new JsonParser(); // args[2].equals("json") ? new JsonParser() : new XmlParser();
052                int size = Integer.parseInt(args[3]);
053                size = 500;
054                if (file.endsWith(".xml")) {
055                        throw new FHIRException("Unimplemented file type "+file);
056                } else if (file.endsWith(".json")) {
057                        throw new FHIRException("Unimplemented file type "+file);
058                } else if (file.endsWith(".zip")) {
059                        LoadZipFile(server, file, p, size, 0, -1);
060                } else if (new File(file).isDirectory()) {
061                  LoadDirectory(server, file, p, size);
062                } else 
063                        throw new FHIRException("Unknown file type "+file);
064          }
065        }
066
067        private static void LoadDirectory(String server, String file, IParser p, int size) throws IOException, Exception {
068//    LoadZipFile(server, Utilities.path(file, "Patient.json.zip"), p, size, 1000, -1);
069//    LoadZipFile(server, Utilities.path(file, "Binary.json.zip"), p, size, 0, -1);
070//        LoadZipFile(server, Utilities.path(file, "DocumentReference.json.zip"), p, size, 0, -1);
071//        LoadZipFile(server, Utilities.path(file, "Encounter.json.zip"), p, size, 0, -1);
072//        LoadZipFile(server, Utilities.path(file, "Organization.json.zip"), p, size, 0, -1);
073//          LoadZipFile(server, Utilities.path(file, "Procedure.json.zip"), p, size, 0, -1);
074//        LoadZipFile(server, Utilities.path(file, "AllergyIntolerance.json.zip"), p, size, 1500, -1);
075//          LoadZipFile(server, Utilities.path(file, "Condition.json.zip"), p, size, 0, -1);
076            LoadZipFile(server, Utilities.path(file, "Immunization.json.zip"), p, size, 0, -1);
077//        LoadZipFile(server, Utilities.path(file, "MedicationStatement.json.zip"), p, size, 0, -1);
078//        LoadZipFile(server, Utilities.path(file, "Observation-res.json.zip"), p, size, 0, -1);
079//        LoadZipFile(server, Utilities.path(file, "Observation-sh.json.zip"), p, size, 0, -1);
080//        LoadZipFile(server, Utilities.path(file, "Observation-vs.json.zip"), p, size, 0, -1);
081//        LoadZipFile(server, Utilities.path(file, "Observation-gen.json.zip"), p, size, 0, -1);
082//        LoadZipFile(server, Utilities.path(file, "List.json.zip"), p, size, 6500, -1);
083//        LoadZipFile(server, Utilities.path(file, "List-res.json.zip"), p, size, 0, -1);
084//        LoadZipFile(server, Utilities.path(file, "List-vs.json.zip"), p, size, 0, -1);
085  }
086
087        
088  private static void LoadZipFile(String server, String file, IParser p, int size, int start, int end) throws IOException, Exception {
089                System.out.println("Load Zip file "+file);
090                Bundle b = new Bundle();
091                b.setType(BundleType.COLLECTION);
092                b.setId(UUID.randomUUID().toString().toLowerCase());
093                ZipInputStream zip = new ZipInputStream(new FileInputStream(file));
094                ZipEntry entry;
095    while((entry = zip.getNextEntry())!=null)
096    {
097        try {
098          Resource r = p.parse(zip);
099          b.addEntry().setResource(r);
100        } catch (Exception e) {
101                throw new Exception("Error parsing "+entry.getName()+": "+e.getMessage(), e);
102        }
103    }
104                loadBundle(server, b, size, start, end);
105        }
106
107  
108        private static int loadBundle(String server, Bundle b, int size, int start, int end) throws URISyntaxException {
109                System.out.println("Post to "+server+". size = "+Integer.toString(size)+", start = "+Integer.toString(start)+", total = "+Integer.toString(b.getEntry().size()));
110                FHIRToolingClient client = new FHIRToolingClient(server);
111          int c = start;
112          if (end == -1)
113            end = b.getEntry().size();
114          while (c < end) {
115                        Bundle bt = new Bundle();
116                        bt.setType(BundleType.BATCH);                   
117                        bt.setId(UUID.randomUUID().toString().toLowerCase());
118                        for (int i = c; i < Math.min(b.getEntry().size(), c+size); i++) {
119                                BundleEntryComponent be = bt.addEntry();
120                                be.setResource(b.getEntry().get(i).getResource());
121                                be.getRequest().setMethod(HTTPVerb.PUT);
122                                be.getRequest().setUrl(be.getResource().getResourceType().toString()+"/"+be.getResource().getId());
123                        }
124                        System.out.print("  posting..");
125                        long ms = System.currentTimeMillis();
126                        Bundle resp = client.transaction(bt);
127                        
128                        for (int i = 0; i < resp.getEntry().size(); i++) {
129                          BundleEntryComponent t = resp.getEntry().get(i);
130                          if (!t.getResponse().getStatus().startsWith("2")) { 
131                            System.out.println("failed status at "+Integer.toString(i)+": "+t.getResponse().getStatus());
132                            return c+i;
133                          }
134                        }
135                        c = c + size;
136      System.out.println("  ..done: "+Integer.toString(c)+". ("+Long.toString(System.currentTimeMillis()-ms)+" ms)");
137          }
138                System.out.println(" done");
139                return c;
140        }
141
142}