/// <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);
        }
        /// <summary>
        /// Append query results to the message
        /// </summary>
        public virtual IMessage AppendQueryResult(IEnumerable results, Expression queryDefinition, IMessage currentResponse, Hl7MessageReceivedEventArgs evt, 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;
            IEnumerable <dynamic> resultScores = patients.Select(o => new { Patient = o, WasScored = false });

            if (this.m_scoringService != null)
            {
                resultScores = this.m_scoringService.Score <Patient>(queryDefinition as Expression <Func <Patient, bool> >, patients).Select(o => new
                {
                    Patient   = o.Result,
                    Score     = o.Score,
                    Method    = o.Method,
                    WasScored = true
                });
            }

            foreach (var itm in resultScores)
            {
                var queryInstance = retVal.GetQUERY_RESPONSE(retVal.QUERY_RESPONSERepetitionsUsed);

                pidHandler.Create(itm.Patient, queryInstance, returnDomains?.ToArray());
                pd1Handler.Create(itm.Patient, queryInstance, null);
                nokHandler.Create(itm.Patient, queryInstance, null);
                queryInstance.PID.SetIDPID.Value = (i++).ToString();

                if (itm.WasScored)
                {
                    queryInstance.QRI.CandidateConfidence.Value = itm.Score.ToString();
                    switch ((RecordMatchMethod)itm.Method)
                    {
                    case RecordMatchMethod.Identifier:
                        queryInstance.QRI.GetMatchReasonCode(0).Value = "SS";
                        break;

                    case RecordMatchMethod.Simple:
                        queryInstance.QRI.GetMatchReasonCode(0).Value = "NA";
                        break;

                    case RecordMatchMethod.Weighted:
                        queryInstance.QRI.GetMatchReasonCode(0).Value = "NP";
                        break;
                    }
                    queryInstance.QRI.AlgorithmDescriptor.Identifier.Value = this.m_scoringService.ServiceName;
                }
                else
                {
                    queryInstance.QRI.CandidateConfidence.Value            = "1.0";
                    queryInstance.QRI.AlgorithmDescriptor.Identifier.Value = "PTNM";
                }
            }

            return(retVal);
        }
        /// <summary>
        /// Represents when the ADT registration occurs
        /// </summary>
        protected void AdtPatientRegistrationInterceptor_Behavior(object sender, DataPersistedEventArgs <Patient> e)
        {
            ApplicationServiceContext.Current.GetService <IThreadPoolService>().QueueNonPooledWorkItem(
                (p) =>
            {
                AuthenticationContext.Current = new AuthenticationContext(AuthenticationContext.SystemPrincipal);

                Patient pat = p as Patient;
                // We want to construct an ADT message if (and only if) the guards are met and if the last ADT was not this version
                var tag = pat.LoadCollection <EntityTag>("Tags").FirstOrDefault(o => o.TagKey == TagName);

                if (tag?.Value == e.Data.VersionKey.ToString())
                {
                    return;     // No need
                }
                else if (base.ExecuteGuard(pat))
                {
                    // Perform notification
                    IMessage notificationMessage;
                    IGroup patientGroup;

                    if (tag?.Value == null)
                    {
                        // Set the tag value and send an ADMIT
                        patientGroup = notificationMessage = new ADT_A01();
                        ApplicationServiceContext.Current.GetService <ITagPersistenceService>().Save(pat.Key.Value, new EntityTag(TagName, pat.VersionKey.ToString()));
                        (notificationMessage.GetStructure("MSH") as MSH).MessageType.TriggerEvent.Value     = "A04";
                        (notificationMessage.GetStructure("MSH") as MSH).MessageType.MessageStructure.Value = "ADT_A01";
                    }
                    else if (pat.LoadCollection <EntityRelationship>("Relationships").Any(o => o.RelationshipTypeKey == EntityRelationshipTypeKeys.Replaces && o.EffectiveVersionSequenceId == pat.VersionSequence))
                    {
                        // Set the tag value and send an ADMIT
                        notificationMessage = new ADT_A39();
                        patientGroup        = (notificationMessage as ADT_A39).GetPATIENT();
                        ApplicationServiceContext.Current.GetService <ITagPersistenceService>().Save(pat.Key.Value, new EntityTag(TagName, pat.VersionKey.ToString()));
                        (notificationMessage.GetStructure("MSH") as MSH).MessageType.TriggerEvent.Value     = "A40";
                        (notificationMessage.GetStructure("MSH") as MSH).MessageType.MessageStructure.Value = "ADT_A40";

                        foreach (var mrg in pat.LoadCollection <EntityRelationship>("Relationships").Where(o => o.RelationshipTypeKey == EntityRelationshipTypeKeys.Replaces && o.EffectiveVersionSequenceId == pat.VersionSequence))
                        {
                            var seg = patientGroup.GetStructure("MRG", patientGroup.GetAll("MRG").Length) as MRG;

                            if (this.Configuration.ExportDomains.Any(o => o.DomainName == this.m_configuration.LocalAuthority.DomainName))
                            {
                                var key = seg.PriorAlternatePatientIDRepetitionsUsed;
                                seg.GetPriorAlternatePatientID(key).IDNumber.Value                           = mrg.TargetEntityKey.Value.ToString();
                                seg.GetPriorAlternatePatientID(key).IdentifierTypeCode.Value                 = "PI";
                                seg.GetPriorAlternatePatientID(key).AssigningAuthority.NamespaceID.Value     = this.m_configuration.LocalAuthority.DomainName;
                                seg.GetPriorAlternatePatientID(key).AssigningAuthority.UniversalID.Value     = this.m_configuration.LocalAuthority.Oid;
                                seg.GetPriorAlternatePatientID(key).AssigningAuthority.UniversalIDType.Value = "ISO";
                            }

                            // Alternate identifiers
                            foreach (var extrn in pat.LoadCollection <EntityIdentifier>("Identifiers"))
                            {
                                var key = seg.PriorAlternatePatientIDRepetitionsUsed;
                                if (this.Configuration.ExportDomains.Any(o => o.DomainName == extrn.LoadProperty <AssigningAuthority>("Authority").DomainName))
                                {
                                    seg.GetPriorAlternatePatientID(key).IDNumber.Value                           = extrn.Value;
                                    seg.GetPriorAlternatePatientID(key).IdentifierTypeCode.Value                 = "PT";
                                    seg.GetPriorAlternatePatientID(key).AssigningAuthority.NamespaceID.Value     = extrn.LoadProperty <AssigningAuthority>("Authority")?.DomainName;
                                    seg.GetPriorAlternatePatientID(key).AssigningAuthority.UniversalID.Value     = extrn.LoadProperty <AssigningAuthority>("Authority")?.Oid;
                                    seg.GetPriorAlternatePatientID(key).AssigningAuthority.UniversalIDType.Value = "ISO";
                                }
                            }
                        }
                    }
                    else
                    {
                        // Set the tag value and send an ADMIT
                        patientGroup = notificationMessage = new ADT_A01();
                        ApplicationServiceContext.Current.GetService <ITagPersistenceService>().Save(pat.Key.Value, new EntityTag(TagName, pat.VersionKey.ToString()));
                        (notificationMessage.GetStructure("MSH") as MSH).MessageType.TriggerEvent.Value     = "A08";
                        (notificationMessage.GetStructure("MSH") as MSH).MessageType.MessageStructure.Value = "ADT_A08";
                    }

                    if (!String.IsNullOrEmpty(this.Configuration.Version))
                    {
                        (notificationMessage.GetStructure("MSH") as MSH).VersionID.VersionID.Value = this.Configuration.Version;
                    }

                    // Add SFT
                    if (new Version(this.Configuration.Version ?? "2.5") >= new Version(2, 4))
                    {
                        (notificationMessage.GetStructure("SFT", 0) as SFT).SetDefault();
                    }

                    // Create the PID segment
                    SegmentHandlers.GetSegmentHandler("PID").Create(e.Data, patientGroup, this.Configuration.ExportDomains.ToArray());
                    SegmentHandlers.GetSegmentHandler("PD1").Create(e.Data, patientGroup, this.Configuration.ExportDomains.ToArray());
                    SegmentHandlers.GetSegmentHandler("NK1").Create(e.Data, patientGroup, this.Configuration.ExportDomains.ToArray());
                    //SegmentHandlers.GetSegmentHandler("EVN").Create(e.Data, patientGroup, this.Configuration.ExportDomains.ToArray());


                    foreach (var itm in this.Configuration.Endpoints)
                    {
                        try
                        {
                            // TODO: Create an HL7 Queue
                            (notificationMessage.GetStructure("MSH") as MSH).SetDefault(itm.ReceivingDevice, itm.ReceivingFacility, itm.SecurityToken);
                            var response = itm.GetSender().SendAndReceive(notificationMessage);

                            if (!(response.GetStructure("MSA") as MSA).AcknowledgmentCode.Value.EndsWith("A"))
                            {
                                throw new HL7Exception("Remote server rejected message");
                            }
                        }
                        catch (Exception ex)
                        {
                            this.m_tracer.TraceEvent(EventLevel.Error, "Error dispatching message {0} to {1}: {2} \r\n {3}", pat, itm.Address, ex, new PipeParser().Encode(notificationMessage));
                        }
                    }
                }
            }, e.Data
                );
        }
Exemple #4
0
        /// <summary>
        /// Represents a message parser to a bundle
        /// </summary>
        internal static Bundle Parse(IGroup message)
        {
            Bundle retVal = new Bundle();
            var    finder = new SegmentFinder(message);

            while (finder.HasNextChild())
            {
                finder.NextChild();
                foreach (var current in finder.CurrentChildReps)
                {
                    if (current is AbstractGroupItem)
                    {
                        foreach (var s in (current as AbstractGroupItem)?.Structures.OfType <IGroup>())
                        {
                            var parsed = Parse(s);
                            retVal.Item.AddRange(parsed.Item.Select(i =>
                            {
                                var ret = i.Clone();
                                (ret as ITaggable)?.AddTag("$v2.group", current.GetStructureName());
                                return(ret);
                            }));
                            retVal.FocalObjects.AddRange(parsed.FocalObjects);
                        }
                    }
                    else if (current is AbstractSegment)
                    {
                        // Empty, don't parse
                        if (PipeParser.Encode(current as AbstractSegment, new EncodingCharacters('|', "^~\\&")).Length == 3)
                        {
                            continue;
                        }
                        var handler = SegmentHandlers.GetSegmentHandler(current.GetStructureName());
                        if (handler != null)
                        {
                            var parsed = handler.Parse(current as AbstractSegment, retVal.Item);
                            if (parsed.Any())
                            {
                                retVal.FocalObjects.AddRange(parsed
                                                             .OfType <ITaggable>()
                                                             .Where(o => o.GetTag(Hl7Constants.FocalObjectTag) == "true")
                                                             .OfType <IIdentifiedEntity>()
                                                             .Select(o => o.Key.GetValueOrDefault())
                                                             .Where(o => Guid.Empty != o)
                                                             );
                                retVal.Item.AddRange(parsed.Select(i =>
                                {
                                    var ret = i.Clone();
                                    (ret as ITaggable)?.AddTag("$v2.segment", current.GetStructureName());
                                    return(ret);
                                }));
                            }
                        }
                    }
                    else if (current is AbstractGroup)
                    {
                        var subObject = Parse(current as AbstractGroup);
                        retVal.Item.Add(subObject);
                        retVal.FocalObjects.AddRange(subObject.FocalObjects);
                    }

                    // Tag the objects
                }
            }

            return(retVal);
        }
Exemple #5
0
        /// <summary>
        /// Represents a message parser to a bundle
        /// </summary>
        internal static Bundle Parse(IGroup message)
        {
            Bundle retVal = new Bundle();
            var    finder = new SegmentFinder(message);

            while (finder.hasNextChild())
            {
                finder.nextChild();
                foreach (var current in finder.CurrentChildReps)
                {
                    if (current is AbstractGroupItem)
                    {
                        foreach (var s in (current as AbstractGroupItem)?.Structures.OfType <IGroup>())
                        {
                            var parsed = Parse(s);
                            retVal.Item.AddRange(parsed.Item.Select(i =>
                            {
                                var ret = i.Clone();
                                (ret as ITaggable)?.AddTag(".v2.group", current.GetStructureName());
                                return(ret);
                            }));
                            retVal.ExpansionKeys.AddRange(parsed.ExpansionKeys);
                        }
                    }
                    else if (current is AbstractSegment)
                    {
                        // Empty, don't parse
                        if (PipeParser.Encode(current as AbstractSegment, new EncodingCharacters('|', "^~\\&")).Length == 3)
                        {
                            continue;
                        }
                        var handler = SegmentHandlers.GetSegmentHandler(current.GetStructureName());
                        if (handler != null)
                        {
                            var parsed = handler.Parse(current as AbstractSegment, retVal.Item);
                            if (parsed.Any())
                            {
                                retVal.ExpansionKeys.Add(parsed.First().Key.GetValueOrDefault());
                                retVal.Item.AddRange(parsed.Select(i =>
                                {
                                    var ret = i.Clone();
                                    (ret as ITaggable)?.AddTag(".v2.segment", current.GetStructureName());
                                    return(ret);
                                }));
                            }
                        }
                    }
                    else if (current is AbstractGroup)
                    {
                        var subObject = Parse(current as AbstractGroup);
                        retVal.Item.AddRange(subObject.Item.Select(i =>
                        {
                            var ret = i.Clone();
                            (ret as ITaggable)?.AddTag(".v2.group", current.GetStructureName());
                            return(ret);
                        }));
                        retVal.ExpansionKeys.AddRange(subObject.ExpansionKeys);
                    }

                    // Tag the objects
                }
            }
            return(retVal);
        }