001package org.hl7.fhir.convertors.misc;
002
003import java.io.FileInputStream;
004import java.io.FileNotFoundException;
005import java.io.IOException;
006import java.util.HashMap;
007import java.util.HashSet;
008import java.util.Map;
009import java.util.Set;
010
011import javax.xml.parsers.ParserConfigurationException;
012
013import org.hl7.fhir.convertors.analytics.PackageVisitor;
014import org.hl7.fhir.convertors.analytics.PackageVisitor.IPackageVisitorProcessor;
015import org.hl7.fhir.convertors.analytics.PackageVisitor.PackageContext;
016import org.hl7.fhir.exceptions.FHIRException;
017import org.hl7.fhir.r5.utils.EOperationOutcome;
018import org.hl7.fhir.utilities.CSVReader;
019import org.hl7.fhir.utilities.Utilities;
020import org.hl7.fhir.utilities.json.model.JsonObject;
021import org.hl7.fhir.utilities.json.parser.JsonParser;
022import org.hl7.fhir.utilities.npm.NpmPackage;
023import org.hl7.fhir.utilities.npm.PackageServer;
024import org.xml.sax.SAXException;
025
026@SuppressWarnings("checkstyle:systemout")
027public class VSACFinder implements IPackageVisitorProcessor {
028
029  public static void main(String[] args) throws FHIRException, IOException, ParserConfigurationException, SAXException, EOperationOutcome {
030    new VSACFinder().execute();
031
032  }
033  
034  private class VsacVS {
035    private String oid;
036    private String steward;
037    private String status;
038    private Set<String> used = new HashSet<>();
039    
040    public void use(String pid) {
041      used.add(pid);  
042    }
043  }
044  
045  private Map<String, VsacVS> oids = new HashMap<>();
046
047  private void execute() throws FHIRException, IOException, ParserConfigurationException, SAXException, EOperationOutcome {
048    loadVSACOids();
049    PackageVisitor pv = new PackageVisitor();
050    pv.setCorePackages(false);
051    pv.setClientPackageServer(PackageServer.secondaryServer());
052    pv.setResourceTypes("StructureDefinition", "ValueSet");
053    pv.setProcessor(this);
054    pv.visitPackages();
055    for (String oid : Utilities.sorted(oids.keySet())) {
056      VsacVS vs = oids.get(oid);
057      if (!vs.used.isEmpty()) {
058        System.out.println("* "+oid+" ("+vs.status+") @ "+vs.steward+" used by "+vs.used.toString());
059      }
060    }
061  }
062
063  private void loadVSACOids() throws FHIRException, FileNotFoundException, IOException {
064    CSVReader csv = new CSVReader(new FileInputStream("/Users/grahamegrieve/Downloads/valuesets.csv"));
065    csv.readHeaders();
066    while (csv.line()) {
067      VsacVS vvs = new VsacVS();
068      vvs.oid = csv.cell("OID");
069      vvs.steward = csv.cell("Steward");
070      vvs.status = csv.cell("Expansion Status");
071      oids.put("http://cts.nlm.nih.gov/fhir/ValueSet/"+vvs.oid, vvs);
072    }
073  }
074
075  @Override
076  public Object startPackage(PackageContext context) throws FHIRException, IOException, EOperationOutcome {
077    if (usesVSAC(context.getNpm())) {
078      System.out.println(context.getPid()+" uses VSAC");
079      return this;
080    } else {
081      return null;
082    }
083  }
084
085  private boolean usesVSAC(NpmPackage npm) {
086    if (npm != null) {
087      for (String s : npm.dependencies()) {
088        if (s.contains("vsac")) {
089          return true;
090        }
091      }
092    }
093    return false;
094  }
095
096  @Override
097  public void processResource(PackageContext context, Object clientContext, String type, String id, byte[] content)
098      throws FHIRException, IOException, EOperationOutcome {
099    if (clientContext != null) {
100      JsonObject r = JsonParser.parseObject(content);
101      if ("StructureDefinition".equals(type)) {
102        JsonObject diff = r.getJsonObject("differential");
103        if (diff != null) {
104          for (JsonObject ed : diff.getJsonObjects("element")) {
105            JsonObject b = ed.getJsonObject("binding");
106            if (b != null) {
107              String url = b.asString("valueSet");
108              checkVSUrl(context, url);
109            }
110          }
111        }
112      } else {
113        JsonObject compose = r.getJsonObject("compose");
114        if (compose != null) {
115          for (JsonObject inc : compose.getJsonObjects("include")) {
116            for (String url : inc.getStrings("valueSet")) {
117              checkVSUrl(context, url);
118            }
119          }
120          for (JsonObject inc : compose.getJsonObjects("exclude")) {
121            for (String url : inc.getStrings("valueSet")) {
122              if (url.startsWith("http://cts.nlm.nih.gov/fhir/ValueSet/")) {
123                checkVSUrl(context, url);
124              }
125            }
126          }
127        }
128      }
129    }
130  }
131
132  private void checkVSUrl(PackageContext context, String url) {
133    if (url.startsWith("http://cts.nlm.nih.gov/fhir/ValueSet/")) {
134      VsacVS vs = oids.get(url);
135      if (vs != null) {
136        vs.use(context.getPid());
137      }
138    }
139  }
140
141  @Override
142  public void finishPackage(PackageContext context) throws FHIRException, IOException, EOperationOutcome {    
143  }
144
145  @Override
146  public void alreadyVisited(String pid) throws FHIRException, IOException, EOperationOutcome {
147  }
148
149}