private object ProcessValuesRecursive()

in src/Microsoft.Atlas.CommandLine/Execution/ValuesEngine.cs [62:161]


        private object ProcessValuesRecursive(object source, IList<object> contexts, bool promoteArrays)
        {
            if (source is IDictionary<object, object> sourceDictionary)
            {
                var arrayIsPromoting = false;
                var arrayLength = 0;

                void CheckArrayIsPromoting(object result)
                {
                    if (promoteArrays && result is IList<object> resultArray)
                    {
                        if (!arrayIsPromoting)
                        {
                            arrayIsPromoting = true;
                            arrayLength = resultArray.Count();
                        }
                        else
                        {
                            if (arrayLength != resultArray.Count())
                            {
                                throw new ApplicationException("Foreach arrays must all be same size");
                            }
                        }
                    }
                }

                var output = new Dictionary<object, object>();
                foreach (var kv in sourceDictionary)
                {
                    var propertyName = Convert.ToString(kv.Key, CultureInfo.InvariantCulture);
                    if (propertyName.StartsWith('(') && propertyName.EndsWith(')'))
                    {
                        var propertyGroupings = contexts
                            .Select(eachContext =>
                            {
                                var eachPropertyName = _jmesPathQuery.Search(propertyName, eachContext);
                                return (eachPropertyName, eachContext);
                            })
                            .ToList()
                            .GroupBy(x => x.eachPropertyName, x => x.eachContext);

                        foreach (var propertyGrouping in propertyGroupings)
                        {
                            var result = ProcessValuesRecursive(kv.Value, propertyGrouping.ToList(), promoteArrays: promoteArrays);
                            output[propertyGrouping.Key] = result;
                            CheckArrayIsPromoting(result);
                        }
                    }
                    else
                    {
                        var result = ProcessValuesRecursive(kv.Value, contexts, promoteArrays: promoteArrays);
                        output[propertyName] = result;
                        CheckArrayIsPromoting(result);
                    }
                }

                if (arrayIsPromoting)
                {
                    var arrayOutput = new List<object>();
                    for (var index = 0; index < arrayLength; ++index)
                    {
                        var arrayItem = output.ToDictionary(kv => kv.Key, kv => kv.Value is IList<object> valueArray ? valueArray[index] : kv.Value);
                        arrayOutput.Add(arrayItem);
                    }

                    return arrayOutput;
                }

                return output;
            }

            if (source is IList<object> sourceList)
            {
                return sourceList.Select(value => ProcessValuesRecursive(value, contexts, promoteArrays: promoteArrays)).ToList();
            }

            if (source is string sourceString)
            {
                if (sourceString.StartsWith('(') && sourceString.EndsWith(')'))
                {
                    var mergedResult = default(object);
                    foreach (var context in contexts)
                    {
                        var result = _jmesPathQuery.Search(sourceString, context);
                        if (result is IList<object> resultList && mergedResult is IList<object> mergedList)
                        {
                            mergedResult = mergedList.Concat(resultList).ToList();
                        }
                        else
                        {
                            mergedResult = MergeUtils.Merge(result, mergedResult);
                        }
                    }

                    return mergedResult;
                }
            }

            return source;
        }