/// <summary> /// Validate the message /// </summary> internal static void Validate(IMessage message, ISystemConfigurationService config, List <IResultDetail> dtls, IServiceProvider context) { // Structure validation PipeParser pp = new PipeParser() { ValidationContext = new DefaultValidation() }; try { pp.Encode(message); } catch (Exception e) { dtls.Add(new ValidationResultDetail(ResultDetailType.Error, e.Message, e)); } // Validation of sending application try { Terser msgTerser = new Terser(message); object obj = msgTerser.getSegment("MSH") as NHapi.Model.V25.Segment.MSH; if (obj != null) { var msh = obj as NHapi.Model.V25.Segment.MSH; var domainId = new ComponentUtility() { Context = context }.CreateDomainIdentifier(msh.SendingApplication, dtls); if (!config.IsRegisteredDevice(domainId)) { dtls.Add(new UnrecognizedSenderResultDetail(domainId)); } } else { obj = msgTerser.getSegment("MSH") as NHapi.Model.V231.Segment.MSH; if (obj != null) { var msh = obj as NHapi.Model.V231.Segment.MSH; var domainId = new ComponentUtility() { Context = context }.CreateDomainIdentifier(msh.SendingApplication, dtls); if (!config.IsRegisteredDevice(domainId)) { dtls.Add(new UnrecognizedSenderResultDetail(domainId)); } } else { dtls.Add(new MandatoryElementMissingResultDetail(ResultDetailType.Error, "Missing MSH", "MSH")); } } } catch (Exception e) { dtls.Add(new ResultDetail(ResultDetailType.Error, e.Message, e)); } }
/// <summary> /// Create NACK /// </summary> internal static IMessage CreateNack(IMessage request, List <IResultDetail> errors, IServiceProvider context, Type errType) { var config = context.GetService(typeof(ISystemConfigurationService)) as ISystemConfigurationService; IMessage ack = errType.GetConstructor(Type.EmptyTypes).Invoke(null) as IMessage; Trace.TraceError("Validation Errors:"); errors.ForEach(o => Trace.TraceError("\t{0} : {1}", o.Type, o.Message)); Terser terser = new Terser(ack); MessageUtil.UpdateMSH(terser, request, config); int errLevel = 0; int ec = 0; foreach (var dtl in errors) { try { ISegment errSeg; if (ack.Version == "2.5") { errSeg = terser.getSegment(String.Format("/ERR({0})", ec++)); } else { errSeg = terser.getSegment(String.Format("/ERR", ec++)); } if (errSeg is NHapi.Model.V231.Segment.ERR) { var tErr = MessageUtil.UpdateERR(errSeg as NHapi.Model.V231.Segment.ERR, dtl, context); if (tErr > errLevel) { errLevel = tErr; } } else if (errSeg is NHapi.Model.V25.Segment.ERR) { var tErr = MessageUtil.UpdateERR(errSeg as NHapi.Model.V25.Segment.ERR, dtl, context); if (tErr > errLevel) { errLevel = tErr; } } } catch (Exception e) { Trace.TraceError(e.ToString()); } } terser.Set("/MSA-1", errLevel == 0 ? "AA" : errLevel == 1 ? "AE" : "AR"); return(ack); }
/// <summary> /// Create a new instance of HL7Message /// </summary> /// <param name="message"></param> public HL7Message(IMessage message) { this.m_Message = message; this.m_HL7Parser = new HL7Parser(); this.m_Terser = new Terser(m_Message); this.m_MSH = m_Terser.getSegment("MSH"); }
private void SetACK(AckTypes ackType, String messageString) { Terser terser = new Terser(hl7Ack.Message); ISegment err = terser.getSegment("/ERR(0)"); ISegment criticalSegment = TryToRecoverCriticalDataFromMessage(messageString); try { FillMSHSegment((ISegment)hl7Ack.Message.GetStructure("MSH"), criticalSegment); if (criticalSegment == null) { terser.Set("/MSA-1", Enum.GetName(typeof(AckTypes), ackType)); terser.Set("/MSA-2", ""); } else { terser.Set("/MSA-1", Enum.GetName(typeof(AckTypes), ackType)); terser.Set("/MSA-2", Terser.Get(criticalSegment, 10, 0, 1, 1)); } } catch (HL7Exception he) { _errorMessage.Append(he.Message); return; //do not throw exceptions; } //terser.Set("ERR(0)-7", _errorMessage); terser.Set("/ERR(0)-7-1-1", _errorMessage.ToString()); }
/// <summary> /// Create an Ack message based on a received message /// </summary> /// <param name="inboundMessage">received message</param> /// <param name="ackCode">Should be "AE" or "AR", can be "AA".</param> /// <param name="errorMessage">The reason the message was rejected or an error. If "AA" was supplied as ackCode the errorMessage should be null.</param> /// <returns>Created ACK message</returns> public static IMessage MakeACK(IMessage inboundMessage, string ackCode, string errorMessage) { IMessage ackMessage = null; // Get an object from the right ACK class string ackClassType = string.Format("NHapi.Model.V{0}.Message.ACK, NHapi.Model.V{0}", inboundMessage.Version.Remove(inboundMessage.Version.IndexOf('.'), 1)); Type x = Type.GetType(ackClassType); ackMessage = (IMessage)Activator.CreateInstance(x); Terser inboundTerser = new Terser(inboundMessage); ISegment inboundHeader = null; inboundHeader = inboundTerser.getSegment("MSH"); // Find the HL7 version of the inbound message: // string version = null; try { version = Terser.Get(inboundHeader, 12, 0, 1, 1); } catch (NHapi.Base.HL7Exception) { // I'm not happy to proceed if we can't identify the inbound // message version. throw new NHapi.Base.HL7Exception("Failed to get valid HL7 version from inbound MSH-12-1"); } // Create a Terser instance for the outbound message (the ACK). Terser terser = new Terser(ackMessage); // Populate outbound MSH fields using data from inbound message ISegment outHeader = (ISegment)terser.getSegment("MSH"); DeepCopy.copy(inboundHeader, outHeader); // Now set the message type, HL7 version number, acknowledgement code // and message control ID fields: string sendingApp = terser.Get("/MSH-3"); string sendingEnv = terser.Get("/MSH-4"); terser.Set("/MSH-3", CommunicationName); terser.Set("/MSH-4", EnvironmentIdentifier); terser.Set("/MSH-5", sendingApp); terser.Set("/MSH-6", sendingEnv); terser.Set("/MSH-7", DateTime.Now.ToString("yyyyMMddmmhh")); terser.Set("/MSH-9", "ACK"); terser.Set("/MSH-12", version); terser.Set("/MSA-1", ackCode == null ? "AA" : ackCode); terser.Set("/MSA-2", Terser.Get(inboundHeader, 10, 0, 1, 1)); // Set error message if (errorMessage != null) { terser.Set("/ERR-7", errorMessage); } return(ackMessage); }
/// <summary> /// Validates a message. /// </summary> /// <param name="message">The message to be validated.</param> /// <param name="details">The result details for storing the message validation results.</param> /// <returns>Returns a list of validation results.</returns> public static List <IResultDetail> Validate(IMessage message, List <IResultDetail> details) { var pipeParser = new PipeParser() { ValidationContext = new DefaultValidation() }; try { pipeParser.Encode(message); } catch (Exception e) { details.Add(new ValidationResultDetail(ResultDetailType.Error, e.Message, e)); } try { var terser = new Terser(message); var msh = terser.getSegment("MSH"); if (msh is MSH) { var v231Msh = (MSH)msh; var result = ConvertAssigningAuthority(v231Msh.SendingApplication, details); if (result == null) { details.Add(new UnrecognizedSenderResultDetail(ResultDetailType.Error, v231Msh.SendingApplication.NamespaceID.Value, "MSH^3")); } } else if (msh is NHapi.Model.V25.Segment.MSH) { var v25Msh = (NHapi.Model.V25.Segment.MSH)msh; var result = ConvertAssigningAuthority(v25Msh.SendingApplication, details); if (result == null) { details.Add(new UnrecognizedSenderResultDetail(ResultDetailType.Error, v25Msh.SendingApplication.NamespaceID.Value, "MSH^3")); } } else { details.Add(new MandatoryElementMissingResultDetail(ResultDetailType.Error, "Missing MSH", "MSH")); } } catch (Exception e) { details.Add(new ResultDetail(ResultDetailType.Error, e.Message, e)); } return(details); }
public static void MakeACK(ISegment inboundHeader, string ackCode, IMessage ackMessage, string errorMessage) { if (!inboundHeader.GetStructureName().Equals("MSH")) { throw new NHapi.Base.HL7Exception("Need an MSH segment to create a response ACK (got " + inboundHeader.GetStructureName() + ")"); } // Find the HL7 version of the inbound message: string version = null; try { version = Terser.Get(inboundHeader, 12, 0, 1, 1); } catch (NHapi.Base.HL7Exception) { // I'm not happy to proceed if we can't identify the inbound // message version. throw new NHapi.Base.HL7Exception("Failed to get valid HL7 version from inbound MSH-12-1"); } // Create a Terser instance for the outbound message (the ACK). Terser terser = new Terser(ackMessage); // Populate outbound MSH fields using data from inbound message ISegment outHeader = (ISegment)terser.getSegment("MSH"); DeepCopy.copy(inboundHeader, outHeader); // Now set the message type, HL7 version number, acknowledgement code // and message control ID fields: string sendingApp = terser.Get("/MSH-3"); string sendingEnv = terser.Get("/MSH-4"); // Make sure you fill the MSH-3 and MSH-4 with the correct values // for you application, preferably with configuration terser.Set("/MSH-3", "HL7Client"); terser.Set("/MSH-4", "EnvironmentIdentifier"); terser.Set("/MSH-5", sendingApp); terser.Set("/MSH-6", sendingEnv); terser.Set("/MSH-7", DateTime.Now.ToString("yyyyMMddmmhh")); terser.Set("/MSH-9", "ACK"); terser.Set("/MSH-12", version); terser.Set("/MSA-1", ackCode == null ? "AA" : ackCode); terser.Set("/MSA-2", Terser.Get(inboundHeader, 10, 0, 1, 1)); // Set error message if (errorMessage != null) { terser.Set("/ERR-7", errorMessage); } }
public static IMessage MakeACK(ISegment inboundHeader, string ackCode) { if (!inboundHeader.GetStructureName().Equals("MSH")) { throw new NHapi.Base.HL7Exception( "Need an MSH segment to create a response ACK (got " + inboundHeader.GetStructureName() + ")"); } // Find the HL7 version of the inbound message: // string version = null; try { version = Terser.Get(inboundHeader, 12, 0, 1, 1); } catch (NHapi.Base.HL7Exception) { // I'm not happy to proceed if we can't identify the inbound // message version. throw new NHapi.Base.HL7Exception("Failed to get valid HL7 version from inbound MSH-12-1"); } IMessage ackMessage = new ACK(); // Create a Terser instance for the outbound message (the ACK). Terser terser = new Terser(ackMessage); // Populate outbound MSH fields using data from inbound message ISegment outHeader = (ISegment)terser.getSegment("MSH"); DeepCopy.copy(inboundHeader, outHeader); // Now set the message type, HL7 version number, acknowledgement code // and message control ID fields: string sendingApp = terser.Get("/MSH-3"); string sendingEnv = terser.Get("/MSH-4"); terser.Set("/MSH-3", CommunicationName); terser.Set("/MSH-4", EnvironmentIdentifier); terser.Set("/MSH-5", sendingApp); terser.Set("/MSH-6", sendingEnv); terser.Set("/MSH-7", DateTime.Now.ToString("yyyyMMddmmhh")); terser.Set("/MSH-9", "ACK"); terser.Set("/MSH-12", version); terser.Set("/MSA-1", ackCode == null ? "AA" : ackCode); terser.Set("/MSA-2", Terser.Get(inboundHeader, 10, 0, 1, 1)); return(ackMessage); }
public static IMessage MakeACK(IMessage inboundMessage, string ackCode) { Terser t = new Terser(inboundMessage); ISegment inboundHeader = null; try { inboundHeader = t.getSegment("MSH"); } catch (NHapi.Base.HL7Exception) { throw new NHapi.Base.HL7Exception("Need an MSH segment to create a response ACK"); } return(MakeACK(inboundHeader, ackCode)); }
internal void SetACK(AckTypes ackType, String messageString, IMessage message) { if (message == null) { SetACK(ackType, messageString); return; } Terser inboundTerser = new Terser(message); ISegment inboundHeader = inboundTerser.getSegment("MSH"); string version = null; version = message.Version; if (string.IsNullOrEmpty(version)) { try { version = Terser.Get(inboundHeader, 12, 0, 1, 1); } catch (NHapi.Base.HL7Exception he) { version = NHapi.Model.V251.Constants.VERSION; } } FillMSHSegment((ISegment)message.GetStructure("MSH"), (ISegment)hl7Ack.Message.GetStructure("MSH")); string messageTypeName = message.GetMessageType(); string acktype = HL7Parser.GetAckTypeFromRequest(messageTypeName, version); string AckID = HL7Parser.GetMessageIDFromMessageType(acktype, version); hl7Ack.SetValue("/MSH(0)-21-1", AckID); //MEssage Code if (acktype.Split('_').Length > 1) { hl7Ack.SetValue("/MSH-9-1-1", acktype.Split('_')[0]); //MEssage Code hl7Ack.SetValue("/MSH-9-2-1", acktype.Split('_')[1]); //MEssage Code } //ackTerser.Set("/MSH-12", NHapi.Model.V251.Constants.VERSION); hl7Ack.SetValue("/MSA-1", Enum.GetName(typeof(AckTypes), ackType)); string code = Terser.Get(inboundHeader, 10, 0, 1, 1); hl7Ack.SetValue("/MSA-2", Terser.Get(inboundHeader, 10, 0, 1, 1)); }
/// <summary> /// Create an Ack message based on a received message /// </summary> /// <param name="inboundMessage">received message</param> /// <param name="ackResult">Send AA, AE or AR message.</param> /// <param name="errorMessage">The reason the message was rejected or an error. If "AA" was supplied as ackCode the errorMessage should be null.</param> /// <returns>Created ACK message</returns> public IMessage MakeACK(IMessage inboundMessage, AckTypes ackResult, string errorMessage) { //this should avoid an unhandled null reference exception in "inboundMessage.Version", because people tend to send the inboudMessage without a check if (inboundMessage == null) { throw new ArgumentNullException("Either process the valid message while retreiving the ack or handle invalid message differently"); } IMessage ackMessage = null; // Get an object from the right ACK class string ackClassType = string.Format("NHapi.Model.V{0}.Message.ACK, NHapi.Model.V{0}", inboundMessage.Version.Replace(".", "")); Type x = Type.GetType(ackClassType); if (x != null) { ackMessage = (IMessage)Activator.CreateInstance(x); } else { // Fix for V2.2 and V2.1 Since tha ACK message class is missing there in NHapi if (inboundMessage.Version == "2.1") { ackMessage = (IMessage) new NHapiTools.Base.CustomImplementation.V21.Messages.ACK(); } if (inboundMessage.Version == "2.2") { ackMessage = (IMessage) new NHapiTools.Base.CustomImplementation.V22.Messages.ACK(); } } Terser inboundTerser = new Terser(inboundMessage); ISegment inboundHeader = null; inboundHeader = inboundTerser.getSegment("MSH"); // Find the HL7 version of the inbound message: string version = null; try { version = Terser.Get(inboundHeader, 12, 0, 1, 1); } catch (NHapi.Base.HL7Exception) { // I'm not happy to proceed if we can't identify the inbound // message version. throw new NHapi.Base.HL7Exception("Failed to get valid HL7 version from inbound MSH-12-1"); } // Create a Terser instance for the outbound message (the ACK). Terser terser = new Terser(ackMessage); // Populate outbound MSH fields using data from inbound message ISegment outHeader = (ISegment)terser.getSegment("MSH"); DeepCopy.copy(inboundHeader, outHeader); // Now set the message type, HL7 version number, acknowledgement code // and message control ID fields: string sendingApp = terser.Get("/MSH-3"); string sendingEnv = terser.Get("/MSH-4"); terser.Set("/MSH-3", appCommunicationName); terser.Set("/MSH-4", environmentIdentifier); terser.Set("/MSH-5", sendingApp); terser.Set("/MSH-6", sendingEnv); terser.Set("/MSH-7", DateTime.Now.ToString("yyyyMMddmmhh")); terser.Set("/MSH-9", "ACK"); terser.Set("/MSH-9-3", "ACK"); terser.Set("/MSH-12", version); terser.Set("/MSA-1", Enum.GetName(typeof(AckTypes), ackResult)); terser.Set("/MSA-2", Terser.Get(inboundHeader, 10, 0, 1, 1)); // Set error message if (errorMessage != null) { terser.Set("/ERR-1-1", errorMessage); } return(ackMessage); }
/// <summary> /// Creates a negative acknowledgement message. /// </summary> /// <param name="request">The request.</param> /// <param name="errors">The errors.</param> /// <param name="errType">Type of the error.</param> /// <returns>Returns the created negative acknowledgement message instance.</returns> public static IMessage CreateNack(IMessage request, List <IResultDetail> errors, Type errType) { var ack = errType.GetConstructor(Type.EmptyTypes).Invoke(null) as IMessage; if (errors.Any()) { tracer.TraceEvent(TraceEventType.Warning, 0, "Validation Errors:"); errors.ForEach(o => tracer.TraceEvent(TraceEventType.Error, 0, $"\t{o.Type} : {o.Message}")); } var terser = new Terser(ack); MessageUtil.UpdateMSH(terser, request); var errLevel = 0; var ec = 0; foreach (var dtl in errors) { try { ISegment errSeg; if (ack.Version == "2.5") { errSeg = terser.getSegment($"/ERR({ec++})"); } else { errSeg = terser.getSegment(string.Format("/ERR", ec++)); } if (errSeg is ERR) { var tErr = UpdateERR(errSeg as ERR, dtl); if (tErr > errLevel) { errLevel = tErr; } } else if (errSeg is NHapi.Model.V25.Segment.ERR) { var tErr = UpdateERR(errSeg as ERR, dtl); if (tErr > errLevel) { errLevel = tErr; } } } catch (Exception e) { Trace.TraceError(e.ToString()); } } terser.Set("/MSA-1", errLevel == 0 ? "AA" : errLevel == 1 ? "AE" : "AR"); return(ack); }