001package org.hl7.fhir.r5.utils;
002
003import java.io.File;
004import java.io.FileOutputStream;
005import java.io.IOException;
006import java.util.List;
007
008import org.hl7.fhir.r5.formats.IParser.OutputStyle;
009import org.hl7.fhir.utilities.CommaSeparatedStringBuilder;
010import org.hl7.fhir.utilities.FileUtilities;
011import org.hl7.fhir.utilities.MarkedToMoveToAdjunctPackage;
012import org.hl7.fhir.utilities.Utilities;
013import org.hl7.fhir.utilities.json.JsonException;
014import org.hl7.fhir.utilities.json.model.JsonElement;
015import org.hl7.fhir.utilities.json.model.JsonObject;
016import org.hl7.fhir.utilities.json.model.JsonProperty;
017import org.hl7.fhir.utilities.json.parser.JsonParser;
018
019@MarkedToMoveToAdjunctPackage
020@SuppressWarnings("checkstyle:systemout")
021public class JsonResourceTemplateFixer {
022
023  public static void main(String[] args) throws JsonException, IOException {
024  new JsonResourceTemplateFixer().execute(
025      "/Users/grahamegrieve/work/fhir-tx-ecosystem-ig/tests",
026      "/Users/grahamegrieve/temp/tx-tests", "");
027  }
028
029  private void execute(String source, String dest, String path) throws JsonException, IOException {
030    File src = new File(source);
031    for (File f : src.listFiles()) {
032      if (f.isDirectory()) {
033        execute(f.getAbsolutePath(), dest, "".equals(path) ? f.getName() : Utilities.path(path, f.getName()));
034      } else if (f.getName().endsWith(".json")) {
035        JsonObject j = JsonParser.parseObject(f);
036        if (j.has("resourceType")) {
037          FileUtilities.createDirectory(Utilities.path(dest, "in", path));
038          JsonParser.compose(j, new File(Utilities.path(dest, "in", path, f.getName())), true);
039          checkJsonObject(j);
040          FileUtilities.createDirectory(Utilities.path(dest, "out", path));
041          File tgt = new File(Utilities.path(dest, "out", path, f.getName()));
042          JsonParser.compose(j, tgt, true);
043          try {
044            var res = new org.hl7.fhir.r5.formats.JsonParser().parse(FileUtilities.fileToBytes(tgt));
045            new org.hl7.fhir.r5.formats.JsonParser().setOutputStyle(OutputStyle.PRETTY).compose(new FileOutputStream(tgt), res);
046          } catch (Exception e) {
047            System.out.println("Error reading "+tgt.getAbsolutePath()+": "+e.getMessage());
048          }
049        }
050      }
051    } 
052  }
053
054  private void checkJsonObject(JsonObject j) {
055    if (j.has("$optional-properties$")) {
056      List<String> names = j.getJsonArray("$optional-properties$").asStrings();
057      j.remove("$optional-properties$");
058      addExtension(j, "optional-properties", "string", CommaSeparatedStringBuilder.join(",", names));
059//      for (String n : names) {
060//        if (j.hasObject(n)) {
061//          addExtension(j.getJsonObject(n), "optional", true);
062//        } else {
063////          addExtension(j.forceObject("_"+n), "optional", true);
064//          addExtension(j, "optional-property", "code", n);
065//        }
066//      }
067    }
068    if (j.has("$optional$")) {
069      j.remove("$optional$");
070      addExtension(j, "optional", true);
071      
072    }
073    if (j.has("$count-arrays$")) {
074      List<String> names = j.getJsonArray("$count-arrays$").asStrings();
075      j.remove("$count-arrays$");
076      addExtension(j, "count-arrays", "string", CommaSeparatedStringBuilder.join(",", names));
077//      for (String n : names) {
078//        addExtension(j, "count-array", "code", n);
079//      }
080    }
081
082    for (int i = j.getProperties().size() -1; i >= 0; i--) {
083      JsonProperty p = j.getProperties().get(i);
084       if (p.getValue().isJsonArray()) {
085         for (JsonElement e : p.getValue().asJsonArray()) {
086            checkJsonElement(j, p.getName(), e);
087         }
088      } else {
089        checkJsonElement(j, p.getName(), p.getValue());
090      }
091    }
092  }
093
094  public void addExtension(JsonObject j, String url, String type, String value) {
095    JsonObject ext = new JsonObject();
096    ext.set("url", "http://hl7.org/fhir/uv/tools/StructureDefinition/test-template-"+url);
097    ext.set("value"+Utilities.capitalize(type), value);
098    j.forceArray(0, "extension").add(ext);
099  }
100
101  public void addExtension(JsonObject j, String url, boolean value) {
102    JsonObject ext = new JsonObject();
103    ext.set("url", "http://hl7.org/fhir/uv/tools/StructureDefinition/test-template-"+url);
104    ext.set("valueBoolean", value);
105    j.forceArray(0, "extension").add(ext);
106  }
107
108  public void addNamedExtension(JsonObject parent, String name, String url, String type, String value) {
109    JsonObject k = parent.getJsonObject("_"+name);
110    if (k == null) {
111      k = new JsonObject();
112      parent.add("_"+name, k);
113    }
114    JsonObject ext = new JsonObject();
115    ext.set("url", "http://hl7.org/fhir/uv/tools/StructureDefinition/test-template-"+url);
116    ext.set("value"+Utilities.capitalize(type), value);
117    k.forceArray("extension").add(ext);
118  }
119  
120  private void checkJsonElement(JsonObject parent, String name, JsonElement value) {
121    if (value.isJsonObject()) {
122      checkJsonObject(value.asJsonObject());
123    } else if (value.isJsonPrimitive()) {
124      checkJsonPrimitive(parent, name, value.asString());
125    } else {
126      // ignore?
127      // System.out.println("What?");
128    }
129  }
130
131  private void checkJsonPrimitive(JsonObject parent, String name, String value) {
132    if (true) {
133      return;
134    }
135    if (value.startsWith("$")) {
136      parent.remove(name);
137      switch (value) {
138      case "$$" : 
139        addNamedExtension(parent, name, "value-rule", "string", "string");
140        break;
141      case "$id$" :
142        addNamedExtension(parent, name, "value-rule", "string", "id");
143        break;
144      case "$semver$" : 
145        addNamedExtension(parent, name, "value-rule", "string", "semver");
146        break;
147      case "$url$" : 
148        addNamedExtension(parent, name, "value-rule", "string", "url");
149        break;
150      case "$token$" : 
151        addNamedExtension(parent, name, "value-rule", "string", "token");
152        break;
153      case "$string$" : 
154        addNamedExtension(parent, name, "value-rule", "string", "string");
155        break;
156      case "$date$" : 
157        addNamedExtension(parent, name, "value-rule", "string", "date");
158        break;
159      case "$version$" : 
160        addNamedExtension(parent, name, "value-rule", "string", "version");
161        break;
162      case "$uuid$" : 
163        addNamedExtension(parent, name, "value-rule", "string", "uuid");
164        break;
165      case "$instant$" : 
166        addNamedExtension(parent, name, "value-rule", "string", "instant");
167        break;
168      default:
169        if (value.startsWith("$choice:")) {
170          String[] list = value.substring(8).replace("$", "").split("\\|");
171          for (String n : list) {
172            addNamedExtension(parent, name, "value-choice", "string", n);
173          }
174        } else {
175          System.out.println("not handled yet: "+value);
176        }
177      }
178    } else {
179    }
180    
181  }
182}