using System;
using System.Collections.Generic;
using System.Text;
using ThirdParty.Json.LitJson;
namespace Amazon.Lambda.Tools.TemplateProcessor
{
///
/// JSON implementation of ITemplateParser
///
public class JsonTemplateParser : ITemplateParser
{
JsonData Root { get; }
public JsonTemplateParser(string templateBody)
{
try
{
this.Root = JsonMapper.ToObject(templateBody);
}
catch (Exception e)
{
throw new LambdaToolsException($"Error parsing CloudFormation template: {e.Message}", LambdaToolsException.LambdaErrorCode.ServerlessTemplateParseError, e);
}
}
public string GetUpdatedTemplate()
{
var json = JsonMapper.ToJson(this.Root);
return json;
}
public IEnumerable UpdatableResources()
{
var resources = this.Root["Resources"];
if (resources == null)
throw new LambdaToolsException("CloudFormation template does not define any AWS resources", LambdaToolsException.LambdaErrorCode.ServerlessTemplateMissingResourceSection);
foreach (var field in resources.PropertyNames)
{
var resource = resources[field];
if (resource == null)
continue;
var properties = resource["Properties"];
if (properties == null)
continue;
var type = resource["Type"]?.ToString();
UpdatableResourceDefinition updatableResourceDefinition;
if (!UpdatableResourceDefinition.ValidUpdatableResourceDefinitions.TryGetValue(type,
out updatableResourceDefinition))
continue;
var updatableResource = new UpdatableResource(field, updatableResourceDefinition, new JsonUpdatableResourceDataSource(this.Root, resource, properties));
yield return updatableResource;
}
}
///
/// The JSON implementation of IUpdatableResourceDataSource
///
public class JsonUpdatableResourceDataSource : IUpdatableResourceDataSource
{
JsonData Root { get; }
JsonData Resource { get; }
JsonData Properties { get; }
public JsonUpdatableResourceDataSource(JsonData root, JsonData resource, JsonData properties)
{
this.Root = root;
this.Resource = resource;
this.Properties = properties;
}
public string GetValueFromRoot(params string[] keyPath)
{
return GetValue(this.Root, keyPath);
}
public string[] GetValueListFromRoot(params string[] keyPath)
{
return GetValueList(this.Root, keyPath);
}
public string GetValueFromResource(params string[] keyPath)
{
return GetValue(this.Resource, keyPath);
}
public string GetValue(params string[] keyPath)
{
return GetValue(this.Properties, keyPath);
}
private static string GetValue(JsonData node, params string[] keyPath)
{
foreach (var key in keyPath)
{
if (node == null)
return null;
node = node[key];
}
return node?.ToString();
}
public string[] GetValueList(params string[] keyPath)
{
return GetValueList(this.Properties, keyPath);
}
public Dictionary GetValueDictionaryFromResource(params string[] keyPath)
{
return GetValueDictionaryFromResource(this.Resource, keyPath);
}
private static string[] GetValueList(JsonData node, params string[] keyPath)
{
foreach (var key in keyPath)
{
if (node == null)
return null;
node = node[key];
}
if (node == null || !node.IsArray || node.Count == 0)
return null;
var values = new string[node.Count];
for (var i = 0; i < values.Length; i++)
{
values[i] = node[i]?.ToString();
}
return values;
}
public void SetValue(string value, params string[] keyPath)
{
JsonData node = Properties;
for (int i = 0; i < keyPath.Length - 1; i++)
{
var childNode = node[keyPath[i]];
if (childNode == null)
{
childNode = new JsonData();
node[keyPath[i]] = childNode;
}
node = childNode;
}
node[keyPath[keyPath.Length - 1]] = value;
}
private static Dictionary GetValueDictionaryFromResource(JsonData node, params string[] keyPath)
{
foreach (var key in keyPath)
{
if (node == null)
return null;
node = node[key];
}
if (node == null || !node.IsObject || node.Count == 0)
return null;
var dictionary = new Dictionary(node.Count);
foreach (string key in node.PropertyNames)
{
if (dictionary.ContainsKey(key))
{
dictionary[key] = node[key]?.ToString();
}
else
{
dictionary.Add(key, node[key]?.ToString());
}
}
return dictionary;
}
}
}
}