View Javadoc
1   package ca.uhn.hl7v2.conf.store;
2   
3   import java.io.IOException;
4   import java.net.URL;
5   import java.util.ArrayList;
6   import java.util.HashMap;
7   import java.util.List;
8   import java.util.Map;
9   
10  import org.xml.sax.Attributes;
11  import org.xml.sax.XMLReader;
12  import org.xml.sax.helpers.DefaultHandler;
13  import org.xml.sax.helpers.XMLReaderFactory;
14  
15  import ca.uhn.hl7v2.conf.ProfileException;
16  
17  /**
18   * 
19   * This particular implementation of CodeStore retrieves valid codes and validates codeSystems using
20   * tables found in 'spec xml tables only' docs generated from the HL7 Messaging Workbench tool.
21   * 
22   * Note: The codeSystem parameter value used in the following methods must be a concatenation of a
23   * coding authority and coding table number that is 4 digits long.
24   * 
25   * Note: The current implementation only accepts a coding authority of HL7
26   * 
27   * @author Neal Acharya
28   * @author Christian Ohr
29   */
30  public class ProfileCodeStore extends AbstractCodeStore {
31  
32      private final Map<String, List<String>> codes = new HashMap<>();
33  
34      /**
35       * Creates a ProfileCodeStore object that uses tables found in an 'spec xml tables only' xml doc
36       * specified by the input URI. The private field member tableDoc is created with content from
37       * the xml doc specified by the URI.
38       * 
39       * @param uri the location of the specification XML file
40       * 
41       * @throws ProfileException
42       * @throws IOException
43       * 
44       */
45      public ProfileCodeStore(String uri) throws ProfileException, IOException {
46          try {
47              if (uri == null) {
48                  throw new ProfileException("The input url parameter cannot be null");
49              }
50              XMLReader reader = XMLReaderFactory.createXMLReader();
51              reader.setContentHandler(new ProfileCodeStoreHandler());
52              reader.parse(uri);
53          } catch (IOException e) {
54              throw e;
55          } catch (Exception e) {
56              throw new ProfileException(e.toString(), e);
57          }
58      }
59  
60      /** As string constructor but accepts a URL object */
61      public ProfileCodeStore(URL url) throws ProfileException, IOException {
62          this(url.toExternalForm());
63      }
64  
65      /**
66       * Retrieves all codes for a given conformance profile and codeSystem. Note: The codeSystem
67       * parameter value must be a concatenation of a coding authority and coding table number that is
68       * 4 digits long.
69       * 
70       * Note: The current implementation only accepts a coding authority of HL7
71       * 
72       * @param codeSystem
73       * @return String[]
74       * @throws ProfileException
75       * 
76       */
77      public String[] getValidCodes(String codeSystem) throws ProfileException {
78          List<String> result = getCodeTable(codeSystem);
79          if (result == null)
80              throw new ProfileException("Unknown code system: " + codeSystem);
81          return result.toArray(new String[0]);
82      }
83  
84      /**
85       * Validates the codeSystem against the input conformance profile. If valid then output is
86       * 'true' else 'false'. Note: The codeSystem parameter value must be a concatenation of a coding
87       * authority and coding table number that is 4 digits long.
88       * 
89       * Note: The current implementation only accepts a coding authority of HL7
90       * 
91       * @param codeSystem
92       * 
93       * @return boolean
94       * 
95       */
96      public boolean knowsCodes(String codeSystem) {
97          try {
98              return getCodeTable(codeSystem) != null;
99          } 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 }