/// <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)
                {
                    this.m_tracer.TraceError("Error processing query parameter", "QPD", "1", 3, 0, e);
                    throw new HL7ProcessingException(this.m_localizationService.FormatString("error.type.HL7ProcessingException", new
                    {
                        param = "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)
                {
                    this.m_tracer.TraceError("Error processing return domains", "QPD", "1", 8, 0, e);
                    throw new HL7ProcessingException(this.m_localizationService.FormatString("error.type.HL7ProcessingException", new
                    {
                        param = "return domains"
                    }), "QPD", "1", 8, 0, e);
                }
            }

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

            return(retVal);
        }
        /// <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)
                {
                    this.m_tracer.TraceError("Error processing patient identity", "QPD", "1", 3, 4, e);
                    throw new HL7ProcessingException(this.m_localizationService.FormatString("error.type.HL7ProcessingException", new
                    {
                        param = "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)
                {
                    this.m_tracer.TraceError("Error processing what domains returned", "QPD", "1", 4, 4, e);
                    throw new HL7ProcessingException(this.m_localizationService.FormatString("error.type.HL7ProcessingException", new
                    {
                        param = "what domains returned"
                    }), "QPD", "1", 4, 4, e);
                }
            }


            return(retVal);
        }
Exemple #3
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);
        }
Exemple #4
0
        /// <summary>
        /// Rewrite a QPD query to an HDSI query
        /// </summary>
        public static NameValueCollection ParseQueryElement(IEnumerable <Varies> varies, Hl7QueryParameterType map, String matchAlgorithm, double?matchStrength = null)
        {
            NameValueCollection retVal = new NameValueCollection();
            var config = ApplicationServiceContext.Current.GetService <IConfigurationManager>().GetSection <Hl7ConfigurationSection>();

            // Query parameters
            foreach (var qp in varies)
            {
                var composite = qp.Data as GenericComposite;

                // Parse the parameters
                var qfield = (composite.Components[0] as Varies)?.Data?.ToString();
                var qvalue = (composite.Components[1] as Varies)?.Data?.ToString();

                // Attempt to find the query parameter and map
                var parm = map.Parameters.Where(o => o.Hl7Name == qfield || o.Hl7Name == qfield + ".1" || o.Hl7Name == qfield + ".1.1").OrderBy(o => o.Hl7Name.Length - qfield.Length).FirstOrDefault();
                if (parm == null)
                {
                    throw new ArgumentOutOfRangeException($"{qfield} not mapped to query parameter");
                }

                switch (parm.ParameterType)
                {
                case "concept":
                    retVal.Add($"{parm.ModelName}.referenceTerm.term.mnemonic", qvalue);
                    break;

                case "string":     // Enables phonetic matching
                    String transform = null;
                    if (parm.AllowFuzzy)
                    {
                        switch ((matchAlgorithm ?? "pattern").ToLower())
                        {
                        case "approx":
                            transform = ":(approx|{0})";
                            break;

                        case "exact":
                            transform = "{0}";
                            break;

                        case "pattern":
                            transform = "~*{0}*";
                            break;

                        case "soundex":
                            if (matchStrength.HasValue)
                            {
                                transform = ":(soundex){0}";
                            }
                            else
                            {
                                transform = $":(phonetic_diff|{{0}},soundex)<={matchStrength * qvalue.Length}";
                            }
                            break;

                        case "metaphone":
                            if (matchStrength.HasValue)
                            {
                                transform = ":(metaphone){0}";
                            }
                            else
                            {
                                transform = $":(phonetic_diff|{{0}},metaphone)<={matchStrength * qvalue.Length}";
                            }
                            break;

                        case "dmetaphone":
                            if (matchStrength.HasValue)
                            {
                                transform = ":(dmetaphone){0}";
                            }
                            else
                            {
                                transform = $":(phonetic_diff|{{0}},dmetaphone)<={matchStrength * qvalue.Length}";
                            }
                            break;

                        case "alias":
                            transform = $":(alias|{{0}})>={matchStrength ?? 3}";
                            break;

                        default:
                            transform = "~{0}";
                            break;
                        }
                    }
                    else
                    {
                        transform = "{0}";
                    }
                    retVal.Add(parm.ModelName, transform.Split(',').Select(tx => String.Format(tx, qvalue)).ToList());
                    break;

                case "date":

                    if (qvalue.Length == 4)     // partial date
                    {
                        retVal.Add(parm.ModelName, $"~{qvalue}");
                    }
                    else if (qvalue.Length == 6)     // partial to month
                    {
                        retVal.Add(parm.ModelName, $"~{qvalue.Insert(4, "-")}");
                    }
                    else
                    {
                        retVal.Add(parm.ModelName, qvalue);
                    }
                    break;

                default:
                    var txv = parm.ValueTransform ?? "{0}";
                    retVal.Add(parm.ModelName, txv.Split(',').Select(tx => String.Format(tx, qvalue)).ToList());
                    break;
                }
            }

            // HACK: Are they asking for the @PID.3.4.1 of our local auth?
            List <String> localId = null;

            if (retVal.TryGetValue("identifier.authority.domainName", out localId) &&
                localId.Contains(config.LocalAuthority.DomainName))
            {
                retVal.Remove("identifier.authority.domainName");
                localId = retVal["identifier.value"];
                retVal.Remove("identifier.value");
                retVal.Add("_id", localId);
            }

            return(retVal);
        }
Exemple #5
0
        /// <summary>
        /// Create query response for the data according to ITI-9
        /// </summary>
        protected override IMessage CreateQueryResponse(Hl7MessageReceivedEventArgs request, Expression filter, Hl7QueryParameterType map, IEnumerable results, Guid queryId, int offset, int count, int totalResults)
        {
            var retVal = base.CreateQueryResponse(request, filter, map, results, queryId, offset, count, totalResults) as RSP_K23;

            // CASE 3: Domains are recognized but no results
            if (results.OfType <Patient>().Count() == 0)
            {
                retVal.MSA.AcknowledgmentCode.Value                  = "AE";
                retVal.MSA.TextMessage.Value                         = "Query Error";
                retVal.QAK.QueryResponseStatus.Value                 = "AE";
                retVal.ERR.GetErrorLocation(0).SegmentID.Value       = "QPD";
                retVal.ERR.GetErrorLocation(0).SegmentSequence.Value = "1";
                retVal.ERR.GetErrorLocation(0).FieldPosition.Value   = "3";
                retVal.ERR.GetErrorLocation(0).FieldRepetition.Value = "1";
                retVal.ERR.GetErrorLocation(0).ComponentNumber.Value = "1";
                retVal.ERR.HL7ErrorCode.Identifier.Value             = "204";
                retVal.ERR.HL7ErrorCode.Text.Value                   = "Unknown Key Identifier";
            }

            return(retVal);
        }