001package org.hl7.fhir.utilities;
002
003import java.io.BufferedInputStream;
004import java.io.BufferedWriter;
005import java.io.File;
006import java.io.FileInputStream;
007import java.io.FileNotFoundException;
008import java.io.FileOutputStream;
009import java.io.FileWriter;
010import java.io.IOException;
011import java.io.OutputStream;
012import java.io.OutputStreamWriter;
013import java.io.StringWriter;
014import java.util.ArrayList;
015import java.util.Collections;
016import java.util.HashMap;
017import java.util.HashSet;
018import java.util.List;
019import java.util.Map;
020import java.util.Set;
021import java.util.zip.ZipEntry;
022
023import org.apache.commons.codec.Charsets;
024
025import com.google.gson.Gson;
026import com.google.gson.GsonBuilder;
027import com.google.gson.JsonElement;
028import com.google.gson.JsonObject;
029import com.google.gson.JsonSyntaxException;
030
031public class NDJsonWriter {
032
033  private class ResourceInfo {
034    private FileOutputStream stream;
035    private Set<String> ids = new HashSet<String>();
036    public OutputStreamWriter writer;
037  }
038  
039  private static com.google.gson.JsonParser  parser = new com.google.gson.JsonParser();
040  private Gson gson = new GsonBuilder().create();
041  private Map<String, ResourceInfo> outputs = new HashMap<String, ResourceInfo>();
042  private String filename;
043  private String scratch;
044  
045  public NDJsonWriter(String filename, String scratch) {
046    this.filename = filename;
047    this.scratch = scratch;
048    outputs.clear();
049  }
050
051  public void addFilesFiltered(String actualDir, String ext, String[] noExt) throws IOException {
052    File f = new CSFile(actualDir);
053
054    String files[] = f.list();
055    for (int i = 0; i < files.length; i++) {
056      if ( new CSFile(actualDir + files[i]).isFile() && ((ext == null || files[i].endsWith(ext)))) {
057        boolean ok = true;
058        for (String n : noExt) {
059          ok = ok && !files[i].endsWith(n);
060        }
061        if (ok) {
062          addFile(Utilities.path(actualDir, files[i]));
063        }
064      }
065    }
066  }
067
068  private void addFile(String path) throws JsonSyntaxException, FileNotFoundException, IOException {
069    JsonObject js = parser.parse(TextFile.fileToString(path)).getAsJsonObject();
070    if (js.has("resourceType")) {
071      addResource(js);  
072    }
073  }
074
075  private void addResource(JsonObject js) throws IOException {
076    String rn = js.get("resourceType").getAsString();    
077    if (rn.equals("Bundle")) {
078      if (js.has("entry")) {
079        for (JsonElement item : js.getAsJsonArray("entry")) {
080          if (item instanceof JsonObject && ((JsonObject) item).has("resource")) {
081            JsonObject r = (JsonObject) ((JsonObject) item).get("resource");
082            rn = r.get("resourceType").getAsString();
083            addResource(r);  
084          }
085        }
086      }
087    } else {
088      if (!js.has("id"))
089        return;
090
091      String id = js.get("id").getAsString();
092      String json = gson.toJson(js);
093      
094      if (outputs.containsKey(rn)) { 
095        ResourceInfo ri = outputs.get(rn);
096        if (!ri.ids.contains(id)) {
097          ri.ids.add(id);
098          ri.writer.append("\r\n");      
099          ri.writer.append(json);
100        }
101      } else {
102        ResourceInfo ri = new ResourceInfo();
103        outputs.put(rn, ri);
104        ri.ids.add(id);
105        ri.stream = new FileOutputStream(Utilities.path(scratch, rn+".ndjson"));
106        ri.writer = new OutputStreamWriter(ri.stream, "UTF-8");
107        ri.writer.append(json);      
108      }
109    }
110  }
111
112  public void close() throws IOException {
113    ZipGenerator zip = new ZipGenerator(filename);
114    for (String rn : sorted(outputs.keySet())) {
115      ResourceInfo ri = outputs.get(rn);
116      ri.writer.flush();
117      ri.writer.close();
118      ri.stream.close();
119      
120      zip.addStream(rn+".ndjson", new FileInputStream(Utilities.path(scratch, rn+".ndjson")), false);
121    }
122    zip.close();
123  }
124
125  private List<String> sorted(Set<String> keys) {
126    List<String> res = new ArrayList<String>();
127    res.addAll(keys);
128    Collections.sort(res);
129    return res;
130  }
131
132  public static void main(String[] args) throws IOException {
133    String dstDir = "C:\\work\\org.hl7.fhir\\build\\publish\\";
134    NDJsonWriter ndjson = new NDJsonWriter(dstDir + "examples-ndjson.zip", "c:\\temp\\ndjson");
135    ndjson.addFilesFiltered(dstDir, ".json", new String[] {".schema.json", ".canonical.json", ".diff.json", "expansions.json", "package.json"});
136    ndjson.close();
137  }
138
139}