Пример #1
0
        public override async IAsyncEnumerable <Path> ComputeSelect(EvaluationContext ctx)
        {
            if (ListCandidate != null && Template != null)
            {
                // Expression select
                var select = ListCandidate.ComputeSelect(ctx);
                await foreach (var atom in select)
                {
                    yield return(atom);
                }

                // Expression paths
                var paths = ListCandidate.ComputePaths(ctx);
                await foreach (var path in paths)
                {
                    yield return(path.Append("Id"));
                }

                // Inner template select
                var scopedCtx = ctx.Clone();
                scopedCtx.SetLocalVariable(IteratorVariableName, new EvaluationVariable(
                                               eval: TemplateUtil.VariableThatThrows(IteratorVariableName),
                                               selectResolver: () => select,
                                               pathsResolver: () => paths
                                               ));

                await foreach (var atom in Template.ComputeSelect(scopedCtx))
                {
                    yield return(atom);
                }
            }
        }
Пример #2
0
        public override async Task GenerateOutputs(EvaluationContext ctx)
        {
            _listCandidate ??= TemplexBase.Parse(ListExpression);

            if (_listCandidate != null)
            {
                var listObj = (await _listCandidate.Evaluate(ctx)) ?? new List <object>();
                if (listObj is IList list)
                {
                    foreach (var listItem in list)
                    {
                        // Initialize new evaluation context with the new variable in it
                        var scopedCtx = ctx.Clone();
                        scopedCtx.SetLocalVariable(IteratorVariableName, new EvaluationVariable(
                                                       evalAsync: () => Task.FromResult(listItem),
                                                       selectResolver: () => AsyncUtil.Empty <Path>(), // It doesn't matter when generating output
                                                       pathsResolver: () => AsyncUtil.Empty <Path>()   // It doesn't matter when generating output
                                                       ));

                        // Run the template again on that context
                        await Inner.GenerateOutputs(scopedCtx);
                    }
                }
                else
                {
                    throw new TemplateException($"Expression does not evaluate to a list ({_listCandidate}).");
                }
            }
        }
Пример #3
0
        public override async Task GenerateOutputs(EvaluationContext ctx)
        {
            if (ctx.TryGetApiResult(QueryInfo, out object result))
            {
                ctx = ctx.Clone();
                ctx.SetLocalVariable(VariableName, new EvaluationVariable(value: result));
            }

            await Inner.GenerateOutputs(ctx);
        }
Пример #4
0
        /// <summary>
        /// Clones the <see cref="EvaluationContext"/> and returns a new one that contains the new variable.
        /// </summary>
        private EvaluationContext GetScopeLocalContext(EvaluationContext ctx)
        {
            var variable = new EvaluationVariable(
                evalAsync: () => Value.Evaluate(ctx),
                selectResolver: () => Value.ComputeSelect(ctx),
                pathsResolver: () => Value.ComputePaths(ctx));

            var ctxClone = ctx.Clone();

            ctxClone.SetLocalVariable(VariableName, variable);

            return(ctxClone);
        }
Пример #5
0
        public override async IAsyncEnumerable <Path> ComputeSelect(EvaluationContext ctx)
        {
            var ctxClone = ctx.Clone();

            ctxClone.SetLocalVariable(VariableName, new EvaluationVariable(
                                          eval: TemplateUtil.VariableThatThrows(varName: VariableName), // This is what makes it a "static" context
                                          pathsResolver: () => AsyncUtil.Singleton(Path.Empty(QueryInfo))
                                          ));

            await foreach (var path in Inner.ComputeSelect(ctxClone))
            {
                yield return(path);
            }
        }
Пример #6
0
        /// <summary>
        /// Clones the <see cref="EvaluationContext"/> and returns a new one that contains the new variable.
        /// </summary>
        private EvaluationContext GetScopeLocalContext(EvaluationContext ctx)
        {
            _varExpression ??= TemplexBase.Parse(VariableExpression);

            var variable = new EvaluationVariable(
                evalAsync: () => _varExpression.Evaluate(ctx),
                selectResolver: () => _varExpression.ComputeSelect(ctx),
                pathsResolver: () => _varExpression.ComputePaths(ctx));

            var ctxClone = ctx.Clone();

            ctxClone.SetLocalVariable(VariableName, variable);

            return(ctxClone);
        }
Пример #7
0
        public override async Task GenerateOutput(StringBuilder builder, EvaluationContext ctx, Func <string, string> encodeFunc = null)
        {
            if (ListCandidate != null && Template != null)
            {
                var listObj = (await ListCandidate.Evaluate(ctx)) ?? new List <object>();
                if (listObj is IList list)
                {
                    int index = 0;
                    foreach (var listItem in list)
                    {
                        // Initialize new evaluation context with the new variable in it
                        var scopedCtx = ctx.Clone();
                        scopedCtx.SetLocalVariable(IteratorVariableName, new EvaluationVariable(
                                                       evalAsync: () => Task.FromResult(listItem),
                                                       selectResolver: () => AsyncUtil.Empty <Path>(), // It doesn't matter when generating output
                                                       pathsResolver: () => AsyncUtil.Empty <Path>()   // It doesn't matter when generating output
                                                       ));

                        // Index, useful for setting line numbers
                        scopedCtx.SetLocalVariable(IteratorVariableName + "_index", new EvaluationVariable(
                                                       evalAsync: () => Task.FromResult <object>(index),
                                                       selectResolver: () => AsyncUtil.Empty <Path>(), // It doesn't matter when generating output
                                                       pathsResolver: () => AsyncUtil.Empty <Path>()   // It doesn't matter when generating output
                                                       ));

                        // Run the template again on that context
                        await Template.GenerateOutput(builder, scopedCtx, encodeFunc);

                        index++;
                    }
                }
                else
                {
                    throw new TemplateException($"Foreach expression could not be applied. Expression ({ListCandidate}) does not evaluate to a list.");
                }
            }
        }