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

Last change on this file since 17353 was 17353, checked in by dpiringe, 11 months ago

#3026:

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