/* * Licensed under the Apache License, Version 2.0 (the "License"); * * You may not use this file except in compliance with the License. * * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * * See the License for the specific language governing permissions and * limitations under the License. * * Contributions from 2013-2017 where performed either by US government * employees, or under US Veterans Health Administration contracts. * * US Veterans Health Administration contributions by government employees * are work of the U.S. Government and are not subject to copyright * protection in the United States. Portions contributed by government * employees are USGovWork (17USC ยง105). Not subject to copyright. * * Contribution by contractors to the US Veterans Health Administration * during this period are contractually contributed under the * Apache License, Version 2.0. * * See: https://www.usa.gov/government-works * * Contributions prior to 2013: * * Copyright (C) International Health Terminology Standards Development Organisation. * Licensed under the Apache License, Version 2.0. * */ package sh.isaac.convert.loinc; //~--- JDK imports ------------------------------------------------------------ import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.FileReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Arrays; import java.util.Date; import java.util.TreeMap; //~--- non-JDK imports -------------------------------------------------------- import org.apache.commons.io.input.BOMInputStream; import com.opencsv.CSVReader; import sh.isaac.api.util.AlphanumComparator; import sh.isaac.converters.sharedUtils.ConsoleUtil; //~--- classes ---------------------------------------------------------------- /** * * {@link LoincCsvFileReader} * * Reads the CSV formatted release files of LOINC, and the custom release notes file * to extract the date and time information. * * @author <a href="mailto:daniel.armbrust.list@gmail.com">Dan Armbrust</a> */ public class LoincCsvFileReader extends LOINCReader { /** The version. */ String version = null; /** The release. */ String release = null; /** The version time map. */ private final TreeMap<String, Long> versionTimeMap = new TreeMap<String, Long>(new AlphanumComparator(true)); /** The header. */ String[] header; /** The reader. */ CSVReader reader; //~--- constructors -------------------------------------------------------- /** * Instantiates a new loinc csv file reader. * * @param is the is * @throws IOException Signals that an I/O exception has occurred. */ public LoincCsvFileReader(InputStream is) throws IOException { // Their new format includes the (optional) UTF-8 BOM, which chokes java for stupid legacy reasons. this.reader = new CSVReader(new BufferedReader(new InputStreamReader(is))); this.header = readLine(); } /** * Instantiates a new loinc csv file reader. * * @param f the f * @param populateVersionTimeMap the populate version time map * @throws IOException Signals that an I/O exception has occurred. */ public LoincCsvFileReader(File f, boolean populateVersionTimeMap) throws IOException { ConsoleUtil.println("Using the data file " + f.getAbsolutePath()); // Their new format includes the (optional) UTF-8 BOM, which chokes java for stupid legacy reasons. this.reader = new CSVReader(new BufferedReader(new InputStreamReader(new BOMInputStream(new FileInputStream(f))))); this.header = readLine(); readReleaseNotes(f.getParentFile(), populateVersionTimeMap); } //~--- methods ------------------------------------------------------------- /** * Close. * * @throws IOException Signals that an I/O exception has occurred. */ @Override public void close() throws IOException { this.reader.close(); } /** * Read line. * * @return the string[] * @throws IOException Signals that an I/O exception has occurred. */ @Override public String[] readLine() throws IOException { String[] temp = this.reader.readNext(); if (temp != null) { if (this.fieldCount_ == 0) { this.fieldCount_ = temp.length; int i = 0; for (final String s: temp) { this.fieldMapInverse.put(i, s); this.fieldMap.put(s, i++); } } else if (temp.length < this.fieldCount_) { temp = Arrays.copyOf(temp, this.fieldCount_); } else if (temp.length > this.fieldCount_) { throw new RuntimeException("Data error - to many fields found on line: " + Arrays.toString(temp)); } } return temp; } /** * Read release notes. * * @param dataFolder the data folder * @param populateVersionTimeMap the populate version time map * @throws IOException Signals that an I/O exception has occurred. */ @SuppressWarnings("deprecation") public void readReleaseNotes(File dataFolder, boolean populateVersionTimeMap) throws IOException { File relNotes = null; for (final File f: dataFolder.listFiles()) { if (f.getName() .toLowerCase() .contains("releasenotes.txt")) { relNotes = f; break; } } if (relNotes.exists()) { final SimpleDateFormat[] sdf = new SimpleDateFormat[] { new SimpleDateFormat("MMM dd, yyyy"), new SimpleDateFormat("MMM yyyy"), new SimpleDateFormat("MMMyyyy"), new SimpleDateFormat("MM/dd/yy") }; final BufferedReader br = new BufferedReader(new FileReader(relNotes)); String line = br.readLine(); boolean first = true; String versionCache = null; while (line != null) { if (line.matches("\\s*\\|\\s*Version [\\w\\.\\-\\(\\)]*\\s*\\|\\s*")) { final String temp = line.substring(line.indexOf("Version") + "Version ".length()); versionCache = temp.replace('|', ' ') .trim(); if (first) { this.version = versionCache; } } if (line.matches("\\s*\\|\\s*Released [\\w\\s/,]*\\|")) { String temp = line.substring(line.indexOf("Released") + "Released ".length()); temp = temp.replace('|', ' ') .trim(); if (first) { this.release = temp; first = false; if (!populateVersionTimeMap) { break; } } Long time = -1l; for (final SimpleDateFormat f: sdf) { try { time = f.parse(temp) .getTime(); break; } catch (final ParseException e) { // noop } } if (time < 0) { throw new IOException("Failed to parse " + temp); } if (versionCache == null) { ConsoleUtil.printErrorln("No version for line " + line); } else { this.versionTimeMap.put(versionCache, time); } versionCache = null; } line = br.readLine(); } br.close(); if (populateVersionTimeMap) { // release notes is missing this one...set it to a time before 2.03. if (!this.versionTimeMap.containsKey("2.02")) { final Date temp = new Date(this.versionTimeMap.get("2.03")); temp.setMonth(temp.getMonth() - 1); this.versionTimeMap.put("2.02", temp.getTime()); } // Debug codel // ConsoleUtil.println("Release / Time map read from readme file:"); // for (Entry<String, Long> x : versionTimeMap.entrySet()) // { // ConsoleUtil.println(x.getKey() + " " + new Date(x.getValue()).toString()); // } } } else { ConsoleUtil.printErrorln("Couldn't find release notes file - can't read version or release date!"); } } //~--- get methods --------------------------------------------------------- /** * Gets the header. * * @return the header */ @Override public String[] getHeader() { return this.header; } /** * Gets the release date. * * @return the release date */ @Override public String getReleaseDate() { return this.release; } /** * Gets the time version map. * * @return the time version map */ public TreeMap<String, Long> getTimeVersionMap() { return this.versionTimeMap; } /** * Gets the version. * * @return the version */ @Override public String getVersion() { return this.version; } }