Free cookie consent management tool by TermsFeed Policy Generator

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

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

#3026 moved JsonItem, ResultItem and UnsupportedJsonItem into new folder Models

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 : IJsonItem {
17
18    public class JsonItemValidator : IJsonItemValidator {
19      private IDictionary<int, bool> Cache = new Dictionary<int, bool>();
20      private JsonItem Root { get; set; }
21      public JsonItemValidator(JsonItem root) {
22        Root = root;
23      }
24
25      public bool Validate(ref IList<IJsonItem> faultyItems) {
26        faultyItems = new List<IJsonItem>();
27        return ValidateHelper(Root, ref faultyItems);
28      }
29
30      private bool ValidateHelper(JsonItem item, ref IList<IJsonItem> faultyItems) {
31        int hash = item.GetHashCode();
32        if (Cache.TryGetValue(hash, out bool r))
33          return r;
34
35        bool res = true;
36        if (item.Value != null && item.Range != null)
37          res = item.IsInRange();
38        if (!res) faultyItems.Add(item);
39        Cache.Add(hash, res);
40        foreach (var child in item.Children)
41          res = res && ValidateHelper(child as JsonItem, ref faultyItems);
42        return res;
43      }
44    }
45
46    public virtual string Name { get; set; }
47
48    public virtual string Path {
49      get {
50        IJsonItem tmp = Parent;
51        StringBuilder builder = new StringBuilder(this.Name);
52        while(tmp != null) {
53          builder.Insert(0, tmp.Name + ".");
54          tmp = tmp.Parent;
55        }
56        return builder.ToString();
57      }
58    }
59
60    [JsonIgnore]
61    public virtual IList<IJsonItem> Children { get; protected set; }
62
63    [JsonIgnore]
64    public virtual IJsonItem Parent { get; set; }
65
66    public virtual object Value { get; set; }
67
68    public virtual IEnumerable<object> Range { get; set; }
69   
70    public virtual string ActualName { get; set; }
71
72    #region Constructors
73    public JsonItem() { }
74
75    public JsonItem(IEnumerable<IJsonItem> childs) {
76      AddChilds(childs);
77    }
78    #endregion
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<IJsonItem>)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 IJsonItem[] childs) =>
97      AddChilds(childs as IEnumerable<IJsonItem>);
98
99    public void AddChilds(IEnumerable<IJsonItem> childs) {
100      if (Children == null)
101        Children = new List<IJsonItem>();
102      foreach (var child in childs) {
103        Children.Add(child);
104        child.Parent = this;
105      }
106    }
107
108    public virtual IJsonItemValidator GetValidator() => new JsonItemValidator(this);
109    #endregion
110
111    #region Helper
112    protected bool IsInRange() {
113      bool b1 = true, b2 = true;
114      if (Value is IEnumerable && !(Value is string)) {
115        foreach (var x in (IEnumerable)Value) {
116          b1 = b1 ? IsInRangeList(x) : b1;
117          b2 = b2 ? IsInNumericRange(x) : b2;
118        }
119      }
120      else {
121        b1 = IsInRangeList(Value);
122        b2 = IsInNumericRange(Value);
123      }
124      return b1 || b2;
125    }
126
127    protected bool IsInRangeList(object value) {
128      foreach (var x in Range)
129        if (x.Equals(value)) return true;
130      return false;
131    }
132
133    protected bool IsInNumericRange(object value) =>
134      IsInNumericRange<ulong>(value)
135      || IsInNumericRange<uint>(value)
136      || IsInNumericRange<ushort>(value)
137      || IsInNumericRange<long>(value)
138      || IsInNumericRange<int>(value)
139      || IsInNumericRange<short>(value)
140      || IsInNumericRange<byte>(value)
141      || IsInNumericRange<float>(value)
142      || IsInNumericRange<double>(value)
143      || (value is float && float.IsNaN((float)value))
144      || (value is double && double.IsNaN((double)value));
145
146    protected bool IsInNumericRange<T>(object value) where T : IComparable {
147      object min = Range.First(), max = Range.Last();
148      return
149        value != null && min != null && max != null && value is T && min is T && max is T &&
150        (((T)min).CompareTo(value) == -1 || ((T)min).CompareTo(value) == 0) &&
151        (((T)max).CompareTo(value) == 1 || ((T)max).CompareTo(value) == 0);
152    }
153    #endregion
154
155    #region BuildJsonItemMethods
156    public static IJsonItem BuildJsonItem(JObject obj) {
157      object val = obj[nameof(Value)]?.ToObject<object>();
158      if (val is JContainer jContainer) // for resolving array values
159        val = jContainer.ToObject<object[]>();
160       
161      return new JsonItem() {
162        Name = obj[nameof(Name)]?.ToString(),
163        Value = val,
164        Range = obj[nameof(Range)]?.ToObject<object[]>(),
165        ActualName = obj[nameof(ActualName)]?.ToString()
166      };
167    }
168    #endregion
169  }
170}
Note: See TracBrowser for help on using the repository browser.