Free cookie consent management tool by TermsFeed Policy Generator

source: branches/3026_IntegrationIntoSymSpace/HeuristicLab.JsonInterface/JCGenerator.cs @ 17349

Last change on this file since 17349 was 17349, checked in by dpiringe, 4 years ago

#3026

  • added ConvertableAttribute, a new attribute for classes/structs (usage: convertable with JsonInterface)
  • changed JCGenerator -> is now a static class with one public static method Instantiate
  • changed JCInstantiator -> is now a static class with one public static method GenerateTemplate
  • refactored JsonItem
File size: 5.2 KB
RevLine 
[17263]1using System;
2using System.Collections.Generic;
3using System.Linq;
4using HeuristicLab.Core;
5using HeuristicLab.Data;
6using HeuristicLab.Optimization;
7using Newtonsoft.Json;
8using Newtonsoft.Json.Linq;
9
[17284]10namespace HeuristicLab.JsonInterface {
[17349]11  public static class JCGenerator {
[17280]12
[17349]13    private struct GenData {
14      public JObject Template { get; set; }
15      public IDictionary<string, string> TypeList { get; set; }
16      public JArray JsonItems { get; set; }
17    }
[17330]18
[17349]19
20    public static string GenerateTemplate(IAlgorithm algorithm) {
21      // data container
22      GenData genData = new GenData() {
23        Template = JObject.Parse(Constants.Template),
24        TypeList = new Dictionary<string, string>(),
25        JsonItems = new JArray()
26      };
27
[17330]28      // 1.1. extract JsonItem, save the name in the metadata section of the
29      // template and save it an JArray incl. all parameters of the JsonItem,
30      // which have parameters aswell
[17349]31      AddInstantiableIItem(Constants.Algorithm, algorithm, genData);
32      IsConvertable(algorithm, true);
33      if (algorithm.Problem != null && IsConvertable(algorithm.Problem, true)) // 1.2. only when an problem exists
34        AddInstantiableIItem(Constants.Problem, algorithm.Problem, genData);
[17330]35
36      // 2. save the JArray with JsonItems (= IParameterizedItems)
[17349]37      genData.Template[Constants.Objects] = genData.JsonItems;
[17330]38      // 3. save the types of the JsonItems (for instatiation)
[17349]39      genData.Template[Constants.Types] = JObject.FromObject(genData.TypeList);
[17330]40      // 4. serialize template and return string
[17349]41      return CustomJsonWriter.Serialize(genData.Template);
[17330]42    }
[17349]43   
[17330]44    #region Helper
[17349]45    private static bool IsConvertable(object obj, bool throwException) {
46      bool tmp = ConvertableAttribute.IsConvertable(obj);
47      if (throwException && tmp)
48        throw new NotSupportedException($"Type {obj.GetType().Name} is not convertable!");
49      return tmp;
50    }
51    private static void AddInstantiableIItem(string metaDataTagName, IItem item, GenData genData) {
[17330]52      JsonItem jsonItem = JsonItemConverter.Extract(item);
[17349]53      genData.Template[Constants.Metadata][metaDataTagName] = item.ItemName;
54      PopulateJsonItems(jsonItem, genData);
[17330]55    }
56
[17349]57    // serializes ParameterizedItems and saves them in list "JsonItems".
58    private static void PopulateJsonItems(JsonItem item, GenData genData) {
[17283]59      if (item.Parameters != null) {
[17330]60        if (item.Range == null)
[17349]61          genData.JsonItems.Add(Serialize(item, genData));
[17283]62        foreach (var p in item.Parameters)
[17349]63          if (p.IsParameterizedItem)
64            PopulateJsonItems(p, genData);
[17280]65      }
66    }
67
[17349]68    private static JObject Serialize(JsonItem item, GenData genData) {
[17283]69      JObject obj = JObject.FromObject(item, Settings());
[17287]70      obj[Constants.StaticParameters] = obj[nameof(JsonItem.Parameters)];
71      obj[Constants.FreeParameters] = obj[nameof(JsonItem.Parameters)];
[17280]72
[17287]73      obj.Property(nameof(JsonItem.Parameters))?.Remove();
[17330]74      RefactorFreeParameters(obj);
[17280]75      RefactorStaticParameters(obj);
76
[17342]77      obj.Property(nameof(JsonItem.Value))?.Remove();
[17287]78      obj.Property(nameof(JsonItem.Type))?.Remove();
[17280]79
[17349]80      genData.TypeList.Add(item.Path, item.Type);
[17280]81      return obj;
82    }
83
[17349]84    // deletes unnecessary properties for free parameters.
85    private static void RefactorFreeParameters(JToken token) {
[17266]86      IList<JObject> objToRemove = new List<JObject>();
87      TransformNodes(x => {
[17283]88        var p = x.ToObject<JsonItem>();
[17342]89        if ((p.Value == null || (p.Value != null && p.Value.GetType() == typeof(string) && p.Range == null) && p.ActualName == null)) {
[17266]90          objToRemove.Add(x);
91        } else {
[17287]92          x.Property(nameof(JsonItem.Type))?.Remove();
93          x.Property(nameof(JsonItem.Parameters))?.Remove();
[17266]94        }
[17287]95      }, token[Constants.FreeParameters]);
[17266]96      foreach (var x in objToRemove) x.Remove();
[17263]97    }
98
[17349]99    // deletes unnecessary properties for static parameters.
100    private static void RefactorStaticParameters(JToken token) {
[17266]101      IList<JObject> objToRemove = new List<JObject>();
102      TransformNodes(x => {
[17283]103        var p = x.ToObject<JsonItem>();
[17287]104        x.Property(nameof(JsonItem.Range))?.Remove();
105        x.Property(nameof(JsonItem.Operators))?.Remove();
106        x.Property(nameof(JsonItem.Parameters))?.Remove();
107        x.Property(nameof(JsonItem.Type))?.Remove();
[17349]108        //TODO: maybe allow JsonItems with Value==null in static parameters too?
109        if (p.Value == null) objToRemove.Add(x);
[17287]110      }, token[Constants.StaticParameters]);
[17266]111      foreach (var x in objToRemove) x.Remove();
[17263]112    }
113
[17349]114    /// <summary>
115    /// Settings for the json serialization.
116    /// </summary>
117    /// <returns>A configured JsonSerializer.</returns>
118    private static JsonSerializer Settings() => new JsonSerializer() {
[17263]119      TypeNameHandling = TypeNameHandling.None,
[17280]120      NullValueHandling = NullValueHandling.Ignore,
121      ReferenceLoopHandling = ReferenceLoopHandling.Serialize
[17263]122    };
123
[17349]124    private static void TransformNodes(Action<JObject> action, params JToken[] tokens) {
[17280]125      foreach(JObject obj in tokens.SelectMany(x => x.Children<JObject>()))
[17263]126        action(obj);
127    }
128    #endregion
129  }
130}
Note: See TracBrowser for help on using the repository browser.