All Downloads are FREE. Search and download functionalities are using the official Maven repository.

ca.uhn.hl7v2.util.FileCodeMapper Maven / Gradle / Ivy

There is a newer version: 2.5.1
Show newest version
package ca.uhn.hl7v2.util;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileFilter;
import java.io.FileReader;
import java.io.FilenameFilter;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.StringTokenizer;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import ca.uhn.hl7v2.ErrorCode;
import ca.uhn.hl7v2.HL7Exception;

/**
 * 

Implements CodeMapper using files to store code values. Files are arranged * in the following directory structure. The base directory is called "codemap". * This should be created under the hapi.home directory (see Home class; defaults to .). * Under the base directory, there should be one directory for each interface, and * each of these directories should be named after the interface. For example if you * had interfaces to pharmacy and lab systems you might have the following directories:

*

/codemap/pharmacy
* /codemap/lab

*

Each directory should contain two files per HL7 table, named after the table numbers as * follows: "hl7nnnn.li" and "hl7nnnn.il", where nnnn is the 4 digit table number. The .il * file contains maps from interface codes to local codes, and the .li file contains maps from * local codes to interface codes (these unfortunately may not be symmetrical).

*

Each line of a file contains a single code map, with the "from" value and the "to" value * separated by a tab. For example, the file /lab/HL70001.li (to map local codes to interface * codes for the HL7 admnistrative sex table in your lab system interface) might contain the * following line:

*

male&tab;M

*

This means that the local code "male" maps to the interface code "M".

*

Lines that start with "//" are treated as comments.

* @author Bryan Tripp */ public class FileCodeMapper extends CodeMapper { private static final Logger log = LoggerFactory.getLogger(FileCodeMapper.class); private boolean throwIfNoMatch = false; File baseDir; private Map>> interfaceToLocal; private Map>> localToInterface; /** * Creates a new instance of FileCodeMapper. You should probably not * construct a FileCodeMapper directly. Use CodeMapper.getInstance() * instead ... this will ensure that only a single instance is created, * which is important for performance because code maps are loaded from * disk every time this constructor is called. */ public FileCodeMapper() throws HL7Exception { baseDir = new File(Home.getHomeDirectory().getAbsolutePath() + "/codemap"); refreshCache(); } /** * If values are cached in such a way that they are not guaranteed to be current, a call * to this method refreshes the values. */ public void refreshCache() throws HL7Exception { localToInterface = new HashMap>>(10); interfaceToLocal = new HashMap>>(10); log.info("Refreshing cache"); try { //get list of child directories File[] interfaceDirs = this.baseDir.listFiles(new FileFilter() { public boolean accept(File pathname) { boolean acc = false; if (pathname.isDirectory()) acc = true; return acc; } }); //loop through directories and set up maps for (int i = 0; i < interfaceDirs.length; i++) { log.info( "Checking directory {} for interface code maps.", interfaceDirs[i].getName()); //get list of .li (local -> interface) and .il (interface -> local) files File[] mapFiles = interfaceDirs[i].listFiles(new FilenameFilter() { public boolean accept(File dir, String name) { boolean acc = false; if (name.toUpperCase().startsWith("HL7")) { if (name.substring(name.lastIndexOf('.')).equals(".li") || name.substring(name.lastIndexOf('.')).equals(".il")) acc = true; } return acc; } }); //read map entries from each file and add to hash maps for li and il codes HashMap> li = new HashMap>(50); HashMap> il = new HashMap>(50); for (int j = 0; j < mapFiles.length; j++) { log.info("Reading map entries from file {}", mapFiles[j]); String fName = mapFiles[j].getName(); String tableName = fName.substring(0, fName.lastIndexOf('.')); String mapDirection = fName.substring(fName.lastIndexOf('.') + 1); //read values and store in HashMap Map codeMap = new HashMap(25); BufferedReader in = null; try { in = new BufferedReader(new FileReader(mapFiles[j])); while (in.ready()) { String line = in.readLine(); if (!line.startsWith("//")) { StringTokenizer tok = new StringTokenizer(line, "\t", false); String from = null; String to = null; if (tok.hasMoreTokens()) from = tok.nextToken(); if (tok.hasMoreTokens()) to = tok.nextToken(); if (from != null && to != null) codeMap.put(from, to); } } } finally { if (in != null) in.close(); } //add to appropriate map for this interface if (mapDirection.equals("il")) { il.put(tableName.toUpperCase(), codeMap); log.debug("Adding {} codes to interface -> local map for {} in {} interface", new Object[] {codeMap.size(), tableName, interfaceDirs[i].getName()}); } else { li.put(tableName.toUpperCase(), codeMap); log.debug("Adding {} codes to local -> interface map for {} in {} interface", new Object[] {codeMap.size(), tableName, interfaceDirs[i].getName()}); } } //add maps for this interface (this directory) to global list interfaceToLocal.put(interfaceDirs[i].getName(), il); localToInterface.put(interfaceDirs[i].getName(), li); } } catch (IOException e) { throw new HL7Exception( "Can't read interface code maps from disk", e); } } /** * Returns the local code for the given interface code as it appears in * the given interface. */ public String getLocalCode(String interfaceName, int hl7Table, String interfaceCode) throws HL7Exception { String localCode = null; try { Map> interfaceMap = interfaceToLocal.get(interfaceName); localCode = getCode(interfaceMap, hl7Table, interfaceCode); } catch (NullPointerException npe) { if (this.throwIfNoMatch) throw new HL7Exception( "No local mapping for the interface code " + interfaceCode + " for HL7 table " + hl7Table + " for the interface '" + interfaceName + "'", ErrorCode.TABLE_VALUE_NOT_FOUND); } return localCode; } /** * Common code for getLocalcode and getInterfaceCode */ private String getCode(Map> interfaceMap, int hl7Table, String code) { String ret = null; //get map for the given table StringBuffer tableName = new StringBuffer(); tableName.append("HL7"); if (hl7Table < 1000) tableName.append("0"); if (hl7Table < 100) tableName.append("0"); if (hl7Table < 10) tableName.append("0"); tableName.append(hl7Table); Map tableMap = interfaceMap.get(tableName.toString()); //get code ret = tableMap.get(code).toString(); return ret; } /** * Returns the interface code for the given local code, for use in the context * of the given interface. */ public String getInterfaceCode(String interfaceName, int hl7Table, String localCode) throws HL7Exception { String interfaceCode = null; try { Map> interfaceMap = localToInterface.get(interfaceName); interfaceCode = getCode(interfaceMap, hl7Table, localCode); } catch (NullPointerException npe) { if (this.throwIfNoMatch) throw new HL7Exception( "No interface mapping for the local code " + localCode + " for HL7 table " + hl7Table + " for the interface '" + interfaceName + "'", ErrorCode.TABLE_VALUE_NOT_FOUND); } return interfaceCode; } /** * Determines what happens if no matching code is found during a lookup. If set to true, * an HL7Exception is thrown if there is no match. If false, null is returned. The default * is false. */ public void throwExceptionIfNoMatch(boolean throwException) { this.throwIfNoMatch = throwException; } /** * Test harness. */ public static void main(String args[]) { try { //FileCodeMapper mapper = new FileCodeMapper(); CodeMapper.getInstance().throwExceptionIfNoMatch(true); System.out.println("Local code for M is " + CodeMapper.getLocal("test", 1, "M")); System.out.println("Interface code for female is " + CodeMapper.getInt("test", 1, "female")); } catch (HL7Exception e) { e.printStackTrace(); } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy