using System; using System.Collections; using System.Collections.Generic; using System.IO; using System.Linq; using System.Reflection; using System.Text; using System.Threading.Tasks; using HEAL.Attic; using HeuristicLab.Core; using HeuristicLab.Data; using HeuristicLab.Optimization; using Newtonsoft.Json.Linq; namespace HeuristicLab.JsonInterface { /// /// Static class to instantiate an IAlgorithm object with a json interface template and config. /// public static class JsonTemplateInstantiator { private struct InstData { public JToken Template { get; set; } public JArray Config { get; set; } public IDictionary Objects { get; set; } } /// /// Instantiate an IAlgorithm object with a template and config. /// /// Template file (json), generated with JCGenerator. /// Config file (json) for the template. /// confugrated IOptimizer object public static IOptimizer Instantiate(string templateFile, string configFile = "") { InstData instData = new InstData() { Objects = new Dictionary() }; // parse template and config files instData.Template = JToken.Parse(File.ReadAllText(templateFile)); if(!string.IsNullOrEmpty(configFile)) instData.Config = JArray.Parse(File.ReadAllText(configFile)); // extract metadata information string optimizerName = instData.Template[Constants.Metadata][Constants.Optimizer].ToString(); string hLFileLocation = instData.Template[Constants.Metadata][Constants.HLFileLocation].ToString(); // deserialize hl file ProtoBufSerializer serializer = new ProtoBufSerializer(); IOptimizer optimizer = (IOptimizer)serializer.Deserialize(hLFileLocation); // collect all parameterizedItems from template CollectParameterizedItems(instData); // if config != null -> merge Template and Config if (instData.Config != null) MergeTemplateWithConfig(instData); // get algorthm data and object JsonItem optimizerData = instData.Objects[optimizerName]; // inject configuration JsonItemConverter.Inject(optimizer, optimizerData); return optimizer; } #region Helper private static void CollectParameterizedItems(InstData instData) { foreach (JObject item in instData.Template[Constants.Parameters]) { string[] pathParts = item.Property("Path").Value.ToString().Split('.'); // rebuilds object tree JsonItem parent = null; StringBuilder partialPath = new StringBuilder(); for(int i = 0; i < pathParts.Length-1; ++i) { partialPath.Append(pathParts[i]); JsonItem tmp = null; if (instData.Objects.TryGetValue(partialPath.ToString(), out JsonItem value)) { tmp = value; } else { tmp = new JsonItem() { Name = pathParts[i] }; if (parent != null) parent.AddChilds(tmp); instData.Objects.Add(partialPath.ToString(), tmp); } partialPath.Append("."); parent = tmp; } JsonItem data = JsonItem.BuildJsonItem(item); parent.AddChilds(data); instData.Objects.Add(data.Path, data); } } private static void MergeTemplateWithConfig(InstData instData) { foreach (JObject obj in instData.Config) { // build item from config object JsonItem item = JsonItem.BuildJsonItem(obj); // override default value if (instData.Objects.TryGetValue(item.Path, out JsonItem param)) { param.Value = item.Value; // override ActualName (for LookupParameters) if (param.ActualName != null) param.ActualName = item.ActualName; } else throw new InvalidDataException($"No parameter with path='{item.Path}' defined!"); } } private static JsonItem GetData(string key, InstData instData) { if (instData.Objects.TryGetValue(key, out JsonItem value)) return value; else throw new InvalidDataException($"Type of item '{key}' is not defined!"); } #endregion } }