source: branches/3026_IntegrationIntoSymSpace/HeuristicLab.JsonInterface/JsonTemplateInstantiator.cs @ 17394

Last change on this file since 17394 was 17394, checked in by dpiringe, 8 weeks ago

#3026:

  • deleted: ConvertableAttribute, DummyConverter, ObjectExtensions
  • renamed: CustomJsonWriter -> SingleLineArrayJsonWriter, JCInstantiator -> JsonTemplateInstantiator
  • added: JsonItemConverterFactory, UnsupportedJsonItem
  • IJsonItemConverter:
    • added two new properties: Priority and ConvertableType -> because converters are automatically collected by plugin infrastructure now
    • Extract, Inject references a root converter now -> typically an instance of JsonItemConverter -> to prevent cycles
  • JsonItemConverter:
    • now implements the interface IJsonItemConverter
    • is now a dynamic class
    • is only instantiable with an factory (JsonItemConverterFactory)
    • still has the old (but now public) static methods Extract and Inject (without ref param IJsonItemConverter root) -> creates instance with factory and calls methods of instance
    • removed register and unregister methods, because the factory collects all converters automatically now (on first call of Create)
    • has cycle detection for Extract and Inject
    • renamed method Get to GetConverter
File size: 4.6 KB
Line 
1using System;
2using System.Collections;
3using System.Collections.Generic;
4using System.IO;
5using System.Linq;
6using System.Reflection;
7using System.Text;
8using System.Threading.Tasks;
9using HEAL.Attic;
10using HeuristicLab.Core;
11using HeuristicLab.Data;
12using HeuristicLab.Optimization;
13using Newtonsoft.Json.Linq;
14
15namespace HeuristicLab.JsonInterface {
16  /// <summary>
17  /// Static class to instantiate an IAlgorithm object with a json interface template and config.
18  /// </summary>
19  public static class JsonTemplateInstantiator {
20    private struct InstData {
21      public JToken Template { get; set; }
22      public JArray Config { get; set; }
23      public IDictionary<string, JsonItem> Objects { get; set; }
24    }
25
26    /// <summary>
27    /// Instantiate an IAlgorithm object with a template and config.
28    /// </summary>
29    /// <param name="templateFile">Template file (json), generated with JCGenerator.</param>
30    /// <param name="configFile">Config file (json) for the template.</param>
31    /// <returns>confugrated IAlgorithm object</returns>
32    public static IAlgorithm Instantiate(string templateFile, string configFile = "") {
33      InstData instData = new InstData() {
34        Objects = new Dictionary<string, JsonItem>()
35      };
36
37      // parse template and config files
38      instData.Template = JToken.Parse(File.ReadAllText(templateFile));
39      if(!string.IsNullOrEmpty(configFile))
40        instData.Config = JArray.Parse(File.ReadAllText(configFile));
41
42      // extract metadata information
43      string algorithmName = instData.Template[Constants.Metadata][Constants.Algorithm].ToString();
44      string problemName = instData.Template[Constants.Metadata][Constants.Problem].ToString();
45      string hLFileLocation = instData.Template[Constants.Metadata][Constants.HLFileLocation].ToString();
46
47      // deserialize hl file
48      ProtoBufSerializer serializer = new ProtoBufSerializer();
49      IAlgorithm algorithm = (IAlgorithm)serializer.Deserialize(hLFileLocation);
50
51      // collect all parameterizedItems from template
52      CollectParameterizedItems(instData);
53     
54      // if config != null -> merge Template and Config
55      if (instData.Config != null)
56        MergeTemplateWithConfig(instData);
57
58      // get algorthm data and object
59      JsonItem algorithmData = GetData(algorithmName, instData);
60
61      // get problem data and object
62      JsonItem problemData = GetData(problemName, instData);
63
64      // inject configuration
65      JsonItemConverter.Inject(algorithm, algorithmData);
66      if(algorithm.Problem != null)
67        JsonItemConverter.Inject(algorithm.Problem, problemData);
68
69      return algorithm;
70    }
71
72    #region Helper
73    private static void CollectParameterizedItems(InstData instData) {
74      foreach (JObject item in instData.Template[Constants.Parameters]) {
75        string[] pathParts = item.Property("Path").Value.ToString().Split('.');
76       
77        // rebuilds object tree
78        JsonItem parent = null;
79        StringBuilder partialPath = new StringBuilder();
80        for(int i = 0; i < pathParts.Length-1; ++i) {
81          partialPath.Append(pathParts[i]);
82          JsonItem tmp = null;
83          if (instData.Objects.TryGetValue(partialPath.ToString(), out JsonItem value)) {
84            tmp = value;
85          } else {
86            tmp = new JsonItem() { Name = pathParts[i] };
87            if (parent != null) parent.AddChilds(tmp);
88            instData.Objects.Add(partialPath.ToString(), tmp);
89          }
90          partialPath.Append(".");
91          parent = tmp;
92        }
93
94        JsonItem data = JsonItem.BuildJsonItem(item);
95        parent.AddChilds(data);
96        instData.Objects.Add(data.Path, data);
97      }
98    }
99   
100    private static void MergeTemplateWithConfig(InstData instData) {
101      foreach (JObject obj in instData.Config) {
102        // build item from config object
103        JsonItem item = JsonItem.BuildJsonItem(obj);
104        // override default value
105        if (instData.Objects.TryGetValue(item.Path, out JsonItem param)) {
106          param.Value = item.Value;
107          // override ActualName (for LookupParameters)
108          if (param.ActualName != null)
109            param.ActualName = item.ActualName;
110        } else throw new InvalidDataException($"No parameter with path='{item.Path}' defined!");
111      }
112    }
113
114    private static JsonItem GetData(string key, InstData instData)
115    {
116      if (instData.Objects.TryGetValue(key, out JsonItem value))
117        return value;
118      else
119        throw new InvalidDataException($"Type of item '{key}' is not defined!");
120    }
121    #endregion
122  }
123}
Note: See TracBrowser for help on using the repository browser.