001package org.hl7.fhir.convertors.analytics; 002 003import java.io.IOException; 004import java.util.ArrayList; 005import java.util.Collections; 006import java.util.HashMap; 007import java.util.HashSet; 008import java.util.List; 009import java.util.Map; 010import java.util.Set; 011 012import javax.xml.parsers.ParserConfigurationException; 013 014import org.hl7.fhir.convertors.analytics.PackageVisitor.IPackageVisitorProcessor; 015import org.hl7.fhir.dstu2.model.SearchParameter; 016import org.hl7.fhir.exceptions.FHIRException; 017import org.hl7.fhir.exceptions.FHIRFormatError; 018import org.hl7.fhir.r5.model.Bundle.BundleEntryComponent; 019import org.hl7.fhir.utilities.Utilities; 020import org.hl7.fhir.utilities.VersionUtilities; 021import org.xml.sax.SAXException; 022 023public class SearchParameterAnalysis implements IPackageVisitorProcessor { 024 025 public static class SearchParameterTypeUsage { 026 private Set<String> coreUsage = new HashSet<>(); 027 private Set<String> igUsage = new HashSet<>(); 028 public String summary() { 029 return ""+coreUsage.size()+" / "+igUsage.size(); 030 } 031 } 032 033 public static class SearchParameterType { 034 private Map<String, SearchParameterTypeUsage> usages = new HashMap<>(); 035 public void seeUsage(boolean core, String usage, String url) { 036 if (!usages.containsKey(usage)) { 037 usages.put(usage, new SearchParameterTypeUsage()); 038 } 039 SearchParameterTypeUsage tu = usages.get(usage); 040 if (core) { 041 tu.coreUsage.add(url); 042 } else { 043 tu.igUsage.add(url); 044 } 045 046 } 047 } 048 049 public static class SearchParameterVersionAnalysis { 050 private Map<String, SearchParameterType> types = new HashMap<>(); 051 private String version; 052 053 public void seeUsage(boolean core, String type, String usage, String url) { 054// System.out.println("v"+version+" "+Utilities.padRight(url, ' ', 60)+" "+type+"/"+usage); 055 if (type == null) { 056 type = "n/a"; 057 } 058 if (usage == null) { 059 usage = "n/a"; 060 } 061 if (!types.containsKey(type)) { 062 types.put(type, new SearchParameterType()); 063 } 064 SearchParameterType tu = types.get(type); 065 tu.seeUsage(core, usage, url); 066 } 067 068 public void printSummary() { 069 Set<String> usages = new HashSet<>(); 070 for (SearchParameterType tu : types.values()) { 071 usages.addAll(tu.usages.keySet()); 072 } 073 List<String> ul = new ArrayList<String>(); 074 ul.addAll(usages); 075 Collections.sort(ul); 076 System.out.print(Utilities.padRight("", ' ', 10)); 077 for (String u : ul) { 078 System.out.print(Utilities.padRight(u, ' ', 10)); 079 } 080 System.out.println(); 081 for (String t : types.keySet()) { 082 System.out.print(Utilities.padRight(t, ' ', 10)); 083 SearchParameterType tu = types.get(t); 084 for (String u : ul) { 085 SearchParameterTypeUsage uu = tu.usages.get(u); 086 if (uu == null) { 087 System.out.print(Utilities.padRight("0 / 0", ' ', 10)); 088 } else { 089 System.out.print(Utilities.padRight(uu.summary(), ' ', 10)); 090 } 091 } 092 System.out.println(); 093 } 094 095 } 096 097 } 098 099 private Map<String, SearchParameterVersionAnalysis> versions = new HashMap<String, SearchParameterAnalysis.SearchParameterVersionAnalysis>(); 100 101 @Override 102 public void processResource(String pid, String version, String type, byte[] content) throws FHIRException { 103// System.out.println("v"+version+" "+type+" from "+pid); 104 boolean core = pid.startsWith("hl7.fhir.r") && (pid.contains(".core") || pid.contains(".examples")); 105 version = VersionUtilities.getMajMin(version); 106 if (!versions.containsKey(version)) { 107 versions.put(version, new SearchParameterVersionAnalysis()); 108 versions.get(version).version = version; 109 } 110 try { 111 if (VersionUtilities.isR5Ver(version)) { 112 processR5SP(core, versions.get(version), content); 113 } else if (VersionUtilities.isR4BVer(version)) { 114 processR4SP(core, versions.get(version), content); 115 } else if (VersionUtilities.isR4Ver(version)) { 116 processR4SP(core, versions.get(version), content); 117 } else if (VersionUtilities.isR3Ver(version)) { 118 processR3SP(core, versions.get(version), content); 119 } else if (VersionUtilities.isR2Ver(version)) { 120 processR2SP(core, versions.get(version), content); 121 } 122 } catch (IOException e) { 123 throw new FHIRException(e); 124 } 125 } 126 127 private void processR5SP(boolean core, SearchParameterVersionAnalysis analysis, byte[] content) throws FHIRFormatError, IOException { 128 org.hl7.fhir.r5.model.Resource res = new org.hl7.fhir.r5.formats.JsonParser().parse(content); 129 if (res instanceof org.hl7.fhir.r5.model.Bundle) { 130 for (org.hl7.fhir.r5.model.Bundle.BundleEntryComponent bnd : ((org.hl7.fhir.r5.model.Bundle) res).getEntry()) { 131 if (bnd.getResource() != null && bnd.getResource() instanceof org.hl7.fhir.r5.model.SearchParameter) { 132 org.hl7.fhir.r5.model.SearchParameter sp = (org.hl7.fhir.r5.model.SearchParameter) bnd.getResource(); 133 analysis.seeUsage(core, sp.getTypeElement().primitiveValue(), sp.getXpathUsageElement().primitiveValue(), sp.getUrl()); 134 } 135 } 136 } else { 137 org.hl7.fhir.r5.model.SearchParameter sp = (org.hl7.fhir.r5.model.SearchParameter) res; 138 analysis.seeUsage(core, sp.getTypeElement().primitiveValue(), sp.getXpathUsageElement().primitiveValue(), sp.getUrl()); 139 } 140 } 141 142 private void processR4SP(boolean core, SearchParameterVersionAnalysis analysis, byte[] content) throws FHIRFormatError, IOException { 143 org.hl7.fhir.r4.model.Resource res = new org.hl7.fhir.r4.formats.JsonParser().parse(content); 144 if (res instanceof org.hl7.fhir.r4.model.Bundle) { 145 for (org.hl7.fhir.r4.model.Bundle.BundleEntryComponent bnd : ((org.hl7.fhir.r4.model.Bundle) res).getEntry()) { 146 if (bnd.getResource() != null && bnd.getResource() instanceof org.hl7.fhir.r4.model.SearchParameter) { 147 org.hl7.fhir.r4.model.SearchParameter sp = (org.hl7.fhir.r4.model.SearchParameter) bnd.getResource(); 148 analysis.seeUsage(core, sp.getTypeElement().primitiveValue(), sp.getXpathUsageElement().primitiveValue(), sp.getUrl()); 149 } 150 } 151 } else { 152 org.hl7.fhir.r4.model.SearchParameter sp = (org.hl7.fhir.r4.model.SearchParameter) res; 153 analysis.seeUsage(core, sp.getTypeElement().primitiveValue(), sp.getXpathUsageElement().primitiveValue(), sp.getUrl()); 154 } 155 } 156 157 private void processR3SP(boolean core, SearchParameterVersionAnalysis analysis, byte[] content) throws FHIRFormatError, IOException { 158 org.hl7.fhir.dstu3.model.Resource res = new org.hl7.fhir.dstu3.formats.JsonParser().parse(content); 159 if (res instanceof org.hl7.fhir.dstu3.model.Bundle) { 160 for (org.hl7.fhir.dstu3.model.Bundle.BundleEntryComponent bnd : ((org.hl7.fhir.dstu3.model.Bundle) res).getEntry()) { 161 if (bnd.getResource() != null && bnd.getResource() instanceof org.hl7.fhir.dstu3.model.SearchParameter) { 162 org.hl7.fhir.dstu3.model.SearchParameter sp = (org.hl7.fhir.dstu3.model.SearchParameter) bnd.getResource(); 163 analysis.seeUsage(core, sp.getTypeElement().primitiveValue(), sp.getXpathUsageElement().primitiveValue(), sp.getUrl()); 164 } 165 } 166 } else { 167 org.hl7.fhir.dstu3.model.SearchParameter sp = (org.hl7.fhir.dstu3.model.SearchParameter) res; 168 analysis.seeUsage(core, sp.getTypeElement().primitiveValue(), sp.getXpathUsageElement().primitiveValue(), sp.getUrl()); 169 } 170 } 171 172 private void processR2SP(boolean core, SearchParameterVersionAnalysis analysis, byte[] content) throws FHIRFormatError, IOException { 173 org.hl7.fhir.dstu2.model.Resource res = new org.hl7.fhir.dstu2.formats.JsonParser().parse(content); 174 if (res instanceof org.hl7.fhir.dstu2.model.Bundle) { 175 for (org.hl7.fhir.dstu2.model.Bundle.BundleEntryComponent bnd : ((org.hl7.fhir.dstu2.model.Bundle) res).getEntry()) { 176 if (bnd.getResource() != null && bnd.getResource() instanceof org.hl7.fhir.dstu2.model.SearchParameter) { 177 org.hl7.fhir.dstu2.model.SearchParameter sp = (org.hl7.fhir.dstu2.model.SearchParameter) bnd.getResource(); 178 analysis.seeUsage(core, sp.getTypeElement().primitiveValue(), sp.getXpathUsageElement().primitiveValue(), sp.getUrl()); 179 } 180 } 181 } else { 182 org.hl7.fhir.dstu2.model.SearchParameter sp = (org.hl7.fhir.dstu2.model.SearchParameter) res; 183 analysis.seeUsage(core, sp.getTypeElement().primitiveValue(), sp.getXpathUsageElement().primitiveValue(), sp.getUrl()); 184 } 185 } 186 187 public static void main(String[] args) throws Exception { 188 new SearchParameterAnalysis().execute(); 189 } 190 191 private void execute() throws IOException, ParserConfigurationException, SAXException { 192 PackageVisitor pv = new PackageVisitor(); 193 pv.getResourceTypes().add("SearchParameter"); 194 pv.getResourceTypes().add("Bundle"); 195 pv.setOldVersions(false); 196 pv.setCorePackages(true); 197 pv.setProcessor(this); 198 pv.visitPackages(); 199 200 printSummary(); 201 } 202 203 private void printSummary() { 204 for (String v : versions.keySet()) { 205 System.out.println("-- v"+v+"---------------------"); 206 versions.get(v).printSummary(); 207 System.out.println(""); 208 } 209 210 } 211}