001/* 002 * Created on 10-May-2004 003 */ 004package ca.uhn.hl7v2.protocol.impl; 005 006import java.io.IOException; 007 008import org.slf4j.Logger; 009import org.slf4j.LoggerFactory; 010 011import ca.uhn.hl7v2.HL7Exception; 012import ca.uhn.hl7v2.app.DefaultApplication; 013import ca.uhn.hl7v2.model.Message; 014import ca.uhn.hl7v2.model.Segment; 015import ca.uhn.hl7v2.parser.GenericParser; 016import ca.uhn.hl7v2.parser.Parser; 017import ca.uhn.hl7v2.protocol.AcceptValidator; 018import ca.uhn.hl7v2.protocol.Processor; 019import ca.uhn.hl7v2.protocol.ProcessorContext; 020import ca.uhn.hl7v2.protocol.Transportable; 021import ca.uhn.hl7v2.util.Terser; 022 023/** 024 * Checks whether messages can be accepted and creates appropriate 025 * ACK messages. 026 * 027 * @author <a href="mailto:bryan.tripp@uhn.on.ca">Bryan Tripp</a> 028 * @version $Revision: 1.1 $ updated on $Date: 2007-02-19 02:24:26 $ by $Author: jamesagnew $ 029 */ 030public class AcceptAcknowledger { 031 032 private static final Logger log = LoggerFactory.getLogger(AcceptAcknowledger.class); 033 034 private static Parser ourParser = new GenericParser(); 035 036 /** 037 * Validates the given message against our accept validators, attempts to commit 038 * the message to safe storage, and returns an ACK message indicating acceptance 039 * or rejection at the accept level (see enhanced mode processing rules in HL7 040 * chapter 2, v2.5). 041 */ 042 public static AcceptACK validate(ProcessorContext theContext, Transportable theMessage) throws HL7Exception { 043 AcceptACK ruling = null; 044 045 AcceptValidator[] validators = theContext.getValidators(); 046 for (int i = 0; i < validators.length && ruling == null; i++) { 047 AcceptValidator.AcceptRuling vr = validators[i].check(theMessage); 048 if (!vr.isAcceptable()) { 049 String description = (vr.getReasons().length > 0) ? vr.getReasons()[0] : null; 050 Transportable ack = makeAcceptAck(theMessage, vr.getAckCode(), vr.getErrorCode(), description); 051 ruling = new AcceptACK(false, ack); 052 } 053 } 054 055 if (ruling == null) { 056 try { 057 theContext.getSafeStorage().store(theMessage); 058 Transportable ack = makeAcceptAck(theMessage, Processor.CA, HL7Exception.MESSAGE_ACCEPTED, ""); 059 ruling = new AcceptACK(true, ack); 060 } catch (HL7Exception e) { 061 log.error(e.getMessage(), e); 062 int code = HL7Exception.APPLICATION_INTERNAL_ERROR; 063 Transportable ack = makeAcceptAck(theMessage, Processor.CR, code, e.getMessage()); 064 ruling = new AcceptACK(false, ack); 065 } 066 } 067 068 return ruling; 069 } 070 071 072 private static Transportable makeAcceptAck(Transportable theMessage, String theAckCode, int theErrorCode, String theDescription) throws HL7Exception { 073 074 Segment header = ourParser.getCriticalResponseData(theMessage.getMessage()); 075 Message out; 076 try { 077 out = DefaultApplication.makeACK(header); 078 } catch (IOException e) { 079 throw new HL7Exception(e); 080 } 081 082 Terser t = new Terser(out); 083 t.set("/MSA-1", theAckCode); 084 085 //TODO: when 2.5 is available, use 2.5 fields for remaining problems 086 if (theErrorCode != HL7Exception.MESSAGE_ACCEPTED) { 087 t.set("/MSA-3", theDescription.substring(0, Math.min(80, theDescription.length()))); 088 t.set("/ERR-1-4-1", String.valueOf(theErrorCode)); 089 t.set("/ERR-1-4-3", "HL70357"); 090 } 091 092 String originalEncoding = ourParser.getEncoding(theMessage.getMessage()); 093 String ackText = ourParser.encode(out, originalEncoding); 094 return new TransportableImpl(ackText); 095 } 096 097 098 /** 099 * A structure for decisions as to whether a message can be accepted, 100 * along with a corresponding accept or reject acknowlegement message. 101 * 102 * @author <a href="mailto:bryan.tripp@uhn.on.ca">Bryan Tripp</a> 103 * @version $Revision: 1.1 $ updated on $Date: 2007-02-19 02:24:26 $ by $Author: jamesagnew $ 104 */ 105 public static class AcceptACK { 106 private Transportable myAck; 107 private boolean myIsAcceptable; 108 109 public AcceptACK(boolean isAcceptable, Transportable theAck) { 110 myIsAcceptable = isAcceptable; 111 myAck = theAck; 112 } 113 114 public boolean isAcceptable() { 115 return myIsAcceptable; 116 } 117 118 public Transportable getMessage() { 119 return myAck; 120 } 121 } 122 123}