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