001package ca.uhn.hl7v2.validation.app; 002 003import org.apache.log4j.NDC; 004import org.slf4j.LoggerFactory; 005 006import ca.uhn.hl7v2.HL7Exception; 007import ca.uhn.hl7v2.model.Message; 008import ca.uhn.hl7v2.parser.PipeParser; 009import ca.uhn.hl7v2.util.Terser; 010 011/** 012 * An application intended for testing messages. The intended use is to route a copy 013 * of (selected) messages to a test application, which identifies and acts on problems independently 014 * of the normal error acknowledgement path (for example by notifying an administrator). 015 * This makes the most sense when used within an interface engine, for example if the 016 * sending nor receiving system use HAPI, but it is desired to route messages to HAPI in 017 * parallel so that they can be fully validated. 018 * @author Bryan Tripp 019 * @deprecated 020 */ 021public abstract class TestApplication implements ca.uhn.hl7v2.app.Application { 022 023 private PipeParser parser; 024 025 /** Creates a new instance of TestApplication */ 026 public TestApplication() { 027 parser = new PipeParser(); 028 } 029 030 /** 031 * Returns true if this Application wishes to accept the message. By returning 032 * true, this Application declares itself the recipient of the message, accepts 033 * responsibility for it, and must be able to respond appropriately to the sending system. 034 */ 035 public abstract boolean canProcess(Message in); 036 037 038 /** 039 * <p>Calls test(Message in), routes resulting exceptions to configured destinations, and 040 * returns an ack (which should not normally be used since the test app is intended 041 * to operate in parallel with system-to-system communication). </p> 042 * <p>Notification routing is performed using log4j, so you need appropriate settings in a log4j 043 * config file (by default, ./log4j.properties). Different types of exceptions 044 * are all given the same severity (ERROR) but they have different loggers, based 045 * on the exception class name. Specifically, the loggers will be named 046 * ca.uhn.hl7v2.validation.error.{exception class name}. For example: 047 * "ca.uhn.hl7v2.validation.error.DataTypeException". Note that this allows default 048 * settings for all validation errors using the logger "ca.uhn.hl7v2.validation.error". 049 * The intent is for different exceptions to result in different actions, e.g. a 050 * ProfileNotHL7CompliantException should probably just be logged or ignored, while a 051 * ProfileNotFollowedException should probably be emailed to an administrator. </p> 052 */ 053 public Message processMessage(Message in) throws HL7Exception { 054 String context = null; 055 try { 056 context = this.parser.encode(in); 057 } catch (HL7Exception e) { 058 context = "message not encodable"; 059 } 060 //update logging context with message text 061 NDC.push(context); 062 063 LoggerFactory.getLogger("ca.uhn.hl7v2.validation.error").info("Testing message"); 064 065 HL7Exception[] problems = test(in); 066 sendNotifications(problems); 067 068 NDC.pop(); 069 070 try { 071 Message ack = in.generateACK(); 072 addProblemsToACK(ack, problems); 073 return ack; 074 } catch (java.io.IOException e) { 075 throw new HL7Exception(e); 076 } 077 } 078 079 /** 080 * <p>Send notification of problems to specified destinations (e.g. log file, email). 081 */ 082 private void sendNotifications(HL7Exception[] problems) { 083 for (int i = 0; i < problems.length; i++) { 084 String exName = problems[i].getClass().getName(); 085 String logName = "ca.uhn.hl7v2.validation.error" + exName.substring(exName.lastIndexOf('.')); 086 LoggerFactory.getLogger(logName).error("message validation failure", problems[i]); 087 } 088 } 089 090 private void addProblemsToACK(Message ack, HL7Exception[] problems) throws HL7Exception { 091 Terser t = new Terser(ack); 092 093 if (problems.length > 0) { 094 t.set("MSA-1", "AE"); 095 t.set("MSA-3", "Errors were encountered while testing the message"); 096 } 097 /* 098 Segment err = (Segment) ack.get("ERR"); 099 for (int i = 0; i < problems.length; i++) { 100 // problems[i].populate(err); FIXME: broken! needs database 101 } 102 */ 103 } 104 105 /** 106 * Tests the message in some way (as defined by implementing class). 107 * @return exceptions that describe any identified problems with the message 108 * @throws HL7Exception if the message can't be tested (not for errors disovered 109 * during testing) 110 */ 111 public abstract HL7Exception[] test(Message in) throws HL7Exception; 112 113}