Free cookie consent management tool by TermsFeed Policy Generator

source: branches/3026_IntegrationIntoSymSpace/HeuristicLab.JsonInterface/JsonItem.cs @ 17354

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

#3026:

  • relocated BuildJsonItem from JCInstantiator into JsonItem
  • in JsonItem: removed JContainer usage in setter for Value (now in BuildJsonItem)
File size: 6.2 KB
Line 
1using System;
2using System.Collections.Generic;
3using System.IO;
4using System.Linq;
5using System.Text;
6using System.Threading.Tasks;
7using HeuristicLab.Core;
8using Newtonsoft.Json;
9using Newtonsoft.Json.Linq;
10
11namespace HeuristicLab.JsonInterface {
12  /// <summary>
13  /// Main data class for json interface.
14  /// </summary>
15  public class JsonItem {
16
17    #region Private Fields
18    private string name;
19    private object value;
20    private IEnumerable<object> range;
21    #endregion
22
23    public string Name {
24      get => name;
25      set {
26        name = value;
27        Path = Name;
28        UpdatePath();
29      }
30    }
31    public string Type { get; set; }
32    public string Path { get; set; }
33    public IList<JsonItem> Parameters { get; set; } // -> für flachen aufbau -> childs?
34    public IList<JsonItem> Operators { get; set; }
35    public object Value {
36      get => value;
37      set {
38        this.value = value;
39        CheckConstraints();
40      }
41    }
42    public IEnumerable<object> Range {
43      get => range;
44      set {
45        range = value;
46        CheckConstraints();
47      }
48    }
49    public string ActualName { get; set; }
50
51    #region JsonIgnore Properties
52    [JsonIgnore]
53    public JsonItem Reference { get; set; }
54
55    [JsonIgnore]
56    public bool IsConfigurable => (Value != null && Range != null);
57
58    [JsonIgnore]
59    public bool IsParameterizedItem => Parameters != null;
60    #endregion
61
62    #region Public Static Methods
63    public static void Merge(JsonItem target, JsonItem from) {
64      target.Name = from.Name ?? target.Name;
65      target.Type = from.Type ?? target.Type;
66      target.Range = from.Range ?? target.Range;
67      target.Path = from.Path ?? target.Path;
68      target.Value = from.Value ?? target.Value;
69      target.Reference = from.Reference ?? target.Reference;
70      target.ActualName = from.ActualName ?? target.ActualName;
71      target.Parameters = from.Parameters ?? target.Parameters;
72      target.Operators = from.Operators ?? target.Operators;
73    }
74    #endregion
75
76    #region Public Methods
77    public void UpdatePath() {
78      if (Parameters != null)
79        UpdatePathHelper(Parameters);
80
81      if (Operators != null)
82        UpdatePathHelper(Operators);
83
84      if (Reference != null)
85        UpdatePathHelper(Reference);
86    }
87    #endregion
88
89    #region Helper
90    private void UpdatePathHelper(params JsonItem[] items) =>
91      UpdatePathHelper((IEnumerable<JsonItem>)items);
92
93    private void UpdatePathHelper(IEnumerable<JsonItem> items) {
94      foreach (var item in items) {
95        item.Path = $"{Path}.{item.Name}";
96        item.UpdatePath();
97      }
98    }
99
100    private void CheckConstraints() {
101      if (Range != null && Value != null && !IsInRange())
102        throw new ArgumentOutOfRangeException(nameof(Value), $"{nameof(Value)} is not in range.");
103    }
104
105    private bool IsInRange() => IsInRangeList() ||
106      (Value.GetType().IsArray && ((object[])Value).All(x => IsInNumericRange(x))) ||
107      (!Value.GetType().IsArray && IsInNumericRange(Value));
108
109    private bool IsInRangeList() {
110      foreach (var x in Range)
111        if (x.Equals(Value)) return true;
112      return false;
113    }
114
115    private bool IsInNumericRange(object value) =>
116      IsInNumericRange<long>(value)
117      || IsInNumericRange<int>(value)
118      || IsInNumericRange<short>(value)
119      || IsInNumericRange<byte>(value)
120      || IsInNumericRange<float>(value)
121      || IsInNumericRange<double>(value);
122
123    private bool IsInNumericRange<T>(object value) where T : IComparable {
124      object min = Range.First(), max = Range.Last();
125      return value != null && min != null && max != null && value is T && min is T && max is T &&
126            (((T)min).CompareTo(value) == -1 || ((T)min).CompareTo(value) == 0) &&
127            (((T)max).CompareTo(value) == 1 || ((T)max).CompareTo(value) == 0);
128    }
129
130    #endregion
131
132    #region BuildJsonItemMethods
133    public static JsonItem BuildJsonItem(JObject obj, IDictionary<string, string> typeList) {
134      object val = obj[nameof(Value)]?.ToObject<object>();
135      if (val is JContainer)
136        val = ((JContainer)val).ToObject<object[]>();
137
138      return new JsonItem() {
139        Name = obj[nameof(Name)]?.ToString(),
140        Path = obj[nameof(Path)]?.ToString(),
141        Value = val,
142        Range = obj[nameof(Range)]?.ToObject<object[]>(),
143        Type = GetType(obj[nameof(Path)]?.ToObject<string>(), typeList),
144        ActualName = obj[nameof(ActualName)]?.ToString(),
145        Parameters = PopulateParameters(obj, typeList),
146        Operators = PopulateOperators(obj, typeList)
147      };
148  }
149
150    private static string GetType(string path, IDictionary<string, string> typeList) {
151      if (!string.IsNullOrEmpty(path))
152        if (typeList.TryGetValue(path, out string value))
153          return value;
154      return null;
155    }
156
157    private static IList<JsonItem> PopulateParameters(JObject obj, IDictionary<string, string> typeList) {
158      IList<JsonItem> list = new List<JsonItem>();
159
160      // add staticParameters
161      if (obj[Constants.StaticParameters] != null)
162        foreach (JObject param in obj[Constants.StaticParameters])
163          list.Add(BuildJsonItem(param, typeList));
164
165      // merge staticParameter with freeParameter
166      if (obj[Constants.FreeParameters] != null) {
167        foreach (JObject param in obj[Constants.FreeParameters]) {
168          JsonItem tmp = BuildJsonItem(param, typeList);
169
170          // search staticParameter from list
171          JsonItem comp = null;
172          foreach (var p in list)
173            if (p.Name == tmp.Name) comp = p;
174          if (comp == null)
175            throw new InvalidDataException($"Invalid {Constants.FreeParameters.Trim('s')}: '{tmp.Name}'!");
176
177          JsonItem.Merge(comp, tmp);
178        }
179      }
180      return list;
181    }
182
183    private static IList<JsonItem> PopulateOperators(JObject obj, IDictionary<string, string> typeList) {
184      IList<JsonItem> list = new List<JsonItem>();
185      JToken operators = obj[nameof(JsonItem.Operators)];
186      if (operators != null)
187        foreach (JObject sp in operators)
188          list.Add(BuildJsonItem(sp, typeList));
189      return list;
190    }
191    #endregion
192  }
193}
Note: See TracBrowser for help on using the repository browser.