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