コード例 #1
0
        internal static ModelInfo.SearchParamDefinition FindSearchParamDefinition(this Criterium param, string resourceType)
        {
            return(param.SearchParameters?.FirstOrDefault(sp => sp.Resource == resourceType || sp.Resource == "Resource"));

            //var sp = ModelInfo.SearchParameters;
            //return sp.Find(defn => defn.Name == param.ParamName && defn.Resource == resourceType);
        }
コード例 #2
0
        public void ParseCriterium()
        {
            var crit = Criterium.Parse("paramX=18");

            Assert.AreEqual("paramX", crit.ParamName);
            Assert.IsNull(crit.Modifier);
            Assert.AreEqual("18", crit.Operand.ToString());
            Assert.AreEqual(Operator.EQ, crit.Type);

            crit = Criterium.Parse("paramX=>18");
            Assert.AreEqual("paramX", crit.ParamName);
            Assert.IsNull(crit.Modifier);
            Assert.AreEqual("18", crit.Operand.ToString());
            Assert.AreEqual(Operator.GT, crit.Type);

            crit = Criterium.Parse("paramX:modif1=~18");
            Assert.AreEqual("paramX", crit.ParamName);
            Assert.AreEqual("18", crit.Operand.ToString());
            Assert.AreEqual("modif1", crit.Modifier);
            Assert.AreEqual(Operator.APPROX, crit.Type);

            crit = Criterium.Parse("paramX:missing=true");
            Assert.AreEqual("paramX", crit.ParamName);
            Assert.IsNull(crit.Operand);
            Assert.IsNull(crit.Modifier);
            Assert.AreEqual(Operator.ISNULL, crit.Type);

            crit = Criterium.Parse("paramX:missing=false");
            Assert.AreEqual("paramX", crit.ParamName);
            Assert.IsNull(crit.Operand);
            Assert.IsNull(crit.Modifier);
            Assert.AreEqual(Operator.NOTNULL, crit.Type);
        }
コード例 #3
0
ファイル: MongoSearcher.cs プロジェクト: manjufmcna/spark
        /// <summary>
        /// Change something like Condition/subject:Patient=Patient/10014
        /// to Condition/subject:Patient.internal_id=Patient/10014, so it is correctly handled as a chained parameter,
        /// including the filtering on the type in the modifier (if any).
        /// </summary>
        /// <param name="criteria"></param>
        /// <param name="resourceType"></param>
        /// <returns></returns>
        private List <Criterium> NormalizeNonChainedReferenceCriteria(List <Criterium> criteria, string resourceType)
        {
            var result = new List <Criterium>();

            foreach (var crit in criteria)
            {
                var critSp = crit.FindSearchParamDefinition(resourceType);
                if (critSp != null && critSp.Type == Conformance.SearchParamType.Reference && crit.Type != Operator.CHAIN)
                {
                    var subCrit = new Criterium();
                    subCrit.ParamName = InternalField.ID;
                    subCrit.Type      = crit.Type;
                    subCrit.Operand   = crit.Operand;

                    var superCrit = new Criterium();
                    superCrit.ParamName = crit.ParamName;
                    superCrit.Modifier  = crit.Modifier;
                    superCrit.Type      = Operator.CHAIN;
                    superCrit.Operand   = subCrit;

                    result.Add(superCrit);
                }
                else
                {
                    result.Add(crit);
                }
            }

            return(result);
        }
コード例 #4
0
        /// <summary>
        /// CloseCriterium("patient.name=\"Teun\"") -> "patient IN (id1,id2)"
        /// </summary>
        /// <param name="resourceType"></param>
        /// <param name="crit"></param>
        /// <returns></returns>
        private Criterium CloseCriterium(Criterium crit, string resourceType, int level)
        {
            List <string> targeted = crit.GetTargetedReferenceTypes(resourceType);
            List <string> allKeys  = new List <string>();
            var           errors   = new List <Exception>();

            foreach (var target in targeted)
            {
                try {
                    Criterium innerCriterium = (Criterium)crit.Operand;
                    var       keys           = CollectKeys(target, new List <Criterium> {
                        innerCriterium
                    }, ++level);                                                                                   //Recursive call to CollectKeys!
                    allKeys.AddRange(keys.Select(k => k.ToString()));
                }
                catch (Exception ex)
                {
                    errors.Add(ex);
                }
            }
            if (errors.Count == targeted.Count())
            {
                //It is possible that some of the targets don't support the current parameter. But if none do, there is a serious problem.
                throw new ArgumentException(String.Format("None of the possible target resources support querying for parameter {0}", crit.ParamName));
            }
            crit.Operator = Operator.IN;
            crit.Operand  = ChoiceValue.Parse(String.Join(",", allKeys));
            return(crit);
        }
コード例 #5
0
        private bool TryEnrichCriteriumWithSearchParameters(Criterium criterium, ResourceType resourceType)
        {
            var sp = _fhirModel.FindSearchParameter(resourceType, criterium.ParamName);

            if (sp == null)
            {
                return(false);
            }

            var result = true;

            var spDef = sp.GetOriginalDefinition();

            if (spDef != null)
            {
                criterium.SearchParameters.Add(spDef);
            }

            if (criterium.Operator == Operator.CHAIN)
            {
                var subCrit = (Criterium)(criterium.Operand);
                foreach (var targetType in criterium.SearchParameters.SelectMany(spd => spd.Target))
                {
                    result &= TryEnrichCriteriumWithSearchParameters(subCrit, targetType);
                }
            }
            return(result);
        }
コード例 #6
0
        public void HandleDateParam()
        {
            // Brian: Not sure tha these tests SHOULD pass...
            // a time component on the Date?
            var p1 = new DateValue(new DateTimeOffset(1972, 11, 30, 15, 20, 49, TimeSpan.Zero));

            Assert.AreEqual("1972-11-30", p1.ToString());

            // we can parse a valid FHIR datetime and strip the time part off
            // (but it must be a valid FHIR datetime)
            var p2 = DateValue.Parse("1972-11-30T18:45:36Z");

            Assert.AreEqual("1972-11-30", p2.ToString());

            var crit = Criterium.Parse("paramX=1972-11-30");
            var p3   = ((UntypedValue)crit.Operand).AsDateValue();

            Assert.AreEqual("1972-11-30", p3.Value);

            try
            {
                // Test with an invalid FHIR datetime (no timezone specified)
                var p4 = DateValue.Parse("1972-11-30T18:45:36");
                Assert.Fail("The datetime [1972-11-30T18:45:36] does not have a timezone, hence should fail parsing as a datevalue (via fhirdatetime)");
            }
            catch (ArgumentException)
            {
            }
        }
コード例 #7
0
        private IMongoQuery createSimpleQuery(Query query) // without chains
        {
            IMongoQuery resourceFilter = query.ResourceFilter();
            var         criteria       = query.Criteria.Select(c => Criterium.Parse(c));
            IMongoQuery criteriaFilter = M.Query.And(criteria.Select(c => c.ToFilter(query.ResourceType)));

            return(M.Query.And(resourceFilter, criteriaFilter));
        }
コード例 #8
0
 private string GetValue(Criterium crit)
 {
     foreach (KeyValuePair <Criterium, int> critPair in criteriumTable)
     {
         if (critPair.Key.Name.Equals(crit.Name))
         {
             return(critPair.Value.ToString());
         }
     }
     return(String.Empty);
 }
コード例 #9
0
        private Criterium GetCritMaxValue(string critName)
        {
            foreach (Criterium crit in mMatrix.Criteriums)
            {
                if (crit.Name.Equals(critName))
                {
                    return(crit);
                }
            }
            Criterium c = new Criterium();

            return(c);
        }
コード例 #10
0
        public void ParseCriteriumFromParameter()
        {
            Parameters.ParametersParameterComponent parameter = Parameters.BuildParamExtension("Subject.name", "Teun");
            Criterium sut = Criterium.Parse(parameter);

            Assert.AreEqual("Subject", sut.ParamName);
            Assert.IsTrue(sut.Operand is Criterium);

            Criterium sub = sut.Operand as Criterium;

            Assert.AreEqual("Teun", sub.Operand.ToString());
            Assert.AreEqual(Operator.EQ, sub.Type);
        }
コード例 #11
0
        public void HandleDateTimeParam()
        {
            var p1 = new FhirDateTime(new DateTimeOffset(1972, 11, 30, 15, 20, 49, TimeSpan.Zero));

            Assert.AreEqual("1972-11-30T15:20:49+00:00", p1.Value.ToString());

            var crit = Criterium.Parse("paramX=1972-11-30T18:45:36Z");
            var p3   = ((UntypedValue)crit.Operand).AsDateValue();

            Assert.AreEqual("1972-11-30", p3.Value);

            var p4 = ((UntypedValue)crit.Operand).AsDateTimeValue();

            Assert.AreEqual("1972-11-30T18:45:36Z", p4.Value);
        }
コード例 #12
0
        public void HandleReferenceParam()
        {
            var p1 = new ReferenceValue("2");

            Assert.AreEqual("2", p1.Value);

            var p2 = new ReferenceValue("http://server.org/fhir/Patient/1");

            Assert.AreEqual("http://server.org/fhir/Patient/1", p2.Value);

            var crit = Criterium.Parse(@"paramX=http://server.org/\$4/fhir/Patient/1");
            var p3   = ((UntypedValue)crit.Operand).AsReferenceValue();

            Assert.AreEqual("http://server.org/$4/fhir/Patient/1", p3.Value);
        }
コード例 #13
0
        public void HandleTokenParam()
        {
            var p1 = new TokenValue("NOK", "http://somewhere.nl/codes");

            Assert.AreEqual("http://somewhere.nl/codes|NOK", p1.ToString());

            var p2 = new TokenValue("y|n", "http://some|where.nl/codes");

            Assert.AreEqual(@"http://some\|where.nl/codes|y\|n", p2.ToString());

            var p3 = new TokenValue("NOK", matchAnyNamespace: true);

            Assert.AreEqual("NOK", p3.ToString());

            var p4 = new TokenValue("NOK", matchAnyNamespace: false);

            Assert.AreEqual("|NOK", p4.ToString());

            var p5 = TokenValue.Parse("http://somewhere.nl/codes|NOK");

            Assert.AreEqual("http://somewhere.nl/codes", p5.Namespace);
            Assert.AreEqual("NOK", p5.Value);
            Assert.IsFalse(p4.AnyNamespace);

            var p6 = TokenValue.Parse(@"http://some\|where.nl/codes|y\|n");

            Assert.AreEqual(@"http://some|where.nl/codes", p6.Namespace);
            Assert.AreEqual("y|n", p6.Value);
            Assert.IsFalse(p6.AnyNamespace);

            var p7 = TokenValue.Parse("|NOK");

            Assert.AreEqual(null, p7.Namespace);
            Assert.AreEqual("NOK", p7.Value);
            Assert.IsFalse(p7.AnyNamespace);

            var p8 = TokenValue.Parse("NOK");

            Assert.AreEqual(null, p8.Namespace);
            Assert.AreEqual("NOK", p8.Value);
            Assert.IsTrue(p8.AnyNamespace);

            var crit = Criterium.Parse("paramX=|NOK");
            var p9   = ((UntypedValue)crit.Operand).AsTokenValue();

            Assert.AreEqual("NOK", p9.Value);
            Assert.IsFalse(p9.AnyNamespace);
        }
コード例 #14
0
ファイル: MongoSearcher.cs プロジェクト: manjufmcna/spark
        /// <summary>
        /// CloseCriterium("patient.name=\"Teun\"") -> "patient=id1,id2"
        /// </summary>
        /// <param name="resourceType"></param>
        /// <param name="crit"></param>
        /// <returns></returns>
        private Criterium CloseCriterium(Criterium crit, string resourceType)
        {
            List <string> targeted = crit.GetTargetedReferenceTypes(resourceType);
            List <string> allKeys  = new List <string>();

            foreach (var target in targeted)
            {
                var keys = CollectKeys(target, new List <Criterium> {
                    (Criterium)crit.Operand
                });                                                                                            //Recursive call to CollectKeys!
                allKeys.AddRange(keys.Select(k => k.ToString()));
            }
            crit.Type    = Operator.IN;
            crit.Operand = ChoiceValue.Parse(String.Join(",", allKeys));
            return(crit);
        }
コード例 #15
0
        private string BuildAndReturnQueryFilterAsJsonString(ResourceType resourceType, string searchParameter, string query)
        {
            var bsonSerializerRegistry = new BsonSerializerRegistry();

            bsonSerializerRegistry.RegisterSerializationProvider(new BsonSerializationProvider());

            var resourceTypeAsString = resourceType.GetLiteral();
            var criterium            = Criterium.Parse(query);

            criterium.SearchParameters.AddRange(ModelInfo.SearchParameters.Where(p => p.Resource == resourceTypeAsString && p.Name == searchParameter));

            var filter     = criterium.ToFilter(resourceType.GetLiteral());
            var jsonFilter = filter?.Render(null, bsonSerializerRegistry)?.ToJson();

            return(jsonFilter);
        }
コード例 #16
0
        //TODO: Delete, F.Query is obsolete.

        /*
         * public SearchResults Search(F.Query query)
         * {
         *  SearchResults results = new SearchResults();
         *
         *  var criteria = parseCriteria(query, results);
         *
         *  if (!results.HasErrors)
         *  {
         *      results.UsedCriteria = criteria;
         *      //TODO: ResourceType.ToString() sufficient, or need to use EnumMapping?
         *      var normalizedCriteria = NormalizeNonChainedReferenceCriteria(criteria, query.ResourceType.ToString());
         *      List<BsonValue> keys = CollectKeys(query.ResourceType.ToString(), normalizedCriteria, results);
         *
         *      int numMatches = keys.Count();
         *
         *      results.AddRange(KeysToSearchResults(keys));
         *      results.MatchCount = numMatches;
         *  }
         *
         *  return results;
         * }
         */

        private List <Criterium> parseCriteria(SearchParams searchCommand, SearchResults results)
        {
            var result = new List <Criterium>();

            foreach (var c in searchCommand.Parameters)
            {
                try
                {
                    result.Add(Criterium.Parse(c.Item1, c.Item2));
                }
                catch (Exception ex)
                {
                    results.AddIssue(String.Format("Could not parse parameter [{0}] for reason [{1}].", c.ToString(), ex.Message));
                }
            }
            return(result);
        }
コード例 #17
0
        public void StringQueryTest()
        {
            var resourceType    = ResourceType.Subscription.GetLiteral();
            var searchParamName = "criteria";

            var criterium = Criterium.Parse("criteria=Observation?patient.identifier=http://somehost.no/fhir/Name%20Hospital|someId");

            criterium.SearchParameters.AddRange(ModelInfo.SearchParameters.Where(p => p.Resource == resourceType && p.Name == searchParamName));

            var filter = criterium.ToFilter(resourceType);

            var jsonFilter = filter?.Render(null, null)?.ToJson();

            Assert.Equal(
                "{ \"criteria\" : /^Observation?patient.identifier=http:\\/\\/somehost.no\\/fhir\\/Name%20Hospital|someId/i }",
                jsonFilter);
        }
コード例 #18
0
        private static IMongoQuery TagQuery(Criterium crit, Uri tagscheme)
        {
            if (crit.Type == Operator.IN)
            {
                IEnumerable <ValueExpression> opMultiple = ((ChoiceValue)crit.Operand).Choices;
                var optionQueries = new List <IMongoQuery>();
                foreach (var choice in opMultiple)
                {
                    Criterium option = new Criterium();
                    option.Type      = Operator.EQ;
                    option.Operand   = choice;
                    option.Modifier  = crit.Modifier;
                    option.ParamName = crit.ParamName;
                    optionQueries.Add(TagQuery(option, tagscheme));
                }
                return(M.Query.Or(optionQueries));
            }

            //From here there's only 1 operand.
            IMongoQuery schemeQuery = M.Query.EQ(InternalField.TAGSCHEME, tagscheme.AbsoluteUri);
            IMongoQuery argQuery;

            var operand = (ValueExpression)crit.Operand;

            switch (crit.Modifier)
            {
            case Modifier.PARTIAL:
                argQuery = StringQuery(InternalField.TAGTERM, Operator.EQ, Modifier.NONE, operand);
                break;

            case Modifier.TEXT:
                argQuery = StringQuery(InternalField.TAGLABEL, Operator.EQ, Modifier.NONE, operand);
                break;

            case Modifier.NONE:
            case null:
                argQuery = StringQuery(InternalField.TAGTERM, Operator.EQ, Modifier.EXACT, operand);
                break;

            default:
                throw new ArgumentException(String.Format("Invalid modifier {0} in parameter {1}", crit.Modifier, crit.ParamName));
            }

            return(M.Query.ElemMatch(InternalField.TAG, M.Query.And(schemeQuery, argQuery)));
        }
コード例 #19
0
        public void ParseChain()
        {
            var crit = Criterium.Parse("par1:type1.par2.par3:text=hoi");

            Assert.IsTrue(crit.Type == Operator.CHAIN);
            Assert.AreEqual("type1", crit.Modifier);
            Assert.IsTrue(crit.Operand is Criterium);

            crit = crit.Operand as Criterium;
            Assert.IsTrue(crit.Type == Operator.CHAIN);
            Assert.AreEqual(null, crit.Modifier);
            Assert.IsTrue(crit.Operand is Criterium);

            crit = crit.Operand as Criterium;
            Assert.IsTrue(crit.Type == Operator.EQ);
            Assert.AreEqual("text", crit.Modifier);
            Assert.IsTrue(crit.Operand is UntypedValue);
        }
コード例 #20
0
        public void HandleNumberParam()
        {
            var p1 = new NumberValue(18);

            Assert.AreEqual("18", p1.ToString());

            var p2 = NumberValue.Parse("18");

            Assert.AreEqual(18M, p2.Value);

            var p3 = NumberValue.Parse("18.00");

            Assert.AreEqual(18.00M, p3.Value);

            var crit = Criterium.Parse("paramX=18.34");
            var p4   = ((UntypedValue)crit.Operand).AsNumberValue();

            Assert.AreEqual(18.34M, p4.Value);
        }
コード例 #21
0
        public void HandleStringParam()
        {
            var p1 = new StringValue("Hello, world");

            Assert.AreEqual(@"Hello\, world", p1.ToString());

            var p2 = new StringValue("Pay $300|Pay $100|");

            Assert.AreEqual(@"Pay \$300\|Pay \$100\|", p2.ToString());

            var p3 = StringValue.Parse(@"Pay \$300\|Pay \$100\|");

            Assert.AreEqual("Pay $300|Pay $100|", p3.Value);

            var crit = Criterium.Parse(@"paramX=Hello\, world");
            var p4   = ((UntypedValue)crit.Operand).AsStringValue();

            Assert.AreEqual("Hello, world", p4.Value);
        }
コード例 #22
0
        public Criterium GetNormalizedReferenceCriteria(Criterium c)
        {
            if (c == null)
            {
                throw new ArgumentNullException(nameof(c));
            }

            Expression operand;

            if (c.Operand is ChoiceValue choiceOperand)
            {
                var normalizedChoicesList = new ChoiceValue(
                    choiceOperand.Choices.Select(choice =>
                                                 GetNormalizedReferenceValue(choice as UntypedValue, c.Modifier))
                    .Where(normalizedValue => normalizedValue != null)
                    .ToList());

                if (!normalizedChoicesList.Choices.Any())
                {
                    return(null); // Choice operator without choices: ignore it.
                }

                operand = normalizedChoicesList;
            }
            else
            {
                var normalizedValue = GetNormalizedReferenceValue(c.Operand as UntypedValue, c.Modifier);
                if (normalizedValue == null)
                {
                    return(null);
                }

                operand = normalizedValue;
            }

            var cloned = c.Clone();

            cloned.Modifier = null;
            cloned.Operand  = operand;
            cloned.SearchParameters.AddRange(c.SearchParameters);
            return(cloned);
        }
コード例 #23
0
        internal static List <string> GetTargetedReferenceTypes(this Criterium chainCriterium, string resourceType)
        {
            if (chainCriterium.Operator != Operator.CHAIN)
            {
                throw new ArgumentException("Targeted reference types are only relevent for chained criteria.");
            }

            var critSp        = chainCriterium.FindSearchParamDefinition(resourceType);
            var modifier      = chainCriterium.Modifier;
            var nextInChain   = (Criterium)chainCriterium.Operand;
            var nextParameter = nextInChain.ParamName;
            // The modifier contains the type of resource that the referenced resource must be. It is optional.
            // If not present, search all possible types of resources allowed at this reference.
            // If it is present, it should be of one of the possible types.

            var searchResourceTypes = GetTargetedReferenceTypes(critSp, modifier);

            // Afterwards, filter on the types that actually have the requested searchparameter.
            return(searchResourceTypes.Where(rt => InternalField.All.Contains(nextParameter) || UniversalField.All.Contains(nextParameter) || ModelInfo.SearchParameters.Exists(sp => rt.Equals(sp.Resource) && nextParameter.Equals(sp.Name))).ToList());
        }
コード例 #24
0
        public void SerializeChain()
        {
            var crit = new Criterium
            {
                ParamName = "par1",
                Modifier  = "type1",
                Type      = Operator.CHAIN,
                Operand   =
                    new Criterium
                {
                    ParamName = "par2",
                    Type      = Operator.CHAIN,
                    Operand   =
                        new Criterium {
                        ParamName = "par3", Modifier = "text", Type = Operator.EQ, Operand = new StringValue("hoi")
                    }
                }
            };

            Assert.AreEqual("par1:type1.par2.par3:text=hoi", crit.ToString());
        }
コード例 #25
0
        internal static IMongoQuery ToFilter(this Criterium param, string resourceType)
        {
            //Maybe it's a generic parameter.
            MethodInfo methodForParameter = FixedQueries.Find(m => m.Name.Equals(param.ParamName + "FixedQuery"));

            if (methodForParameter != null)
            {
                return((IMongoQuery)methodForParameter.Invoke(null, new object[] { param }));
            }

            //Otherwise it should be a parameter as defined in the metadata
            var critSp = FindSearchParamDefinition(param, resourceType);

            if (critSp != null)
            {
                // todo: DSTU2 - modifier not in SearchParameter
                return(CreateFilter(critSp, param.Operator, param.Modifier, param.Operand));
                //return null;
            }

            throw new ArgumentException(String.Format("Resource {0} has no parameter with the name {1}.", resourceType, param.ParamName));
        }
コード例 #26
0
        public void HandleQuantityParam()
        {
            var p1 = new QuantityValue(3.141M, "http://unitsofmeasure.org", "mg");

            Assert.AreEqual("3.141|http://unitsofmeasure.org|mg", p1.ToString());

            var p2 = new QuantityValue(3.141M, "mg");

            Assert.AreEqual("3.141||mg", p2.ToString());

            var p3 = new QuantityValue(3.141M, "http://system.com/id$4", "$/d");

            Assert.AreEqual(@"3.141|http://system.com/id\$4|\$/d", p3.ToString());

            var p4 = QuantityValue.Parse("3.141|http://unitsofmeasure.org|mg");

            Assert.AreEqual(3.141M, p4.Number);
            Assert.AreEqual("http://unitsofmeasure.org", p4.Namespace);
            Assert.AreEqual("mg", p4.Unit);

            var p5 = QuantityValue.Parse("3.141||mg");

            Assert.AreEqual(3.141M, p5.Number);
            Assert.IsNull(p5.Namespace);
            Assert.AreEqual("mg", p5.Unit);

            var p6 = QuantityValue.Parse(@"3.141|http://system.com/id\$4|\$/d");

            Assert.AreEqual(3.141M, p6.Number);
            Assert.AreEqual("http://system.com/id$4", p6.Namespace);
            Assert.AreEqual("$/d", p6.Unit);

            var crit = Criterium.Parse("paramX=3.14||mg");
            var p7   = ((UntypedValue)crit.Operand).AsQuantityValue();

            Assert.AreEqual(3.14M, p7.Number);
            Assert.IsNull(p7.Namespace);
            Assert.AreEqual("mg", p7.Unit);
        }
コード例 #27
0
        public void SerializeCriterium()
        {
            var crit = new Criterium {
                ParamName = "paramX", Modifier = "modif1", Operand = new NumberValue(18), Type = Operator.GTE
            };

            Assert.AreEqual("paramX:modif1=>=18", crit.ToString());

            crit = new Criterium {
                ParamName = "paramX", Operand = new NumberValue(18)
            };
            Assert.AreEqual("paramX=18", crit.ToString());

            crit = new Criterium {
                ParamName = "paramX", Type = Operator.ISNULL
            };
            Assert.AreEqual("paramX:missing=true", crit.ToString());

            crit = new Criterium {
                ParamName = "paramX", Type = Operator.NOTNULL
            };
            Assert.AreEqual("paramX:missing=false", crit.ToString());
        }
コード例 #28
0
ファイル: MartenFhirIndex.cs プロジェクト: jjrdk/spark
        /// <inheritdoc />
        public async Task <SearchResults> Search(string resource, SearchParams searchCommand)
        {
            _logger.LogDebug($"{resource} search requested with {searchCommand.ToUriParamList().ToQueryString()}");
            var resources = await GetIndexValues(resource, searchCommand).ConfigureAwait(false);

            var count = resources.Count;

            if (searchCommand.Count.HasValue && searchCommand.Count.Value > 0)
            {
                resources = resources.Take(searchCommand.Count.Value).ToList();
            }

            var keys    = resources.ToList();
            var results = new SearchResults
            {
                MatchCount   = count,
                UsedCriteria = searchCommand.Parameters.Select(t => Criterium.Parse(t.Item1, t.Item2)).ToList()
            };

            results.AddRange(keys);

            return(results);
        }
コード例 #29
0
        private static IMongoQuery CompositeQuery(ModelInfo.SearchParamDefinition parameterDef, Operator optor, String modifier, ValueExpression operand)
        {
            if (optor == Operator.IN)
            {
                var choices = ((ChoiceValue)operand);
                var queries = new List <IMongoQuery>();
                foreach (var choice in choices.Choices)
                {
                    queries.Add(CompositeQuery(parameterDef, Operator.EQ, modifier, choice));
                }
                return(M.Query.Or(queries));
            }
            else if (optor == Operator.EQ)
            {
                var typedOperand = (CompositeValue)operand;
                var queries      = new List <IMongoQuery>();
                var components   = typedOperand.Components;
                var subParams    = parameterDef.CompositeParams;

                if (components.Count() != subParams.Count())
                {
                    throw new ArgumentException(String.Format("Parameter {0} requires exactly {1} composite values, not the currently provided {2} values.", parameterDef.Name, subParams.Count(), components.Count()));
                }

                for (int i = 0; i < subParams.Count(); i++)
                {
                    var subCrit = new Criterium();
                    subCrit.Operator  = Operator.EQ;
                    subCrit.ParamName = subParams[i];
                    subCrit.Operand   = components[i];
                    subCrit.Modifier  = modifier;
                    queries.Add(subCrit.ToFilter(parameterDef.Resource));
                }
                return(M.Query.And(queries));
            }
            throw new ArgumentException(String.Format("Invalid operator {0} on composite parameter {1}", optor.ToString(), parameterDef.Name));
        }
コード例 #30
0
        /// <summary>
        /// Getting Max Value from Criterium list
        /// </summary>
        /// <param name="critTable">Criterium - weight of criterium</param>
        /// <returns></returns>
        private Criterium GetMaxFromCrit
            (Dictionary <Criterium, int> critTable)
        {
            int       maxVal = 0;
            Criterium crit   = new Criterium();

            foreach (KeyValuePair <Criterium, int> critPair in criteriumTable)
            {
                if (maxVal < critPair.Value)
                {
                    maxVal = critPair.Value;
                }
            }

            foreach (KeyValuePair <Criterium, int> critPair in criteriumTable)
            {
                if (critPair.Value == maxVal)
                {
                    crit = critPair.Key;
                }
            }

            return(crit);
        }
コード例 #31
0
ファイル: MongoSearcher.cs プロジェクト: Condeti/spark
        /// <summary>
        /// Change something like Condition/subject:Patient=Patient/10014 
        /// to Condition/subject:Patient.internal_id=Patient/10014, so it is correctly handled as a chained parameter, 
        /// including the filtering on the type in the modifier (if any).
        /// </summary>
        /// <param name="criteria"></param>
        /// <param name="resourceType"></param>
        /// <returns></returns>
        private List<Criterium> NormalizeNonChainedReferenceCriteria(List<Criterium> criteria, string resourceType)
        {
            var result = new List<Criterium>();

            foreach (var crit in criteria)
            {
                var critSp = crit.FindSearchParamDefinition(resourceType);
//                var critSp_ = _fhirModel.FindSearchParameter(resourceType, crit.ParamName); HIER VERDER: kunnen meerdere searchParameters zijn, hoewel dat alleen bij subcriteria van chains het geval is...
                if (critSp != null && critSp.Type == SearchParamType.Reference && crit.Operator != Operator.CHAIN && crit.Modifier != Modifier.MISSING && crit.Operand != null)
                {
                    var subCrit = new Criterium();
                    subCrit.Operator = crit.Operator;
                    string modifier = crit.Modifier;

                    //operand can be one of three things:
                    //1. just the id: 10014 (in the index as internal_justid), the type could be in the modifier
                    //2. full id: Patient/10014 (in the index as internal_id), the type in the modifier is no longer relevant
                    //3. full url: http://localhost:xyz/fhir/Patient/100014, the type in the modifier is also no longer relevant.
                    string operand = (crit.Operand as UntypedValue).Value;
                    if (!operand.Contains("/")) //Situation 1
                    {
                        if (String.IsNullOrWhiteSpace(modifier)) // no modifier, so no info about the referenced type at all
                        {
                            subCrit.ParamName = InternalField.JUSTID;
                            subCrit.Operand = new UntypedValue(operand);
                        }
                        else //modifier contains the referenced type
                        {
                            subCrit.ParamName = InternalField.ID;
                            subCrit.Operand = new UntypedValue(modifier + "/" + operand);
                        }
                    }
                    else //Situation 2 or Situation 3 .
                    {
                        subCrit.ParamName = InternalField.ID;

                        Uri uriOperand;
                        if (Uri.TryCreate(operand, UriKind.RelativeOrAbsolute, out uriOperand)) //Situation 3
                        {
                            var refUri = _localhost.RemoveBase(uriOperand); //Drop the first part if it points to our own server.
                            subCrit.Operand = new UntypedValue(refUri.ToString().TrimStart(new char[] { '/' }));
                        }
                        else
                        {
                            subCrit.Operand = new UntypedValue(operand);
                        }
                    }
                    //subCrit.Operand = crit.Operand;

                    var superCrit = new Criterium();
                    superCrit.ParamName = crit.ParamName;
                    superCrit.Modifier = crit.Modifier;
                    superCrit.Operator = Operator.CHAIN;
                    superCrit.Operand = subCrit;
                    superCrit.SearchParameters.AddRange(crit.SearchParameters);

                    result.Add(superCrit);
                }
                else result.Add(crit);
            }

            return result;
        }
コード例 #32
0
 internal static IMongoQuery _securityFixedQuery(Criterium crit)
 {
     return TagQuery(crit, Tag.FHIRTAGSCHEME_SECURITY);
 }
コード例 #33
0
ファイル: MongoSearcher.cs プロジェクト: Condeti/spark
        private bool TryEnrichCriteriumWithSearchParameters(Criterium criterium, ResourceType resourceType)
        {
            var sp = _fhirModel.FindSearchParameter(resourceType, criterium.ParamName);
            if (sp == null)
            {
                return false;
            }

            var result = true;

            var spDef = sp.GetOriginalDefinition();

            if (spDef != null)
            {
                criterium.SearchParameters.Add(spDef);
            }

            if (criterium.Operator == Operator.CHAIN)
            {
                var subCrit = (Criterium)(criterium.Operand);
                foreach (var targetType in criterium.SearchParameters.SelectMany(spd => spd.Target))
                {
                    result &= TryEnrichCriteriumWithSearchParameters(subCrit, targetType);
                }
            }
            return result;
        }
コード例 #34
0
ファイル: ExpressionTests.cs プロジェクト: tiloc/fhir-net-api
        public void SerializeCriterium()
        {
            var crit = new Criterium { ParamName = "paramX", Modifier = "modif1", Operand = new NumberValue(18), Type = Operator.GTE };
            Assert.AreEqual("paramX:modif1=>=18", crit.ToString());

            crit = new Criterium { ParamName = "paramX", Operand = new NumberValue(18) };
            Assert.AreEqual("paramX=18", crit.ToString());

            crit = new Criterium { ParamName = "paramX", Type = Operator.ISNULL };
            Assert.AreEqual("paramX:missing=true", crit.ToString());

            crit = new Criterium { ParamName = "paramX", Type = Operator.NOTNULL };
            Assert.AreEqual("paramX:missing=false", crit.ToString());
        }
コード例 #35
0
        //internal static IMongoQuery _idFixedQuery(Criterium crit)
        //{
        //    return StringQuery(InternalField.JUSTID, crit.Operator, "exact", (ValueExpression)crit.Operand);
        //}

        internal static IMongoQuery internal_idFixedQuery(Criterium crit)
        {
            return StringQuery(InternalField.ID, crit.Operator, "exact", (ValueExpression)crit.Operand);
        }
コード例 #36
0
        private static IMongoQuery CompositeQuery(ModelInfo.SearchParamDefinition parameterDef, Operator optor, String modifier, ValueExpression operand)
        {
            if (optor == Operator.IN)
            {
                var choices = ((ChoiceValue)operand);
                var queries = new List<IMongoQuery>();
                foreach (var choice in choices.Choices)
                {
                    queries.Add(CompositeQuery(parameterDef, Operator.EQ, modifier, choice));
                }
                return M.Query.Or(queries);
            }
            else if (optor == Operator.EQ)
            {
                var typedOperand = (CompositeValue)operand;
                var queries = new List<IMongoQuery>();
                var components = typedOperand.Components;
                var subParams = parameterDef.CompositeParams;

                if (components.Count() != subParams.Count())
                {
                    throw new ArgumentException(String.Format("Parameter {0} requires exactly {1} composite values, not the currently provided {2} values.", parameterDef.Name, subParams.Count(), components.Count()));
                }

                for (int i = 0; i < subParams.Count(); i++)
                {
                    var subCrit = new Criterium();
                    subCrit.Operator = Operator.EQ;
                    subCrit.ParamName = subParams[i];
                    subCrit.Operand = components[i];
                    subCrit.Modifier = modifier;
                    queries.Add(subCrit.ToFilter(parameterDef.Resource));
                }
                return M.Query.And(queries);
            }
            throw new ArgumentException(String.Format("Invalid operator {0} on composite parameter {1}", optor.ToString(), parameterDef.Name));
        }
コード例 #37
0
ファイル: MongoSearcher.cs プロジェクト: raysearchlabs/spark
        /// <summary>
        /// Change something like Condition/subject:Patient=Patient/10014 
        /// to Condition/subject:Patient.internal_id=Patient/10014, so it is correctly handled as a chained parameter, 
        /// including the filtering on the type in the modifier (if any).
        /// </summary>
        /// <param name="criteria"></param>
        /// <param name="resourceType"></param>
        /// <returns></returns>
        private List<Criterium> NormalizeNonChainedReferenceCriteria(List<Criterium> criteria, string resourceType)
        {
            var result = new List<Criterium>();

            foreach (var crit in criteria)
            {
                var critSp = crit.FindSearchParamDefinition(resourceType);
                if (critSp != null && critSp.Type == Conformance.SearchParamType.Reference && crit.Type != Operator.CHAIN)
                {
                    var subCrit = new Criterium();
                    subCrit.ParamName = InternalField.ID;
                    subCrit.Type = crit.Type;
                    subCrit.Operand = crit.Operand;

                    var superCrit = new Criterium();
                    superCrit.ParamName = crit.ParamName;
                    superCrit.Modifier = crit.Modifier;
                    superCrit.Type = Operator.CHAIN;
                    superCrit.Operand = subCrit;

                    result.Add(superCrit);
                }
                else result.Add(crit);
            }

            return result;
        }
コード例 #38
0
 internal static IMongoQuery _profileFixedQuery(Criterium crit)
 {
     return TagQuery(crit, Tag.FHIRTAGSCHEME_PROFILE);
 }
コード例 #39
0
 internal static IMongoQuery _tagFixedQuery(Criterium crit)
 {
     return TagQuery(crit, Tag.FHIRTAGSCHEME_GENERAL);
 }
コード例 #40
0
 internal static IMongoQuery _profileFixedQuery(Criterium crit)
 {
     return TagQuery(crit, new Uri(XmlNs.TAG_PROFILE, UriKind.Absolute));
 }
コード例 #41
0
 internal static IMongoQuery _securityFixedQuery(Criterium crit)
 {
     return TagQuery(crit, new Uri(XmlNs.TAG_SECURITY, UriKind.Absolute));
 }
コード例 #42
0
 internal static IMongoQuery _tagFixedQuery(Criterium crit)
 {
     return TagQuery(crit, new Uri(XmlNs.FHIRTAG, UriKind.Absolute));
 }
コード例 #43
0
ファイル: MongoSearcher.cs プロジェクト: Condeti/spark
        /// <summary>
        /// CloseCriterium("patient.name=\"Teun\"") -> "patient IN (id1,id2)"
        /// </summary>
        /// <param name="resourceType"></param>
        /// <param name="crit"></param>
        /// <returns></returns>
        private Criterium CloseCriterium(Criterium crit, string resourceType, int level)
        {

            List<string> targeted = crit.GetTargetedReferenceTypes(resourceType);
            List<string> allKeys = new List<string>();
            var errors = new List<Exception>();
            foreach (var target in targeted)
            {
                try {
                    Criterium innerCriterium = (Criterium)crit.Operand;
                    var keys = CollectKeys(target, new List<Criterium> { innerCriterium }, ++level);               //Recursive call to CollectKeys!
                    allKeys.AddRange(keys.Select(k => k.ToString()));
                }
                catch (Exception ex)
                {
                    errors.Add(ex);
                }
                }
            if (errors.Count == targeted.Count())
            {
                //It is possible that some of the targets don't support the current parameter. But if none do, there is a serious problem.
                throw new ArgumentException(String.Format("None of the possible target resources support querying for parameter {0}", crit.ParamName));
            }
            crit.Operator = Operator.IN;
            crit.Operand = ChoiceValue.Parse(String.Join(",", allKeys));
            return crit;
        }
コード例 #44
0
ファイル: ExpressionTests.cs プロジェクト: tiloc/fhir-net-api
        public void SerializeChain()
        {
            var crit = new Criterium
            {
                ParamName = "par1",
                Modifier = "type1",
                Type = Operator.CHAIN,
                Operand =
                    new Criterium
                    {
                        ParamName = "par2",
                        Type = Operator.CHAIN,
                        Operand =
                            new Criterium { ParamName = "par3", Modifier = "text", Type = Operator.EQ, Operand = new StringValue("hoi") }
                    }
            };

            Assert.AreEqual("par1:type1.par2.par3:text=hoi", crit.ToString());
        }
コード例 #45
0
ファイル: MongoSearcher.cs プロジェクト: raysearchlabs/spark
 /// <summary>
 /// CloseCriterium("patient.name=\"Teun\"") -> "patient=id1,id2"
 /// </summary>
 /// <param name="resourceType"></param>
 /// <param name="crit"></param>
 /// <returns></returns>
 private Criterium CloseCriterium(Criterium crit, string resourceType)
 {
     List<string> targeted = crit.GetTargetedReferenceTypes(resourceType);
     List<string> allKeys = new List<string>();
     foreach (var target in targeted)
     {
         var keys = CollectKeys(target, new List<Criterium> { (Criterium)crit.Operand });               //Recursive call to CollectKeys!
         allKeys.AddRange(keys.Select(k => k.ToString()));
     }
     crit.Type = Operator.IN;
     crit.Operand = ChoiceValue.Parse(String.Join(",", allKeys));
     return crit;
 }
コード例 #46
0
        private static IMongoQuery TagQuery(Criterium crit, Uri tagscheme)
        {
            if (crit.Type == Operator.IN)
            {
                IEnumerable<ValueExpression> opMultiple = ((ChoiceValue)crit.Operand).Choices;
                var optionQueries = new List<IMongoQuery>();
                foreach (var choice in opMultiple)
                {
                    Criterium option = new Criterium();
                    option.Type = Operator.EQ;
                    option.Operand = choice;
                    option.Modifier = crit.Modifier;
                    option.ParamName = crit.ParamName;
                    optionQueries.Add(TagQuery(option, tagscheme));
                }
                return M.Query.Or(optionQueries);
            }

            //From here there's only 1 operand.
            IMongoQuery schemeQuery = M.Query.EQ(InternalField.TAGSCHEME, tagscheme.AbsoluteUri);
            IMongoQuery argQuery;

            var operand = (ValueExpression)crit.Operand;
            switch (crit.Modifier)
            {
                case Modifier.PARTIAL:
                    argQuery = StringQuery(InternalField.TAGTERM, Operator.EQ, Modifier.NONE, operand);
                    break;
                case Modifier.TEXT:
                    argQuery = StringQuery(InternalField.TAGLABEL, Operator.EQ, Modifier.NONE, operand);
                    break;
                case Modifier.NONE:
                case null:
                    argQuery = StringQuery(InternalField.TAGTERM, Operator.EQ, Modifier.EXACT, operand);
                    break;
                default:
                    throw new ArgumentException(String.Format("Invalid modifier {0} in parameter {1}", crit.Modifier, crit.ParamName));
            }

            return M.Query.ElemMatch(InternalField.TAG, M.Query.And(schemeQuery, argQuery));
        }