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