/// <summary>
        ///实现处理的接口
        /// </summary>
        /// <param name="message">传入的消息字符</param>
        /// <returns></returns>
        public string Process(string message)
        {
            IMessage m = null;

            try
            {
                m = parser.Parse(message);
            }
            catch (Exception ex)
            {
                //MediII.Common.LogHelper.LogError(string.Format("消息消息失败,传入消息为:\n\r{0}",message),LogCatagories.AdapterBiz);
                string sendingApp = System.Configuration.ConfigurationManager.AppSettings["SedingApplication"];
                string recvApp    = "MediII";
                string ackMsg     = MediII.Common.MessageHelper.SetACK("ACK", "", "", sendingApp, sendingApp,
                                                                       recvApp, recvApp, "123456789", ex.Message);
                return(ackMsg);
            }
            ISegment msh       = (ISegment)m.GetStructure("MSH");
            string   messageID = Terser.Get(msh, 10, 0, 1, 1);
            string   guid      = MediII.Common.GUIDHelper.NewGUID();

            OnProcessing(guid, messageID, message);
            string ack = DoProcess(m);

            OnProcessed(guid, parser.GetAckID(ack), ack, true);
            return(ack);
        }
Exemple #2
0
        /// Create an Ack message based on a received message///
        /// received message///
        /// Acknowlegde code///
        /// Message to be created///
        /// Created message
        public string MakeACK(string AckHead, string version, string ackCode, IMessage ackMessage)
        {
            // Create a Terser instance for the outbound message (the ACK).
            Terser terser = new Terser(ackMessage);

            // Populate outbound MSH fields using data from inbound message


            // 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");
            string CommunicationNameOfThisApplication     = string.Empty;
            string EnvironmentIdentifierOfThisApplication = string.Empty;

            terser.Set("/MSH-3", CommunicationNameOfThisApplication);
            terser.Set("/MSH-4", EnvironmentIdentifierOfThisApplication);
            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);
            // The ackCode should be "AA" if the message was correctly handled and "AE" if there was an error
            terser.Set("/MSA-1", ackCode == null ? "AA" : ackCode);
            terser.Set("/MSA-2", AckHead);


            return(PipeParser.Encode(ackMessage, new EncodingCharacters('|', '^', '~', '\\', '&')));
        }
Exemple #3
0
        /// <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));
            }
        }
Exemple #4
0
        public void Parse_UnknownMessageType_ReturnsGenericMessage(string version, Type expectedType)
        {
            // Arrange
            // a valid ORU_R01 message in which MSH-9 has been changed
            var input = $"MSH|^~\\&|LABGL1||DMCRES||19951002185200||ZZZ^ZZZ|LABGL1199510021852632|P|{version}\r"
                        + "PID|||T12345||TEST^PATIENT^P||19601002|M||||||||||123456\r"
                        + "PV1|||NER|||||||GSU||||||||E||||||||||||||||||||||||||19951002174900|19951006\r"
                        + "OBR|1||09527539437000040|7000040^ETHANOL^^^ETOH|||19951002180500|||||||19951002182500||||1793561||0952753943||19951002185200||100|F||^^^^^RT\r"
                        + "OBX||NM|7000040^ETHANOL^^^ETOH|0001|224|mg/dL|||||F|||19951002185200||182\r"
                        + "NTE|||          Reference Ranges\r" + "NTE|||          ****************\r"
                        + "NTE|||           Normal:              Negative\r"
                        + "NTE|||           Toxic Concentration: >80 mg/dL\r";

            var expectedMsh5 = "DMCRES";
            var expectedObx2 = "NM";

            var sut = new PipeParser();

            // Act
            var message = sut.Parse(input);

            sut.Encode(message);

            var terser = new Terser(message);

            // Assert
            Assert.AreEqual(expectedType, message.GetType());
            Assert.AreEqual(expectedMsh5, terser.Get("/MSH-5"));
            Assert.AreEqual(expectedObx2, terser.Get("/OBX-2"));
        }
Exemple #5
0
        private void FillMSHSegment(ISegment mshIn, ISegment mshOut)
        {
            if (mshOut == null)
            {
                throw new System.Exception("mshout");
            }

            Guid g = Guid.NewGuid();

            Terser.Set(mshIn, 7, 0, 1, 1, DateTime.Now.ToString("yyyyMMddHHmmss"));
            Terser.Set(mshIn, 7, 0, 1, 1, DateTime.Now.ToString("yyyyMMddHHmmss"));

            if (mshIn == null)
            {
                Terser.Set(mshIn, 3, 0, 1, 1, "");
                Terser.Set(mshIn, 4, 0, 1, 1, "");
                Terser.Set(mshIn, 5, 0, 1, 1, "");
                Terser.Set(mshIn, 6, 0, 1, 1, "");
                Terser.Set(mshIn, 9, 0, 1, 1, "ACK");
            }
            else
            {
                Terser.Set(mshIn, 3, 0, 1, 1, Terser.Get(mshIn, 5, 0, 1, 1));
                Terser.Set(mshIn, 4, 0, 1, 1, Terser.Get(mshIn, 6, 0, 1, 1));
                Terser.Set(mshIn, 5, 0, 1, 1, Terser.Get(mshIn, 3, 0, 1, 1));
                Terser.Set(mshIn, 6, 0, 1, 1, Terser.Get(mshIn, 4, 0, 1, 1));
                Terser.Set(mshIn, 9, 0, 1, 1, Terser.Get(mshIn, 9, 0, 1, 1));
                Terser.Set(mshIn, 9, 0, 2, 1, Terser.Get(mshIn, 9, 0, 2, 1));
            }
        }
Exemple #6
0
        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());
        }
        public override bool Send(IMessage msg)
        {
            bool result = true;

            EditMessageHeader(msg);

            try
            {
                PipeParser    parser     = new PipeParser();
                string        res        = SendRequest(parser.Encode(msg));
                IMessage      response   = parser.Parse(res);
                HLMessageToDB hl7message = new HLMessageToDB();
                hl7message.HL7MessageToDB(Convert.ToString(msg));
                Terser terser  = new Terser(response);
                string ackCode = terser.Get("/MSA-1");
                result = (ackCode == "AA");
            }
            catch (Exception ex)
            {
                Logger.ErrorFormat("Error in delivering message '{0}' to Http endpoint with uri '{1}'. Error: {2}", msg.GetStructureName(), serverUri, ex.Message);
                result = false;
            }

            return(result);
        }
Exemple #8
0
        /// <summary>
        /// Creates a negative acknowledgement message.
        /// </summary>
        /// <param name="request">The request message to use to create the response message.</param>
        /// <param name="responseCode">The response code of the message.</param>
        /// <param name="errCode">The error code of the message.</param>
        /// <param name="errDescription">The error description of the message.</param>
        /// <returns>Returns the created negative acknowledgement message instance.</returns>
        public static IMessage CreateNack(IMessage request, string responseCode, string errCode, string errDescription)
        {
            MessageUtil.tracer.TraceEvent(TraceEventType.Warning, 0, $"NACK Condition : {errDescription}");

            if (request.Version == "2.3.1")
            {
                var ack = new ACK();

                var terser = new Terser(ack);

                terser.Set("/MSA-1", responseCode);
                terser.Set("/MSA-3", "Error occurred");
                terser.Set("/MSA-6-1", errCode);
                terser.Set("/MSA-6-2", errDescription);

                UpdateMSH(terser, request);

                return(ack);
            }
            else
            {
                var ack = new NHapi.Model.V25.Message.ACK();

                var terser = new Terser(ack);

                terser.Set("/MSA-1", responseCode);

                UpdateMSH(terser, request);

                terser.Set("/ERR-3-1", errCode);
                terser.Set("/ERR-3-2", errDescription);

                return(ack);
            }
        }
Exemple #9
0
        public void TestMultiArg()
        {
            var msh  = suiS12.MSH;
            var test = Terser.Get(msh, 9, 0, 2, 1);

            Assert.AreEqual("a", test);
        }
Exemple #10
0
        /// <summary> Populates the given error segment with information from this Exception.</summary>
        // TODO: this is out of sync with hapi see
        // https://github.com/hapifhir/hapi-hl7v2/blob/809516e3f4851d7cd97573efb6dedf24959a1063/hapi-base/src/main/java/ca/uhn/hl7v2/AbstractHL7Exception.java#L134
        public virtual void populate(ISegment errorSegment)
        {
            //make sure it's an ERR
            if (!errorSegment.GetStructureName().Equals("ERR"))
            {
                throw new HL7Exception("Can only populate an ERR segment with an exception -- got: " +
                                       errorSegment.GetType().FullName);
            }

            var rep = errorSegment.GetField(1).Length;             //append after existing reps

            if (SegmentName != null)
            {
                Terser.Set(errorSegment, 1, rep, 1, 1, SegmentName);
            }


            if (SegmentRepetition >= 0)
            {
                Terser.Set(errorSegment, 1, rep, 2, 1, Convert.ToString(SegmentRepetition));
            }


            if (FieldPosition >= 0)
            {
                Terser.Set(errorSegment, 1, rep, 3, 1, Convert.ToString(FieldPosition));
            }

            Terser.Set(errorSegment, 1, rep, 4, 1, Convert.ToString(ErrorCode));
            // this replaces the need to connect to the database
            Terser.Set(errorSegment, 1, rep, 4, 2, ErrorCode.GetName());
            Terser.Set(errorSegment, 1, rep, 4, 3, "hl70357");
            Terser.Set(errorSegment, 1, rep, 4, 5, Message);
        }
Exemple #11
0
        public bool Match(IMessage message)
        {
            bool result = false;

            result = Compare(Hl7Version, message.Version);
            if (result)
            {
                // Dib0 20150125: Changed the compare. This method doesn't work with messages
                // that are parsed as generic messages
                //result = Compare(Structurename, message.GetStructureName());

                Terser terser      = new Terser(message);
                string messageType = string.Format("{0}_{1}", terser.Get("MSH-9-1"), terser.Get("MSH-9-2"));

                result = Compare(Structurename, messageType);
            }

            // Check the field filter
            if (result)
            {
                result = CheckFieldFilter(message);
            }

            return(result);
        }
Exemple #12
0
        /// <summary> Fills a field with values from an unparsed string representing the field.  </summary>
        /// <param name="destinationField">the field Type
        /// </param>
        /// <param name="data">the field string (including all components and subcomponents; not including field delimiters)
        /// </param>
        /// <param name="encodingCharacters">the encoding characters used in the message
        /// </param>
        private static void Parse(IType destinationField, String data, EncodingCharacters encodingCharacters)
        {
            String[] components = Split(data, Convert.ToString(encodingCharacters.ComponentSeparator));
            for (int i = 0; i < components.Length; i++)
            {
                int index = i + 1;

                if (components[i] != null && (Terser.isPrimitive(destinationField, index) &&
                                              components[i].Contains(Convert.ToString(encodingCharacters.SubcomponentSeparator))))
                {   // sometimes someone sends us bad data and if the destinition is a primitive we should escape what needs to be escaped
                    components[i] = Escape.escape(components[i], encodingCharacters);
                }

                String[] subcomponents = Split(components[i], Convert.ToString(encodingCharacters.SubcomponentSeparator));
                for (int j = 0; j < subcomponents.Length; j++)
                {
                    String val = subcomponents[j];
                    if (val != null)
                    {
                        val = Escape.unescape(val, encodingCharacters);
                    }
                    Terser.getPrimitive(destinationField, index, j + 1).Value = val;
                }
            }
        }
        /// <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);
        }
Exemple #14
0
        /// <summary>
        /// Create a PDQ search message
        /// </summary>
        /// <param name="filters">The parameters for query</param>
        private QBP_Q21 CreatePDQSearch(int offset, int count, object state, params KeyValuePair <String, String>[] filters)
        {
            // Search - Construct a v2 message this is found in IHE ITI TF-2:3.21
            QBP_Q21 message = new QBP_Q21();

            this.UpdateMSH(message.MSH, "QBP_Q21", "QBP", "Q22");
            //message.MSH.VersionID.VersionID.Value = "2.3.1";

            // Message query
            message.QPD.MessageQueryName.Identifier.Value             = "Patient Demographics Query";
            message.DSC.ContinuationPointer.Value                     = state?.ToString();
            message.RCP.QuantityLimitedRequest.Quantity.Value         = count.ToString();
            message.RCP.QuantityLimitedRequest.Units.Identifier.Value = "RD";

            // Sometimes it is easier to use a terser
            Terser terser = new Terser(message);

            terser.Set("/QPD-2", Guid.NewGuid().ToString());    // Tag of the query
            terser.Set("/QPD-1", "Patient Demographics Query"); // Name of the query
            for (int i = 0; i < filters.Length; i++)
            {
                terser.Set(String.Format("/QPD-3({0})-1", i), filters[i].Key);
                terser.Set(String.Format("/QPD-3({0})-2", i), filters[i].Value);
            }

            return(message);
        }
Exemple #15
0
        public void GetPrimitive_SubComponentIsLessThen0_ArgumentOutOfRangeException()
        {
            var type = suiS12.MSH.MessageType;

            Assert.Throws <ArgumentOutOfRangeException>(
                () => Terser.GetPrimitive(type, 0, -1));
        }
Exemple #16
0
        public void Get_RepIsLessThan0_ThrowsArgumentOutOfRangeException()
        {
            var segment = suiS12.MSH;

            Assert.Throws <ArgumentOutOfRangeException>(
                () => Terser.Get(segment, 0, -1, 0, 0));
        }
Exemple #17
0
        internal IHL7Message DoParse(IMessage message)
        {
            if (message == null)
            {
                throw new HL7apiException("Cannot parse an invalid message");
            }

            IHL7Message ret = null;

            Terser t = new Terser(message);


            string messageID = t.Get("/MSH-21(0)-1-1");

            if (string.IsNullOrEmpty(messageID))
            {
                messageID = GetMessageIDFromMessageType(message.GetMessageType(), message.Version);
                if (string.IsNullOrEmpty(messageID))
                {
                    throw new HL7apiException("Invalid Message type");
                }
            }

            ret = (IHL7Message)InstantiateMessage(messageID, message.Version, message);

            return(ret);
        }
Exemple #18
0
 /// <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");
 }
        /// <summary>
        /// Create NACK
        /// </summary>
        internal static IMessage CreateNack(IMessage request, string responseCode, string errCode, string errDescription, ISystemConfigurationService config)
        {
            System.Diagnostics.Trace.TraceWarning(String.Format("NACK Condition : {0}", errDescription));

            if (request.Version == "2.3.1")
            {
                NHapi.Model.V231.Message.ACK ack = new NHapi.Model.V231.Message.ACK();
                Terser terser = new Terser(ack);
                terser.Set("/MSA-1", responseCode);
                terser.Set("/MSA-3", "Error occurred");
                terser.Set("/MSA-6-1", errCode);
                terser.Set("/MSA-6-2", errDescription);
                MessageUtil.UpdateMSH(terser, request, config);
                return(ack);
            }
            else
            {
                NHapi.Model.V25.Message.ACK ack = new NHapi.Model.V25.Message.ACK();
                Terser terser = new Terser(ack);
                terser.Set("/MSA-1", responseCode);
                MessageUtil.UpdateMSH(terser, request, config);
                terser.Set("/ERR-3-1", errCode);
                terser.Set("/ERR-3-2", errDescription);
                return(ack);
            }
        }
        /// <summary>
        /// Set request message parameters
        /// </summary>
        protected void SetRequestMessageParams(NHapi.Base.Model.IMessage request)
        {
            Terser setTerser = new Terser(request);

            setTerser.Set("/MSH-7", DateTime.Now.ToString("yyyyMMddHHmmss"));
            setTerser.Set("/EVN-2", DateTime.Today.ToString("yyyyMMdd"));
        }
Exemple #21
0
        /// <summary>   Validates the given message. </summary>
        ///
        /// <exception cref="HL7Exception"> Thrown when a HL 7 error condition occurs. </exception>
        ///
        /// <param name="message">  a parsed message to validate (note that MSH-9-1 and MSH-9-2 must be
        ///                         valued) </param>
        ///
        /// <returns>   true if the message is OK. </returns>

        public virtual bool validate(IMessage message)
        {
            Terser t = new Terser(message);

            IMessageRule[] rules = this.myContext.getMessageRules(message.Version, t.Get("MSH-9-1"), t.Get("MSH-9-2"));

            ValidationException toThrow = null;
            bool result = true;

            for (int i = 0; i < rules.Length; i++)
            {
                ValidationException[] ex = rules[i].test(message);
                for (int j = 0; j < ex.Length; j++)
                {
                    result = false;
                    ourLog.Error("Invalid message", ex[j]);
                    if (this.failOnError && toThrow == null)
                    {
                        toThrow = ex[j];
                    }
                }
            }

            if (toThrow != null)
            {
                throw new HL7Exception("Invalid message", toThrow);
            }

            return(result);
        }
Exemple #22
0
        public void UnEscapesData()
        {
            // Arrange
            const string content = @"MSH|^~\&|TestSys|432^testsys practice|TEST||201402171537||MDM^T02|121906|P|2.3.1||||||||
OBX|1|TX|PROBLEM FOCUSED^PROBLEM FOCUSED^test|1|\T\#39;Thirty days have September,\X000d\April\X0A\June,\X0A\and November.\X0A\When short February is done,\E\X0A\E\all the rest have\T\nbsp;31.\T\#39";

            var parser = new PipeParser();
            var msg    = parser.Parse(content);


            // Act
            var segment     = msg.GetStructure("OBX") as ISegment;
            var idx         = Terser.getIndices("OBX-5");
            var segmentData = Terser.Get(segment, idx[0], idx[1], idx[2], idx[3]);

            // Assert

            // verify that data was properly unescaped by NHapi
            // \E\X0A\E\ should be escaped to \X0A\
            // \X0A\ should be unescaped to \n
            // \X000d\ should be unescaped to \r
            // \t\ should be unescaped to &


            const string expectedResult =
                "&#39;Thirty days have September,\rApril\nJune,\nand November.\nWhen short February is done,\\X0A\\all the rest have&nbsp;31.&#39";

            Assert.AreEqual(expectedResult, segmentData);
        }
Exemple #23
0
        /// <summary>
        /// Returns given <see cref="IType"/> as a pipe-encoded string, using the given encoding characters.
        /// <para>
        /// It is assumed that the Type represents a complete field rather than a component.
        /// </para>
        /// </summary>
        /// <param name="source">An <see cref="IType"/> object from which to construct an encoded string.</param>
        /// <param name="encodingChars">Encoding characters to be used.</param>
        /// <returns>The encoded type.</returns>
        /// <exception cref="HL7Exception">Thrown if the data fields in the group do not permit encoding (e.g. required fields are null).</exception>
        /// <exception cref="EncodingNotSupportedException">Thrown if the requested encoding is not supported by this parser.</exception>
        public static string Encode(IType source, EncodingCharacters encodingChars)
        {
            if (source is Varies)
            {
                var varies = (Varies)source;
                if (varies.Data != null)
                {
                    source = varies.Data;
                }
            }

            var field = new StringBuilder();

            for (var i = 1; i <= Terser.NumComponents(source); i++)
            {
                var comp = new StringBuilder();
                for (var j = 1; j <= Terser.NumSubComponents(source, i); j++)
                {
                    var p = Terser.GetPrimitive(source, i, j);
                    comp.Append(EncodePrimitive(p, encodingChars));
                    comp.Append(encodingChars.SubcomponentSeparator);
                }

                field.Append(StripExtraDelimiters(comp.ToString(), encodingChars.SubcomponentSeparator));
                field.Append(encodingChars.ComponentSeparator);
            }

            return(StripExtraDelimiters(field.ToString(), encodingChars.ComponentSeparator));
        }
Exemple #24
0
        private EncodingCharacters GetValidEncodingCharacters(char fieldSep, ISegment msh)
        {
            var encCharString = Terser.Get(msh, 2, 0, 1, 1);

            if (encCharString == null)
            {
                // cdc: This was breaking when trying to construct a blank message, and there is no way to set the EncChars, so fill in a default
                // throw new HL7Exception("Can't encode message: MSH-2 (encoding characters) is missing");
                encCharString = @"^~\&";
                Terser.Set(msh, 2, 0, 1, 1, encCharString);
            }

            var version27 = "2.7";

            if (string.CompareOrdinal(version27, msh.Message.Version) > 0 && encCharString.Length != 4)
            {
                throw new HL7Exception(
                          $"Encoding characters (MSH-2) value '{encCharString}' invalid -- must be 4 characters", ErrorCode.DATA_TYPE_ERROR);
            }

            if (encCharString.Length != 4 && encCharString.Length != 5)
            {
                throw new HL7Exception(
                          $"Encoding characters (MSH-2) value '{encCharString}' invalid -- must be 4 or 5 characters", ErrorCode.DATA_TYPE_ERROR);
            }

            return(new EncodingCharacters(fieldSep, encCharString));
        }
        public static String GetHL7Event(String message)
        {
            var parser        = new NHapi.Base.Parser.PipeParser();
            var parsedMessage = parser.Parse(message);

            //Terse it!
            Terser terser = new Terser(parsedMessage);

            //Grab RequiredFields

            string sEventType   = terser.Get("/MSH-9-1");
            string sMessageType = terser.Get("/MSH-9-2");


            //Get the message type and trigger event
            var msgType = parsedMessage.GetStructureName();

            //Console.WriteLine("msg type = {0}", sMessageType); // = ADT_EVENT

            //Get the message in raw, pipe-delimited format
            var pipeDelimitedMessage = parser.Encode(parsedMessage);


            //Console.WriteLine("msg = {0}", pipeDelimitedMessage);

            return(sMessageType); //msgType; //pipeDelimitedMessage;
        }
        public void ProcessA01(string sHL7)
        {
            var parser        = new NHapi.Base.Parser.PipeParser();
            var parsedMessage = parser.Parse(sHL7);
            var a01           = parsedMessage as ADT_A01;

            string sPtName = "";

            //Terser terser;

            Terser terser = new Terser(parsedMessage);


            sPtName = terser.Get("/PID-5");
            string sFName = terser.Get("/PID-5-2");
            string sLName = terser.Get("/PID-5-1");

            //attempt parsing of a field that does not exist in transaction
            string sPatientID = terser.Get("/PID-1");

            Console.WriteLine("Patient First Name = {0}", sFName);
            Console.WriteLine("Patient Last Name = {0}", sLName);



            //var patientMR = a01.PID.PatientID.IDNumber.Value;
            //var patientAcctNo= a01.PID.PatientAccountNumber.IDNumber.Value;
            //var patientName = a01.PID.GetPatientName(0);
            //string sLName = patientName.FamilyName.Surname.Value;
            //string sFName = patientName.GivenName.Value;

            //Console.WriteLine("Patient FName = {0}", sFName);
        }
Exemple #27
0
        /// <summary>
        /// Test
        /// </summary>
        /// <param name="msg"></param>
        /// <returns></returns>
        public override ValidationException[] test(NHapi.Base.Model.IMessage msg)
        {
            ValidationException[] result = new ValidationException[0];

            foreach (MessageFieldMandatoryRuleElement rule in mandatoryRules)
            {
                bool flag1 = (rule.Version == "*") || (msg.Version == rule.Version);

                string   structureName = msg.GetStructureName();
                string[] sNames        = structureName.Split('_');
                bool     flag2         = (rule.MessageType == "*") || (sNames[0] == rule.MessageType);
                bool     flag3         = (rule.TriggerEvent == "*") || (sNames[1] == rule.TriggerEvent);

                if (flag1 && flag2 && flag3)
                {
                    Terser terser = new Terser(msg);
                    string value  = terser.Get(rule.FieldIndicator);
                    if (string.IsNullOrEmpty(value))
                    {
                        result = new ValidationException[1] {
                            new ValidationException(string.Format("Field '{1}' is mandatory.", value, rule.FieldIndicator))
                        };
                    }
                }

                if (result.Length > 0)
                {
                    break;
                }
            }

            return(result);
        }
Exemple #28
0
        /// <summary> <p>Returns a minimal amount of data from a message string, including only the
        /// data needed to send a response to the remote system.  This includes the
        /// following fields:
        /// <ul><li>field separator</li>
        /// <li>encoding characters</li>
        /// <li>processing ID</li>
        /// <li>message control ID</li></ul>
        /// This method is intended for use when there is an error parsing a message,
        /// (so the Message object is unavailable) but an error message must be sent
        /// back to the remote system including some of the information in the inbound
        /// message.  This method parses only that required information, hopefully
        /// avoiding the condition that caused the original error.  The other
        /// fields in the returned MSH segment are empty.</p>
        /// </summary>
        public override ISegment GetCriticalResponseData(String message)
        {
            //try to get MSH segment
            int locStartMSH = message.IndexOf("MSH");

            if (locStartMSH < 0)
            {
                throw new HL7Exception("Couldn't find MSH segment in message: " + message, ErrorCode.SEGMENT_SEQUENCE_ERROR);
            }
            int locEndMSH = message.IndexOf('\r', locStartMSH + 1);

            if (locEndMSH < 0)
            {
                locEndMSH = message.Length;
            }
            String mshString = message.Substring(locStartMSH, (locEndMSH) - (locStartMSH));

            //find out what the field separator is
            char fieldSep = mshString[3];

            //get field array
            String[] fields = Split(mshString, Convert.ToString(fieldSep));

            ISegment msh = null;

            try
            {
                //parse required fields
                String   encChars      = fields[1];
                char     compSep       = encChars[0];
                String   messControlID = fields[9];
                String[] procIDComps   = Split(fields[10], Convert.ToString(compSep));

                //fill MSH segment
                String version = "2.4";                 //default
                try
                {
                    version = GetVersion(message);
                }
                catch (Exception)
                {
                    /* use the default */
                }

                msh = MakeControlMSH(version, Factory);
                Terser.Set(msh, 1, 0, 1, 1, Convert.ToString(fieldSep));
                Terser.Set(msh, 2, 0, 1, 1, encChars);
                Terser.Set(msh, 10, 0, 1, 1, messControlID);
                Terser.Set(msh, 11, 0, 1, 1, procIDComps[0]);
            }
            catch (Exception e)
            {
                SupportClass.WriteStackTrace(e, Console.Error);
                throw new HL7Exception(
                          "Can't parse critical fields from MSH segment (" + e.GetType().FullName + ": " + e.Message + "): " + mshString,
                          ErrorCode.REQUIRED_FIELD_MISSING);
            }

            return(msh);
        }
Exemple #29
0
        public static string GetMessageType(this IMessage message)
        {
            ISegment msh         = (ISegment)message.GetStructure("MSH");
            string   messageType = $"{Terser.Get(msh, 9, 0, 1, 1)}" +
                                   $"_{Terser.Get(msh, 9, 0, 2, 1)}";

            return(messageType);
        }
Exemple #30
0
        private static void TerserMessageHL7()
        {
            var stringMessage = File.ReadAllText(
                @"N:\hl7-master\hl7-master\Test HL7 Message Files\FileWithObservationResultMessage.txt");

            // instantiate a PipeParser, which handles the normal HL7 encoding
            var pipeParser = new PipeParser();

            // parse the message string into a message object
            var orderResultHl7Message = pipeParser.Parse(stringMessage);

            // create a terser object instance by wrapping it around the message object
            var terser = new Terser(orderResultHl7Message);

            var terserHelper = new TerserHelper(terser);

            var terserExpression = "/.MSH-6";
            var dataRetrieved    = terserHelper.GetData(terserExpression);

            LogToDebugConsole($"Field 6 of MSH segment using expression '{terserExpression}' was '{dataRetrieved}'");

            terserExpression = "/.PID-5-2"; // notice the /. to indicate relative position to root node
            dataRetrieved    = terserHelper.GetData(terserExpression);
            LogToDebugConsole($"Field 5 and Component 2 of the PID segment using expression '{terserExpression}' was {dataRetrieved}'");

            terserExpression = "/.*ID-5-2";
            dataRetrieved    = terserHelper.GetData(terserExpression);
            LogToDebugConsole($"Field 5 and Component 2 of the PID segment using wildcard-based expression '{terserExpression}' was '{dataRetrieved}'");

            terserExpression = "/.P?D-5-2";
            dataRetrieved    = terserHelper.GetData(terserExpression);
            LogToDebugConsole($"Field 5 and Component 2 of the PID segment using another wildcard-based expression '{terserExpression}' was '{dataRetrieved}'");


            terserExpression = "/.PV1-9(1)"; // note: field repetitions are zero-indexed
            dataRetrieved    = terserHelper.GetData(terserExpression);
            LogToDebugConsole($"2nd repetition of Field 9 and Component 1 for it in the PV1 segment using expression '{terserExpression}' was '{dataRetrieved}'");

            terserExpression = "/RESPONSE/PATIENT/PID-5-1";
            dataRetrieved    = terserHelper.GetData(terserExpression);
            LogToDebugConsole($"Terser expression  '{terserExpression}' yielded '{dataRetrieved}'");

            terserExpression = "/RESPONSE/PATIENT/VISIT/PV1-9-3";
            dataRetrieved    = terserHelper.GetData(terserExpression);
            LogToDebugConsole($"Terser expression '{terserExpression}' yielded '{dataRetrieved}'");

            terserExpression = "/RESPONSE/ORDER_OBSERVATION(0)/ORC-12-3";
            dataRetrieved    = terserHelper.GetData(terserExpression);
            LogToDebugConsole($"Terser expression '{terserExpression}' yielded '{dataRetrieved}'");

            //let us now try a set operation using the terser
            terserExpression = "/.OBSERVATION(0)/NTE-3";
            terserHelper.SetData(terserExpression, "This is our override value using the setter");
            LogToDebugConsole("Set the data for second repetition of the NTE segment and its Third field..");

            LogToDebugConsole("\nWill display our modified message below \n");
            LogToDebugConsole(pipeParser.Encode(orderResultHl7Message));
        }