Free cookie consent management tool by TermsFeed Policy Generator

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

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

#3026:

  • deleted: ConvertableAttribute, DummyConverter, ObjectExtensions
  • renamed: CustomJsonWriter -> SingleLineArrayJsonWriter, JCInstantiator -> JsonTemplateInstantiator
  • added: JsonItemConverterFactory, UnsupportedJsonItem
  • IJsonItemConverter:
    • added two new properties: Priority and ConvertableType -> because converters are automatically collected by plugin infrastructure now
    • Extract, Inject references a root converter now -> typically an instance of JsonItemConverter -> to prevent cycles
  • JsonItemConverter:
    • now implements the interface IJsonItemConverter
    • is now a dynamic class
    • is only instantiable with an factory (JsonItemConverterFactory)
    • still has the old (but now public) static methods Extract and Inject (without ref param IJsonItemConverter root) -> creates instance with factory and calls methods of instance
    • removed register and unregister methods, because the factory collects all converters automatically now (on first call of Create)
    • has cycle detection for Extract and Inject
    • renamed method Get to GetConverter
File size: 5.2 KB
Line 
1using System;
2using System.Collections;
3using System.Collections.Generic;
4using System.IO;
5using System.Linq;
6using System.Text;
7using System.Threading.Tasks;
8using HeuristicLab.Core;
9using Newtonsoft.Json;
10using Newtonsoft.Json.Linq;
11
12namespace HeuristicLab.JsonInterface {
13  /// <summary>
14  /// Main data class for json interface.
15  /// </summary>
16  public class JsonItem {
17    public class JsonItemValidator {
18      private IDictionary<int, bool> Cache = new Dictionary<int, bool>();
19      private JsonItem Root { get; set; }
20      public JsonItemValidator(JsonItem root) {
21        Root = root;
22      }
23
24      public bool Validate(ref IList<JsonItem> faultyItems) {
25        faultyItems = new List<JsonItem>();
26        return ValidateHelper(Root, ref faultyItems);
27      }
28
29      private bool ValidateHelper(JsonItem item, ref IList<JsonItem> faultyItems) {
30        int hash = item.GetHashCode();
31        if (Cache.TryGetValue(hash, out bool r))
32          return r;
33
34        bool res = true;
35        if (item.Value != null && item.Range != null)
36          res = item.IsInRange();
37        if (!res) faultyItems.Add(item);
38        Cache.Add(hash, res);
39        foreach (var child in item.Children)
40          res = res && ValidateHelper(child, ref faultyItems);
41        return res;
42      }
43    }
44
45    public virtual string Name { get; set; }
46
47    public virtual string Path {
48      get {
49        JsonItem tmp = Parent;
50        StringBuilder builder = new StringBuilder(this.Name);
51        while(tmp != null) {
52          builder.Insert(0, tmp.Name + ".");
53          tmp = tmp.Parent;
54        }
55        return builder.ToString();
56      }
57    }
58
59    [JsonIgnore]
60    public virtual IList<JsonItem> Children { get; protected set; }
61
62    [JsonIgnore]
63    public virtual JsonItem Parent { get; set; }
64
65    public virtual object Value { get; set; }
66
67    public virtual IEnumerable<object> Range { get; set; }
68   
69    public virtual string ActualName { get; set; }
70
71    #region Constructors
72    public JsonItem() { }
73
74    public JsonItem(IEnumerable<JsonItem> childs) {
75      AddChilds(childs);
76    }
77    #endregion
78
79
80    #region Public Static Methods
81    public static void Merge(JsonItem target, JsonItem from) {
82      target.Name = from.Name ?? target.Name;
83      target.Range = from.Range ?? target.Range;
84      target.Value = from.Value ?? target.Value;
85      target.ActualName = from.ActualName ?? target.ActualName;
86      if(target.Children != null) {
87        if (from.Children != null)
88          ((List<JsonItem>)from.Children).AddRange(target.Children);
89      } else {
90        target.Children = from.Children;
91      }
92    }
93    #endregion
94
95    #region Public Methods
96    public void AddChilds(params JsonItem[] childs) =>
97      AddChilds(childs as IEnumerable<JsonItem>);
98
99    public void AddChilds(IEnumerable<JsonItem> childs) {
100      if (Children == null)
101        Children = new List<JsonItem>();
102      foreach (var child in childs) {
103        Children.Add(child);
104        child.Parent = this;
105      }
106    }
107
108    public virtual JsonItemValidator GetValidator() => new JsonItemValidator(this);
109    #endregion
110
111    #region Helper
112
113
114    protected bool IsInRange() {
115      bool b1 = true, b2 = true;
116      if (Value is IEnumerable && !(Value is string)) {
117        foreach (var x in (IEnumerable)Value) {
118          b1 = b1 ? IsInRangeList(x) : b1;
119          b2 = b2 ? IsInNumericRange(x) : b2;
120        }
121      }
122      else {
123        b1 = IsInRangeList(Value);
124        b2 = IsInNumericRange(Value);
125      }
126      return b1 || b2;
127    }
128
129    protected bool IsInRangeList(object value) {
130      foreach (var x in Range)
131        if (x.Equals(value)) return true;
132      return false;
133    }
134
135    protected bool IsInNumericRange(object value) =>
136      IsInNumericRange<ulong>(value)
137      || IsInNumericRange<uint>(value)
138      || IsInNumericRange<ushort>(value)
139      || IsInNumericRange<long>(value)
140      || IsInNumericRange<int>(value)
141      || IsInNumericRange<short>(value)
142      || IsInNumericRange<byte>(value)
143      || IsInNumericRange<float>(value)
144      || IsInNumericRange<double>(value)
145      || (value is float && float.IsNaN((float)value))
146      || (value is double && double.IsNaN((double)value));
147
148    protected bool IsInNumericRange<T>(object value) where T : IComparable {
149      object min = Range.First(), max = Range.Last();
150      return
151        value != null && min != null && max != null && value is T && min is T && max is T &&
152        (((T)min).CompareTo(value) == -1 || ((T)min).CompareTo(value) == 0) &&
153        (((T)max).CompareTo(value) == 1 || ((T)max).CompareTo(value) == 0);
154    }
155    #endregion
156
157    #region BuildJsonItemMethods
158    public static JsonItem BuildJsonItem(JObject obj) {
159      object val = obj[nameof(Value)]?.ToObject<object>();
160      if (val is JContainer jContainer) // for resolving array values
161        val = jContainer.ToObject<object[]>();
162       
163      return new JsonItem() {
164        Name = obj[nameof(Name)]?.ToString(),
165        Value = val,
166        Range = obj[nameof(Range)]?.ToObject<object[]>(),
167        ActualName = obj[nameof(ActualName)]?.ToString()
168      };
169    }
170    #endregion
171  }
172}
Note: See TracBrowser for help on using the repository browser.