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})."); } } }
public override IAsyncEnumerable <Path> ComputePaths(EvaluationContext ctx) { bool found = ctx.TryGetVariable(VariableName, out TemplateVariable variableEntry); return(found ? variableEntry.ResolvePaths() : AsyncUtil.Empty <Path>()); }
/// <summary> /// If the <see cref="EvaluationFunction"/> returns an model <see cref="Entity"/>, this function returns /// the possible <see cref="Path"/>s leading to the returned <see cref="Entity"/>. The result is computed in /// the form of <see cref="IEnumerable{Path}"/>. /// A static <see cref="EvaluationContext"/> is provided in case some of the arguments had to be evaluated /// before calling the APIs in order to compute the required paths. /// A static <see cref="EvaluationContext"/> is one where any function that accesses an API or any variable that /// should be populated by model entities retrieved from an API will throw exceptions if invoked/accessed. /// </summary> /// <param name="args">The list of un-evaluated function arguments.</param> /// <param name="ctx">The static <see cref="EvaluationContext"/>.</param> public IAsyncEnumerable <Path> ComputePaths(TemplexBase[] args, EvaluationContext ctx) { if (_pathsResolver != null) { return(_pathsResolver.Invoke(args, ctx)); } else { return(AsyncUtil.Empty <Path>()); } }
public override IAsyncEnumerable <Path> ComputeSelect(EvaluationContext ctx) { if (Template == null) { return(AsyncUtil.Empty <Path>()); } var scopedCtx = GetScopeLocalContext(ctx); return(Template.ComputeSelect(scopedCtx)); }
/// <summary> /// If the variable contains a model <see cref="Entity"/>, this function should return the base /// <see cref="Path"/>(s) of this entity, which include the <see cref="QueryInfo"/> it will be loaded from /// </summary> public IAsyncEnumerable <Path> ResolvePaths() { if (_pathsResolver != null) { return(_pathsResolver.Invoke()); } else { return(AsyncUtil.Empty <Path>()); } }
/// <summary> /// Compute the list of API calls and SELECTs (in the form of <see cref="IEnumerable{Path}"/>) that are /// needed for <see cref="Evaluate()"/> to run correctly. /// </summary> public IAsyncEnumerable <Path> ResolveSelect() { if (_selectResolver != null) { return(_selectResolver.Invoke()); } else { return(AsyncUtil.Empty <Path>()); } }
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."); } } }
public override IAsyncEnumerable <Path> ComputePaths(EvaluationContext ctx) { return(AsyncUtil.Empty <Path>()); }
public override IAsyncEnumerable <Path> ComputePaths(EvaluationContext ctx) { // Constants aren't based on any paths return(AsyncUtil.Empty <Path>()); }
public override IAsyncEnumerable <Path> ComputeSelect(EvaluationContext ctx) { // Constants don't need any select return(AsyncUtil.Empty <Path>()); }