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 * 039 * Abstract base class for Exceptions that are able to create acknowledgement 040 * messages from their error code and location information 041 * 042 * @author Christian Ohr 043 * 044 */ 045@SuppressWarnings("serial") 046public abstract class AbstractHL7Exception extends Exception { 047 048 private Location location; 049 private ErrorCode errorCode = ErrorCode.APPLICATION_INTERNAL_ERROR; 050 private Severity severity = Severity.ERROR; 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.setField(pos); 080 } 081 082 public void setSegmentName(String segmentName) { 083 if (location == null) 084 location = new Location(); 085 location.setSegmentName(segmentName); 086 } 087 088 public void setSegmentRepetition(int segmentRepetition) { 089 if (location == null) 090 location = new Location(); 091 location.setSegmentRepetition(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 /** 119 * Populates the generated response based on this exception. 120 * 121 * @param response response message 122 * @param acknowledgmentCode the acknowledgement code 123 * @return response message 124 * @throws HL7Exception if populating the response fails 125 */ 126 public Message populateResponse(Message response, AcknowledgmentCode acknowledgmentCode, int repetition) 127 throws HL7Exception { 128 if (acknowledgmentCode == null) acknowledgmentCode = AcknowledgmentCode.AA; 129 if (V25.isGreaterThan(versionOf(response.getVersion()))) { 130 return populateResponseBefore25(response, acknowledgmentCode, repetition); 131 } 132 return populateResponseAsOf25(response, acknowledgmentCode, repetition); 133 } 134 135 /** 136 * Fill segments for HL7 versions 2.5 or newer. 137 * <p> 138 * HL7 versions before 2.5 require to set MSA-1. The ERR segment has various fields (ERR-2, 139 * ERR-3) containing details about the exception. ERR-1 is marked as obsolete. 140 * 141 * @param response the raw response message 142 * @param acknowledgmentCode acknowledgmentCode 143 * @param repetition repetition of the ERR segment that shall be populated 144 * @throws HL7Exception 145 */ 146 private Message populateResponseAsOf25(Message response, AcknowledgmentCode acknowledgmentCode, 147 int repetition) throws HL7Exception { 148 // TODO define what should happen if there is no MSA or ERR 149 Segment msa = (Segment) response.get("MSA"); 150 Terser.set(msa, 1, 0, 1, 1, acknowledgmentCode.name()); 151 Segment err = (Segment) response.get("ERR", repetition); 152 if (location != null) { 153 if (location.getSegmentName() != null) 154 Terser.set(err, 2, 0, 1, 1, location.getSegmentName()); 155 if (location.getField() > 0) 156 Terser.set(err, 2, 0, 3, 1, Integer.toString(location.getField())); 157 if (location.getFieldRepetition() > 0) 158 Terser.set(err, 2, 0, 4, 1, Integer.toString(location.getFieldRepetition())); 159 if (location.getComponent() > 0) 160 Terser.set(err, 2, 0, 5, 1, Integer.toString(location.getComponent())); 161 if (location.getSubcomponent() > 0) 162 Terser.set(err, 2, 0, 6, 1, Integer.toString(location.getSubcomponent())); 163 } 164 Terser.set(err, 3, 0, 1, 1, Integer.toString(errorCode.getCode())); 165 Terser.set(err, 3, 0, 2, 1, errorCode.getMessage()); 166 Terser.set(err, 3, 0, 3, 1, ErrorCode.codeTable()); 167 Terser.set(err, 3, 0, 9, 1, getMessage()); 168 Terser.set(err, 4, 0, 1, 1, "E"); 169 return response; 170 } 171 172 /** 173 * Fill segments for HL7 versions before 2.5. 174 * <p> 175 * HL7 versions before 2.5 require to set MSA-1 and MSA-3. The ERR segment only has one 176 * repeatable field (ERR-1) with components containing details about the exception. 177 * 178 * @param response the raw response message 179 * @param acknowledgmentCode acknowledgment code 180 * @param repetition repetition of the ERR segment that shall be popualted 181 * @throws HL7Exception 182 */ 183 private Message populateResponseBefore25(Message response, AcknowledgmentCode acknowledgmentCode, 184 int repetition) throws HL7Exception { 185 // TODO define what should happen if there is no MSA or ERR 186 Segment msa = (Segment) response.get("MSA"); 187 Terser.set(msa, 1, 0, 1, 1, acknowledgmentCode.name()); 188 Terser.set(msa, 3, 0, 1, 1, errorCode.getMessage()); 189 Segment err = (Segment) response.get("ERR"); 190 if (location != null) { 191 if (location.getSegmentName() != null) 192 Terser.set(err, 1, repetition, 1, 1, location.getSegmentName()); 193 if (location.getField() > 0) 194 Terser.set(err, 1, repetition, 3, 1, Integer.toString(location.getField())); 195 } 196 Terser.set(err, 1, repetition, 4, 1, Integer.toString(errorCode.getCode())); 197 Terser.set(err, 1, repetition, 4, 2, errorCode.getMessage()); 198 Terser.set(err, 1, repetition, 4, 3, ErrorCode.codeTable()); 199 Terser.set(err, 1, repetition, 4, 5, getMessage()); 200 return response; 201 } 202 203 public String getMessage() { 204 String message = getMessageWithoutLocation(); 205 StringBuilder msg = new StringBuilder(message); 206 if (getLocation() != null && !getLocation().isUnknown()) { 207 msg.append(" at ").append(getLocation().toString()); 208 } 209 return msg.toString(); 210 } 211 212 public String getMessageWithoutLocation() { 213 String message = super.getMessage(); 214 if (message == null) message = "Exception"; 215 return message; 216 } 217 218}