001package org.hl7.fhir.convertors.misc; 002 003import java.io.File; 004import java.io.FileInputStream; 005import java.io.FileNotFoundException; 006import java.io.IOException; 007import java.util.ArrayList; 008import java.util.HashMap; 009import java.util.HashSet; 010import java.util.List; 011import java.util.Map; 012import java.util.Map.Entry; 013import java.util.Set; 014 015import javax.xml.parsers.ParserConfigurationException; 016 017import org.hl7.fhir.dstu2.model.ElementDefinition; 018import org.hl7.fhir.dstu2.model.StructureDefinition; 019import org.hl7.fhir.dstu2.model.StructureDefinition.StructureDefinitionSnapshotComponent; 020import org.hl7.fhir.exceptions.FHIRFormatError; 021import org.hl7.fhir.utilities.Utilities; 022import org.hl7.fhir.utilities.filesystem.ManagedFileAccess; 023import org.hl7.fhir.utilities.json.JsonTrackingParser; 024import org.xml.sax.SAXException; 025 026import com.google.gson.JsonArray; 027import com.google.gson.JsonElement; 028import com.google.gson.JsonObject; 029 030public class XVerPackegeFixer { 031 032 public static class References { 033 private boolean modifier; 034 private boolean inherited; 035 036 public boolean getModifier() { 037 return modifier; 038 } 039 040 public void setModifier(boolean value) { 041 this.modifier = value; 042 } 043 044 public boolean getInherited() { 045 return inherited; 046 } 047 048 public void setInherited(boolean inherited) { 049 this.inherited = inherited; 050 } 051 052 } 053 054 055 private static final String R5_FOLDER = "/Users/grahamegrieve/work/packages/hl7.fhir.rX/hl7.fhir.r5.core/package"; 056 private static final String R4_FOLDER = "/Users/grahamegrieve/work/packages/hl7.fhir.rX/hl7.fhir.r4.core/package"; 057 private static final String R3_FOLDER = "/Users/grahamegrieve/work/packages/hl7.fhir.rX/hl7.fhir.r3.core/package"; 058 private static final String R2B_FOLDER = "/Users/grahamegrieve/work/packages/hl7.fhir.rX/hl7.fhir.r2b.core/package"; 059 private static final String R2_FOLDER = "/Users/grahamegrieve/work/packages/hl7.fhir.rX/hl7.fhir.r2.core/package"; 060 private static int modCount; 061 062 private static Map<String, org.hl7.fhir.r5.model.StructureDefinition> map5 = new HashMap<>(); 063 private static Map<String, org.hl7.fhir.r4.model.StructureDefinition> map4 = new HashMap<>(); 064 private static Map<String, org.hl7.fhir.dstu3.model.StructureDefinition> map3 = new HashMap<>(); 065 private static Map<String, org.hl7.fhir.dstu2.model.StructureDefinition> map2 = new HashMap<>(); 066 private static Map<String, org.hl7.fhir.dstu2016may.model.StructureDefinition> map2b = new HashMap<>(); 067 068 public static void main(String[] args) throws FileNotFoundException, ParserConfigurationException, SAXException, IOException { 069 modCount = 0; 070 for (File f : ManagedFileAccess.file(args[0]).listFiles()) { 071 if (f.getName().startsWith("xver-") && f.getName().contains("1.0")) { 072 JsonObject j = JsonTrackingParser.parseJson(f); 073 fixUp(j, f.getName()); 074 JsonTrackingParser.write(j, f, true); 075 } 076 } 077 System.out.println("all done: "+modCount+" modifiers"); 078 } 079 080 private static void fixUp(JsonObject j, String name) throws FHIRFormatError, FileNotFoundException, IOException { 081 name = name.replace(".json", ""); 082 System.out.println("Process "+name); 083 String version = name.substring(name.lastIndexOf("-")+1); 084 Set<String> pr = new HashSet<>(); 085 086 int i = 0; 087 for (Entry<String, JsonElement> e : j.entrySet()) { 088 if (i == 50) { 089 i = 0; 090 System.out.print("."); 091 } 092 i++; 093 String n = e.getKey(); 094 JsonObject o = ((JsonObject) e.getValue()); 095 // boolean ok = (o.has("types") && o.getAsJsonArray("types").size() > 0) || (o.has("elements") && o.getAsJsonArray("elements").size() > 0); 096// if (!ok) { 097 if (o.has("types")) { 098 o.remove("types"); 099 } 100 if (o.has("elements")) { 101 o.remove("elements"); 102 } 103 if (o.has("modifier")) { 104 o.remove("modifier"); 105 } 106 List<String> types = new ArrayList<>(); 107 List<String> elements = new ArrayList<>(); 108 References mod = new References(); 109 getElementInfo(version, n, types, elements, mod); 110 if (mod.getInherited()) { 111 pr.add(n); 112 } 113 if (elements.size() > 0) { 114 JsonArray arr = o.getAsJsonArray("elements"); 115 if (arr == null) { 116 arr = new JsonArray(); 117 o.add("elements", arr); 118 } 119 for (String s : elements) { 120 arr.add(s); 121 } 122 } else if (types.size() > 0) { 123 JsonArray arr = o.getAsJsonArray("types"); 124 if (arr == null) { 125 arr = new JsonArray(); 126 o.add("types", arr); 127 } 128 for (String s : types) { 129 arr.add(s); 130 } 131 } 132 if (mod.getModifier()) { 133 o.addProperty("modifier", true); 134 modCount++; 135 } 136// } 137 } 138 for (String s : pr) { 139 j.remove(s); 140 } 141 System.out.println("done"); 142 } 143 144 private static boolean getElementInfo(String version, String n, List<String> types, List<String> elements, References mod) throws FHIRFormatError, FileNotFoundException, IOException { 145// if ("contained".equals(n.substring(n.indexOf(".")+1))) { 146// return false; 147// } 148 switch (version) { 149 case "4.6": return getElementInfoR5(n, types, elements, mod); 150 case "4.0": return getElementInfoR4(n, types, elements, mod); 151 case "3.0": return getElementInfoR3(n, types, elements, mod); 152 case "1.4": return getElementInfoR2B(n, types, elements, mod); 153 case "1.0": return getElementInfoR2(n, types, elements, mod); 154 } 155 return false; 156 } 157 158 private static String tail(String value) { 159 return value.contains("/") ? value.substring(value.lastIndexOf("/")+1) : value; 160 } 161 162 private static boolean getElementInfoR5(String n, List<String> types, List<String> elements, References mod) throws FHIRFormatError, FileNotFoundException, IOException { 163 String tn = n.substring(0, n.indexOf(".")); 164 org.hl7.fhir.r5.model.StructureDefinition sd = null; 165 if (map5.containsKey(tn)) { 166 sd = map5.get(tn); 167 } else { 168 sd = (org.hl7.fhir.r5.model.StructureDefinition) new org.hl7.fhir.r5.formats.JsonParser().parse(ManagedFileAccess.inStream(Utilities.path(R5_FOLDER, "StructureDefinition-"+tn+".json"))); 169 map5.put(tn, sd); 170 } 171 for (org.hl7.fhir.r5.model.ElementDefinition ed : sd.getSnapshot().getElement()) { 172 if (ed.getPath().equals(n)) { 173 mod.setModifier(ed.getIsModifier()); 174 List<org.hl7.fhir.r5.model.ElementDefinition> children = listChildrenR5(sd.getSnapshot().getElement(), ed); 175 if (children.size() > 0) { 176 for (org.hl7.fhir.r5.model.ElementDefinition c : children) { 177 String en = c.getPath().substring(ed.getPath().length()+1); 178 elements.add(en); 179 } 180 } else { 181 for (org.hl7.fhir.r5.model.ElementDefinition.TypeRefComponent t : ed.getType()) { 182 if (t.hasTargetProfile()) { 183 StringBuilder b = new StringBuilder(); 184 b.append(t.getWorkingCode()); 185 b.append("("); 186 boolean first = true; 187 for (org.hl7.fhir.r5.model.CanonicalType u : t.getTargetProfile()) { 188 if (first) first = false; else b.append("|"); 189 b.append(tail(u.getValue())); 190 } 191 b.append(")"); 192 types.add(b.toString()); 193 } else { 194 types.add(t.getWorkingCode()); 195 } 196 } 197 } 198 } 199 } 200 return false; 201 } 202 203 204 private static List<org.hl7.fhir.r5.model.ElementDefinition> listChildrenR5(List<org.hl7.fhir.r5.model.ElementDefinition> list, org.hl7.fhir.r5.model.ElementDefinition ed) { 205 List<org.hl7.fhir.r5.model.ElementDefinition> res = new ArrayList<>(); 206 for (org.hl7.fhir.r5.model.ElementDefinition t : list) { 207 String p = t.getPath(); 208 if (p.startsWith(ed.getPath()+".")) { 209 p = p.substring(ed.getPath().length()+1); 210 if (!p.contains(".")) { 211 res.add(t); 212 } 213 } 214 } 215 return res; 216 } 217 218 private static boolean getElementInfoR4(String n, List<String> types, List<String> elements, References mod) throws FHIRFormatError, FileNotFoundException, IOException { 219 String tn = n.substring(0, n.indexOf(".")); 220 org.hl7.fhir.r4.model.StructureDefinition sd = null; 221 if (map4.containsKey(tn)) { 222 sd = map4.get(tn); 223 } else { 224 sd = (org.hl7.fhir.r4.model.StructureDefinition) new org.hl7.fhir.r4.formats.JsonParser().parse(ManagedFileAccess.inStream(Utilities.path(R4_FOLDER, "StructureDefinition-"+tn+".json"))); 225 map4.put(tn, sd); 226 } 227 for (org.hl7.fhir.r4.model.ElementDefinition ed : sd.getSnapshot().getElement()) { 228 if (ed.getPath().equals(n)) { 229 mod.setModifier(ed.getIsModifier()); 230 List<org.hl7.fhir.r4.model.ElementDefinition> children = listChildrenR4(sd.getSnapshot().getElement(), ed); 231 if (children.size() > 0) { 232 for (org.hl7.fhir.r4.model.ElementDefinition c : children) { 233 String en = c.getPath().substring(ed.getPath().length()+1); 234 elements.add(en); 235 } 236 } else { 237 for (org.hl7.fhir.r4.model.ElementDefinition.TypeRefComponent t : ed.getType()) { 238 if (t.hasTargetProfile()) { 239 StringBuilder b = new StringBuilder(); 240 b.append(t.getWorkingCode()); 241 b.append("("); 242 boolean first = true; 243 for (org.hl7.fhir.r4.model.CanonicalType u : t.getTargetProfile()) { 244 if (first) first = false; else b.append("|"); 245 b.append(tail(u.getValue())); 246 } 247 b.append(")"); 248 types.add(b.toString()); 249 } else { 250 types.add(t.getWorkingCode()); 251 } 252 } 253 } 254 } 255 } 256 return false; 257 } 258 259 260 private static List<org.hl7.fhir.r4.model.ElementDefinition> listChildrenR4(List<org.hl7.fhir.r4.model.ElementDefinition> list, org.hl7.fhir.r4.model.ElementDefinition ed) { 261 List<org.hl7.fhir.r4.model.ElementDefinition> res = new ArrayList<>(); 262 for (org.hl7.fhir.r4.model.ElementDefinition t : list) { 263 String p = t.getPath(); 264 if (p.startsWith(ed.getPath()+".")) { 265 p = p.substring(ed.getPath().length()+1); 266 if (!p.contains(".")) { 267 res.add(t); 268 } 269 } 270 } 271 return res; 272 } 273 274 275 private static boolean getElementInfoR3(String n, List<String> types, List<String> elements, References mod) throws FHIRFormatError, FileNotFoundException, IOException { 276 String tn = n.substring(0, n.indexOf(".")); 277 org.hl7.fhir.dstu3.model.StructureDefinition sd = null; 278 if (map3.containsKey(tn)) { 279 sd = map3.get(tn); 280 } else { 281 sd = (org.hl7.fhir.dstu3.model.StructureDefinition) new org.hl7.fhir.dstu3.formats.JsonParser().parse(ManagedFileAccess.inStream(Utilities.path(R3_FOLDER, "StructureDefinition-"+tn+".json"))); 282 map3.put(tn, sd); 283 } 284 for (org.hl7.fhir.dstu3.model.ElementDefinition ed : sd.getSnapshot().getElement()) { 285 if (ed.getPath().equals(n)) { 286 mod.setModifier(ed.getIsModifier()); 287 List<org.hl7.fhir.dstu3.model.ElementDefinition> children = listChildrenR3(sd.getSnapshot().getElement(), ed); 288 if (children.size() > 0) { 289 for (org.hl7.fhir.dstu3.model.ElementDefinition c : children) { 290 String en = c.getPath().substring(ed.getPath().length()+1); 291 elements.add(en); 292 } 293 } else { 294 for (org.hl7.fhir.dstu3.model.ElementDefinition.TypeRefComponent t : ed.getType()) { 295 if (t.hasTargetProfile()) { 296 StringBuilder b = new StringBuilder(); 297 b.append(t.getCode()); 298 b.append("("); 299 b.append(tail(t.getTargetProfile())); 300 b.append(")"); 301 types.add(b.toString()); 302 } else { 303 types.add(t.getCode()); 304 } 305 } 306 } 307 } 308 } 309 return false; 310 } 311 312 313 private static List<org.hl7.fhir.dstu3.model.ElementDefinition> listChildrenR3(List<org.hl7.fhir.dstu3.model.ElementDefinition> list, org.hl7.fhir.dstu3.model.ElementDefinition ed) { 314 List<org.hl7.fhir.dstu3.model.ElementDefinition> res = new ArrayList<>(); 315 for (org.hl7.fhir.dstu3.model.ElementDefinition t : list) { 316 String p = t.getPath(); 317 if (p.startsWith(ed.getPath()+".")) { 318 p = p.substring(ed.getPath().length()+1); 319 if (!p.contains(".")) { 320 res.add(t); 321 } 322 } 323 } 324 return res; 325 } 326 327 328 private static boolean getElementInfoR2(String n, List<String> types, List<String> elements, References mod) throws FHIRFormatError, FileNotFoundException, IOException { 329 String tn = n.substring(0, n.indexOf(".")); 330 org.hl7.fhir.dstu2.model.StructureDefinition sd = null; 331 sd = loadType(tn); 332 mod.setInherited(isInherited(n, sd)); 333 for (org.hl7.fhir.dstu2.model.ElementDefinition ed : sd.getSnapshot().getElement()) { 334 if (ed.getPath().equals(n)) { 335 mod.setModifier(ed.getIsModifier()); 336 List<org.hl7.fhir.dstu2.model.ElementDefinition> children = listChildrenR2(sd.getSnapshot().getElement(), ed); 337 if (children.size() > 0) { 338 for (org.hl7.fhir.dstu2.model.ElementDefinition c : children) { 339 String en = c.getPath().substring(ed.getPath().length()+1); 340 elements.add(en); 341 } 342 } else { 343 boolean isReference = false; 344 StringBuilder r = new StringBuilder(); 345 r.append("Reference("); 346 for (org.hl7.fhir.dstu2.model.ElementDefinition.TypeRefComponent t : ed.getType()) { 347 if (t.hasProfile()) { 348 if ("Reference".equals(t.getCode())) { 349 for (org.hl7.fhir.dstu2.model.UriType u : t.getProfile()) { 350 if (isReference) 351 r.append("|"); 352 r.append(tail(u.getValue())); 353 isReference = true; 354 } 355 } else { 356 StringBuilder b = new StringBuilder(); 357 b.append(t.getCode()); 358 b.append("("); 359 boolean first = true; 360 for (org.hl7.fhir.dstu2.model.UriType u : t.getProfile()) { 361 if (first) first = false; else b.append("|"); 362 b.append(tail(u.getValue())); 363 } 364 b.append(")"); 365 types.add(b.toString()); 366 } 367 } else { 368 types.add(t.getCode()); 369 } 370 } 371 if (isReference) { 372 r.append(")"); 373 types.add(r.toString()); 374 } 375 } 376 } 377 } 378 return false; 379 } 380 381 private static org.hl7.fhir.dstu2.model.StructureDefinition loadType(String tn) 382 throws IOException, FileNotFoundException { 383 org.hl7.fhir.dstu2.model.StructureDefinition sd; 384 if (map2.containsKey(tn)) { 385 sd = map2.get(tn); 386 } else { 387 sd = (org.hl7.fhir.dstu2.model.StructureDefinition) new org.hl7.fhir.dstu2.formats.JsonParser().parse(ManagedFileAccess.inStream(Utilities.path(R2_FOLDER, "StructureDefinition-"+tn+".json"))); 388 map2.put(tn, sd); 389 } 390 return sd; 391 } 392 393 394 private static boolean isInherited(String n, StructureDefinition sd) throws FileNotFoundException, IOException { 395 String tail = n.substring(n.indexOf(".")+1); 396 while (sd != null) { 397 sd = sd.hasBase() ? loadType(tail(sd.getBase())) : null; 398 if (sd != null && hasPath(sd.getSnapshot(), sd.getName()+"."+tail)) { 399 return true; 400 } 401 } 402 return false; 403 } 404 405 private static boolean hasPath(StructureDefinitionSnapshotComponent snapshot, String path) { 406 for (ElementDefinition ed : snapshot.getElement()) { 407 if (ed.getPath().equals(path)) { 408 return true; 409 } 410 } 411 return false; 412 } 413 414 private static List<org.hl7.fhir.dstu2.model.ElementDefinition> listChildrenR2(List<org.hl7.fhir.dstu2.model.ElementDefinition> list, org.hl7.fhir.dstu2.model.ElementDefinition ed) { 415 List<org.hl7.fhir.dstu2.model.ElementDefinition> res = new ArrayList<>(); 416 for (org.hl7.fhir.dstu2.model.ElementDefinition t : list) { 417 String p = t.getPath(); 418 if (p.startsWith(ed.getPath()+".")) { 419 p = p.substring(ed.getPath().length()+1); 420 if (!p.contains(".")) { 421 res.add(t); 422 } 423 } 424 } 425 return res; 426 } 427 428 429 private static boolean getElementInfoR2B(String n, List<String> types, List<String> elements, References mod) throws FHIRFormatError, FileNotFoundException, IOException { 430 String tn = n.substring(0, n.indexOf(".")); 431 org.hl7.fhir.dstu2016may.model.StructureDefinition sd = null; 432 if (map2b.containsKey(tn)) { 433 sd = map2b.get(tn); 434 } else { 435 sd = (org.hl7.fhir.dstu2016may.model.StructureDefinition) new org.hl7.fhir.dstu2016may.formats.JsonParser().parse(ManagedFileAccess.inStream(Utilities.path(R2B_FOLDER, "StructureDefinition-"+tn+".json"))); 436 map2b.put(tn, sd); 437 } 438 for (org.hl7.fhir.dstu2016may.model.ElementDefinition ed : sd.getSnapshot().getElement()) { 439 if (ed.getPath().equals(n)) { 440 mod.setModifier(ed.getIsModifier()); 441 List<org.hl7.fhir.dstu2016may.model.ElementDefinition> children = listChildrenR2B(sd.getSnapshot().getElement(), ed); 442 if (children.size() > 0) { 443 for (org.hl7.fhir.dstu2016may.model.ElementDefinition c : children) { 444 String en = c.getPath().substring(ed.getPath().length()+1); 445 elements.add(en); 446 } 447 } else { 448 for (org.hl7.fhir.dstu2016may.model.ElementDefinition.TypeRefComponent t : ed.getType()) { 449 if (t.hasProfile()) { 450 StringBuilder b = new StringBuilder(); 451 b.append(t.getCode()); 452 b.append("("); 453 boolean first = true; 454 for (org.hl7.fhir.dstu2016may.model.UriType u : t.getProfile()) { 455 if (first) first = false; else b.append("|"); 456 b.append(tail(u.getValue())); 457 } 458 b.append(")"); 459 types.add(b.toString()); 460 } else { 461 types.add(t.getCode()); 462 } 463 } 464 } 465 } 466 } 467 return false; 468 } 469 470 471 private static List<org.hl7.fhir.dstu2016may.model.ElementDefinition> listChildrenR2B(List<org.hl7.fhir.dstu2016may.model.ElementDefinition> list, org.hl7.fhir.dstu2016may.model.ElementDefinition ed) { 472 List<org.hl7.fhir.dstu2016may.model.ElementDefinition> res = new ArrayList<>(); 473 for (org.hl7.fhir.dstu2016may.model.ElementDefinition t : list) { 474 String p = t.getPath(); 475 if (p.startsWith(ed.getPath()+".")) { 476 p = p.substring(ed.getPath().length()+1); 477 if (!p.contains(".")) { 478 res.add(t); 479 } 480 } 481 } 482 return res; 483 } 484 485 486}