001    package ca.uhn.hl7v2.conf.store;
002    
003    import java.io.IOException;
004    import java.net.URL;
005    import java.util.Iterator;
006    import java.util.List;
007    
008    import org.jdom.Document;
009    import org.jdom.Element;
010    import org.jdom.input.SAXBuilder;
011    import org.jdom.xpath.XPath;
012    
013    import ca.uhn.hl7v2.conf.ProfileException;
014    
015    /**
016     * @author Neal Acharya
017     * Created on 27-Aug-2003
018     *
019     * This particular implementation of CodeStore retrieves valid codes and validates codeSystems
020     * using tables found in 'spec xml tables only' docs generated from the HL7 Messaging
021     * Workbench tool.
022     *
023     * Note:  The codeSystem parameter value used in the following methods must be a concatenation
024     * of a 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     */
029    public class ProfileCodeStore extends AbstractCodeStore {
030        
031        private Document tableDoc;
032        
033        /**
034         * @param uri the location of the specification XML file
035         * @throws ProfileException
036         * @throws IOException
037         *
038         * Creates a ProfileCodeStore object that uses tables found in an 'spec xml tables only'
039         * xml doc specified by the input URI. The private field member tableDoc is created with
040         * content from the xml doc specified by the URI.
041         */
042        public ProfileCodeStore(String uri) throws ProfileException, IOException {
043            try {
044                if (uri == null) {
045                    throw new ProfileException("The input url parameter cannot be null");
046                } //end if
047                //create tableDoc object
048                tableDoc = new SAXBuilder().build(uri);
049            } //end try
050            catch (ProfileException e) {
051                throw e;
052            } //end catch
053            catch (IOException e){
054                throw e;
055            }//end catch
056            catch (Exception e) {
057                throw new ProfileException(e.toString(), e);
058            } //end catch
059        } //end constructor
060    
061        /** As string constructor but accepts a URL object */
062        public ProfileCodeStore(URL url) throws ProfileException, IOException {
063            if (url == null) 
064                throw new ProfileException("The input url parameter cannot be null");
065            
066            try {            
067                tableDoc = new SAXBuilder().build(url);
068            } catch (org.jdom.JDOMException e) {
069                throw new ProfileException(e.toString(), e); 
070            } 
071        } 
072        
073        /**
074         * @param codeSystem
075         * @return String[]
076         * @throws ProfileException
077         * @see ca.uhn.hl7v2.conf.store.CodeStore#getValidCodes(java.lang.String, java.lang.String)
078         *
079         * Retreives all codes for a given conformance profile and codeSystem.
080         * Note:  The codeSystem parameter value must be a concatenation of a coding authority
081         * and coding table number that is 4 digits long.
082         *
083         * Note: The current implementation only accepts a coding authority of HL7
084         */
085        public String[] getValidCodes(String codeSystem) throws ProfileException {
086            String[] codeValues = null;
087            //obtain the table for the codesystem
088            try {
089                Element table = getCodeTable(codeSystem);
090                List tableElementList = table.getChildren("tableElement");
091                Iterator itr = tableElementList.iterator();
092                codeValues = new String[tableElementList.size()];
093                int i = 0;
094                while (itr.hasNext()) {
095                    Element tableElement = (Element) itr.next();
096                    codeValues[i] = tableElement.getAttributeValue("code");
097                    i++;
098                } //end while
099            } //end try
100            catch (NullPointerException e) {
101                throw new ProfileException("The spec xml table doc is missing one or more of the following: tableElement element, code attribute", e);
102            } //end catch
103            return codeValues;
104        } //end method
105        
106        /**
107         * @param codeSystem
108         * @return boolean
109         * @see ca.uhn.hl7v2.conf.store.CodeStore#knowsCodes(java.lang.String, java.lang.String)
110         *
111         * Validates the codeSytem against the input conformance profile. If valid then
112         * output is 'true' else 'false'.
113         * Note:  The codeSystem parameter value must be a concatenation of a coding authority
114         * and coding table number that is 4 digits long.
115         *
116         * Note: The current implementation only accepts a coding authority of HL7
117         */
118        public boolean knowsCodes(String codeSystem){
119            try{
120                Element table = getCodeTable(codeSystem);
121                if (table != null) {
122                    return true;
123                } //end if
124                else {
125                    return false;
126                } //end else
127            }//end try
128            catch (Exception e){
129                return false;
130            }//end catch
131        } //end method
132        
133        /**
134         * @param profileId
135         * @throws ProfileException
136         * void
137         *
138         * Validates the input conformance profile. Returns an exception if invalid.
139         */    
140        /*private void validateProfile(String profileId) throws ProfileException {
141            try {
142                if (profileId == null) {
143                    throw new ProfileException("The input profileId parameter cannot be null");
144                } //end if
145                XPath path = XPath.newInstance("/Specification/Conformance[@StaticID]");
146                Element conformance = (Element) path.selectSingleNode(tableDoc);
147                String staticId = conformance.getAttributeValue("StaticID");
148                if (!staticId.equals(profileId)) {
149                    throw new ProfileException("The input profileId is not valid or is not specified for the spec xml table doc");
150                } //end if
151            } //end try
152            catch (ProfileException e) {
153                throw e;
154            } //end catch
155            catch (Exception e) {
156                throw new ProfileException(e.toString(), e);
157            } //end catch
158        }*/ //end method
159        
160        /**
161         * @param profileId
162         * @param codeSystem
163         * @return Element
164         * @throws ProfileException
165         * Element
166         *
167         * Retreives the hl7Table Element from the tableDoc object defined by the table number
168         * in the input codeSystem.
169         */
170        private Element getCodeTable(String codeSystem) throws ProfileException {
171            //initialize return param
172            Element table = null;
173            //Validate the input Profile
174            //validateProfile(profileId);
175            //Validate the codeSystem
176            if (codeSystem == null) {
177                throw new ProfileException("The input codeSystem parameter cannot be null");
178            } //end if
179            if (codeSystem.length() < 4) {
180                throw new ProfileException("The input codeSystem parameter cannot be less than 4 characters long");
181            } //end if
182            try {
183                //Extract the last 4 characters from the codeSystem param
184                String tableId = codeSystem.substring(codeSystem.length() - 4);
185                //System.out.println(tableId);
186                XPath path = XPath.newInstance("/Specification/hl7tables/hl7table[@id='" + tableId + "']");
187                table = (Element) path.selectSingleNode(tableDoc);
188            } //end try
189            catch (Exception e) {
190                throw new ProfileException(e.toString(), e);
191            } //end catch
192            return table;
193        } //end method
194    } //end class