001/**
002The 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. 
004You may obtain a copy of the License at http://www.mozilla.org/MPL/ 
005Software distributed under the License is distributed on an "AS IS" basis, 
006WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for the 
007specific language governing rights and limitations under the License. 
008
009The Original Code is "HL7Exception.java".  Description: 
010"Represents an exception encountered while processing 
011  an HL7 message" 
012
013The Initial Developer of the Original Code is University Health Network. Copyright (C) 
0142001.  All Rights Reserved. 
015
016Contributor(s): ______________________________________. 
017
018Alternatively, the contents of this file may be used under the terms of the 
019GNU General Public License (the  "GPL"), in which case the provisions of the GPL are 
020applicable instead of those above.  If you wish to allow use of your version of this 
021file only under the terms of the GPL and not to allow others to use your version 
022of this file under the MPL, indicate your decision by deleting  the provisions above 
023and replace  them with the notice and other provisions required by the GPL License.  
024If you do not delete the provisions above, a recipient may use your version of 
025this file under either the MPL or the GPL. 
026
027*/
028
029package ca.uhn.hl7v2;
030
031import ca.uhn.hl7v2.model.Segment;
032import ca.uhn.hl7v2.util.Terser;
033
034/** 
035 * Represents an exception encountered while processing 
036 * an HL7 message.  
037 * @author Bryan Tripp (bryan_tripp@sourceforge.net)
038 */
039@SuppressWarnings("serial")
040public class HL7Exception extends Exception {
041
042    /** Original mode: Application Accept - Enhanced mode: Application acknowledgment: Accept */
043    public static final int ACK_AA = 1;
044
045    /** Original mode: Application Error - Enhanced mode: Application acknowledgment: Error */
046    public static final int ACK_AE = 2;
047
048    /** Original mode: Application Reject - Enhanced mode: Application acknowledgment: Reject */
049    public static final int ACK_AR = 3;
050
051    /** Enhanced mode: Accept acknowledgment: Commit Accept */
052    public static final int ACK_CA = 4;
053
054    /** Enhanced mode: Accept acknowledgment: Commit Error */
055    public static final int ACK_CE = 5;
056
057    /** Enhanced mode: Accept acknowledgment: Commit Reject */
058    public static final int ACK_CR = 6;
059
060
061    public static final int MESSAGE_ACCEPTED = 0;
062    public static final int SEGMENT_SEQUENCE_ERROR = 100;
063    public static final int REQUIRED_FIELD_MISSING = 101;
064    public static final int DATA_TYPE_ERROR = 102;
065    public static final int TABLE_VALUE_NOT_FOUND = 103;
066    public static final int UNSUPPORTED_MESSAGE_TYPE = 200;
067    public static final int UNSUPPORTED_EVENT_CODE = 201;
068    public static final int UNSUPPORTED_PROCESSING_ID = 202;
069    public static final int UNSUPPORTED_VERSION_ID = 203;
070    public static final int UNKNOWN_KEY_IDENTIFIER = 204;
071    public static final int DUPLICATE_KEY_IDENTIFIER = 205;
072    public static final int APPLICATION_RECORD_LOCKED = 206;
073    public static final int APPLICATION_INTERNAL_ERROR = 207;
074
075    private String segment = null;
076    private int segmentRep = -1;
077    private int fieldPosition = -1;
078    private int errCode = -1;
079
080    /** 
081     * Creates an HL7Exception.
082     *  
083     * @param errorCondition a code describing the the error condition, from HL7
084     *        table 0357 (see section 2.16.8 of standard v 2.4) - HL7Exception defines 
085     *        these codes as integer constants that can be used here (e.g. 
086     *        HL7Exception.UNSUPPORTED_MESSAGE_TYPE)
087     * 
088     * @param cause The exception that caused this exception to be thrown.
089     */
090    public HL7Exception(String message, int errorCondition, Throwable cause) {
091        super(message, cause);
092        this.errCode = errorCondition;
093    }
094
095    /** 
096     * Creates an HL7Exception.
097     *  
098     * @param errorCondition a code describing the the error condition, from HL7
099     *        table 0357 (see section 2.16.8 of standard v 2.4) - HL7Exception defines 
100     *        these codes as integer constants that can be used here (e.g. 
101     *        HL7Exception.UNSUPPORTED_MESSAGE_TYPE)
102     */
103    public HL7Exception(String message, int errorCondition) {
104        super(message);
105        this.errCode = errorCondition;
106    }
107
108    /**
109     * Creates an HL7Exception with the code APPLICATION_INTERNAL_ERROR
110     * 
111     * @param cause The excption that caused this exception tobe thrown.
112     */
113    public HL7Exception(String message, Throwable cause) {
114        super(message, cause);
115        this.errCode = HL7Exception.APPLICATION_INTERNAL_ERROR;
116    }
117    
118    /**
119     * Creates an HL7Exception with the code APPLICATION_INTERNAL_ERROR
120     * 
121     * @param cause The excption that caused this exception tobe thrown.
122     */
123    public HL7Exception(Throwable cause) {
124        super(cause);
125        this.errCode = HL7Exception.APPLICATION_INTERNAL_ERROR;
126    }
127
128    /**
129     * Creates an HL7Exception with the code APPLICATION_INTERNAL_ERROR
130     */
131    public HL7Exception(String message) {
132        super(message);
133        this.errCode = HL7Exception.APPLICATION_INTERNAL_ERROR;
134    }
135
136    /**
137     * Sets the name of the segment where the error occured. 
138     */
139    public void setSegmentName(String segmentName) {
140        this.segment = segmentName;
141    }
142
143    /** 
144     * Returns the name of the segment where the error occured, if this has been set
145     * (null otherwise).
146     */
147    public String getSegmentName() {
148        return this.segment;
149    }
150
151    /** 
152     * Sets the sequence number of the segment where the error occured if there 
153     * are multiplt segments with the same name (ie the sequenceNum'th segment 
154     * with the name specified in <code>setSegmentName</code>).  Numbering 
155     * starts at 1.
156     */
157    public void setSegmentRepetition(int sequenceNum) {
158        this.segmentRep = sequenceNum;
159    }
160
161    /**
162     * Returns the sequence number of the segment where the error occured (if there 
163     * are multiple segments with the same name) if this has been set, -1 otherwise - 
164     * numbering starts at 1.
165     */
166    public int getSegmentRepetition() {
167        return this.segmentRep;
168    }
169
170    /** 
171     * Sets the field number (within a segment) where the error occured; numbering 
172     * starts at 1. 
173     */
174    public void setFieldPosition(int fieldNum) {
175        this.fieldPosition = fieldNum;
176    }
177
178    /** 
179     * Returns the field number within the segment where the error occured if it has been 
180     * set, -1 otherwise; numbering starts at 1.
181     */
182    public int getFieldPosition() {
183        return this.fieldPosition;
184    }
185    
186    /**
187     * @return Returns the error code associated with this exception, or <code>-1</code> if none
188     */
189    public int getErrorCode() {
190        return this.errCode;
191    }
192
193    /**
194     * Overrides Throwable.getMessage() to add the field location of the problem if 
195     * available.
196     */
197    public String getMessage() {
198        StringBuffer msg = new StringBuffer();
199        msg.append(super.getMessage());
200        if (getSegmentName() != null) {
201            msg.append(": Segment: ");
202            msg.append(getSegmentName());
203        }
204        if (getSegmentRepetition() != -1) {
205            msg.append(" (rep ");
206            msg.append(getSegmentRepetition());
207            msg.append(")");
208        }
209        if (getFieldPosition() != -1) {
210            msg.append(" Field #");
211            msg.append(getFieldPosition());
212        }
213        return msg.toString();
214    }
215
216    /**
217     * Populates the given error segment with information from this Exception.
218     */
219    public void populate(Segment errorSegment, String theJdbcUrl) throws HL7Exception {
220        //make sure it's an ERR
221        if (!errorSegment.getName().equals("ERR"))
222            throw new HL7Exception(
223                "Can only populate an ERR segment with an exception -- got: " + errorSegment.getClass().getName());
224
225        int rep = errorSegment.getField(1).length; //append after existing reps
226
227        if (this.getSegmentName() != null)
228            Terser.set(errorSegment, 1, rep, 1, 1, this.getSegmentName());
229
230        if (this.getSegmentRepetition() >= 0)
231            Terser.set(errorSegment, 1, rep, 2, 1, String.valueOf(this.getSegmentRepetition()));
232
233        if (this.getFieldPosition() >= 0)
234            Terser.set(errorSegment, 1, rep, 3, 1, String.valueOf(this.getFieldPosition()));
235
236        Terser.set(errorSegment, 1, rep, 4, 1, String.valueOf(this.errCode));
237        Terser.set(errorSegment, 1, rep, 4, 3, "hl70357");
238        Terser.set(errorSegment, 1, rep, 4, 5, this.getMessage());
239
240        //try to get error condition text
241//        try {
242            // FIXME: make this work
243            String desc = "ERROR"; // TableRepository.getInstance(theJdbcUrl).getDescription(357, String.valueOf(this.errCode));
244            Terser.set(errorSegment, 1, rep, 4, 2, desc);
245//        }
246//        catch (LookupException e) {
247//            ourLog.debug(
248//                "Warning: LookupException getting error condition text (are we connected to a TableRepository?)", e);
249//        } catch (SQLException e) {
250//            throw new HL7Exception(e);
251//        }
252    }
253}