001package ca.uhn.hl7v2.conf.store; 002 003import java.io.IOException; 004import java.net.URL; 005import java.util.ArrayList; 006import java.util.HashMap; 007import java.util.List; 008import java.util.Map; 009 010import org.xml.sax.Attributes; 011import org.xml.sax.SAXException; 012import org.xml.sax.XMLReader; 013import org.xml.sax.helpers.DefaultHandler; 014import org.xml.sax.helpers.XMLReaderFactory; 015 016import ca.uhn.hl7v2.conf.ProfileException; 017 018/** 019 * 020 * This particular implementation of CodeStore retrieves valid codes and validates codeSystems using 021 * tables found in 'spec xml tables only' docs generated from the HL7 Messaging Workbench tool. 022 * 023 * Note: The codeSystem parameter value used in the following methods must be a concatenation of a 024 * coding authority and coding table number that is 4 digits long. 025 * 026 * Note: The current implementation only accepts a coding authority of HL7 027 * 028 * @author Neal Acharya 029 * @author Christian Ohr 030 */ 031public class ProfileCodeStore extends AbstractCodeStore { 032 033 private Map<String, List<String>> codes = new HashMap<String, List<String>>(); 034 035 /** 036 * Creates a ProfileCodeStore object that uses tables found in an 'spec xml tables only' xml doc 037 * specified by the input URI. The private field member tableDoc is created with content from 038 * the xml doc specified by the URI. 039 * 040 * @param uri the location of the specification XML file 041 * 042 * @throws ProfileException 043 * @throws IOException 044 * 045 */ 046 public ProfileCodeStore(String uri) throws ProfileException, IOException { 047 try { 048 if (uri == null) { 049 throw new ProfileException("The input url parameter cannot be null"); 050 } 051 XMLReader reader = XMLReaderFactory.createXMLReader(); 052 reader.setContentHandler(new ProfileCodeStoreHandler()); 053 reader.parse(uri); 054 } catch (IOException e) { 055 throw e; 056 } catch (Exception e) { 057 throw new ProfileException(e.toString(), e); 058 } 059 } 060 061 /** As string constructor but accepts a URL object */ 062 public ProfileCodeStore(URL url) throws ProfileException, IOException { 063 this(url.toExternalForm()); 064 } 065 066 /** 067 * Retrieves all codes for a given conformance profile and codeSystem. Note: The codeSystem 068 * parameter value must be a concatenation of a coding authority and coding table number that is 069 * 4 digits long. 070 * 071 * Note: The current implementation only accepts a coding authority of HL7 072 * 073 * @param codeSystem 074 * @return String[] 075 * @throws ProfileException 076 * @see ca.uhn.hl7v2.conf.store.CodeStore#getValidCodes(java.lang.String, java.lang.String) 077 * 078 */ 079 public String[] getValidCodes(String codeSystem) throws ProfileException { 080 List<String> result = getCodeTable(codeSystem); 081 if (result == null) 082 throw new ProfileException("Unknown code system: " + codeSystem); 083 return result.toArray(new String[result.size()]); 084 } 085 086 /** 087 * Validates the codeSystem against the input conformance profile. If valid then output is 088 * 'true' else 'false'. Note: The codeSystem parameter value must be a concatenation of a coding 089 * authority and coding table number that is 4 digits long. 090 * 091 * Note: The current implementation only accepts a coding authority of HL7 092 * 093 * @param codeSystem 094 * 095 * @return boolean 096 * @see ca.uhn.hl7v2.conf.store.CodeStore#knowsCodes(java.lang.String, java.lang.String) 097 * 098 */ 099 public boolean knowsCodes(String codeSystem) { 100 try { 101 return getCodeTable(codeSystem) != null; 102 } catch (ProfileException e) { 103 return false; 104 } 105 } 106 107 /** 108 * Retrieves the hl7Table Element from the tableDoc object defined by the table number in the 109 * input codeSystem. 110 * 111 * @param profileId 112 * 113 * @param codeSystem 114 * @return Element 115 * @throws ProfileException Element 116 */ 117 private List<String> getCodeTable(String codeSystem) throws ProfileException { 118 if (codeSystem == null) { 119 throw new ProfileException("The input codeSystem parameter cannot be null"); 120 } 121 if (codeSystem.length() < 4) { 122 throw new ProfileException("The input codeSystem parameter cannot be less than 4 characters long"); 123 } 124 // Extract the last 4 characters from the codeSystem param 125 String tableId = codeSystem.substring(codeSystem.length() - 4); 126 return codes.get(tableId); 127 } 128 129 private class ProfileCodeStoreHandler extends DefaultHandler { 130 131 private String currentTable; 132 private static final String HL7_TABLE_QNAME = "hl7table"; 133 private static final String TABLE_ELEMENT_QNAME = "tableElement"; 134 135 @Override 136 public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { 137 if (HL7_TABLE_QNAME.equals(qName)) { 138 currentTable = attributes.getValue("id"); 139 codes.put(currentTable, new ArrayList<String>()); 140 } else if (TABLE_ELEMENT_QNAME.equals(qName)) { 141 codes.get(currentTable).add(attributes.getValue("code")); 142 } 143 } 144 145 } 146}