source: branches/HeuristicLab.Problems.BioBoost/HeuristicLab.Problems.BioBoost/3.3/Data/DataItem.cs @ 13069

Last change on this file since 13069 was 13069, checked in by gkronber, 5 years ago

#2499: imported source code for HeuristicLab.BioBoost from private repository with some changes

File size: 6.0 KB
Line 
1using HeuristicLab.Common;
2using HeuristicLab.Core;
3using HeuristicLab.Data;
4using HeuristicLab.Parameters;
5using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
6using System;
7using System.Collections.Generic;
8using System.Globalization;
9using System.IO;
10using System.Linq;
11using System.Text;
12using System.Text.RegularExpressions;
13using YamlDotNet.RepresentationModel;
14
15namespace HeuristicLab.BioBoost.Data {
16
17  [StorableClass]
18  [Item("DataItem", "Generic Item for holding various pieces of information")]
19  public abstract class DataItem : ParameterizedNamedItem {
20
21    #region Construction & Cloning
22    [StorableConstructor]
23    protected DataItem(bool isDeserializing) : base(isDeserializing) {}
24    protected DataItem(DataItem orig, Cloner cloner) : base(orig, cloner) {}
25    protected DataItem() {}
26    #endregion
27
28    public static IEnumerable<DataItem> ParseFile(string filename) {
29      using (var reader = File.OpenText(filename)) {
30        return ParseStream(reader);
31      }
32    }
33
34    public abstract bool IsEquivalentTo(DataItem other);
35
36    public static IEnumerable<DataItem> ParseStream(TextReader reader) {
37      var yaml = new YamlStream();
38      yaml.Load(reader);
39      if (yaml.Documents.Count == 0) return Enumerable.Empty<DataItem>();
40      var root = yaml.Documents[0].RootNode as YamlMappingNode;
41      if (root == null) return Enumerable.Empty<DataItem>();
42      return ParseItems(root);
43    }
44
45    private static IEnumerable<DataItem> ParseItems(YamlMappingNode root) {
46      foreach (var child in root.Children) {
47        var type = child.Key as YamlScalarNode;
48        var value = child.Value as YamlSequenceNode;
49        if (type == null || value == null) {
50          // ignore or error?
51        } else {
52          switch (((string) type).ToLowerInvariant()) {
53            case "products":
54              foreach (var item in ParseSequence<Product>(value))
55                yield return item;
56              break;
57            case "logistics":
58              foreach (var item in ParseSequence<Logistic>(value))
59                yield return item;
60              break;
61            case "conversions":
62              foreach (var item in ParseSequence<Conversion>(value))
63                yield return item;
64              break;
65            case "cost-factors":
66              foreach (var item in ParseSequence<CostFactors>(value))
67                yield return item;
68              break;
69          }
70        }
71      }
72    }
73
74    public static IEnumerable<T> ParseSequence<T>(YamlSequenceNode seq) where T : DataItem, new() {
75      foreach (var node in seq.Children) {
76        var mappingNode = node as YamlMappingNode;
77        if (mappingNode == null) continue;
78        var item = new T();
79        item.Parse(mappingNode);
80        yield return item;
81      }
82    }
83
84    protected virtual void Parse(YamlMappingNode node) {
85      foreach (var child in node) {
86        var parameterNode = child.Key as YamlScalarNode;
87        if (parameterNode == null) continue;
88        var parameterName = ConvertNameYAML2NET(parameterNode.ToString());
89        IParameter param;
90        if (Parameters.TryGetValue(parameterName, out param) && param is IValueParameter) {
91          SetParameter(param, child.Value);
92        }
93      }
94      // TODO: check that all parameters have been filled
95    }
96
97    private static void SetParameter(IParameter param, YamlNode node) {
98      if (node is YamlScalarNode) {
99        SetScalarParameter((IValueParameter) param, (YamlScalarNode) node);
100      } else if (node is YamlMappingNode) {
101        SetMappingParameter((IValueParameter) param, (YamlMappingNode) node);
102      } else {
103        // TODO: parse error/warning?
104      }
105    }
106
107    private static void SetScalarParameter(IValueParameter param, YamlScalarNode node) {
108      if (param.DataType == typeof(StringValue)) {
109        param.Value = new StringValue(node.ToString());
110      } else if (param.DataType == typeof(DoubleValue)) {
111        param.Value = new DoubleValue(Double.Parse(node.ToString(), CultureInfo.InvariantCulture));
112      } else {
113        // TODO: parse error/warning?
114      }
115    }
116
117    private static void SetMappingParameter(IValueParameter param, YamlMappingNode node) {
118      if (typeof (DataItem).IsAssignableFrom(param.DataType)) {
119        var constructorInfo = param.DataType.GetConstructor(Type.EmptyTypes);
120        if (constructorInfo != null) {
121          var item = (DataItem) constructorInfo.Invoke(new object[0]);
122          item.Parse(node);
123          param.Value = item;
124          return;
125        }
126      } else if (param.DataType.IsAssignableFrom(typeof(ValueParameterCollection))) {
127        var dict = new ValueParameterCollection();
128        foreach (var child in node.Children) {
129          var key = child.Key as YamlScalarNode;
130          if (key != null) {
131            var p = new ValueParameter<DoubleValue>(key.ToString());
132            SetParameter(p, child.Value);
133            dict.Add(p);
134          } else {
135            // TODO: parse error/warning?
136          }
137        }
138        param.Value = dict;
139      }
140      // TODO: parse error? warning?
141    }
142
143    public static IItem CreateItem(YamlNode node) {
144      var n = node as YamlScalarNode;
145      if (n == null) return null;
146      double d;
147      string s = n.ToString();
148      if (Double.TryParse(s, NumberStyles.Float, CultureInfo.InvariantCulture, out d)) {
149        return new DoubleValue(d);
150      } else {
151        return new StringValue(s);
152      }
153    }
154
155    #region Auxiliary Methods
156    public static string ConvertNameYAML2NET(string s) {
157      var sb = new StringBuilder();
158      foreach (var word in s.Split('-')) {
159        sb.Append(CultureInfo.InvariantCulture.TextInfo.ToTitleCase(word.ToLower()));
160      }
161      return sb.ToString();
162    }
163
164    public static string ConvertNameNET2YAML(string s) {
165      return Regex.Replace(s, "([A-Z])", "-$1", RegexOptions.Compiled).Trim().ToLower();
166    }
167    #endregion
168
169  }
170}
Note: See TracBrowser for help on using the repository browser.