Free cookie consent management tool by TermsFeed Policy Generator

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

Last change on this file since 18183 was 18077, checked in by dpiringe, 3 years ago

#3026

  • added the dockerhub readme file
  • fixed a bug which caused changed values (changed by events) to be overwritten with wrong values
File size: 6.6 KB
RevLine 
[17828]1using System;
2using System.Collections.Generic;
[17263]3using System.IO;
4using System.Linq;
[18030]5using System.Text.RegularExpressions;
[17379]6using HEAL.Attic;
[17263]7using HeuristicLab.Optimization;
[18046]8using HeuristicLab.PluginInfrastructure;
[17263]9using Newtonsoft.Json.Linq;
10
[17284]11namespace HeuristicLab.JsonInterface {
[17481]12  public readonly struct InstantiatorResult {
13
[18059]14    public InstantiatorResult(IOptimizer optimizer, IEnumerable<IRunCollectionModifier> runCollectionModifiers) {
[18046]15      Optimizer = optimizer;
[18055]16      RunCollectionModifiers = runCollectionModifiers;
[18046]17    }
18
[17481]19    public IOptimizer Optimizer { get; }
[18055]20    public IEnumerable<IRunCollectionModifier> RunCollectionModifiers { get; }
[17477]21  }
22
23
[17353]24  /// <summary>
[17477]25  /// Class to instantiate an IAlgorithm object with a json interface template and config.
[17353]26  /// </summary>
[17477]27  public class JsonTemplateInstantiator {
[17263]28
[18039]29    #region Constants
30    private const string RelativePathCurrentDirectoryRegex = @"^(\.)";
31    #endregion
32
[17477]33    #region Private Properties
34    private JToken Template { get; set; }
35    private JArray Config { get; set; }
36    private IDictionary<string, IJsonItem> Objects { get; set; } = new Dictionary<string, IJsonItem>();
37    #endregion
[17442]38
[17353]39    /// <summary>
40    /// Instantiate an IAlgorithm object with a template and config.
41    /// </summary>
42    /// <param name="templateFile">Template file (json), generated with JCGenerator.</param>
43    /// <param name="configFile">Config file (json) for the template.</param>
[17395]44    /// <returns>confugrated IOptimizer object</returns>
[17477]45    public static InstantiatorResult Instantiate(string templateFile, string configFile = null) {
46      JsonTemplateInstantiator instantiator = new JsonTemplateInstantiator();
47      return instantiator.ExecuteInstantiaton(templateFile, configFile);
48    }
[17322]49
[17477]50    #region Helper
51    private InstantiatorResult ExecuteInstantiaton(string templateFile, string configFile = null) {
52
53      #region Parse Files
[18040]54      string templateFileFullPath = Path.GetFullPath(templateFile);
[17477]55      Template = JToken.Parse(File.ReadAllText(templateFile));
[17330]56      if(!string.IsNullOrEmpty(configFile))
[18040]57        Config = JArray.Parse(File.ReadAllText(Path.GetFullPath(configFile)));
[17477]58      #endregion
[17379]59
[18050]60      #region Deserialize HL File
[17379]61      // extract metadata information
[18039]62      string relativePath = Template[Constants.Metadata][Constants.HLFileLocation].ToString().Trim(); // get relative path
[18030]63      // convert to absolute path
[18039]64      if (Regex.IsMatch(relativePath, RelativePathCurrentDirectoryRegex))
65        relativePath = relativePath.Remove(0, 2); // remove first 2 chars -> indicates the current directory
[17263]66
[18040]67      string hLFileLocation = Path.Combine(Path.GetDirectoryName(templateFileFullPath), relativePath);
[17379]68      ProtoBufSerializer serializer = new ProtoBufSerializer();
[17395]69      IOptimizer optimizer = (IOptimizer)serializer.Deserialize(hLFileLocation);
[18059]70      optimizer.Prepare(true);
[17477]71      #endregion
[17379]72
73      // collect all parameterizedItems from template
[17477]74      CollectParameterizedItems(optimizer);
[17394]75     
[17477]76      if (Config != null)
77        MergeTemplateWithConfig();
[17322]78
[17477]79      // get algorithm root item
80      IJsonItem rootItem = Objects.First().Value;
[17560]81
[17828]82      // validation
83      ValidationResult validationResult = rootItem.GetValidator().Validate();
84      if (!validationResult.Success)
85        throw validationResult.GenerateException();
[17560]86
[17379]87      // inject configuration
[17477]88      JsonItemConverter.Inject(optimizer, rootItem);
[17266]89
[18059]90      return new InstantiatorResult(optimizer, CollectRunCollectionModifiers());
[18050]91    }
92
93    /// <summary>
94    /// Instantiates all defined (in template) ResultCollectionProcessors and injects the configured parameters.
95    /// </summary>
[18055]96    private IEnumerable<IRunCollectionModifier> CollectRunCollectionModifiers() {
97      IList<IRunCollectionModifier> runCollectionModifiers = new List<IRunCollectionModifier>();
[18059]98
99      if (Template is JObject o && !o.ContainsKey(Constants.RunCollectionModifiers))
100        return Enumerable.Empty<IRunCollectionModifier>();
101
[18055]102      foreach (JObject obj in Template[Constants.RunCollectionModifiers]) {
[18050]103        var guid = obj["GUID"].ToString();
104        var parameters = obj[Constants.Parameters];
105        var type = Mapper.StaticCache.GetType(new Guid(guid));
[18059]106        var rcModifier = (IRunCollectionModifier)Activator.CreateInstance(type);
107        var rcModifierItem = JsonItemConverter.Extract(rcModifier);
[18050]108
[18077]109        SetJObjects(rcModifierItem, parameters);       
[18050]110
[18059]111        JsonItemConverter.Inject(rcModifier, rcModifierItem);
112        runCollectionModifiers.Add(rcModifier);
[18046]113      }
[18055]114      return runCollectionModifiers;
[17263]115    }
116
[17477]117    private void CollectParameterizedItems(IOptimizer optimizer) {
118      IJsonItem root = JsonItemConverter.Extract(optimizer);
119      Objects.Add(root.Path, root);
[17410]120
[18077]121      foreach (var kvp in SetJObjects(root, Template[Constants.Parameters]))
122        Objects.Add(kvp);
123    }
124
125    private IDictionary<string, IJsonItem> SetJObjects(IJsonItem root, JToken parameters) {
126      var dict = new Dictionary<string, IJsonItem>();
127      foreach (JObject obj in parameters) {
128        var path = obj[nameof(IJsonItem.Path)].ToString();
129        foreach (var item in root) {
130          if (item.Path == path) {
131            item.SetJObject(obj);
132            item.Active = true;
133            dict.Add(item.Path, item);
[17410]134          }
135        }
136      }
[18077]137      return dict;
[17263]138    }
[18077]139
[17477]140    private void MergeTemplateWithConfig() {
141      foreach (JObject obj in Config) {
[17322]142        // build item from config object
[18030]143        var prop = obj.Property("Path");
144        if (prop == null)
145          throw new ArgumentException("Path property is missing.");
146        string path = prop.Value.ToString();
[17322]147        // override default value
[17477]148        if (Objects.TryGetValue(path, out IJsonItem param)) {
[17483]149          // remove fixed template parameter from config => dont allow to copy them from concrete config
[17828]150          // TODO: shift this into JsonItems?
[17473]151          obj.Property(nameof(IIntervalRestrictedJsonItem<int>.Minimum))?.Remove();
152          obj.Property(nameof(IIntervalRestrictedJsonItem<int>.Maximum))?.Remove();
153          obj.Property(nameof(IConcreteRestrictedJsonItem<string>.ConcreteRestrictedItems))?.Remove();
[17828]154          obj.Property(nameof(IMatrixJsonItem.ColumnsResizable))?.Remove();
155          obj.Property(nameof(IMatrixJsonItem.RowsResizable))?.Remove();
156          obj.Property(nameof(IArrayJsonItem.Resizable))?.Remove();
[17473]157          // merge
[17477]158          param.SetJObject(obj);
[17410]159        } else throw new InvalidDataException($"No parameter with path='{path}' defined!");
[17322]160      }
161    }
162    #endregion
[17263]163  }
164}
Note: See TracBrowser for help on using the repository browser.