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