コード例 #1
0
        /// <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);
        }
コード例 #2
0
        /// <summary>
        /// Create an appropriate response given the results
        /// </summary>
        /// <param name="results">The results that matches the query</param>
        /// <param name="map">The HL7 query parameter mapping</param>
        /// <param name="request">The original request message</param>
        /// <param name="count">The number of results that the user requested</param>
        /// <param name="offset">The offset to the first result</param>
        /// <param name="queryId">The unique query identifier used</param>
        /// <returns>The constructed result message</returns>
        protected virtual IMessage CreateQueryResponse(Hl7MessageReceivedEventArgs request, Expression filter, Hl7QueryParameterType map, IEnumerable results, Guid queryId, int offset, int count, int totalResults)
        {
            var retVal = this.CreateACK(map.ResponseType, request.Message, "AA", "Query Success");
            var omsh   = retVal.GetStructure("MSH") as MSH;
            var qak    = retVal.GetStructure("QAK") as QAK;
            var odsc   = retVal.GetStructure("DSC") as DSC;
            var oqpd   = retVal.GetStructure("QPD") as QPD;

            DeepCopy.copy(request.Message.GetStructure("QPD") as ISegment, oqpd);
            omsh.MessageType.MessageCode.Value      = "RSP";
            omsh.MessageType.MessageStructure.Value = retVal.GetType().Name;
            omsh.MessageType.TriggerEvent.Value     = map.ResponseTrigger;
            omsh.MessageType.MessageStructure.Value = map.ResponseTypeXml;
            qak.HitCount.Value            = totalResults.ToString();
            qak.HitsRemaining.Value       = (totalResults - offset - count > 0 ? totalResults - offset - count : 0).ToString();
            qak.QueryResponseStatus.Value = totalResults == 0 ? "NF" : "OK";
            qak.ThisPayload.Value         = results.OfType <Object>().Count().ToString();

            if (ApplicationServiceContext.Current.GetService <Core.Services.IQueryPersistenceService>() != null &&
                Int32.Parse(qak.HitsRemaining.Value) > 0)
            {
                odsc.ContinuationPointer.Value = queryId.ToString();
                odsc.ContinuationStyle.Value   = "RD";
            }

            // Process results
            retVal = map.QueryHandler.AppendQueryResult(results, filter, retVal, request, map.ScoreConfiguration, offset);

            return(retVal);
        }
コード例 #3
0
        /// <summary>
        /// Append query results to the message
        /// </summary>
        public virtual IMessage AppendQueryResult(IEnumerable results, Expression queryDefinition, IMessage currentResponse, Hl7MessageReceivedEventArgs evt, String matchConfiguration = null, int offset = 0)
        {
            var patients = results.OfType <Patient>();

            if (patients.Count() == 0)
            {
                return(currentResponse);
            }
            var retVal = currentResponse as RSP_K21;

            var pidHandler         = SegmentHandlers.GetSegmentHandler("PID");
            var pd1Handler         = SegmentHandlers.GetSegmentHandler("PD1");
            var nokHandler         = SegmentHandlers.GetSegmentHandler("NK1");
            var matchService       = ApplicationServiceContext.Current.GetService <IRecordMatchingService>();
            var matchConfigService = ApplicationServiceContext.Current.GetService <IRecordMatchingConfigurationService>();

            // Return domains
            var rqo = evt.Message as QBP_Q21;
            List <AssigningAuthority> returnDomains = new List <AssigningAuthority>();

            foreach (var rt in rqo.QPD.GetField(8).OfType <Varies>())
            {
                var rid = new CX(rqo.Message);
                DeepCopy.copy(rt.Data as GenericComposite, rid);
                var authority = rid.AssigningAuthority.ToModel();
                returnDomains.Add(authority);
            }
            if (returnDomains.Count == 0)
            {
                returnDomains = null;
            }

            // Process results
            int i = offset + 1;

            foreach (var itm in patients)
            {
                var queryInstance = retVal.GetQUERY_RESPONSE(retVal.QUERY_RESPONSERepetitionsUsed);
                pidHandler.Create(itm, queryInstance, returnDomains?.ToArray());
                pd1Handler.Create(itm, queryInstance, null);
                nokHandler.Create(itm, queryInstance, null);
                queryInstance.PID.SetIDPID.Value = (i++).ToString();
                // QRI?
                if (matchService != null && !String.IsNullOrEmpty(matchConfiguration))
                {
                    var score = matchService.Score <Patient>(itm, queryDefinition as Expression <Func <Patient, bool> >, matchConfiguration);
                    queryInstance.QRI.CandidateConfidence.Value            = score.Score.ToString();
                    queryInstance.QRI.AlgorithmDescriptor.Identifier.Value = matchConfiguration;
                }
            }

            return(retVal);
        }
コード例 #4
0
ファイル: Program.cs プロジェクト: dib0/NHapiExampleApp
        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);
            }
        }
コード例 #5
0
        /// <summary>
        /// Rewrite a QPD query to an HDSI query
        /// </summary>
        public virtual NameValueCollection ParseQuery(QPD qpd, Hl7QueryParameterType map)
        {
            NameValueCollection retVal = new NameValueCollection();

            // Control of strength
            String strStrength = (qpd.GetField(4, 0) as Varies)?.Data.ToString(),
                   algorithm   = (qpd.GetField(5, 0) as Varies)?.Data.ToString();
            Double?strength    = String.IsNullOrEmpty(strStrength) ? null : (double?)Double.Parse(strStrength);

            // Query parameters
            foreach (var itm in MessageUtils.ParseQueryElement(qpd.GetField(3).OfType <Varies>(), map, algorithm, strength))
            {
                try
                {
                    retVal.Add(itm.Key, itm.Value);
                }
                catch (Exception e)
                {
                    throw new HL7ProcessingException("Error processing query parameter", "QPD", "1", 3, 0, e);
                }
            }

            // Return domains
            foreach (var rt in qpd.GetField(8).OfType <Varies>())
            {
                try
                {
                    var rid = new CX(qpd.Message);
                    DeepCopy.copy(rt.Data as GenericComposite, rid);
                    var authority = rid.AssigningAuthority.ToModel();

                    if (authority.Key == this.m_configuration.LocalAuthority.Key)
                    {
                        retVal.Add("_id", rid.IDNumber.Value);
                    }
                    else
                    {
                        retVal.Add($"identifier[{authority.DomainName}]", "!null");
                    }
                }
                catch (Exception e)
                {
                    throw new HL7ProcessingException("Error processing return domains", "QPD", "1", 8, 0, e);
                }
            }

            retVal.Add("obsoletionTime", "null");

            return(retVal);
        }
コード例 #6
0
        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);
        }
コード例 #7
0
        /// <summary>
        /// Rewrite a QPD query to an HDSI query
        /// </summary>
        public virtual NameValueCollection ParseQuery(QPD qpd, Hl7QueryParameterType map)
        {
            NameValueCollection retVal = new NameValueCollection();

            // Query domains
            foreach (var rt in qpd.GetField(3).OfType <Varies>())
            {
                try
                {
                    var rid = new CX(qpd.Message);
                    DeepCopy.copy(rt.Data as GenericComposite, rid);
                    var authority = rid.AssigningAuthority.ToModel();

                    if (authority.Key == m_configuration.LocalAuthority.Key)
                    {
                        retVal.Add("_id", rid.IDNumber.Value);
                    }
                    else
                    {
                        retVal.Add($"identifier[{authority.DomainName}].value", rid.IDNumber.Value);
                    }
                }
                catch (Exception e)
                {
                    throw new HL7ProcessingException("Error processing patient identity", "QPD", "1", 3, 4, e);
                }
            }


            //// Return domains
            // This just verifies the return domains
            foreach (var rt in qpd.GetField(4).OfType <Varies>())
            {
                try
                {
                    var rid = new CX(qpd.Message);
                    DeepCopy.copy(rt.Data as GenericComposite, rid);
                    var authority = rid.AssigningAuthority.ToModel();
                }
                catch (Exception e)
                {
                    throw new HL7ProcessingException("Error processing what domains returned", "QPD", "1", 4, 4, e);
                }
            }


            return(retVal);
        }
コード例 #8
0
ファイル: Ack.cs プロジェクト: shakenfwz/NHapiTools
        /// <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);
        }
コード例 #9
0
        /// <summary>
        /// Append query results to the message
        /// </summary>
        public virtual IMessage AppendQueryResult(IEnumerable results, Expression queryDefinition, IMessage currentResponse, Hl7MessageReceivedEventArgs evt, String matchConfiguration = null, int offset = 0)
        {
            var patients = results.OfType <Patient>();

            if (patients.Count() == 0)
            {
                return(currentResponse);
            }
            var retVal = currentResponse as RSP_K23;
            var rqo    = evt.Message as QBP_Q21;

            // Return domains
            List <AssigningAuthority> returnDomains = new List <AssigningAuthority>();

            foreach (var rt in rqo.QPD.GetField(4).OfType <Varies>())
            {
                var rid = new CX(rqo.Message);
                DeepCopy.copy(rt.Data as GenericComposite, rid);
                var domain = rid.AssigningAuthority.ToModel();
                returnDomains.Add(domain);
            }

            var matchService       = ApplicationServiceContext.Current.GetService <IRecordMatchingService>();
            var matchConfigService = ApplicationServiceContext.Current.GetService <IRecordMatchingConfigurationService>();

            // Process results
            int i = offset + 1;

            foreach (var itm in patients)
            {
                var queryInstance = retVal.QUERY_RESPONSE;

                // Expose PK?
                if (returnDomains.Count == 0 || returnDomains.Any(d => d.Key == this.m_configuration.LocalAuthority.Key))
                {
                    queryInstance.PID.GetPatientIdentifierList(queryInstance.PID.PatientIdentifierListRepetitionsUsed).FromModel(new EntityIdentifier(this.m_configuration.LocalAuthority, itm.Key.ToString()));
                    queryInstance.PID.GetPatientIdentifierList(queryInstance.PID.PatientIdentifierListRepetitionsUsed - 1).IdentifierTypeCode.Value = "PI";
                }

                foreach (var id in itm.LoadCollection <EntityIdentifier>("Identifiers"))
                {
                    if (returnDomains.Count == 0 || returnDomains.Any(o => o.Key == id.AuthorityKey))
                    {
                        queryInstance.PID.GetPatientIdentifierList(queryInstance.PID.PatientIdentifierListRepetitionsUsed).FromModel(id);
                    }
                }

                if (returnDomains.Any(rid => rid.Key == this.m_configuration.LocalAuthority.Key))
                {
                    int idx = queryInstance.PID.PatientIdentifierListRepetitionsUsed;
                    queryInstance.PID.GetPatientIdentifierList(idx).IDNumber.Value = itm.Key.Value.ToString();
                    queryInstance.PID.GetPatientIdentifierList(idx).AssigningAuthority.NamespaceID.Value     = this.m_configuration.LocalAuthority.DomainName;
                    queryInstance.PID.GetPatientIdentifierList(idx).AssigningAuthority.UniversalID.Value     = this.m_configuration.LocalAuthority.Oid;
                    queryInstance.PID.GetPatientIdentifierList(idx).AssigningAuthority.UniversalIDType.Value = "ISO";
                }

                // No identifiers found in the response domains
                if (queryInstance.PID.PatientIdentifierListRepetitionsUsed > 0)
                {
                    queryInstance.PID.SetIDPID.Value = (i++).ToString();
                    queryInstance.PID.GetPatientName(0).NameTypeCode.Value = "S";
                }
                else
                {
                    (currentResponse.GetStructure("QAK") as QAK).HitCount.Value            = "0";
                    (currentResponse.GetStructure("QAK") as QAK).HitsRemaining.Value       = "0";
                    (currentResponse.GetStructure("QAK") as QAK).ThisPayload.Value         = "0";
                    (currentResponse.GetStructure("QAK") as QAK).QueryResponseStatus.Value = "NF";
                }
            }


            return(retVal);
        }