1
2
3
4 package ca.uhn.hl7v2.protocol.impl;
5
6 import java.io.IOException;
7
8 import ca.uhn.hl7v2.HL7Exception;
9 import ca.uhn.hl7v2.app.DefaultApplication;
10 import ca.uhn.hl7v2.model.Message;
11 import ca.uhn.hl7v2.model.Segment;
12 import ca.uhn.hl7v2.parser.GenericParser;
13 import ca.uhn.hl7v2.parser.Parser;
14 import ca.uhn.hl7v2.protocol.AcceptValidator;
15 import ca.uhn.hl7v2.protocol.Processor;
16 import ca.uhn.hl7v2.protocol.ProcessorContext;
17 import ca.uhn.hl7v2.protocol.Transportable;
18 import ca.uhn.hl7v2.util.Terser;
19 import ca.uhn.log.HapiLog;
20 import ca.uhn.log.HapiLogFactory;
21
22 /**
23 * Checks whether messages can be accepted and creates appropriate
24 * ACK messages.
25 *
26 * @author <a href="mailto:bryan.tripp@uhn.on.ca">Bryan Tripp</a>
27 * @version $Revision: 1.2 $ updated on $Date: 2004/05/24 16:25:33 $ by $Author: bryan_tripp $
28 */
29 public class AcceptAcknowledger {
30
31 private static final HapiLog log = HapiLogFactory.getHapiLog(AcceptAcknowledger.class);
32
33 private static Parser ourParser = new GenericParser();
34
35 /**
36 * Validates the given message against our accept validators, attempts to commit
37 * the message to safe storage, and returns an ACK message indicating acceptance
38 * or rejection at the accept level (see enhanced mode processing rules in HL7
39 * chapter 2, v2.5).
40 */
41 public static AcceptACK validate(ProcessorContext theContext, Transportable theMessage) throws HL7Exception {
42 AcceptACK ruling = null;
43
44 AcceptValidator[] validators = theContext.getValidators();
45 for (int i = 0; i < validators.length && ruling == null; i++) {
46 AcceptValidator.AcceptRuling vr = validators[i].check(theMessage);
47 if (!vr.isAcceptable()) {
48 String description = (vr.getReasons().length > 0) ? vr.getReasons()[0] : null;
49 Transportable ack = makeAcceptAck(theMessage, vr.getAckCode(), vr.getErrorCode(), description);
50 ruling = new AcceptACK(false, ack);
51 }
52 }
53
54 if (ruling == null) {
55 try {
56 theContext.getSafeStorage().store(theMessage);
57 Transportable ack = makeAcceptAck(theMessage, Processor.CA, HL7Exception.MESSAGE_ACCEPTED, "");
58 ruling = new AcceptACK(true, ack);
59 } catch (HL7Exception e) {
60 log.error(e);
61 int code = HL7Exception.APPLICATION_INTERNAL_ERROR;
62 Transportable ack = makeAcceptAck(theMessage, Processor.CR, code, e.getMessage());
63 ruling = new AcceptACK(false, ack);
64 }
65 }
66
67 return ruling;
68 }
69
70
71 private static Transportable makeAcceptAck(Transportable theMessage, String theAckCode, int theErrorCode, String theDescription) throws HL7Exception {
72
73 Segment header = ourParser.getCriticalResponseData(theMessage.getMessage());
74 Message out;
75 try {
76 out = DefaultApplication.makeACK(header);
77 } catch (IOException e) {
78 throw new HL7Exception(e);
79 }
80
81 Terser t = new Terser(out);
82 t.set("/MSA-1", theAckCode);
83
84
85 if (theErrorCode != HL7Exception.MESSAGE_ACCEPTED) {
86 t.set("/MSA-3", theDescription.substring(0, Math.min(80, theDescription.length())));
87 t.set("/ERR-1-4-1", String.valueOf(theErrorCode));
88 t.set("/ERR-1-4-3", "HL70357");
89 }
90
91 String originalEncoding = ourParser.getEncoding(theMessage.getMessage());
92 String ackText = ourParser.encode(out, originalEncoding);
93 return new TransportableImpl(ackText);
94 }
95
96
97 /**
98 * A structure for decisions as to whether a message can be accepted,
99 * 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.2 $ updated on $Date: 2004/05/24 16:25:33 $ by $Author: bryan_tripp $
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 }