Free cookie consent management tool by TermsFeed Policy Generator

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

Last change on this file since 17399 was 17394, checked in by dpiringe, 5 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
RevLine 
[17263]1using System;
[17374]2using System.Collections;
[17263]3using System.Collections.Generic;
[17354]4using System.IO;
[17263]5using System.Linq;
6using System.Text;
7using System.Threading.Tasks;
8using HeuristicLab.Core;
9using Newtonsoft.Json;
[17275]10using Newtonsoft.Json.Linq;
[17263]11
[17284]12namespace HeuristicLab.JsonInterface {
[17353]13  /// <summary>
14  /// Main data class for json interface.
15  /// </summary>
[17283]16  public class JsonItem {
[17394]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      }
[17349]23
[17394]24      public bool Validate(ref IList<JsonItem> faultyItems) {
25        faultyItems = new List<JsonItem>();
26        return ValidateHelper(Root, ref faultyItems);
27      }
[17354]28
[17394]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;
[17354]42      }
[17339]43    }
[17394]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();
[17354]56      }
[17275]57    }
[17394]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);
[17263]76    }
[17394]77    #endregion
[17342]78
[17394]79
[17349]80    #region Public Static Methods
[17283]81    public static void Merge(JsonItem target, JsonItem from) {
[17269]82      target.Name = from.Name ?? target.Name;
83      target.Range = from.Range ?? target.Range;
[17342]84      target.Value = from.Value ?? target.Value;
85      target.ActualName = from.ActualName ?? target.ActualName;
[17379]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      }
[17269]92    }
[17349]93    #endregion
[17269]94
[17349]95    #region Public Methods
[17394]96    public void AddChilds(params JsonItem[] childs) =>
97      AddChilds(childs as IEnumerable<JsonItem>);
98
99    public void AddChilds(IEnumerable<JsonItem> childs) {
[17379]100      if (Children == null)
101        Children = new List<JsonItem>();
[17394]102      foreach (var child in childs) {
103        Children.Add(child);
104        child.Parent = this;
105      }
[17374]106    }
107
[17394]108    public virtual JsonItemValidator GetValidator() => new JsonItemValidator(this);
[17349]109    #endregion
[17280]110
[17339]111    #region Helper
[17280]112
[17349]113
[17394]114    protected bool IsInRange() {
[17374]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
[17394]129    protected bool IsInRangeList(object value) {
[17349]130      foreach (var x in Range)
[17374]131        if (x.Equals(value)) return true;
[17269]132      return false;
133    }
134
[17394]135    protected bool IsInNumericRange(object value) =>
[17374]136      IsInNumericRange<ulong>(value)
137      || IsInNumericRange<uint>(value)
138      || IsInNumericRange<ushort>(value)
139      || IsInNumericRange<long>(value)
[17353]140      || IsInNumericRange<int>(value)
141      || IsInNumericRange<short>(value)
142      || IsInNumericRange<byte>(value)
143      || IsInNumericRange<float>(value)
[17374]144      || IsInNumericRange<double>(value)
145      || (value is float && float.IsNaN((float)value))
146      || (value is double && double.IsNaN((double)value));
[17349]147
[17394]148    protected bool IsInNumericRange<T>(object value) where T : IComparable {
[17353]149      object min = Range.First(), max = Range.Last();
[17374]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);
[17349]154    }
[17269]155    #endregion
[17354]156
157    #region BuildJsonItemMethods
[17379]158    public static JsonItem BuildJsonItem(JObject obj) {
[17354]159      object val = obj[nameof(Value)]?.ToObject<object>();
[17379]160      if (val is JContainer jContainer) // for resolving array values
161        val = jContainer.ToObject<object[]>();
[17371]162       
[17354]163      return new JsonItem() {
164        Name = obj[nameof(Name)]?.ToString(),
165        Value = val,
166        Range = obj[nameof(Range)]?.ToObject<object[]>(),
[17379]167        ActualName = obj[nameof(ActualName)]?.ToString()
[17354]168      };
169    }
170    #endregion
171  }
[17339]172}
Note: See TracBrowser for help on using the repository browser.