Changeset 17349


Ignore:
Timestamp:
11/08/19 11:36:09 (7 days ago)
Author:
dpiringe
Message:

#3026

  • added ConvertableAttribute, a new attribute for classes/structs (usage: convertable with JsonInterface)
  • changed JCGenerator -> is now a static class with one public static method Instantiate
  • changed JCInstantiator -> is now a static class with one public static method GenerateTemplate
  • refactored JsonItem
Location:
branches/3026_IntegrationIntoSymSpace
Files:
2 added
6 edited

Legend:

Unmodified
Added
Removed
  • branches/3026_IntegrationIntoSymSpace/HeuristicLab.JsonInterface.App/Runner.cs

    r17339 r17349  
    1111  internal static class Runner {
    1212    internal static void Run(string template, string config, string outputFile = @"C:\Workspace\test.txt") {
    13       JCInstantiator instantiator = new JCInstantiator();
    14       IAlgorithm alg = instantiator.Instantiate(template, config);
     13      IAlgorithm alg = JCInstantiator.Instantiate(template, config);
    1514 
    1615      Task task = alg.StartAsync();
  • branches/3026_IntegrationIntoSymSpace/HeuristicLab.JsonInterface.OptimizerIntegration/FileManager.cs

    r17339 r17349  
    4343
    4444        if (saveFileDialog.ShowDialog() == DialogResult.OK) {
    45           JCGenerator gen = new JCGenerator();
    4645          IAlgorithm alg = namedItem as IAlgorithm;
    47           File.WriteAllText(saveFileDialog.FileName, gen.GenerateTemplate(alg));
     46          File.WriteAllText(saveFileDialog.FileName, JCGenerator.GenerateTemplate(alg));
    4847        }
    4948      }
     
    6261
    6362      if (openFileDialog.ShowDialog() == DialogResult.OK) {
    64         JCInstantiator instantiator = new JCInstantiator();
    6563        try {
    66           var content = instantiator.Instantiate(openFileDialog.FileName);
     64          var content = JCInstantiator.Instantiate(openFileDialog.FileName);
    6765          IView view = MainFormManager.MainForm.ShowContent(content);
    6866          if (view == null)
  • branches/3026_IntegrationIntoSymSpace/HeuristicLab.JsonInterface/HeuristicLab.JsonInterface.csproj

    r17324 r17349  
    6161  </ItemGroup>
    6262  <ItemGroup>
     63    <Compile Include="Attributes\ConvertableAttribute.cs" />
    6364    <Compile Include="Constants.cs" />
    6465    <Compile Include="Converters\ValueLookupParameterConverter.cs" />
  • branches/3026_IntegrationIntoSymSpace/HeuristicLab.JsonInterface/JCGenerator.cs

    r17342 r17349  
    99
    1010namespace HeuristicLab.JsonInterface {
    11   public class JCGenerator {
    12     private JObject template = JObject.Parse(Constants.Template);
    13     private Dictionary<string, string> TypeList = new Dictionary<string, string>();
    14     private JArray JsonItems { get; set; } = new JArray();
     11  public static class JCGenerator {
    1512
    16     public string GenerateTemplate(IAlgorithm algorithm) {
    17       JsonItems.Clear();
    18       TypeList.Clear();
     13    private struct GenData {
     14      public JObject Template { get; set; }
     15      public IDictionary<string, string> TypeList { get; set; }
     16      public JArray JsonItems { get; set; }
     17    }
     18
     19
     20    public static string GenerateTemplate(IAlgorithm algorithm) {
     21      // data container
     22      GenData genData = new GenData() {
     23        Template = JObject.Parse(Constants.Template),
     24        TypeList = new Dictionary<string, string>(),
     25        JsonItems = new JArray()
     26      };
    1927
    2028      // 1.1. extract JsonItem, save the name in the metadata section of the
    2129      // template and save it an JArray incl. all parameters of the JsonItem,
    2230      // which have parameters aswell
    23       AddInstantiableIItem(Constants.Algorithm, algorithm);
    24       if (algorithm.Problem != null) // 1.2. only when an problem exists
    25         AddInstantiableIItem(Constants.Problem, algorithm.Problem);
     31      AddInstantiableIItem(Constants.Algorithm, algorithm, genData);
     32      IsConvertable(algorithm, true);
     33      if (algorithm.Problem != null && IsConvertable(algorithm.Problem, true)) // 1.2. only when an problem exists
     34        AddInstantiableIItem(Constants.Problem, algorithm.Problem, genData);
    2635
    2736      // 2. save the JArray with JsonItems (= IParameterizedItems)
    28       template[Constants.Objects] = JsonItems;
     37      genData.Template[Constants.Objects] = genData.JsonItems;
    2938      // 3. save the types of the JsonItems (for instatiation)
    30       template[Constants.Types] = JObject.FromObject(TypeList);
     39      genData.Template[Constants.Types] = JObject.FromObject(genData.TypeList);
    3140      // 4. serialize template and return string
    32       return CustomJsonWriter.Serialize(template);
     41      return CustomJsonWriter.Serialize(genData.Template);
     42    }
     43   
     44    #region Helper
     45    private static bool IsConvertable(object obj, bool throwException) {
     46      bool tmp = ConvertableAttribute.IsConvertable(obj);
     47      if (throwException && tmp)
     48        throw new NotSupportedException($"Type {obj.GetType().Name} is not convertable!");
     49      return tmp;
     50    }
     51    private static void AddInstantiableIItem(string metaDataTagName, IItem item, GenData genData) {
     52      JsonItem jsonItem = JsonItemConverter.Extract(item);
     53      genData.Template[Constants.Metadata][metaDataTagName] = item.ItemName;
     54      PopulateJsonItems(jsonItem, genData);
    3355    }
    3456
    35     #region Helper
    36     private void AddInstantiableIItem(string metaDataTagName, IItem item) {
    37       JsonItem jsonItem = JsonItemConverter.Extract(item);
    38       template[Constants.Metadata][metaDataTagName] = item.ItemName;
    39       PopulateJsonItems(jsonItem);
    40     }
    41 
    42     private void PopulateJsonItems(JsonItem item) {
     57    // serializes ParameterizedItems and saves them in list "JsonItems".
     58    private static void PopulateJsonItems(JsonItem item, GenData genData) {
    4359      if (item.Parameters != null) {
    4460        if (item.Range == null)
    45           JsonItems.Add(Serialize(item));
     61          genData.JsonItems.Add(Serialize(item, genData));
    4662        foreach (var p in item.Parameters)
    47           if (p.Parameters != null)
    48             PopulateJsonItems(p);
     63          if (p.IsParameterizedItem)
     64            PopulateJsonItems(p, genData);
    4965      }
    5066    }
    5167
    52     private JObject Serialize(JsonItem item) {
     68    private static JObject Serialize(JsonItem item, GenData genData) {
    5369      JObject obj = JObject.FromObject(item, Settings());
    5470      obj[Constants.StaticParameters] = obj[nameof(JsonItem.Parameters)];
     
    6278      obj.Property(nameof(JsonItem.Type))?.Remove();
    6379
    64       TypeList.Add(item.Path, item.Type);
     80      genData.TypeList.Add(item.Path, item.Type);
    6581      return obj;
    6682    }
    6783
    68     private void RefactorFreeParameters(JToken token) {
     84    // deletes unnecessary properties for free parameters.
     85    private static void RefactorFreeParameters(JToken token) {
    6986      IList<JObject> objToRemove = new List<JObject>();
    7087      TransformNodes(x => {
     
    8097    }
    8198
    82     private void RefactorStaticParameters(JToken token) {
     99    // deletes unnecessary properties for static parameters.
     100    private static void RefactorStaticParameters(JToken token) {
    83101      IList<JObject> objToRemove = new List<JObject>();
    84102      TransformNodes(x => {
     
    88106        x.Property(nameof(JsonItem.Parameters))?.Remove();
    89107        x.Property(nameof(JsonItem.Type))?.Remove();
    90         if (p.Value == null) objToRemove.Add(x);
     108        //TODO: maybe allow JsonItems with Value==null in static parameters too?
     109        if (p.Value == null) objToRemove.Add(x);
    91110      }, token[Constants.StaticParameters]);
    92111      foreach (var x in objToRemove) x.Remove();
    93112    }
    94113
    95     private JsonSerializer Settings() => new JsonSerializer() {
     114    /// <summary>
     115    /// Settings for the json serialization.
     116    /// </summary>
     117    /// <returns>A configured JsonSerializer.</returns>
     118    private static JsonSerializer Settings() => new JsonSerializer() {
    96119      TypeNameHandling = TypeNameHandling.None,
    97120      NullValueHandling = NullValueHandling.Ignore,
     
    99122    };
    100123
    101     private void TransformNodes(Action<JObject> action, params JToken[] tokens) {
     124    private static void TransformNodes(Action<JObject> action, params JToken[] tokens) {
    102125      foreach(JObject obj in tokens.SelectMany(x => x.Children<JObject>()))
    103126        action(obj);
  • branches/3026_IntegrationIntoSymSpace/HeuristicLab.JsonInterface/JCInstantiator.cs

    r17342 r17349  
    1414
    1515namespace HeuristicLab.JsonInterface {
    16   public class JCInstantiator {
     16  public static class JCInstantiator {
     17    private struct InstData {
     18      public JToken Template { get; set; }
     19      public JArray Config { get; set; }
     20      public Dictionary<string, string> TypeList { get; set; }
     21      public IDictionary<string, JsonItem> ParameterizedItems { get; set; }
     22      public IDictionary<string, JsonItem> ConfigurableItems { get; set; }
     23    }
    1724
    18     private JToken Template { get; set; }
    19     private JArray Config { get; set; }
    20 
    21     private Dictionary<string, string> TypeList = new Dictionary<string, string>();
    22     private IDictionary<string, JsonItem> ParameterizedItems { get; set; } = new Dictionary<string, JsonItem>();
    23     private IDictionary<string, JsonItem> ConfigurableItems { get; set; } = new Dictionary<string, JsonItem>();
    24    
    25     public IAlgorithm Instantiate(string templateFile, string configFile = "") {
     25    public static IAlgorithm Instantiate(string templateFile, string configFile = "") {
     26      InstData instData = new InstData() {
     27        TypeList = new Dictionary<string, string>(),
     28        ParameterizedItems = new Dictionary<string, JsonItem>(),
     29        ConfigurableItems = new Dictionary<string, JsonItem>()
     30      };
    2631
    2732      //1. Parse Template and Config files
    28       Template = JToken.Parse(File.ReadAllText(templateFile));
     33      instData.Template = JToken.Parse(File.ReadAllText(templateFile));
    2934      if(!string.IsNullOrEmpty(configFile))
    30         Config = JArray.Parse(File.ReadAllText(configFile));
    31       TypeList = Template[Constants.Types].ToObject<Dictionary<string, string>>();
    32       string algorithmName = Template[Constants.Metadata][Constants.Algorithm].ToString();
    33       string problemName = Template[Constants.Metadata][Constants.Problem].ToString();
     35        instData.Config = JArray.Parse(File.ReadAllText(configFile));
     36      instData.TypeList = instData.Template[Constants.Types].ToObject<Dictionary<string, string>>();
     37      string algorithmName = instData.Template[Constants.Metadata][Constants.Algorithm].ToString();
     38      string problemName = instData.Template[Constants.Metadata][Constants.Problem].ToString();
    3439
    3540      //2. Collect all parameterizedItems from template
    36       CollectParameterizedItems();
     41      CollectParameterizedItems(instData);
    3742
    3843      //3. select all ConfigurableItems
    39       SelectConfigurableItems();
     44      SelectConfigurableItems(instData);
    4045
    4146      //4. if config != null -> merge Template and Config
    42       if (Config != null)
    43         MergeTemplateWithConfig();
     47      if (instData.Config != null)
     48        MergeTemplateWithConfig(instData);
    4449
    4550      //5. resolve the references between parameterizedItems
    46       ResolveReferences();
     51      ResolveReferences(instData);
    4752
    4853      //6. get algorthm data and object
    49       JsonItem algorithmData = GetData(algorithmName);
    50       IAlgorithm algorithm = CreateObject<IAlgorithm>(algorithmData);
     54      JsonItem algorithmData = GetData(algorithmName, instData);
     55      IAlgorithm algorithm = CreateObject<IAlgorithm>(algorithmData, instData);
    5156
    5257      //7. get problem data and object
    53       JsonItem problemData = GetData(problemName);
    54       IProblem problem = CreateObject<IProblem>(problemData);
     58      JsonItem problemData = GetData(problemName, instData);
     59      IProblem problem = CreateObject<IProblem>(problemData, instData);
    5560      algorithm.Problem = problem;
    5661
     
    5964      JsonItemConverter.Inject(problem, problemData);
    6065
     66      // TODO: let the engine be configurable
    6167      if (algorithm is EngineAlgorithm)
    6268        algorithm.Cast<EngineAlgorithm>().Engine = new SequentialEngine.SequentialEngine();
     
    6571    }
    6672
    67     private void CollectParameterizedItems() {
    68       foreach (JObject item in Template[Constants.Objects]) {
    69         JsonItem data = BuildJsonItem(item);
    70         ParameterizedItems.Add(data.Path, data);
     73    #region Helper
     74    private static void CollectParameterizedItems(InstData instData) {
     75      foreach (JObject item in instData.Template[Constants.Objects]) {
     76        JsonItem data = BuildJsonItem(item, instData);
     77        instData.ParameterizedItems.Add(data.Path, data);
    7178      }
    7279    }
    7380
    74     private void SelectConfigurableItems() {
    75       foreach (var item in ParameterizedItems.Values) {
     81    private static void SelectConfigurableItems(InstData instData) {
     82      foreach (var item in instData.ParameterizedItems.Values) {
    7683        if (item.Parameters != null)
    77           AddConfigurableItems(item.Parameters);
     84          AddConfigurableItems(item.Parameters, instData);
    7885
    7986        if (item.Operators != null)
    80           AddConfigurableItems(item.Operators);
     87          AddConfigurableItems(item.Operators, instData);
    8188      }
    8289    }
    8390
    84     private void AddConfigurableItems(IEnumerable<JsonItem> items) {
     91    private static void AddConfigurableItems(IEnumerable<JsonItem> items, InstData instData) {
    8592      foreach (var item in items)
    8693        if (item.IsConfigurable)
    87           ConfigurableItems.Add(item.Path, item);
     94          instData.ConfigurableItems.Add(item.Path, item);
    8895    }
    8996
    90     private void ResolveReferences() {
    91       foreach(var x in ParameterizedItems.Values)
     97    private static void ResolveReferences(InstData instData) {
     98      foreach(var x in instData.ParameterizedItems.Values)
    9299        foreach (var p in x.Parameters)
    93100          if (p.Value is string) {
     
    96103              key = $"{p.Path}.{p.Value.Cast<string>()}";
    97104
    98             if (ParameterizedItems.TryGetValue(key, out JsonItem value))
     105            if (instData.ParameterizedItems.TryGetValue(key, out JsonItem value))
    99106              p.Reference = value;
    100107          }
    101108    }
    102109
    103     private void MergeTemplateWithConfig() {
    104       foreach (JObject obj in Config) {
     110    private static void MergeTemplateWithConfig(InstData instData) {
     111      foreach (JObject obj in instData.Config) {
    105112        // build item from config object
    106         JsonItem item = BuildJsonItem(obj);
     113        JsonItem item = BuildJsonItem(obj, instData);
    107114        // override default value
    108         if (ConfigurableItems.TryGetValue(item.Path, out JsonItem param)) {
     115        if (instData.ConfigurableItems.TryGetValue(item.Path, out JsonItem param)) {
    109116          param.Value = item.Value;
    110117          // override ActualName (for LookupParameters)
     
    115122    }
    116123
    117     private JsonItem GetData(string key)
     124    private static JsonItem GetData(string key, InstData instData)
    118125    {
    119       if (ParameterizedItems.TryGetValue(key, out JsonItem value))
     126      if (instData.ParameterizedItems.TryGetValue(key, out JsonItem value))
    120127        return value;
    121128      else
     
    123130    }
    124131
    125     private T CreateObject<T>(JsonItem data) {
    126       if (TypeList.TryGetValue(data.Name, out string typeName)) {
     132    private static T CreateObject<T>(JsonItem data, InstData instData) {
     133      if (instData.TypeList.TryGetValue(data.Name, out string typeName)) {
    127134        Type type = Type.GetType(typeName);
    128135        return (T)Activator.CreateInstance(type);
     
    131138
    132139    #region BuildJsonItemMethods
    133     private JsonItem BuildJsonItem(JObject obj) =>
     140    private static JsonItem BuildJsonItem(JObject obj, InstData instData) =>
    134141      new JsonItem() {
    135142        Name = obj[nameof(JsonItem.Name)]?.ToString(),
     
    137144        Value = obj[nameof(JsonItem.Value)]?.ToObject<object>(),
    138145        Range = obj[nameof(JsonItem.Range)]?.ToObject<object[]>(),
    139         Type = GetType(obj[nameof(JsonItem.Path)]?.ToObject<string>()),
     146        Type = GetType(obj[nameof(JsonItem.Path)]?.ToObject<string>(), instData),
    140147        ActualName = obj[nameof(JsonItem.ActualName)]?.ToString(),
    141         Parameters = PopulateParameters(obj),
    142         Operators = PopulateOperators(obj)
     148        Parameters = PopulateParameters(obj, instData),
     149        Operators = PopulateOperators(obj, instData)
    143150      };
    144151
    145     private string GetType(string path) {
     152    private static string GetType(string path, InstData instData) {
    146153      if(!string.IsNullOrEmpty(path))
    147         if (TypeList.TryGetValue(path, out string value))
     154        if (instData.TypeList.TryGetValue(path, out string value))
    148155          return value;
    149156      return null;
    150157    }
    151158
    152     private IList<JsonItem> PopulateParameters(JObject obj) {
     159    private static IList<JsonItem> PopulateParameters(JObject obj, InstData instData) {
    153160      IList<JsonItem> list = new List<JsonItem>();
    154161
     
    156163      if (obj[Constants.StaticParameters] != null)
    157164        foreach (JObject param in obj[Constants.StaticParameters])
    158           list.Add(BuildJsonItem(param));
     165          list.Add(BuildJsonItem(param, instData));
    159166
    160167      // merge staticParameter with freeParameter
    161168      if (obj[Constants.FreeParameters] != null) {
    162169        foreach (JObject param in obj[Constants.FreeParameters]) {
    163           JsonItem tmp = BuildJsonItem(param);
     170          JsonItem tmp = BuildJsonItem(param, instData);
    164171         
    165172          // search staticParameter from list
     
    176183    }
    177184
    178     private IList<JsonItem> PopulateOperators(JObject obj) {
     185    private static IList<JsonItem> PopulateOperators(JObject obj, InstData instData) {
    179186      IList<JsonItem> list = new List<JsonItem>();
    180187      JToken operators = obj[nameof(JsonItem.Operators)];
    181188      if (operators != null)
    182189        foreach (JObject sp in operators)
    183           list.Add(BuildJsonItem(sp));
     190          list.Add(BuildJsonItem(sp, instData));
    184191      return list;
    185192    }
    186193    #endregion
     194    #endregion
    187195  }
    188196}
  • branches/3026_IntegrationIntoSymSpace/HeuristicLab.JsonInterface/JsonItem.cs

    r17342 r17349  
    1010namespace HeuristicLab.JsonInterface {
    1111  public class JsonItem {
     12
     13    #region Private Fields
     14    private string name;
     15    private object value;
     16    private IList<object> range;
     17    #endregion
    1218   
    13     private string name;
    1419    public string Name {
    1520      get => name;
     
    2429    public IList<JsonItem> Parameters { get; set; }
    2530    public IList<JsonItem> Operators { get; set; }
    26 
    27     private object value;
    2831    public object Value {
    2932      get => value;
    3033      set {
    3134        this.value = value;
    32         if(Range != null && value != null && !FulfillConstraints())
    33           throw new ArgumentOutOfRangeException("Default", "Default is not in range.");
     35        CheckConstraints();
    3436      }
    3537    }
    36 
    37     private IList<object> range;
    3838    public IList<object> Range {
    3939      get => range;
    4040      set {
    4141        range = value;
    42         if (Value != null && value != null && !FulfillConstraints())
    43           throw new ArgumentOutOfRangeException("Default", "Default is not in range.");
     42        CheckConstraints();
    4443      }
    4544    }
    46    
    4745    public string ActualName { get; set; }
    4846
     47    #region JsonIgnore Properties
    4948    [JsonIgnore]
    5049    public JsonItem Reference { get; set; }
     
    5352    public bool IsConfigurable => (Value != null && Range != null);
    5453
     54    [JsonIgnore]
     55    public bool IsParameterizedItem => Parameters != null;
     56    #endregion
     57
     58    #region Public Static Methods
    5559    public static void Merge(JsonItem target, JsonItem from) {
    5660      target.Name = from.Name ?? target.Name;
     
    6468      target.Operators = from.Operators ?? target.Operators;
    6569    }
     70    #endregion
    6671
    67     public bool FulfillConstraints() => FulfillConstraints(this);
    68 
    69     public static bool FulfillConstraints(JsonItem data) =>
    70       data.Range != null && data.Value != null && (
    71       IsInRangeList(data.Range, data.Value) ||
    72       IsInNumericRange<long>(data.Value, data.Range[0], data.Range[1]) ||
    73       IsInNumericRange<int>(data.Value, data.Range[0], data.Range[1]) ||
    74       IsInNumericRange<short>(data.Value, data.Range[0], data.Range[1]) ||
    75       IsInNumericRange<byte>(data.Value, data.Range[0], data.Range[1]) ||
    76       IsInNumericRange<float>(data.Value, data.Range[0], data.Range[1]) ||
    77       IsInNumericRange<double>(data.Value, data.Range[0], data.Range[1]));
    78 
     72    #region Public Methods
    7973    public void UpdatePath() {
    8074      if (Parameters != null)
     
    8781        UpdatePathHelper(Reference);
    8882    }
     83    #endregion
    8984
    9085    #region Helper
     
    9994    }
    10095
    101     private static bool IsInRangeList(IEnumerable<object> list, object value) {
    102       foreach (var x in list)
    103         if (x.Equals(value)) return true;
     96    private void CheckConstraints() {
     97      if (Range != null && Value != null && !IsInRange())
     98        throw new ArgumentOutOfRangeException("Default", "Default is not in range.");
     99    }
     100
     101
     102    private bool IsInRange() => IsInRangeList() || IsInNumericRange();
     103
     104    private bool IsInRangeList() {
     105      foreach (var x in Range)
     106        if (x.Equals(Value)) return true;
    104107      return false;
    105108    }
    106109
    107     private static bool IsInNumericRange<T>(object value, object min, object max) where T : IComparable =>
    108       (value != null && min != null && max != null && value is T && min is T && max is T &&
    109         (((T)min).CompareTo(value) == -1 || ((T)min).CompareTo(value) == 0) &&
    110         (((T)max).CompareTo(value) == 1 || ((T)max).CompareTo(value) == 0));
     110    private bool IsInNumericRange() =>
     111      IsInNumericRange<long>()
     112      || IsInNumericRange<int>()
     113      || IsInNumericRange<short>()
     114      || IsInNumericRange<byte>()
     115      || IsInNumericRange<float>()
     116      || IsInNumericRange<double>();
     117
     118    private bool IsInNumericRange<T>() where T : IComparable {
     119      object value = Value, min = Range[0], max = Range[1];
     120      return value != null && min != null && max != null && value is T && min is T && max is T &&
     121            (((T)min).CompareTo(value) == -1 || ((T)min).CompareTo(value) == 0) &&
     122            (((T)max).CompareTo(value) == 1 || ((T)max).CompareTo(value) == 0);
     123    }
     124     
    111125    #endregion
    112126  }
Note: See TracChangeset for help on using the changeset viewer.