View Javadoc

1   /*
2    * Created on 10-May-2004
3    */
4   package ca.uhn.hl7v2.protocol.impl;
5   
6   import java.io.IOException;
7   
8   import org.slf4j.Logger;
9   import org.slf4j.LoggerFactory;
10  
11  import ca.uhn.hl7v2.AcknowledgmentCode;
12  import ca.uhn.hl7v2.ErrorCode;
13  import ca.uhn.hl7v2.HL7Exception;
14  import ca.uhn.hl7v2.model.Message;
15  import ca.uhn.hl7v2.model.Segment;
16  import ca.uhn.hl7v2.parser.GenericParser;
17  import ca.uhn.hl7v2.parser.Parser;
18  import ca.uhn.hl7v2.protocol.AcceptValidator;
19  import ca.uhn.hl7v2.protocol.Processor;
20  import ca.uhn.hl7v2.protocol.ProcessorContext;
21  import ca.uhn.hl7v2.protocol.Transportable;
22  import ca.uhn.hl7v2.util.DeepCopy;
23  
24  /**
25   * Checks whether messages can be accepted and creates appropriate
26   * ACK messages.  
27   * 
28   * @author <a href="mailto:bryan.tripp@uhn.on.ca">Bryan Tripp</a>
29   * @version $Revision: 1.1 $ updated on $Date: 2007-02-19 02:24:26 $ by $Author: jamesagnew $
30   */
31  public class AcceptAcknowledger {
32  
33      private static final Logger log = LoggerFactory.getLogger(AcceptAcknowledger.class);
34      
35      private static Parser ourParser = new GenericParser();
36      
37      /** 
38       * Validates the given message against our accept validators, attempts to commit
39       * the message to safe storage, and returns an ACK message indicating acceptance 
40       * or rejection at the accept level (see enhanced mode processing rules in HL7 
41       * chapter 2, v2.5).  
42       */
43      public static AcceptACK validate(ProcessorContext theContext, Transportable theMessage) throws HL7Exception {
44          AcceptACK ruling = null;
45          
46          AcceptValidator[] validators = theContext.getValidators();
47          for (int i = 0; i < validators.length && ruling == null; i++) {
48              AcceptValidator.AcceptRuling vr = validators[i].check(theMessage);            
49              if (!vr.isAcceptable()) {
50                  String description = (vr.getReasons().length > 0) ? vr.getReasons()[0] : null;
51                  Transportable ack = makeAcceptAck(theMessage, vr.getAckCode(), ErrorCode.errorCodeFor(vr.getErrorCode()), description);
52                  ruling = new AcceptACK(false, ack);
53              }
54          }
55          
56          if (ruling == null) {
57              try {
58                  theContext.getSafeStorage().store(theMessage);
59                  Transportable ack = makeAcceptAck(theMessage, Processor.CA, ErrorCode.MESSAGE_ACCEPTED, "");
60                  ruling = new AcceptACK(true, ack);
61              } catch (HL7Exception e) {
62                  log.error(e.getMessage(), e);
63                  Transportable ack = makeAcceptAck(theMessage, Processor.CR, ErrorCode.APPLICATION_INTERNAL_ERROR, e.getMessage());
64                  ruling = new AcceptACK(false, ack);
65              }
66          }        
67          
68          return ruling;
69      }
70  
71  
72      private static Transportable makeAcceptAck(Transportable theMessage, String theAckCode, ErrorCode theErrorCode, String theDescription) throws HL7Exception {        
73          Segment header = ourParser.getCriticalResponseData(theMessage.getMessage());
74          Message dummy = header.getMessage();
75          // MSH header refers to dummy, but not the other way round!
76          DeepCopy.copy(header, (Segment)dummy.get("MSH"));
77  
78          try {
79              HL7Exception hl7e = new HL7Exception(theDescription, theErrorCode);
80              AcknowledgmentCode code = theAckCode == null ?
81              		AcknowledgmentCode.CR :
82              		AcknowledgmentCode.valueOf(theAckCode);
83          	Message out = dummy.generateACK(code, hl7e);
84              String originalEncoding = ourParser.getEncoding(theMessage.getMessage());
85              String ackText = ourParser.encode(out, originalEncoding);
86              return new TransportableImpl(ackText);
87          } catch (IOException e) {
88              throw new HL7Exception(e);
89          }
90          
91      }    
92      
93      
94      /**
95       * A structure for decisions as to whether a message can be accepted, 
96       * along with a corresponding accept or reject acknowlegement message. 
97       *  
98       * @author <a href="mailto:bryan.tripp@uhn.on.ca">Bryan Tripp</a>
99       * @version $Revision: 1.1 $ updated on $Date: 2007-02-19 02:24:26 $ by $Author: jamesagnew $
100      */
101     public static class AcceptACK {
102         private Transportable myAck;
103         private boolean myIsAcceptable;
104         
105         public AcceptACK(boolean isAcceptable, Transportable theAck) {
106             myIsAcceptable = isAcceptable;
107             myAck = theAck;
108         }
109         
110         public boolean isAcceptable() {
111             return myIsAcceptable;
112         }
113         
114         public Transportable getMessage() {
115             return myAck;
116         }
117     }
118 
119 }