001package org.hl7.fhir.convertors.misc;
002
003import java.io.File;
004import java.io.FileInputStream;
005import java.io.FileOutputStream;
006import java.io.IOException;
007import java.net.URISyntaxException;
008import java.text.ParseException;
009import java.util.HashMap;
010import java.util.Map;
011
012import org.hl7.fhir.exceptions.FHIRException;
013import org.hl7.fhir.r4.formats.IParser.OutputStyle;
014import org.hl7.fhir.r4.formats.JsonParser;
015import org.hl7.fhir.r4.model.OperationOutcome;
016import org.hl7.fhir.r4.model.OperationOutcome.IssueSeverity;
017import org.hl7.fhir.r4.model.OperationOutcome.IssueType;
018import org.hl7.fhir.r4.model.ValueSet;
019import org.hl7.fhir.r4.utils.client.FHIRToolingClient;
020import org.hl7.fhir.utilities.CSVReader;
021import org.hl7.fhir.utilities.Utilities;
022
023public class VSACImporter extends OIDBasedValueSetImporter {
024
025  public VSACImporter() throws FHIRException, IOException {
026    super();
027    init();
028  }
029
030  public static void main(String[] args) throws FHIRException, IOException, ParseException, URISyntaxException {
031    VSACImporter self = new VSACImporter();
032    self.process(args[0], args[1], args[2], "true".equals(args[3]));
033  }
034
035  private void process(String source, String dest, String apiKey, boolean onlyNew) throws FHIRException, IOException, URISyntaxException {
036    CSVReader csv = new CSVReader(new FileInputStream(source));
037    csv.readHeaders();
038    Map<String, String> errs = new HashMap<>();
039
040    FHIRToolingClient fhirToolingClient = new FHIRToolingClient("https://cts.nlm.nih.gov/fhir", "fhir/vsac");
041    fhirToolingClient.setUsername("apikey");
042    fhirToolingClient.setPassword(apiKey);
043    fhirToolingClient.setTimeout(120000);
044
045    int i = 0;
046    int j = 0;
047    while (csv.line()) {
048      String oid = csv.cell("OID");
049      try {
050        if (!onlyNew || !(new File(Utilities.path(dest, "ValueSet-" + oid + ".json")).exists())) {
051          ValueSet vs = fhirToolingClient.read(ValueSet.class, oid);
052          try {
053            ValueSet vse = fhirToolingClient.expandValueset(vs.getUrl(), null);
054            vs.setExpansion(vse.getExpansion());
055            j++;
056          } catch (Exception e) {
057            errs.put(oid, "Expansion: " +e.getMessage());
058            System.out.println(e.getMessage());
059          }
060          if (vs.hasTitle()) {
061            if (vs.getTitle().equals(vs.getDescription())) {
062              vs.setTitle(vs.getName());              
063            } else {
064              System.out.println(oid);
065              System.out.println("  name: "+vs.getName());
066              System.out.println("  title: "+vs.getTitle());
067              System.out.println("  desc: "+vs.getDescription());
068            }
069          } else {
070            vs.setTitle(vs.getName());
071          }
072          vs.setName(makeValidName(vs.getName()));
073          new JsonParser().setOutputStyle(OutputStyle.PRETTY).compose(new FileOutputStream(Utilities.path(dest, "ValueSet-" + oid + ".json")), vs);
074        }
075        i++;
076        if (i % 100 == 0) {
077          System.out.println(":"+i+" ("+j+")");
078        }
079      } catch (Exception e) {
080        System.out.println("Unable to fetch OID " + oid + ": " + e.getMessage());
081        errs.put(oid, e.getMessage());
082      }
083    }
084    OperationOutcome oo = new OperationOutcome();
085    for (String oid : errs.keySet()) {
086      oo.addIssue().setSeverity(IssueSeverity.ERROR).setCode(IssueType.EXCEPTION).setDiagnostics(errs.get(oid)).addLocation(oid);
087    }
088    new JsonParser().setOutputStyle(OutputStyle.PRETTY).compose(new FileOutputStream(Utilities.path(dest, "other", "OperationOutcome-vsac-errors.json")), oo);
089    System.out.println("Done. " + i + " ValueSets");
090  }
091
092  private String makeValidName(String name) {
093    StringBuilder b = new StringBuilder();
094    boolean upper = true;
095    for (char ch : name.toCharArray()) {
096      if (ch == ' ') {
097        upper = true;
098      } else if (Character.isAlphabetic(ch)) {
099        if (upper) {
100          b.append(Character.toUpperCase(ch));
101        } else {
102          b.append(ch);
103        }
104        upper = false;
105      } else if (Character.isDigit(ch)) {
106        if (b.length() == 0) {
107          b.append('N');
108        }
109        b.append(ch);
110      } else if (ch == '_' && b.length() != 0) {
111        b.append(ch);
112      } else {
113        upper = true;
114      }
115    }
116    System.out.println(b.toString()+" from "+name);
117    return b.toString();
118  }
119}