001 002/* 003 The contents of this file are subject to the Mozilla Public License Version 1.1 004 (the "License"); you may not use this file except in compliance with the License. 005 You may obtain a copy of the License at http://www.mozilla.org/MPL/ 006 Software distributed under the License is distributed on an "AS IS" basis, 007 WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for the 008 specific language governing rights and limitations under the License. 009 010 The Original Code is "AbstractHL7Exception.java". Description: 011 "Exception containing a Location and Error Code" 012 013 The Initial Developer of the Original Code is University Health Network. Copyright (C) 014 2012. All Rights Reserved. 015 016 Contributor(s): ______________________________________. 017 018 Alternatively, the contents of this file may be used under the terms of the 019 GNU General Public License (the "GPL"), in which case the provisions of the GPL are 020 applicable instead of those above. If you wish to allow use of your version of this 021 file only under the terms of the GPL and not to allow others to use your version 022 of this file under the MPL, indicate your decision by deleting the provisions above 023 and replace them with the notice and other provisions required by the GPL License. 024 If you do not delete the provisions above, a recipient may use your version of 025 this file under either the MPL or the GPL. 026 */ 027 028package ca.uhn.hl7v2; 029 030import static ca.uhn.hl7v2.Version.V25; 031import static ca.uhn.hl7v2.Version.versionOf; 032 033import ca.uhn.hl7v2.model.Message; 034import ca.uhn.hl7v2.model.Segment; 035import ca.uhn.hl7v2.util.Terser; 036 037/** 038 * Abstract base class for Exceptions that are able to create acknowledgement 039 * messages from their error code and location information 040 * 041 * @author Christian Ohr 042 */ 043@SuppressWarnings("serial") 044public abstract class AbstractHL7Exception extends Exception { 045 046 private Location location; 047 private ErrorCode errorCode = ErrorCode.APPLICATION_INTERNAL_ERROR; 048 private Severity severity = Severity.ERROR; 049 private Message responseMessage; 050 051 052 public AbstractHL7Exception() { 053 super(); 054 } 055 056 public AbstractHL7Exception(String message, Throwable cause) { 057 super(message, cause); 058 } 059 060 public AbstractHL7Exception(String message) { 061 super(message); 062 } 063 064 public AbstractHL7Exception(Throwable cause) { 065 super(cause); 066 } 067 068 public Location getLocation() { 069 return location; 070 } 071 072 public void setLocation(Location location) { 073 this.location = location; 074 } 075 076 public void setFieldPosition(int pos) { 077 if (location == null) 078 location = new Location(); 079 location.withField(pos); 080 } 081 082 public void setSegmentName(String segmentName) { 083 if (location == null) 084 location = new Location(); 085 location.withSegmentName(segmentName); 086 } 087 088 public void setSegmentRepetition(int segmentRepetition) { 089 if (location == null) 090 location = new Location(); 091 location.withSegmentRepetition(segmentRepetition); 092 } 093 094 public int getErrorCode() { 095 return errorCode.getCode(); 096 } 097 098 public void setErrorCode(int errorCode) { 099 this.errorCode = ErrorCode.errorCodeFor(errorCode); 100 } 101 102 public ErrorCode getError() { 103 return errorCode; 104 } 105 106 public void setError(ErrorCode errorCode) { 107 this.errorCode = errorCode; 108 } 109 110 public Severity getSeverity() { 111 return severity; 112 } 113 114 public void setSeverity(Severity severity) { 115 this.severity = severity; 116 } 117 118 public Message getResponseMessage() { 119 return responseMessage; 120 } 121 122 public void setResponseMessage(Message responseMessage) { 123 this.responseMessage = responseMessage; 124 } 125 126 /** 127 * Populates the generated response based on this exception. 128 * 129 * @param emptyResponse empty response message 130 * @param acknowledgmentCode the acknowledgement code 131 * @return response message 132 * @throws HL7Exception if populating the response fails 133 */ 134 public Message populateResponse(Message emptyResponse, AcknowledgmentCode acknowledgmentCode, int repetition) 135 throws HL7Exception { 136 if (responseMessage == null) { 137 if (acknowledgmentCode == null) acknowledgmentCode = AcknowledgmentCode.AA; 138 if (V25.isGreaterThan(versionOf(emptyResponse.getVersion()))) { 139 responseMessage = populateResponseBefore25(emptyResponse, acknowledgmentCode, repetition); 140 } else { 141 responseMessage = populateResponseAsOf25(emptyResponse, acknowledgmentCode, repetition); 142 } 143 } 144 return responseMessage; 145 } 146 147 /** 148 * Fill segments for HL7 versions 2.5 or newer. 149 * <p/> 150 * HL7 versions before 2.5 require to set MSA-1. The ERR segment has various fields (ERR-2, 151 * ERR-3) containing details about the exception. ERR-1 is marked as obsolete. 152 * 153 * @param response the raw response message 154 * @param acknowledgmentCode acknowledgmentCode 155 * @param repetition repetition of the ERR segment that shall be populated 156 * @throws HL7Exception 157 */ 158 private Message populateResponseAsOf25(Message response, AcknowledgmentCode acknowledgmentCode, 159 int repetition) throws HL7Exception { 160 // TODO define what should happen if there is no MSA or ERR 161 Segment msa = (Segment) response.get("MSA"); 162 Terser.set(msa, 1, 0, 1, 1, acknowledgmentCode.name()); 163 Segment err = (Segment) response.get("ERR", repetition); 164 if (location != null) { 165 if (location.getSegmentName() != null) 166 Terser.set(err, 2, 0, 1, 1, location.getSegmentName()); 167 if (location.getSegmentRepetition() > 0) 168 Terser.set(err, 2, 0, 2, 1, Integer.toString(location.getSegmentRepetition())); 169 if (location.getField() > 0) 170 Terser.set(err, 2, 0, 3, 1, Integer.toString(location.getField())); 171 if (location.getFieldRepetition() > 0) 172 Terser.set(err, 2, 0, 4, 1, Integer.toString(location.getFieldRepetition())); 173 if (location.getComponent() > 0) 174 Terser.set(err, 2, 0, 5, 1, Integer.toString(location.getComponent())); 175 if (location.getSubcomponent() > 0) 176 Terser.set(err, 2, 0, 6, 1, Integer.toString(location.getSubcomponent())); 177 } 178 Terser.set(err, 3, 0, 1, 1, Integer.toString(errorCode.getCode())); 179 Terser.set(err, 3, 0, 2, 1, errorCode.getMessage()); 180 Terser.set(err, 3, 0, 3, 1, ErrorCode.codeTable()); 181 Terser.set(err, 3, 0, 9, 1, getMessage()); 182 Terser.set(err, 4, 0, 1, 1, "E"); 183 return response; 184 } 185 186 /** 187 * Fill segments for HL7 versions before 2.5. 188 * <p/> 189 * HL7 versions before 2.5 require to set MSA-1 and MSA-3. The ERR segment only has one 190 * repeatable field (ERR-1) with components containing details about the exception. 191 * 192 * @param response the raw response message 193 * @param acknowledgmentCode acknowledgment code 194 * @param repetition repetition of the ERR segment that shall be popualted 195 * @throws HL7Exception 196 */ 197 private Message populateResponseBefore25(Message response, AcknowledgmentCode acknowledgmentCode, 198 int repetition) throws HL7Exception { 199 // TODO define what should happen if there is no MSA or ERR 200 Segment msa = (Segment) response.get("MSA"); 201 Terser.set(msa, 1, 0, 1, 1, acknowledgmentCode.name()); 202 Terser.set(msa, 3, 0, 1, 1, errorCode.getMessage()); 203 Segment err = (Segment) response.get("ERR"); 204 if (location != null) { 205 if (location.getSegmentName() != null) 206 Terser.set(err, 1, repetition, 1, 1, location.getSegmentName()); 207 if (location.getField() > 0) 208 Terser.set(err, 1, repetition, 3, 1, Integer.toString(location.getField())); 209 } 210 Terser.set(err, 1, repetition, 4, 1, Integer.toString(errorCode.getCode())); 211 Terser.set(err, 1, repetition, 4, 2, errorCode.getMessage()); 212 Terser.set(err, 1, repetition, 4, 3, ErrorCode.codeTable()); 213 Terser.set(err, 1, repetition, 4, 5, getMessage()); 214 return response; 215 } 216 217 public String getMessage() { 218 String message = getMessageWithoutLocation(); 219 StringBuilder msg = new StringBuilder(message); 220 if (getLocation() != null && !getLocation().isUnknown()) { 221 msg.append(" at ").append(getLocation().toString()); 222 } 223 return msg.toString(); 224 } 225 226 public String getMessageWithoutLocation() { 227 String message = super.getMessage(); 228 if (message == null) message = "Exception"; 229 return message; 230 } 231 232}