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

Last change on this file since 17349 was 17349, checked in by dpiringe, 12 months 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
Line 
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
10namespace HeuristicLab.JsonInterface {
11  public static class JCGenerator {
12
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    }
18
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
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
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);
35
36      // 2. save the JArray with JsonItems (= IParameterizedItems)
37      genData.Template[Constants.Objects] = genData.JsonItems;
38      // 3. save the types of the JsonItems (for instatiation)
39      genData.Template[Constants.Types] = JObject.FromObject(genData.TypeList);
40      // 4. serialize template and return string
41      return CustomJsonWriter.Serialize(genData.Template);
42    }
43   
44    #region Helper
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) {
52      JsonItem jsonItem = JsonItemConverter.Extract(item);
53      genData.Template[Constants.Metadata][metaDataTagName] = item.ItemName;
54      PopulateJsonItems(jsonItem, genData);
55    }
56
57    // serializes ParameterizedItems and saves them in list "JsonItems".
58    private static void PopulateJsonItems(JsonItem item, GenData genData) {
59      if (item.Parameters != null) {
60        if (item.Range == null)
61          genData.JsonItems.Add(Serialize(item, genData));
62        foreach (var p in item.Parameters)
63          if (p.IsParameterizedItem)
64            PopulateJsonItems(p, genData);
65      }
66    }
67
68    private static JObject Serialize(JsonItem item, GenData genData) {
69      JObject obj = JObject.FromObject(item, Settings());
70      obj[Constants.StaticParameters] = obj[nameof(JsonItem.Parameters)];
71      obj[Constants.FreeParameters] = obj[nameof(JsonItem.Parameters)];
72
73      obj.Property(nameof(JsonItem.Parameters))?.Remove();
74      RefactorFreeParameters(obj);
75      RefactorStaticParameters(obj);
76
77      obj.Property(nameof(JsonItem.Value))?.Remove();
78      obj.Property(nameof(JsonItem.Type))?.Remove();
79
80      genData.TypeList.Add(item.Path, item.Type);
81      return obj;
82    }
83
84    // deletes unnecessary properties for free parameters.
85    private static void RefactorFreeParameters(JToken token) {
86      IList<JObject> objToRemove = new List<JObject>();
87      TransformNodes(x => {
88        var p = x.ToObject<JsonItem>();
89        if ((p.Value == null || (p.Value != null && p.Value.GetType() == typeof(string) && p.Range == null) && p.ActualName == null)) {
90          objToRemove.Add(x);
91        } else {
92          x.Property(nameof(JsonItem.Type))?.Remove();
93          x.Property(nameof(JsonItem.Parameters))?.Remove();
94        }
95      }, token[Constants.FreeParameters]);
96      foreach (var x in objToRemove) x.Remove();
97    }
98
99    // deletes unnecessary properties for static parameters.
100    private static void RefactorStaticParameters(JToken token) {
101      IList<JObject> objToRemove = new List<JObject>();
102      TransformNodes(x => {
103        var p = x.ToObject<JsonItem>();
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();
108        //TODO: maybe allow JsonItems with Value==null in static parameters too?
109        if (p.Value == null) objToRemove.Add(x);
110      }, token[Constants.StaticParameters]);
111      foreach (var x in objToRemove) x.Remove();
112    }
113
114    /// <summary>
115    /// Settings for the json serialization.
116    /// </summary>
117    /// <returns>A configured JsonSerializer.</returns>
118    private static JsonSerializer Settings() => new JsonSerializer() {
119      TypeNameHandling = TypeNameHandling.None,
120      NullValueHandling = NullValueHandling.Ignore,
121      ReferenceLoopHandling = ReferenceLoopHandling.Serialize
122    };
123
124    private static void TransformNodes(Action<JObject> action, params JToken[] tokens) {
125      foreach(JObject obj in tokens.SelectMany(x => x.Children<JObject>()))
126        action(obj);
127    }
128    #endregion
129  }
130}
Note: See TracBrowser for help on using the repository browser.