001    /**
002    The contents of this file are subject to the Mozilla Public License Version 1.1 
003    (the "License"); you may not use this file except in compliance with the License. 
004    You may obtain a copy of the License at http://www.mozilla.org/MPL/ 
005    Software distributed under the License is distributed on an "AS IS" basis, 
006    WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for the 
007    specific language governing rights and limitations under the License. 
008    
009    The Original Code is "MinLLPReader.java".  Description: 
010    "Title:        HL7Reader
011      Description:  A buffered reader specifically designed for use in reading
012                    HL7 ASCII strings" 
013    
014    The Initial Developer of the Original Code is University Health Network. Copyright (C) 
015    2001.  All Rights Reserved. 
016    
017    Contributor(s): ______________________________________. 
018    
019    Alternatively, the contents of this file may be used under the terms of the 
020    GNU General Public License (the  ?GPL?), in which case the provisions of the GPL are 
021    applicable instead of those above.  If you wish to allow use of your version of this 
022    file only under the terms of the GPL and not to allow others to use your version 
023    of this file under the MPL, indicate your decision by deleting  the provisions above 
024    and replace  them with the notice and other provisions required by the GPL License.  
025    If you do not delete the provisions above, a recipient may use your version of 
026    this file under either the MPL or the GPL. 
027    
028    */
029    
030    package ca.uhn.hl7v2.llp;
031    
032    import java.io.*;
033    import java.net.Socket;
034    import java.net.SocketException;
035    
036    import ca.uhn.log.HapiLog;
037    import ca.uhn.log.HapiLogFactory;
038    
039    /**
040     * Title:        HL7Reader
041     * Description:  A buffered reader specifically designed for use in reading
042     *               HL7 ASCII strings. This class assumes that the minimal lower
043     *               layer protocol is being used.
044     * Copyright:    Copyright (c) 2001
045     * Company:      University Health Network
046     * @author       Damian Horton (damian.horton@uhn.on.ca); mods by Bryan Tripp
047     */
048    
049    public class MinLLPReader implements HL7Reader
050    {
051        
052        public static final String CHARSET_KEY = "ca.uhn.hl7v2.llp.charset";
053    
054        private static final HapiLog log = HapiLogFactory.getHapiLog(MinLLPReader.class);
055        
056        private BufferedReader myReader;
057    
058        private static final char END_MESSAGE = '\u001c'; //character indicating the
059                                                  //termination of an HL7 message
060        private static final char START_MESSAGE = '\u000b';//character indicating the
061                                                   //start of an HL7 message
062        private static final char LAST_CHARACTER = 13; //the final character of
063            //a message: a carriage return
064    
065        //NB: The above is as per the minimal lower layer protocol.
066    
067        /** Creates a MinLLPReader with no setup - setInputStream must be set later. 
068        */
069        public MinLLPReader() 
070        {
071        }
072        
073        /** Creates a MinLLPReader which reads from the given InputStream. The stream
074            is assumed to be an ASCII bit stream.
075        */
076        public MinLLPReader(InputStream in) throws IOException
077        {
078            setInputStream(in);
079        }
080    
081        /**
082         * Sets the InputStream from which to read messages.  The InputStream must be set 
083         * before any calls to <code>getMessage()</code>.
084         */
085        public synchronized void setInputStream(InputStream in) throws IOException 
086        {
087            String charset = System.getProperty(CHARSET_KEY, "US-ASCII");
088            
089            if (charset.equals("default")) {
090                myReader = new BufferedReader(new InputStreamReader(in));
091            } else {
092                myReader = new BufferedReader(new InputStreamReader(in, charset));
093            }
094        }
095    
096        /** Calls the same method in the underlying BufferedReader. */
097        /**private int read(char[] parm1, int parm2, int parm3) throws java.io.IOException
098        {
099            return myReader.read(parm1, parm2, parm3);
100        }*/
101    
102        /** Reads an HL7 encoded message from this Reader's InputStream.
103            @return The message, in string format, without the lower level
104            protocol delimeters. Returns null if a -1 is received on the initial
105             read.
106         */
107        public synchronized String getMessage() throws LLPException, IOException 
108        {
109            StringBuffer s_buffer = new StringBuffer();
110    
111            boolean end_of_message = false;
112                            
113                int c = 0;
114                try {
115                    c = myReader.read();                
116                } catch (SocketException e) {
117                    log.info("SocketException on read() attempt.  Socket appears to have been closed: " + e.getMessage());
118                    return null;
119                }
120    
121                //trying to read when there is no data (stream may have been closed at other end)
122                if (c == -1) {
123                    log.info("End of input stream reached.");
124                    return null; 
125                }
126                LowerLayerProtocol.logCharacterReceived(c);
127    
128                if (c != START_MESSAGE)
129                {
130                    throw new LLPException("Message violates the "+
131                        "minimal lower layer protocol: no start of message indicator "+
132                        "received.");
133                }
134    
135                while (! end_of_message)
136                {
137                    c = myReader.read();
138    
139                    if (c == -1)
140                    {
141                        throw new LLPException("Message violates the "+
142                            "minimal lower protocol: message terminated without "+
143                            "a terminating character.");
144                    }
145                    LowerLayerProtocol.logCharacterReceived(c);
146                    
147                    if (c == END_MESSAGE)
148                    {
149                        //subsequent character should be a carriage return
150                        c = myReader.read();
151                        if (c >= 0) LowerLayerProtocol.logCharacterReceived(c);
152                        if (c != LAST_CHARACTER)
153                        {
154                            throw new LLPException("Message "+
155                                "violates the minimal lower layer protocol: "+
156                                "message terminator not followed by a return "+
157                                "character.");
158                        }
159                        end_of_message = true;
160                    }
161                    else
162                    {
163                    //the character wasn't the end of message, append it to the message
164                        s_buffer.append((char) c);
165                    }
166                } //end while
167    
168            return s_buffer.toString();
169        }
170    
171        /** Test driver for the program. Bounces a message off of an echo socket,
172         *  and ascertaines whether or not this class works.
173         */
174        public static void main(String args[])
175        {
176            try
177            {
178                Socket s = new Socket("142.224.51.2", 7);
179    
180                HL7Reader in = new MinLLPReader(s.getInputStream());
181                HL7Writer out = new MinLLPWriter(s.getOutputStream());
182    
183                out.writeMessage("Some message.");
184                System.out.println("wrote");
185                String str = in.getMessage();
186                System.out.println("read");
187    
188                System.out.println(str);
189            }
190            catch (Exception e)
191            {
192                System.out.println(e);
193            }
194        }
195    
196        /** 
197         * Closes the underlying BufferedReader.
198         */
199        public synchronized void close() throws java.io.IOException
200        {
201            myReader.close();
202        }
203        
204        private static OutputStreamWriter getWriter(OutputStream theStream) throws IOException {
205            String charset = System.getProperty(MinLLPWriter.CHARSET_KEY, "US-ASCII");
206            
207            if (charset.equals("default")) {
208                return new OutputStreamWriter(theStream);
209            } else {
210                return new OutputStreamWriter(theStream, charset);
211            }
212        }
213            
214    }
215