using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using HeuristicLab.Core;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace HeuristicLab.JsonInterface {
///
/// Main data class for json interface.
///
public class JsonItem {
#region Private Fields
private string name;
private object value;
private IEnumerable range;
#endregion
public string Name {
get => name;
set {
name = value;
Path = Name;
UpdatePath();
}
}
public string Type { get; set; }
public string Path { get; set; }
public IList Parameters { get; set; } // -> für flachen aufbau -> childs?
public IList Operators { get; set; }
public object Value {
get => value;
set {
this.value = value;
CheckConstraints();
}
}
public IEnumerable Range {
get => range;
set {
range = value;
CheckConstraints();
}
}
public string ActualName { get; set; }
#region JsonIgnore Properties
[JsonIgnore]
public JsonItem Reference { get; set; }
[JsonIgnore]
public bool IsConfigurable => (Value != null && Range != null);
[JsonIgnore]
public bool IsParameterizedItem => Parameters != null;
#endregion
#region Public Static Methods
public static void Merge(JsonItem target, JsonItem from) {
target.Name = from.Name ?? target.Name;
target.Type = from.Type ?? target.Type;
target.Range = from.Range ?? target.Range;
target.Path = from.Path ?? target.Path;
target.Value = from.Value ?? target.Value;
target.Reference = from.Reference ?? target.Reference;
target.ActualName = from.ActualName ?? target.ActualName;
target.Parameters = from.Parameters ?? target.Parameters;
target.Operators = from.Operators ?? target.Operators;
}
#endregion
#region Public Methods
public void UpdatePath() {
if (Parameters != null)
UpdatePathHelper(Parameters);
if (Operators != null)
UpdatePathHelper(Operators);
if (Reference != null)
UpdatePathHelper(Reference);
}
#endregion
#region Helper
private void UpdatePathHelper(params JsonItem[] items) =>
UpdatePathHelper((IEnumerable)items);
private void UpdatePathHelper(IEnumerable items) {
foreach (var item in items) {
item.Path = $"{Path}.{item.Name}";
item.UpdatePath();
}
}
private void CheckConstraints() {
if (Range != null && Value != null && !IsInRange())
throw new ArgumentOutOfRangeException(nameof(Value), $"{nameof(Value)} is not in range.");
}
private bool IsInRange() => IsInRangeList() ||
(Value.GetType().IsArray && ((object[])Value).All(x => IsInNumericRange(x))) ||
(!Value.GetType().IsArray && IsInNumericRange(Value));
private bool IsInRangeList() {
foreach (var x in Range)
if (x.Equals(Value)) return true;
return false;
}
private bool IsInNumericRange(object value) =>
IsInNumericRange(value)
|| IsInNumericRange(value)
|| IsInNumericRange(value)
|| IsInNumericRange(value)
|| IsInNumericRange(value)
|| IsInNumericRange(value);
private bool IsInNumericRange(object value) where T : IComparable {
object min = Range.First(), max = Range.Last();
return value != null && min != null && max != null && value is T && min is T && max is T &&
(((T)min).CompareTo(value) == -1 || ((T)min).CompareTo(value) == 0) &&
(((T)max).CompareTo(value) == 1 || ((T)max).CompareTo(value) == 0);
}
#endregion
#region BuildJsonItemMethods
public static JsonItem BuildJsonItem(JObject obj, IDictionary typeList) {
object val = obj[nameof(Value)]?.ToObject();
if (val is JContainer)
val = ((JContainer)val).ToObject();
return new JsonItem() {
Name = obj[nameof(Name)]?.ToString(),
Path = obj[nameof(Path)]?.ToString(),
Value = val,
Range = obj[nameof(Range)]?.ToObject(),
Type = GetType(obj[nameof(Path)]?.ToObject(), typeList),
ActualName = obj[nameof(ActualName)]?.ToString(),
Parameters = PopulateParameters(obj, typeList),
Operators = PopulateOperators(obj, typeList)
};
}
private static string GetType(string path, IDictionary typeList) {
if (!string.IsNullOrEmpty(path))
if (typeList.TryGetValue(path, out string value))
return value;
return null;
}
private static IList PopulateParameters(JObject obj, IDictionary typeList) {
IList list = new List();
// add staticParameters
if (obj[Constants.StaticParameters] != null)
foreach (JObject param in obj[Constants.StaticParameters])
list.Add(BuildJsonItem(param, typeList));
// merge staticParameter with freeParameter
if (obj[Constants.FreeParameters] != null) {
foreach (JObject param in obj[Constants.FreeParameters]) {
JsonItem tmp = BuildJsonItem(param, typeList);
// search staticParameter from list
JsonItem comp = null;
foreach (var p in list)
if (p.Name == tmp.Name) comp = p;
if (comp == null)
throw new InvalidDataException($"Invalid {Constants.FreeParameters.Trim('s')}: '{tmp.Name}'!");
JsonItem.Merge(comp, tmp);
}
}
return list;
}
private static IList PopulateOperators(JObject obj, IDictionary typeList) {
IList list = new List();
JToken operators = obj[nameof(JsonItem.Operators)];
if (operators != null)
foreach (JObject sp in operators)
list.Add(BuildJsonItem(sp, typeList));
return list;
}
#endregion
}
}