コード例 #1
0
        /// <summary>
        /// Add search parameters
        /// </summary>
        public static void AddSearchParam <TFhirResource>(String fhirQueryParameter, String hdsiQueryParmeter, QueryParameterRewriteType type)
        {
            var resourceType = typeof(TFhirResource).GetResourceType();
            var mapConfig    = s_map.Map.FirstOrDefault(o => resourceType.HasValue ? resourceType.Value == o.Resource : !o.ResourceSpecified);

            if (mapConfig == null)
            {
                mapConfig = new QueryParameterType()
                {
                    Resource = resourceType.Value, ResourceSpecified = resourceType.HasValue
                };
                s_map.Map.Add(mapConfig);
            }

            // parm config
            var parmConfig = mapConfig.Map.FirstOrDefault(o => o.FhirQuery == fhirQueryParameter);

            if (parmConfig == null)
            {
                parmConfig = new QueryParameterMapProperty()
                {
                    FhirQuery  = fhirQueryParameter,
                    ModelQuery = hdsiQueryParmeter,
                    FhirType   = type
                };
            }
            else
            {
                parmConfig.ModelQuery = hdsiQueryParmeter;
                parmConfig.FhirType   = type;
            }
            mapConfig.Map.Add(parmConfig);
        }
コード例 #2
0
ファイル: QueryRewriter.cs プロジェクト: chochohtunn/santedb
        /// <summary>
        /// Re-writes the FHIR query parameter to HDSI query parameter format
        /// </summary>
        /// <returns></returns>
        public static FhirQuery RewriteFhirQuery <TFhirResource, TModelType>(System.Collections.Specialized.NameValueCollection fhirQuery, out NameValueCollection hdsiQuery)
        {
            // Try parse
            if (fhirQuery == null)
            {
                throw new ArgumentNullException(nameof(fhirQuery));
            }

            // Count and offset parameters
            int count = 0, offset = 0, page = 0;

            if (!Int32.TryParse(fhirQuery["_count"] ?? "100", out count))
            {
                throw new ArgumentException("_count");
            }
            if (!Int32.TryParse(fhirQuery["_offset"] ?? "0", out offset))
            {
                throw new ArgumentException("_offset");
            }
            if (fhirQuery["_page"] != null && Int32.TryParse(fhirQuery["_page"], out page))
            {
                offset = page * count;
            }

            Guid queryId = Guid.Empty;

            if (fhirQuery["_stateid"] != null)
            {
                queryId = Guid.Parse(fhirQuery["_stateid"]);
            }
            else
            {
                queryId = Guid.NewGuid();
            }

            // Return new query
            FhirQuery retVal = new FhirQuery()
            {
                ActualParameters   = new System.Collections.Specialized.NameValueCollection(),
                Quantity           = count,
                Start              = offset,
                MinimumDegreeMatch = 100,
                QueryId            = queryId,
                IncludeHistory     = false,
                IncludeContained   = false
            };

            hdsiQuery = new NameValueCollection();

            var map = s_map.Map.FirstOrDefault(o => o.SourceType == typeof(TFhirResource));

            foreach (var kv in fhirQuery.AllKeys)
            {
                List <String> value = new List <string>(fhirQuery.GetValues(kv).Length);

                var parmComponents = kv.Split(':');

                // Is the name extension?
                var parmMap = map?.Map.FirstOrDefault(o => o.FhirName == parmComponents[0]);
                if (parmMap == null)
                {
                    parmMap = s_default.Map.FirstOrDefault(o => o.FhirName == parmComponents[0]);
                }
                if (parmMap == null && kv == "extension")
                {
                    parmMap = new QueryParameterMapProperty()
                    {
                        FhirName  = "extension",
                        ModelName = "extension",
                        FhirType  = "tag"
                    }
                }
                ;
                else if (parmMap == null)
                {
                    continue;
                }

                // Valuse
                foreach (var v in fhirQuery.GetValues(kv))
                {
                    if (String.IsNullOrEmpty(v))
                    {
                        continue;
                    }

                    // Operands
                    bool   chop        = false;
                    string opValue     = String.Empty;
                    string filterValue = v;
                    if (v.Length > 2)
                    {
                        switch (v.Substring(0, 2))
                        {
                        case "ap":
                            chop    = true;
                            opValue = "~";
                            break;

                        case "gt":
                            chop    = true;
                            opValue = ">";
                            break;

                        case "ge":
                            chop    = true;
                            opValue = ">=";
                            break;

                        case "lt":
                            chop    = true;
                            opValue = "<";
                            break;

                        case "le":
                            chop    = true;
                            opValue = "<=";
                            break;

                        case "ne":
                            chop    = true;
                            opValue = "!";
                            break;

                        case "eq":
                            chop = true;
                            break;

                        default:
                            break;
                        }
                    }

                    if (parmComponents.Length > 1)
                    {
                        switch (parmComponents[1])
                        {
                        case "contains":
                            opValue     = "~";
                            filterValue = $"*{filterValue}*";
                            break;

                        case "missing":
                            filterValue = "null";
                            chop        = false;
                            break;
                        }
                    }

                    retVal.ActualParameters.Add(kv, filterValue);
                    value.Add(opValue + filterValue.Substring(chop ? 2 : 0));
                }

                if (value.Count(o => !String.IsNullOrEmpty(o)) == 0)
                {
                    continue;
                }

                // Query
                switch (parmMap.FhirType)
                {
                case "identifier":
                    foreach (var itm in value)
                    {
                        if (itm.Contains("|"))
                        {
                            var segs = itm.Split('|');
                            // Might be a URL
                            if (Uri.TryCreate(segs[0], UriKind.Absolute, out Uri data))
                            {
                                var aa = ApplicationServiceContext.Current.GetService <IAssigningAuthorityRepositoryService>().Get(data);
                                hdsiQuery.Add(String.Format("{0}[{1}].value", parmMap.ModelName, aa.DomainName), segs[1]);
                            }
                            else
                            {
                                hdsiQuery.Add(String.Format("{0}[{1}].value", parmMap.ModelName, segs[0]), segs[1]);
                            }
                        }
                        else
                        {
                            hdsiQuery.Add(parmMap.ModelName + ".value", itm);
                        }
                    }
                    break;

                case "concept":
                    foreach (var itm in value)
                    {
                        if (itm.Contains("|"))
                        {
                            var segs = itm.Split('|');

                            string     codeSystemUri = segs[0];
                            CodeSystem codeSystem    = null;

                            if (codeSystemUri.StartsWith("urn:oid:"))
                            {
                                codeSystemUri = codeSystemUri.Substring(8);
                                codeSystem    = ApplicationServiceContext.Current.GetService <IRepositoryService <CodeSystem> >().Find(o => o.Oid == codeSystemUri).FirstOrDefault();
                            }
                            else if (codeSystemUri.StartsWith("urn:") || codeSystemUri.StartsWith("http:"))
                            {
                                codeSystem = ApplicationServiceContext.Current.GetService <IRepositoryService <CodeSystem> >().Find(o => o.Url == codeSystemUri).FirstOrDefault();
                            }
                            else
                            {
                                codeSystem = ApplicationServiceContext.Current.GetService <IRepositoryService <CodeSystem> >().Find(o => o.Name == codeSystemUri).FirstOrDefault();
                            }


                            s_tracer.TraceInfo("Have translated FHIR domain {0} to {1}", codeSystemUri, codeSystem?.Name);

                            if (codeSystem != null)
                            {
                                hdsiQuery.Add(String.Format("{0}.referenceTerm[{1}].term.mnemonic", parmMap.ModelName, codeSystem.Name), segs[1]);
                            }
                            else
                            {
                                hdsiQuery.Add(String.Format("{0}.mnemonic", parmMap.ModelName), segs[1]);
                            }
                        }
                        else
                        {
                            hdsiQuery.Add(parmMap.ModelName + ".referenceTerm.term.mnemonic", itm);
                        }
                    }
                    break;

                case "reference":
                    foreach (var itm in value)
                    {
                        if (itm.Contains("/"))
                        {
                            var segs = itm.Split('/');
                            hdsiQuery.Add(parmMap.ModelName, segs[1]);
                        }
                        else
                        {
                            hdsiQuery.Add(parmMap.ModelName, itm);
                        }
                    }
                    break;

                case "tag":
                    foreach (var itm in value)
                    {
                        if (itm.Contains("|"))
                        {
                            var segs = itm.Split('|');
                            hdsiQuery.Add(String.Format("{0}[{1}].value", parmMap.ModelName, segs[0]), segs[1]);
                        }
                        else
                        {
                            hdsiQuery.Add(parmMap.ModelName, itm);
                        }
                    }
                    break;

                default:
                    hdsiQuery.Add(parmMap.ModelName, value);
                    break;
                }
            }

            return(retVal);
        }
コード例 #3
0
        /// <summary>
        /// Re-writes the FHIR query parameter to HDSI query parameter format
        /// </summary>
        /// <returns></returns>
        public static FhirQuery RewriteFhirQuery(Type fhirType, Type modelType, System.Collections.Specialized.NameValueCollection fhirQuery, out NameValueCollection hdsiQuery)
        {
            // Try parse
            if (fhirQuery == null)
            {
                throw new ArgumentNullException(nameof(fhirQuery));
            }

            // Count and offset parameters
            int count = 0, offset = 0, page = 0;

            if (!Int32.TryParse(fhirQuery["_count"] ?? "25", out count))
            {
                throw new ArgumentException("_count");
            }
            if (!Int32.TryParse(fhirQuery["_offset"] ?? "0", out offset))
            {
                throw new ArgumentException("_offset");
            }
            if (fhirQuery["_page"] != null && Int32.TryParse(fhirQuery["_page"], out page))
            {
                offset = page * count;
            }

            Guid queryId = Guid.Empty;

            if (fhirQuery["_stateid"] != null)
            {
                queryId = Guid.Parse(fhirQuery["_stateid"]);
            }
            else if (fhirQuery["_total"] == "accurate") // to get an accurate total we have to persist query state
            {
                queryId = Guid.NewGuid();
            }
            else
            {
                queryId = Guid.Empty;
            }

            // Return new query
            FhirQuery retVal = new FhirQuery()
            {
                ActualParameters   = new System.Collections.Specialized.NameValueCollection(),
                Quantity           = count,
                Start              = offset,
                MinimumDegreeMatch = 100,
                QueryId            = queryId,
                IncludeHistory     = false,
                IncludeContained   = false
            };

            hdsiQuery = new NameValueCollection();

            var resourceType = fhirType.GetResourceType();
            var map          = s_map.Map.FirstOrDefault(o => resourceType.HasValue ? resourceType.Value == o.Resource : !o.ResourceSpecified);

            foreach (var kv in fhirQuery.AllKeys)
            {
                List <String> value = new List <string>(fhirQuery.GetValues(kv).Length);

                var parmComponents = kv.Split(':');

                // Is the name extension?
                var parmMap = map?.Map.FirstOrDefault(o => o.FhirQuery == parmComponents[0]);
                if (parmMap == null)
                {
                    parmMap = s_default.Map.FirstOrDefault(o => o.FhirQuery == parmComponents[0]);
                }
                if (parmMap == null && kv == "extension")
                {
                    parmMap = new QueryParameterMapProperty()
                    {
                        FhirQuery  = "extension",
                        ModelQuery = "extension",
                        FhirType   = QueryParameterRewriteType.Tag
                    }
                }
                ;
                else if (parmMap == null)
                {
                    continue;
                }

                // Valuse
                foreach (var v in fhirQuery.GetValues(kv))
                {
                    if (String.IsNullOrEmpty(v))
                    {
                        continue;
                    }

                    // Operands
                    bool   chop        = false;
                    string opValue     = String.Empty;
                    string filterValue = v;
                    if (v.Length > 2)
                    {
                        switch (v.Substring(0, 2))
                        {
                        case "ap":
                            chop    = true;
                            opValue = "~";
                            break;

                        case "gt":
                            chop    = true;
                            opValue = ">";
                            break;

                        case "ge":
                            chop    = true;
                            opValue = ">=";
                            break;

                        case "lt":
                            chop    = true;
                            opValue = "<";
                            break;

                        case "le":
                            chop    = true;
                            opValue = "<=";
                            break;

                        case "ne":
                            chop    = true;
                            opValue = "!";
                            break;

                        case "eq":
                            chop = true;
                            break;

                        default:
                            break;
                        }
                    }

                    if (parmComponents.Length > 1)
                    {
                        switch (parmComponents[1])
                        {
                        case "fuzzy":
                        case "approx":
                            opValue     = "";
                            filterValue = $":(approx|'{filterValue}')";
                            break;

                        case "contains":
                            opValue     = "~";
                            filterValue = $"*{filterValue}*";
                            break;

                        case "exact":
                            opValue = "";
                            break;

                        case "missing":
                            filterValue = "null";
                            chop        = false;
                            break;

                        default:
                            switch (parmMap.FhirType)
                            {
                            case QueryParameterRewriteType.String:         // Default string matching is wonky in FHIR but meh we can mimic it at least
                                opValue     = "~";
                                filterValue = $"*{filterValue.Replace(' ', '?')}*";
                                break;
                            }
                            break;
                        }
                    }

                    retVal.ActualParameters.Add(kv, filterValue);
                    value.Add(opValue + filterValue.Substring(chop ? 2 : 0));
                }

                if (value.Count(o => !String.IsNullOrEmpty(o)) == 0)
                {
                    continue;
                }

                // Apply a function
                if (!String.IsNullOrEmpty(parmMap.Function))
                {
                    value = value.Select(o => parmMap.Function.Replace("$1", o)).ToList();
                }

                // Query
                switch (parmMap.FhirType)
                {
                case QueryParameterRewriteType.Identifier:
                    foreach (var itm in value)
                    {
                        if (itm.Contains("|"))
                        {
                            var segs = itm.Split('|');
                            // Might be a URL
                            if (Uri.TryCreate(segs[0], UriKind.Absolute, out Uri data))
                            {
                                var aa = ApplicationServiceContext.Current.GetService <IAssigningAuthorityRepositoryService>().Get(data);
                                if (aa == null)
                                {
                                    throw new FhirException(System.Net.HttpStatusCode.BadRequest, OperationOutcome.IssueType.NotFound, $"No authority for {data} found");
                                }
                                hdsiQuery.Add(String.Format("{0}[{1}].value", parmMap.ModelQuery, aa.DomainName), segs[1]);
                            }
                            else
                            {
                                hdsiQuery.Add(String.Format("{0}[{1}].value", parmMap.ModelQuery, segs[0]), segs[1]);
                            }
                        }
                        else
                        {
                            hdsiQuery.Add(parmMap.ModelQuery + ".value", itm);
                        }
                    }
                    break;

                case QueryParameterRewriteType.Indicator:
                    var mq = NameValueCollection.ParseQueryString(parmMap.ModelQuery);
                    foreach (var itm in mq)
                    {
                        hdsiQuery.Add(itm.Key, itm.Value);
                    }
                    break;

                case QueryParameterRewriteType.Concept:
                    foreach (var itm in value)
                    {
                        if (itm.Contains("|"))
                        {
                            var segs = itm.Split('|');

                            string codeSystemUri = segs[0];
                            Core.Model.DataTypes.CodeSystem codeSystem = null;

                            if (codeSystemUri.StartsWith("urn:oid:"))
                            {
                                codeSystemUri = codeSystemUri.Substring(8);
                                codeSystem    = ApplicationServiceContext.Current.GetService <IRepositoryService <Core.Model.DataTypes.CodeSystem> >().Find(o => o.Oid == codeSystemUri).FirstOrDefault();
                            }
                            else if (codeSystemUri.StartsWith("urn:") || codeSystemUri.StartsWith("http:"))
                            {
                                codeSystem = ApplicationServiceContext.Current.GetService <IRepositoryService <Core.Model.DataTypes.CodeSystem> >().Find(o => o.Url == codeSystemUri).FirstOrDefault();
                            }
                            else
                            {
                                codeSystem = ApplicationServiceContext.Current.GetService <IRepositoryService <Core.Model.DataTypes.CodeSystem> >().Find(o => o.Name == codeSystemUri).FirstOrDefault();
                            }


                            s_tracer.TraceInfo("Have translated FHIR domain {0} to {1}", codeSystemUri, codeSystem?.Name);

                            if (codeSystem != null)
                            {
                                hdsiQuery.Add(String.Format("{0}.referenceTerm[{1}].term.mnemonic", parmMap.ModelQuery, codeSystem.Name), segs[1]);
                            }
                            else
                            {
                                hdsiQuery.Add(String.Format("{0}.mnemonic", parmMap.ModelQuery), segs[1]);
                            }
                        }
                        else
                        {
                            hdsiQuery.Add(parmMap.ModelQuery + ".referenceTerm.term.mnemonic", itm);
                        }
                    }
                    break;

                case QueryParameterRewriteType.Reference:
                    foreach (var itm in value)
                    {
                        if (itm.Contains("/"))
                        {
                            var segs = itm.Split('/');
                            hdsiQuery.Add(parmMap.ModelQuery, segs[1]);
                        }
                        else
                        {
                            hdsiQuery.Add(parmMap.ModelQuery, itm);
                        }
                    }
                    break;

                case QueryParameterRewriteType.Tag:
                    foreach (var itm in value)
                    {
                        if (itm.Contains("|"))
                        {
                            var segs = itm.Split('|');
                            hdsiQuery.Add(String.Format("{0}[{1}].value", parmMap.ModelQuery, segs[0]), segs[1]);
                        }
                        else
                        {
                            hdsiQuery.Add(parmMap.ModelQuery, itm);
                        }
                    }
                    break;

                default:
                    hdsiQuery.Add(parmMap.ModelQuery, value);
                    break;
                }
            }

            return(retVal);
        }