
001package org.hl7.fhir.convertors.misc; 002 003import java.io.IOException; 004import java.util.ArrayList; 005import java.util.List; 006 007import javax.xml.parsers.ParserConfigurationException; 008 009import org.hl7.fhir.convertors.analytics.PackageVisitor; 010import org.hl7.fhir.convertors.analytics.PackageVisitor.IPackageVisitorProcessor; 011import org.hl7.fhir.convertors.analytics.PackageVisitor.PackageContext; 012import org.hl7.fhir.exceptions.FHIRException; 013import org.hl7.fhir.r5.utils.EOperationOutcome; 014import org.hl7.fhir.utilities.FileUtilities; 015import org.hl7.fhir.utilities.Utilities; 016import org.hl7.fhir.utilities.json.model.JsonObject; 017import org.hl7.fhir.utilities.json.parser.JsonParser; 018import org.hl7.fhir.utilities.npm.NpmPackage; 019import org.hl7.fhir.utilities.npm.PackageServer; 020import org.xml.sax.SAXException; 021 022@SuppressWarnings("checkstyle:systemout") 023public class MustSupportSlicingFinder implements IPackageVisitorProcessor { 024 025 026 public class Issue { 027 private String pvid; 028 private String url; 029 private String path; 030 private String ref; 031 private boolean ms; 032 private boolean smsOne; 033 private boolean smsAll; 034 private int sliceCount; 035 public Issue(String pvid, String url, String path, String ref, boolean ms, int sliceCount, boolean smsOne, boolean smsAll) { 036 super(); 037 this.pvid = pvid; 038 this.url = url; 039 this.path = path; 040 this.ref = ref; 041 this.ms = ms; 042 this.sliceCount = sliceCount; 043 this.smsOne = smsOne; 044 this.smsAll = smsAll; 045 } 046 public String summary() { 047 return url+"#"+path+": "+meaning()+" from "+pvid+" @ "+ref; 048 } 049 050 public String meaning() { 051 if (!ms) { 052 if (sliceCount == 1) { 053 count1++; 054 return "slicer MustSupport = false, but the only slice is must-support"; 055 } else if (sliceCount > 1) { 056 if (smsAll) { 057 count2++; 058 return "slicer MustSupport = false, but all "+sliceCount+" slices are must-support"; 059 } else { 060 count3++; 061 return "slicer MustSupport = false, but some of "+sliceCount+" slices are must-support"; 062 } 063 } else { 064 count4++; 065 return "slicer MustSupport = false, and there are no slices"; 066 } 067 } else if (!smsOne) { 068 if (sliceCount == 0) { 069 count5++; 070 return "slicer MustSupport = true, no slices"; 071 } else if (sliceCount == 1) { 072 count6++; 073 return "slicer MustSupport = true, but the slice is not must-support"; 074 } else { 075 count7++; 076 return "slicer MustSupport = true, but all "+sliceCount+" slices are not must-support"; 077 } 078 } else { 079 if (sliceCount == 1) { 080 count8++; 081 return "slicer MustSupport = true, and the slice is must-support"; 082 } else { 083 count9++; 084 return "slicer MustSupport = true, and some of "+sliceCount+" slices are must-support"; 085 } 086 } 087 } 088 } 089 090 public static void main(String[] args) throws FHIRException, IOException, ParserConfigurationException, SAXException, EOperationOutcome { 091 new MustSupportSlicingFinder().execute(); 092 } 093 094 List<Issue> issues = new ArrayList<>(); 095 public int count1 = 0; 096 public int count2 = 0; 097 public int count3 = 0; 098 public int count4 = 0; 099 public int count5 = 0; 100 public int count6 = 0; 101 public int count7 = 0; 102 public int count8 = 0; 103 public int count9 = 0; 104 105 106 private void execute() throws FHIRException, IOException, ParserConfigurationException, SAXException, EOperationOutcome { 107 PackageVisitor pv = new PackageVisitor(); 108 pv.setCorePackages(false); 109 pv.setClientPackageServer(PackageServer.primaryServer()); 110 pv.setResourceTypes("StructureDefinition", "Patient", "RelatedPerson", "Practitioner", "Person"); 111 pv.setProcessor(this); 112 pv.visitPackages(); 113 for (Issue s : issues) { 114 System.out.println(s.summary()); 115 } 116 117 System.out.println("slicer MustSupport = false, but the only slice is must-support: "+count1); 118 System.out.println("slicer MustSupport = false, but all N slices are must-support: "+count2); 119 System.out.println("slicer MustSupport = false, but some of N slices are must-support: "+count3); 120 System.out.println("slicer MustSupport = false, and there are no slices: "+count4); 121 System.out.println("slicer MustSupport = true, no slices: "+count5); 122 System.out.println("slicer MustSupport = true, but the slice is not must-support: "+count6); 123 System.out.println("slicer MustSupport = true, but all N slices are not must-support: "+count7); 124 System.out.println("slicer MustSupport = true, and the slice is must-support: "+count8); 125 System.out.println("slicer MustSupport = true, and some of N slices are must-support: "+count9); 126 } 127 128 @Override 129 public Object startPackage(PackageContext context) throws FHIRException, IOException, EOperationOutcome { 130 if (isUS(context.getNpm())) { 131 System.out.println(context.getPid()+" is a US Realm package"); 132 return this; 133 } else { 134 return null; 135 } 136 } 137 138 private boolean isUS(NpmPackage npm) { 139 if (npm != null) { 140 return npm.name().contains("hl7.fhir.us"); 141 } 142 return false; 143 } 144 145 @Override 146 public void processResource(PackageContext context, Object clientContext, String type, String id, byte[] content) 147 throws FHIRException, IOException, EOperationOutcome { 148 if (clientContext != null && "StructureDefinition".equals(type)) { 149 JsonObject r = JsonParser.parseObject(content); 150 for (JsonObject ed : r.forceObject("snapshot").forceArray("element").asJsonObjects()) { 151 if (ed.has("slicing")) { 152 boolean smsOne = false; 153 boolean smsAll = true; 154 int count = 0; 155 String eid = ed.asString("id"); 156 for (JsonObject slice : r.forceObject("snapshot").forceArray("element").asJsonObjects()) { 157 if (slice.has("sliceName") && slice.has("id") && slice.asString("id").equals(eid+":"+slice.asString("sliceName"))) { 158 count++; 159 smsOne = smsOne || slice.asBoolean("mustSupport"); 160 smsAll = smsAll && slice.asBoolean("mustSupport"); 161 } 162 } 163 164 if (count > 0 && (ed.asBoolean("mustSupport") || smsOne)) { 165 issues.add(new Issue(context.getPid()+"#"+context.getPid(), r.asString("url")+"|"+r.asString("version"), ed.asString("path"), context.getNpm().getWebLocation(), 166 ed.asBoolean("mustSupport"), count, smsOne, smsAll)); 167 } 168 } 169 } 170 } 171 } 172 173 174 @Override 175 public void finishPackage(PackageContext context) throws FHIRException, IOException, EOperationOutcome { 176 } 177 178 @Override 179 public void alreadyVisited(String pid) throws FHIRException, IOException, EOperationOutcome { 180 } 181 182}