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 "AbstractMessage.java".  Description: 
010    "A default implementation of Message" 
011    
012    The Initial Developer of the Original Code is University Health Network. Copyright (C) 
013    2001.  All Rights Reserved. 
014    
015    Contributor(s): ______________________________________. 
016    
017    Alternatively, the contents of this file may be used under the terms of the 
018    GNU General Public License (the  ???GPL???), in which case the provisions of the GPL are 
019    applicable instead of those above.  If you wish to allow use of your version of this 
020    file only under the terms of the GPL and not to allow others to use your version 
021    of this file under the MPL, indicate your decision by deleting  the provisions above 
022    and replace  them with the notice and other provisions required by the GPL License.  
023    If you do not delete the provisions above, a recipient may use your version of 
024    this file under either the MPL or the GPL. 
025    
026    */
027    
028    package ca.uhn.hl7v2.model;
029    
030    import java.io.IOException;
031    import java.util.regex.Matcher;
032    import java.util.regex.Pattern;
033    
034    import ca.uhn.hl7v2.HL7Exception;
035    import ca.uhn.hl7v2.app.DefaultApplication;
036    import ca.uhn.hl7v2.model.primitive.ID;
037    import ca.uhn.hl7v2.parser.ModelClassFactory;
038    import ca.uhn.hl7v2.parser.Parser;
039    import ca.uhn.hl7v2.parser.PipeParser;
040    import ca.uhn.hl7v2.validation.ValidationContext;
041    
042    /**
043     * A default implementation of Message. 
044     * @author Bryan Tripp (bryan_tripp@sourceforge.net)
045     */
046    public abstract class AbstractMessage extends AbstractGroup implements Message {
047        
048        private ValidationContext myContext;
049            private static final Pattern ourVersionPattern = Pattern.compile("\\.(v2[0-9][0-9]?)\\.");
050            private String myVersion;
051        private transient Parser myParser;
052            
053        /**
054         * @param theFactory factory for model classes (e.g. group, segment) for this message 
055         */
056        public AbstractMessage(ModelClassFactory theFactory) {
057            super(theFactory);
058        }
059        
060        /** 
061         * Returns this Message object - this is an implementation of the 
062         * abstract method in AbstractGroup.  
063         */
064        public Message getMessage() {
065           return this; 
066        }
067        
068        /**
069         * Returns the version number.  This default implementation inspects 
070         * this.getClass().getName().  This should be overridden if you are putting
071         * a custom message definition in your own package, or it will default.  
072         * @see Message#getVersion()
073         * @returns 2.4 if not obvious from package name
074         */
075        public String getVersion() {
076            if (myVersion != null) {
077                    return myVersion;
078            }
079            
080            String version = null;
081            Pattern p = ourVersionPattern;
082            Matcher m = p.matcher(this.getClass().getName());
083            if (m.find()) {
084                String verFolder = m.group(1);
085                if (verFolder.length() > 0) {
086                    char[] chars = verFolder.toCharArray();
087                    StringBuffer buf = new StringBuffer();
088                    for (int i = 1; i < chars.length; i++) { //start at 1 to avoid the 'v'
089                        buf.append(chars[i]);
090                        if (i < chars.length - 1) buf.append('.');
091                    }
092                    version = buf.toString();
093                }
094            }
095            
096            if (version == null) 
097                version = "2.4";
098            
099            myVersion = version;
100            return version;
101        }
102        
103        /**
104         * @return the set of validation rules that applies to this message
105         */
106        public ValidationContext getValidationContext() {
107            return myContext;
108        }
109        
110        /**
111         * @param theContext the set of validation rules that are to apply to this message
112         */
113        public void setValidationContext(ValidationContext theContext) {
114            myContext = theContext;
115        }
116    
117        /**
118         * {@inheritDoc }
119         */
120        public Character getFieldSeparatorValue() throws HL7Exception {
121            Segment firstSegment = (Segment) get(getNames()[0]);
122            Primitive value = (Primitive) firstSegment.getField(1, 0);
123            String valueString = value.getValue();
124            if (valueString == null || valueString.length() == 0) {
125                return null;
126            }
127            return valueString.charAt(0);
128        }
129    
130    
131        /**
132         * {@inheritDoc }
133         */
134        public String getEncodingCharactersValue() throws HL7Exception {
135            Segment firstSegment = (Segment) get(getNames()[0]);
136            Primitive value = (Primitive) firstSegment.getField(2, 0);
137            return value.getValue();
138        }
139    
140    
141        /**
142         * <p>Sets the parser to be used when parse/encode methods are called on this
143         * Message, as well as its children. It is recommended that if these methods
144         * are going to be called, a parser be supplied with the validation context
145         * wanted. Where possible, the parser should be reused for best performance,
146         * unless thread safety is an issue.</p>
147         *
148         * <p>Note that not all parsers can be used. As of version 1.0, only {@link PipeParser}
149         * supports this functionality</p>
150         * 
151         * <p>Serialization note: The message parser is marked as transient, so it will not
152         * survive serialization.</p>
153         */
154        public void setParser(Parser parser) {
155            if (parser == null) {
156                throw new NullPointerException("Value may not be null");
157            }
158    
159            myParser = parser;
160        }
161    
162    
163        /**
164         * <p>Returns the parser to be used when parse/encode methods are called on this
165         * Message, as well as its children. The default value is a new {@link PipeParser}.</p>
166         * 
167         * <p>Serialization note: The message parser is marked as transient, so it will not
168         * survive serialization.</p>
169         */
170        public Parser getParser() {
171            if (myParser == null) {
172                myParser = new PipeParser();
173            }
174    
175            return myParser;
176        }
177    
178    
179        /**
180         * {@inheritDoc }
181         */
182        public void parse(String string) throws HL7Exception {
183            clear();
184                    getParser().parse(this, string);
185        }
186    
187        
188        /**
189         * {@inheritDoc }
190         */
191        public String encode() throws HL7Exception {
192            return getParser().encode(this);
193        }
194    
195        
196        /**
197         * {@inheritDoc }
198         */
199        public Message generateACK() throws HL7Exception, IOException {
200            return generateACK(null, null);
201        }
202    
203    
204        /**
205         * {@inheritDoc }
206         */
207        public Message generateACK(String theAcknowledgementCode, HL7Exception theException) throws HL7Exception, IOException {
208            Message retVal = DefaultApplication.makeACK((Segment) get(getNames()[0]));
209    
210            if (theAcknowledgementCode == null) {
211                theAcknowledgementCode = "AA";
212            }
213    
214            Segment msa = (Segment)retVal.get("MSA");
215            ID ackCode = (ID) msa.getField(1, 0);
216            ackCode.setValue(theAcknowledgementCode);
217    
218            if (theException != null) {
219                Segment err = (Segment) retVal.get("ERR");
220                theException.populate(err, null);
221            }
222    
223            return retVal;
224        }
225    
226    }