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