Пример #1
0
        public override Expression GetExpression(IExpressionParser factory)
        {
            // add constraints for the intents property
            if (string.IsNullOrEmpty(this.Intent))
            {
                throw new ArgumentNullException(nameof(this.Intent));
            }

            var intentExpression = factory.Parse($"{TurnPath.RECOGNIZED}.intent == '{this.Intent.TrimStart('#')}'");

            // build expression to be INTENT AND (@ENTITY1 != null AND @ENTITY2 != null)
            if (this.Entities.Any())
            {
                intentExpression = Expression.AndExpression(
                    intentExpression,
                    Expression.AndExpression(this.Entities.Select(entity =>
                {
                    if (entity.StartsWith("@") || entity.StartsWith(TurnPath.RECOGNIZED, StringComparison.InvariantCultureIgnoreCase))
                    {
                        return(factory.Parse($"exists({entity})"));
                    }

                    return(factory.Parse($"exists(@{entity})"));
                }).ToArray()));
            }

            return(Expression.AndExpression(intentExpression, base.GetExpression(factory)));
        }
Пример #2
0
        private Expression CreateSearchExpression(ResourceElement coverage, ResourceElement patient)
        {
            var coverageValues          = _searchIndexer.Extract(coverage);
            var patientValues           = _searchIndexer.Extract(patient);
            var expressions             = new List <Expression>();
            var reverseChainExpressions = new List <Expression>();

            expressions.Add(Expression.SearchParameter(_resourceTypeSearchParameter, Expression.StringEquals(FieldName.TokenCode, null, KnownResourceTypes.Patient, false)));
            foreach (var patientValue in patientValues)
            {
                if (IgnoreInSearch(patientValue))
                {
                    continue;
                }

                var modifier = string.Empty;
                if (patientValue.SearchParameter.Type == ValueSets.SearchParamType.String)
                {
                    modifier = ":exact";
                }

                expressions.Add(_expressionParser.Parse(new[] { KnownResourceTypes.Patient }, patientValue.SearchParameter.Code + modifier, patientValue.Value.ToString()));
            }

            foreach (var coverageValue in coverageValues)
            {
                if (IgnoreInSearch(coverageValue))
                {
                    continue;
                }

                var modifier = string.Empty;
                if (coverageValue.SearchParameter.Type == ValueSets.SearchParamType.String)
                {
                    modifier = ":exact";
                }

                reverseChainExpressions.Add(_expressionParser.Parse(new[] { KnownResourceTypes.Coverage }, coverageValue.SearchParameter.Code + modifier, coverageValue.Value.ToString()));
            }

            if (reverseChainExpressions.Count != 0)
            {
                Expression reverseChainedExpression;
                if (reverseChainExpressions.Count == 1)
                {
                    reverseChainedExpression = reverseChainExpressions[0];
                }
                else
                {
                    reverseChainedExpression = Expression.And(reverseChainExpressions);
                }

                var expression = Expression.Chained(new[] { KnownResourceTypes.Coverage }, _coverageBeneficiaryParameter, new[] { KnownResourceTypes.Patient }, true, reverseChainedExpression);
                expressions.Add(expression);
            }

            return(Expression.And(expressions));
        }
Пример #3
0
 public override Expression GetExpression(IExpressionParser factory)
 {
     // add constraints for activity type
     return(Expression.AndExpression(
                factory.Parse($"{TurnPath.ACTIVITY}.type == '{this.Type}'"),
                base.GetExpression(factory)));
 }
Пример #4
0
        internal void Parse(ExpressionParserHelper parseHelper)
        {
            IgnoreSpaces(parseHelper);
            if (!parseHelper.HasMore())
            {
                return;
            }
            parseHelper.Next();
            Token             current = parseHelper.Current;
            IExpressionParser parser  = null;

            if (current.Type == TokenType.Seperator)
            {
                parser = PARSERS_BY_STR[current.Contents];
            }
            else
            {
                parser = PARSERS_BY_TYPE[typeof(PropertyOrConstant)];
            }
            parser.Parse(parseHelper);
            if (parseHelper.HasMore())
            {
                Parse(parseHelper);
            }
        }
Пример #5
0
        /// <summary>
        /// Parses <paramref name="expression"/> into new <see cref="Expressions.Expression"/> object and inserts it into internal data structure.
        /// </summary>
        /// <param name="expression">Expression in string format</param>
        /// <param name="negative">Whether expression result should be negative</param>
        /// <param name="instanceCreator">Parser instance creator for parsing sub-expressions</param>
        /// <returns></returns>
        public ExpressionBuilder Expression(string expression, bool negative, ConstructNewParser instanceCreator)
        {
            IExpressionParser parser = instanceCreator.Invoke();
            Expression        expr   = parser.Parse(expression, instanceCreator);

            expr.Negative = negative;
            components.AddLast(expr);
            return(this);
        }
        public override Expression GetExpression(IExpressionParser factory)
        {
            var expressions = new List <Expression> {
                base.GetExpression(factory)
            };

            foreach (var property in this.Properties)
            {
                expressions.Add(factory.Parse($"contains(foreach({TurnPath.DIALOGEVENT}.value, mapping, mapping.property), '{property}')"));
            }

            foreach (var entity in this.Entities)
            {
                expressions.Add(factory.Parse($"contains(foreach({TurnPath.DIALOGEVENT}.value, mapping, mapping.entity.name), '{entity}')"));
            }

            return(Expression.AndExpression(expressions.ToArray()));
        }
Пример #7
0
        public override Expression GetExpression(IExpressionParser factory)
        {
            var expressions = new List <Expression> {
                base.GetExpression(factory)
            };

            if (this.Property != null)
            {
                expressions.Add(factory.Parse($"{TurnPath.DIALOGEVENT}.value.property == '{this.Property}'"));
            }

            if (this.Entity != null)
            {
                expressions.Add(factory.Parse($"{TurnPath.DIALOGEVENT}.value.entity.name == '{this.Entity}'"));
            }

            return(Expression.AndExpression(expressions.ToArray()));
        }
Пример #8
0
        public override void Evaluate(IExpressionParser parser, ITemplateContext context, StringBuilder output)
        {
            bool      result = context.ToBoolean(parser.Parse(this.Expression).Evaluate(context).Value);
            TokenNode node   = result ? TrueNode : FalseNode;

            foreach (TokenNode n in node.ChildNodes)
            {
                n.Evaluate(parser, context, output);
            }
        }
Пример #9
0
        public object FetchValue(TDataModel targetObject, string expression)
        {
            var parsedQuery = mParser.Parse(expression);

            if (!parsedQuery.IsValid)
            {
                throw new ArgumentException($"Expression: {expression ?? "<null>"} could not be parsed.");
            }

            return(FetchValue(targetObject, parsedQuery));
        }
Пример #10
0
 private IMathComponent[] ConvertToComponents(string[] expressionArray, ConstructNewParser instanceCreator)
 {
     IMathComponent[] mathComponents = new IMathComponent[expressionArray.Length];
     for (int i = 0; i < expressionArray.Length; i++)
     {
         IExpressionParser parser     = instanceCreator.Invoke();
         Expression        expression = parser.Parse(expressionArray[i], instanceCreator);
         mathComponents[i] = expression;
     }
     return(mathComponents);
 }
        public override Expression GetExpression(IExpressionParser factory)
        {
            // add constraints for the intents property if set
            if (this.Intents?.Any() == true)
            {
                var constraints = this.Intents.Select(subIntent => factory.Parse($"{TurnPath.RECOGNIZED}.intents.chooseintent.{subIntent} != null"));
                return(Expression.AndExpression(base.GetExpression(factory), Expression.AndExpression(constraints.ToArray())));
            }

            return(base.GetExpression(factory));
        }
		private static void CheckPerformance(IExpressionParser expressionParser, string expression)
		{
			var stopwatch = Stopwatch.StartNew();

			Enumerable
				.Range(1, 100)
				.ToList()
				.ForEach(i => expressionParser.Parse<TestEntity>(expression));

			stopwatch.Stop();
			Debug.WriteLine("{0}: {1}", expressionParser.GetType().Name, stopwatch.ElapsedMilliseconds);
		}
Пример #13
0
        public Func <double, double> Compile(string expression)
        {
            expression = expression.ToLower();
            var tree = _Parser.Parse(expression);

            foreach (var opt in _Optimizers)
            {
                tree = opt.Optimize(tree);
            }

            return(_Compiler.Compile(tree));
        }
Пример #14
0
        private AnalyzerResult AnalyzeExpression(string exp)
        {
            var result = new AnalyzerResult();
            exp = exp.TrimExpression();
            var parsed = _expressionParser.Parse(exp);

            var references = parsed.References();

            result.Union(new AnalyzerResult(variables: new List<string>(references)));
            result.Union(this.AnalyzeExpressionDirectly(parsed));

            return result;
        }
Пример #15
0
        public bool Run(IProcessorStorage storage)
        {
            IMathBuffer mathBuffer = storage.Maths;

            List <string>     history          = null;
            IPathReader       pathReader       = null;
            IExpressionParser expressionParser = null;

            if (storage is IProcessorStorageFilesWork ext)
            {
                history          = ext.OperationsHistory.Data;
                pathReader       = ext.FilePathReader;
                expressionParser = ext.MathExpressionParser;
            }
            else
            {
                throw new ArgumentException();
            }

            var     newOperBuffer = new List <string>();
            var     valBuffer     = new List <double>();
            ICalcIO calcIO        = storage.CalcIO;

            using (var file = new StreamReader(pathReader.Read(calcIO)))
            {
                string expression, rawExpression;

                while ((rawExpression = expression = file.ReadLine()) != null)
                {
                    newOperBuffer.Add(expression);

                    double result = expressionParser.Parse(ref expression, valBuffer, calcIO);

                    if (double.IsNaN(result))
                    {
                        calcIO.Write("Parse error!\n");
                        return(true);
                    }

                    calcIO.Write($"[#{ valBuffer.Count }] { rawExpression } = { (rawExpression != expression ? $"{ expression } = " : "") }{ result }\n");
                }
            }

            mathBuffer.Values   = valBuffer;
            mathBuffer.AccValue = valBuffer.Last();

            history.Clear();
            history.AddRange(newOperBuffer);

            return(true);
        }
 /// <summary>
 /// Evaluates expression in input expression
 /// </summary>
 /// <param name="expr">Input expression to evaluate</param>
 /// <returns>Evaluated value</returns>
 public double Evaluate(string expr)
 {
     try
     {
         var ast    = _astParser.Parse(expr);
         var result = _evaluator.Evaluate(ast);
         return(result);
     }
     catch (CoreException ex)
     {
         // format error message from Core
         throw new ExpressionEvaluationFacadeException(ex);
     }
 }
Пример #17
0
        private Lambda CompileExpression(List <Type> argumentsTypes, string expressionTemplate)
        {
            var parametersDefinition = new List <Parameter>();

            for (int i = 0; i < argumentsTypes.Count(); i++)
            {
                var paramName = GetVariableName(i);

                expressionTemplate = expressionTemplate.Replace("{" + i + "}", paramName);
                parametersDefinition.Add(new Parameter(paramName, argumentsTypes[i]));
            }

            var compiledExpression = parser.Parse(expressionTemplate, parametersDefinition.ToArray());

            return(compiledExpression);
        }
Пример #18
0
        public override void Evaluate(IExpressionParser parser, ITemplateContext context, StringBuilder output)
        {
            int index = 1;
            ITemplateContext local = context.CreateLocal();

            while (context.ToBoolean(parser.Parse(this.Expression).Evaluate(context).Value))
            {
                local.AddLocal("index", index);

                foreach (TokenNode node in this.ChildNodes)
                {
                    node.Evaluate(parser, local, output);
                }

                index++;
            }
        }
Пример #19
0
        public void GivenASupportedSearchParam_WhenCreated_ThenCorrectExpressionShouldBeGenerated()
        {
            const ResourceType resourceType = ResourceType.Patient;
            const string       paramName    = "address-city";
            const string       value        = "Seattle";

            Expression expression = Substitute.For <Expression>();

            _expressionParser.Parse(resourceType.ToString(), paramName, value).Returns(expression);

            SearchOptions options = CreateSearchOptions(
                resourceType: resourceType.ToString(),
                queryParameters: new[] { Tuple.Create(paramName, value) });

            Assert.NotNull(options);
            Assert.NotNull(options.Expression);

            ValidateMultiaryExpression(
                options.Expression,
                MultiaryOperator.And,
                e => ValidateResourceTypeSearchParameterExpression(e, resourceType.ToString()),
                e => Assert.Equal(expression, e));
        }
Пример #20
0
        public string Evaluate(string expression)
        {
            IOperand result;

            try
            {
                var infixExpression   = parser.Parse(expression);
                var postfixExpression = postfixConverter.ConvertInfixToPostfix(infixExpression);
                result = postfixCalculator.EvaluateExpression(postfixExpression);
            }
            catch (Exception ex)
            {
                return(ex.Message);
                //throw new ArgumentNullException();
            }

            return(result.Value.ToString());
        }
Пример #21
0
        public override void Evaluate(IExpressionParser parser, ITemplateContext context, StringBuilder output)
        {
            IEnumerable list = parser.Parse(this.Expression).Evaluate(context).Value as IEnumerable;

            if (list != null)
            {
                int rowIndex           = 1;
                ITemplateContext local = context.CreateLocal();
                foreach (object item in list)
                {
                    local.Add(this.Iterator, item, item.GetType());
                    this.EvaluateIterator(local, rowIndex);
                    foreach (TokenNode node in this.ChildNodes)
                    {
                        node.Evaluate(parser, local, output);
                    }
                    rowIndex++;
                }
            }
        }
Пример #22
0
        public void GivenNoneOfTheSearchParamIsSupported_WhenCreated_ThenCorrectExpressionShouldBeGenerated()
        {
            const ResourceType resourceType = ResourceType.Patient;
            const string       paramName1   = "address-city";
            const string       value1       = "Seattle";

            _expressionParser.Parse(resourceType.ToString(), paramName1, value1).Returns(
                x => throw new SearchParameterNotSupportedException(typeof(Patient), paramName1));

            var queryParameters = new[]
            {
                Tuple.Create(paramName1, value1),
            };

            SearchOptions options = CreateSearchOptions(
                resourceType: resourceType.ToString(),
                queryParameters: queryParameters);

            Assert.NotNull(options);
            ValidateResourceTypeSearchParameterExpression(options.Expression, resourceType.ToString());
        }
Пример #23
0
        public override void Evaluate(IExpressionParser parser, ITemplateContext context, StringBuilder output)
        {
            IValueType type = parser.Parse(_Expression).Evaluate(context);

            if (type == null)
            {
                return;
            }
            object value = type.Value;

            if (value != null)
            {
                if (_TokenMatch.SubMatches.ContainsKey("fmt"))
                {
                    output.AppendFormat("{0:" + _TokenMatch.SubMatches["fmt"] + "}", value);
                }
                else
                {
                    output.Append(value.ToString());
                }
            }
        }
Пример #24
0
        private static bool TryParse(string s, IExpressionParser parser, out SqlExpression expression, out Exception error)
        {
            if (parser == null)
            {
                expression = null;
                error      = new ArgumentNullException("parser");
                return(false);
            }

            try {
                var result = parser.Parse(s);
                if (!result.IsValid)
                {
                    var errors = result.Errors;
                    if (errors.Length == 1)
                    {
                        error = new FormatException(errors[0]);
                    }
                    else
                    {
                        // TODO: aggregate the errors ...
                        error = new FormatException(String.Join(", ", errors));
                    }

                    expression = null;
                    return(false);
                }

                expression = result.Expression;
                error      = null;
                return(true);
            } catch (Exception ex) {
                error      = ex;
                expression = null;
                return(false);
            }
        }
Пример #25
0
        /// <summary>
        /// Get the expression for this rule by calling GatherConstraints().
        /// </summary>
        /// <param name="parser">Expression parser.</param>
        /// <returns>Expression which will be cached and used to evaluate this rule.</returns>
        public virtual Expression GetExpression(IExpressionParser parser)
        {
            lock (this.extraConstraints)
            {
                if (this.fullConstraint == null)
                {
                    List <Expression> allExpressions = new List <Expression>();
                    if (!string.IsNullOrWhiteSpace(this.Condition))
                    {
                        try
                        {
                            allExpressions.Add(parser.Parse(this.Condition));
                        }
                        catch (Exception e)
                        {
                            throw new Exception($"Invalid constraint expression: {this.Condition}, {e.Message}");
                        }
                    }

                    if (this.extraConstraints.Any())
                    {
                        allExpressions.AddRange(this.extraConstraints);
                    }

                    if (allExpressions.Any())
                    {
                        return(Expression.AndExpression(allExpressions.ToArray()));
                    }
                    else
                    {
                        return(Expression.ConstantExpression(true));
                    }
                }
            }

            return(this.fullConstraint);
        }
Пример #26
0
        public SearchOptions Create(string compartmentType, string compartmentId, string resourceType, IReadOnlyList <Tuple <string, string> > queryParameters)
        {
            var searchOptions = new SearchOptions();

            string continuationToken = null;

            var searchParams = new SearchParams();
            var unsupportedSearchParameters = new List <Tuple <string, string> >();

            // Extract the continuation token, filter out the other known query parameters that's not search related.
            foreach (Tuple <string, string> query in queryParameters ?? Enumerable.Empty <Tuple <string, string> >())
            {
                if (query.Item1 == KnownQueryParameterNames.ContinuationToken)
                {
                    if (continuationToken != null)
                    {
                        throw new InvalidSearchOperationException(
                                  string.Format(Core.Resources.MultipleQueryParametersNotAllowed, KnownQueryParameterNames.ContinuationToken));
                    }

                    continuationToken = query.Item2;
                }
                else if (query.Item1 == KnownQueryParameterNames.Format)
                {
                    // TODO: We need to handle format parameter.
                }
                else if (string.IsNullOrWhiteSpace(query.Item1) || string.IsNullOrWhiteSpace(query.Item2))
                {
                    // Query parameter with empty value is not supported.
                    unsupportedSearchParameters.Add(query);
                }
                else
                {
                    // Parse the search parameters.
                    try
                    {
                        searchParams.Add(query.Item1, query.Item2);
                    }
                    catch (Exception ex)
                    {
                        _logger.LogInformation(ex, "Failed to parse the query parameter. Skipping.");

                        // There was a problem parsing the parameter. Add it to list of unsupported parameters.
                        unsupportedSearchParameters.Add(query);
                    }
                }
            }

            searchOptions.ContinuationToken = continuationToken;

            // Check the item count.
            if (searchParams.Count != null)
            {
                searchOptions.MaxItemCount = searchParams.Count.Value;
            }

            // Check to see if only the count should be returned
            searchOptions.CountOnly = searchParams.Summary == SummaryType.Count;

            // If the resource type is not specified, then the common
            // search parameters should be used.
            ResourceType parsedResourceType = ResourceType.DomainResource;

            if (!string.IsNullOrWhiteSpace(resourceType) &&
                !Enum.TryParse(resourceType, out parsedResourceType))
            {
                throw new ResourceNotSupportedException(resourceType);
            }

            var searchExpressions = new List <Expression>();

            if (!string.IsNullOrWhiteSpace(resourceType))
            {
                searchExpressions.Add(Expression.SearchParameter(_resourceTypeSearchParameter, Expression.StringEquals(FieldName.TokenCode, null, resourceType, false)));
            }

            searchExpressions.AddRange(searchParams.Parameters.Select(
                                           q =>
            {
                try
                {
                    return(_expressionParser.Parse(parsedResourceType.ToString(), q.Item1, q.Item2));
                }
                catch (SearchParameterNotSupportedException)
                {
                    unsupportedSearchParameters.Add(q);

                    return(null);
                }
            })
                                       .Where(item => item != null));

            if (!string.IsNullOrWhiteSpace(compartmentType))
            {
                if (Enum.TryParse(compartmentType, out CompartmentType parsedCompartmentType))
                {
                    if (string.IsNullOrWhiteSpace(compartmentId))
                    {
                        throw new InvalidSearchOperationException(Core.Resources.CompartmentIdIsInvalid);
                    }

                    searchExpressions.Add(Expression.CompartmentSearch(compartmentType, compartmentId));
                }
                else
                {
                    throw new InvalidSearchOperationException(string.Format(Core.Resources.CompartmentTypeIsInvalid, compartmentType));
                }
            }

            if (searchExpressions.Count == 1)
            {
                searchOptions.Expression = searchExpressions[0];
            }
            else if (searchExpressions.Count > 1)
            {
                searchOptions.Expression = Expression.And(searchExpressions.ToArray());
            }

            if (unsupportedSearchParameters.Any())
            {
                // TODO: Client can specify whether exception should be raised or not when it encounters unknown search parameters.
                // For now, we will ignore any unknown search parameters.
            }

            searchOptions.UnsupportedSearchParams = unsupportedSearchParameters;

            return(searchOptions);
        }
        /// <summary>
        /// Processes expression in string format.
        /// </summary>
        /// <param name="expression">Expression which will be parsed. Expression is converted to lower case characters and all whitespaces are removed</param>
        /// <returns>Processed expression or throws exception based on <see cref="IExpressionParser"/> implementation</returns>
        public Expression ProcessExpression(string expression)
        {
            IExpressionParser parser = InstanceCreator.Invoke();

            return(parser.Parse(Regex.Replace(expression.ToLower(), @"\s+", ""), InstanceCreator));
        }
Пример #28
0
        private static bool TryParse(string s, IExpressionParser parser, out SqlExpression expression, out Exception error)
        {
            if (parser == null) {
                expression = null;
                error = new ArgumentNullException("parser");
                return false;
            }

            try {
                var result = parser.Parse(s);
                if (!result.IsValid) {
                    var errors = result.Errors;
                    if (errors.Length == 1) {
                        error = new FormatException(errors[0]);
                    } else {
                        // TODO: aggregate the errors ...
                        error = new FormatException(String.Join(", ", errors));
                    }

                    expression = null;
                    return false;
                }

                expression = result.Expression;
                error = null;
                return true;
            } catch (Exception ex) {
                error = ex;
                expression = null;
                return false;
            }
        }
Пример #29
0
        public SearchOptions Create(string compartmentType, string compartmentId, string resourceType, IReadOnlyList <Tuple <string, string> > queryParameters)
        {
            var searchOptions = new SearchOptions();

            string continuationToken = null;

            var  searchParams = new SearchParams();
            var  unsupportedSearchParameters = new List <Tuple <string, string> >();
            bool setDefaultBundleTotal       = true;

            // Extract the continuation token, filter out the other known query parameters that's not search related.
            foreach (Tuple <string, string> query in queryParameters ?? Enumerable.Empty <Tuple <string, string> >())
            {
                if (query.Item1 == KnownQueryParameterNames.ContinuationToken)
                {
                    // This is an unreachable case. The mapping of the query parameters makes it so only one continuation token can exist.
                    if (continuationToken != null)
                    {
                        throw new InvalidSearchOperationException(
                                  string.Format(Core.Resources.MultipleQueryParametersNotAllowed, KnownQueryParameterNames.ContinuationToken));
                    }

                    try
                    {
                        continuationToken = System.Text.Encoding.UTF8.GetString(Convert.FromBase64String(query.Item2));
                    }
                    catch (FormatException)
                    {
                        throw new BadRequestException(Core.Resources.InvalidContinuationToken);
                    }

                    setDefaultBundleTotal = false;
                }
                else if (query.Item1 == KnownQueryParameterNames.Format)
                {
                    // TODO: We need to handle format parameter.
                }
                else if (string.IsNullOrWhiteSpace(query.Item1) || string.IsNullOrWhiteSpace(query.Item2))
                {
                    // Query parameter with empty value is not supported.
                    unsupportedSearchParameters.Add(query);
                }
                else if (string.Compare(query.Item1, KnownQueryParameterNames.Total, StringComparison.OrdinalIgnoreCase) == 0)
                {
                    if (Enum.TryParse <TotalType>(query.Item2, true, out var totalType))
                    {
                        ValidateTotalType(totalType);

                        searchOptions.IncludeTotal = totalType;
                        setDefaultBundleTotal      = false;
                    }
                    else
                    {
                        throw new BadRequestException(string.Format(Core.Resources.InvalidTotalParameter, query.Item2, SupportedTotalTypes));
                    }
                }
                else
                {
                    // Parse the search parameters.
                    try
                    {
                        // Basic format checking (e.g. integer value for _count key etc.).
                        searchParams.Add(query.Item1, query.Item2);
                    }
                    catch (Exception ex)
                    {
                        throw new BadRequestException(ex.Message);
                    }
                }
            }

            searchOptions.ContinuationToken = continuationToken;

            if (setDefaultBundleTotal)
            {
                ValidateTotalType(_featureConfiguration.IncludeTotalInBundle);
                searchOptions.IncludeTotal = _featureConfiguration.IncludeTotalInBundle;
            }

            // Check the item count.
            if (searchParams.Count != null)
            {
                if (searchParams.Count > _featureConfiguration.MaxItemCountPerSearch)
                {
                    searchOptions.MaxItemCount = _featureConfiguration.MaxItemCountPerSearch;

                    _contextAccessor.FhirRequestContext.BundleIssues.Add(
                        new OperationOutcomeIssue(
                            OperationOutcomeConstants.IssueSeverity.Information,
                            OperationOutcomeConstants.IssueType.Informational,
                            string.Format(Core.Resources.SearchParamaterCountExceedLimit, _featureConfiguration.MaxItemCountPerSearch, searchParams.Count)));
                }
                else
                {
                    searchOptions.MaxItemCount = searchParams.Count.Value;
                }
            }
            else
            {
                searchOptions.MaxItemCount = _featureConfiguration.DefaultItemCountPerSearch;
            }

            searchOptions.IncludeCount = _featureConfiguration.DefaultIncludeCountPerSearch;

            // Check to see if only the count should be returned
            searchOptions.CountOnly = searchParams.Summary == SummaryType.Count;

            // If the resource type is not specified, then the common
            // search parameters should be used.
            ResourceType parsedResourceType = ResourceType.DomainResource;

            if (!string.IsNullOrWhiteSpace(resourceType) &&
                !Enum.TryParse(resourceType, out parsedResourceType))
            {
                throw new ResourceNotSupportedException(resourceType);
            }

            var searchExpressions = new List <Expression>();

            if (!string.IsNullOrWhiteSpace(resourceType))
            {
                searchExpressions.Add(Expression.SearchParameter(_resourceTypeSearchParameter, Expression.StringEquals(FieldName.TokenCode, null, resourceType, false)));
            }

            searchExpressions.AddRange(searchParams.Parameters.Select(
                                           q =>
            {
                try
                {
                    return(_expressionParser.Parse(parsedResourceType.ToString(), q.Item1, q.Item2));
                }
                catch (SearchParameterNotSupportedException)
                {
                    unsupportedSearchParameters.Add(q);

                    return(null);
                }
            })
                                       .Where(item => item != null));

            if (searchParams.Include?.Count > 0)
            {
                searchExpressions.AddRange(searchParams.Include.Select(
                                               q => _expressionParser.ParseInclude(parsedResourceType.ToString(), q, false /* not reversed */, false /* no iterate */))
                                           .Where(item => item != null));
            }

            if (searchParams.RevInclude?.Count > 0)
            {
                searchExpressions.AddRange(searchParams.RevInclude.Select(
                                               q => _expressionParser.ParseInclude(parsedResourceType.ToString(), q, true /* reversed */, false /* no iterate */))
                                           .Where(item => item != null));
            }

            // Parse _include:iterate (_include:recurse) parameters.
            // :iterate (:recurse) modifiers are not supported by Hl7.Fhir.Rest, hence not added to the Include collection and exist in the Parameters list.
            // See https://github.com/FirelyTeam/fhir-net-api/issues/222
            // _include:iterate (_include:recurse) expression may appear without a preceding _include parameter
            // when applied on a circular reference
            searchExpressions.AddRange(ParseIncludeIterateExpressions(searchParams));

            // remove _include:iterate and _revinclude:iterate parameters from unsupportedSearchParameters
            unsupportedSearchParameters.RemoveAll(p => AllIterateModifiers.Contains(p.Item1));

            if (!string.IsNullOrWhiteSpace(compartmentType))
            {
                if (Enum.TryParse(compartmentType, out CompartmentType parsedCompartmentType))
                {
                    if (string.IsNullOrWhiteSpace(compartmentId))
                    {
                        throw new InvalidSearchOperationException(Core.Resources.CompartmentIdIsInvalid);
                    }

                    searchExpressions.Add(Expression.CompartmentSearch(compartmentType, compartmentId));
                }
                else
                {
                    throw new InvalidSearchOperationException(string.Format(Core.Resources.CompartmentTypeIsInvalid, compartmentType));
                }
            }

            if (searchExpressions.Count == 1)
            {
                searchOptions.Expression = searchExpressions[0];
            }
            else if (searchExpressions.Count > 1)
            {
                searchOptions.Expression = Expression.And(searchExpressions.ToArray());
            }

            if (unsupportedSearchParameters.Any())
            {
                // TODO: Client can specify whether exception should be raised or not when it encounters unknown search parameters.
                // For now, we will ignore any unknown search parameters.
            }

            searchOptions.UnsupportedSearchParams = unsupportedSearchParameters;

            if (searchParams.Sort?.Count > 0)
            {
                var sortings = new List <(SearchParameterInfo, SortOrder)>();
                List <(string parameterName, string reason)> unsupportedSortings = null;

                foreach (Tuple <string, Hl7.Fhir.Rest.SortOrder> sorting in searchParams.Sort)
                {
                    try
                    {
                        SearchParameterInfo searchParameterInfo = _searchParameterDefinitionManager.GetSearchParameter(parsedResourceType.ToString(), sorting.Item1);

                        if (searchParameterInfo.IsSortSupported())
                        {
                            sortings.Add((searchParameterInfo, sorting.Item2.ToCoreSortOrder()));
                        }
                        else
                        {
                            throw new SearchParameterNotSupportedException(string.Format(Core.Resources.SearchSortParameterNotSupported, searchParameterInfo.Name));
                        }
                    }
                    catch (SearchParameterNotSupportedException)
                    {
                        (unsupportedSortings ??= new List <(string parameterName, string reason)>()).Add((sorting.Item1, string.Format(Core.Resources.SearchSortParameterNotSupported, sorting.Item1)));
                    }
                }

                searchOptions.Sort = sortings;
                searchOptions.UnsupportedSortingParams = (IReadOnlyList <(string parameterName, string reason)>)unsupportedSortings ?? Array.Empty <(string parameterName, string reason)>();
            }
            else
            {
                searchOptions.Sort = Array.Empty <(SearchParameterInfo searchParameterInfo, SortOrder sortOrder)>();
                searchOptions.UnsupportedSortingParams = Array.Empty <(string parameterName, string reason)>();
            }

            return(searchOptions);

            IEnumerable <IncludeExpression> ParseIncludeIterateExpressions(SearchParams searchParams)
            {
                return(searchParams.Parameters
                       .Where(p => p != null && AllIterateModifiers.Where(m => string.Equals(p.Item1, m, StringComparison.OrdinalIgnoreCase)).Any())
                       .Select(p =>
                {
                    var includeResourceType = p.Item2?.Split(':')[0];
                    if (!ModelInfoProvider.IsKnownResource(includeResourceType))
                    {
                        throw new ResourceNotSupportedException(includeResourceType);
                    }

                    var reversed = RevIncludeIterateModifiers.Contains(p.Item1);
                    var expression = _expressionParser.ParseInclude(includeResourceType, p.Item2, reversed, true);

                    // Reversed Iterate expressions (not wildcard) must specify target type if there is more than one possible target type
                    if (expression.Reversed && expression.Iterate && expression.TargetResourceType == null && expression.ReferenceSearchParameter?.TargetResourceTypes?.Count > 1)
                    {
                        throw new BadRequestException(string.Format(Core.Resources.RevIncludeIterateTargetTypeNotSpecified, p.Item2));
                    }

                    // For circular include iterate expressions, add an informational issue indicating that a single iteration is supported.
                    // See https://www.hl7.org/fhir/search.html#revinclude.
                    if (expression.Iterate && expression.CircularReference)
                    {
                        _contextAccessor.FhirRequestContext.BundleIssues.Add(
                            new OperationOutcomeIssue(
                                OperationOutcomeConstants.IssueSeverity.Information,
                                OperationOutcomeConstants.IssueType.Informational,
                                string.Format(Core.Resources.IncludeIterateCircularReferenceExecutedOnce, p.Item1, p.Item2)));
                    }

                    return expression;
                }));
            }

            void ValidateTotalType(TotalType totalType)
            {
                // Estimate is not yet supported.
                if (totalType == TotalType.Estimate)
                {
                    throw new SearchOperationNotSupportedException(string.Format(Core.Resources.UnsupportedTotalParameter, totalType, SupportedTotalTypes));
                }
            }
        }
Пример #30
0
 public StaticCountBuilder <T> Where(Expression <Func <T, bool> > expression)
 {
     _queryExpression = _expressionParser.Parse(expression);
     return(this);
 }
        public object FetchValue(TDataModel targetObject, string expression)
        {
            var parsedExpr = mParser.Parse(expression);

            return(FetchValue(targetObject, parsedExpr));
        }
Пример #32
0
 public override Expression GetExpression(IExpressionParser factory)
 {
     return(Expression.AndExpression(factory.Parse($"{TurnPath.DIALOGEVENT}.name == '{this.Event}'"), base.GetExpression(factory)));
 }