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;
}