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