Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.Services.OKB.AttributeSelector/3.3/RunAttributeSelector.cs @ 4279

Last change on this file since 4279 was 4279, checked in by swagner, 12 years ago

Integrated OKB services (#1166)

File size: 14.5 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2010 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
4 *
5 * This file is part of HeuristicLab.
6 *
7 * HeuristicLab is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * HeuristicLab is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
19 */
20#endregion
21
22using System;
23using System.Collections;
24using System.Collections.Generic;
25using System.Data.Linq;
26using System.Linq;
27using System.Linq.Expressions;
28using System.Reflection;
29using HeuristicLab.Services.OKB.DataAccess;
30
31namespace HeuristicLab.Services.OKB.AttributeSelection {
32
33  public class AttributeSpecifier {
34    public string TableName { get; set; }
35    public string FieldName { get; set; }
36    public Type DataType { get; set; }
37  }
38
39  public class RunAttributeSelector : AttributeSelector {
40
41    public RunAttributeSelector(OKBDataContext okb, string table, string field)
42      : base(okb, table, field) { }
43
44    public RunAttributeSelector(OKBDataContext okb, IAttributeSelector selector)
45      : base(okb, selector.TableName, selector.FieldName) {
46      IsHidden = selector.IsHidden;
47      MinValue = selector.MinValue;
48      MaxValue = selector.MaxValue;
49      AllowedValues = selector.AllowedValues;
50    }
51
52    protected RunAttributeSelector(Type tableType, string fieldName, bool isDynamic, Type dataType, int parentId)
53      : base(tableType, fieldName, isDynamic, dataType, parentId) { }
54
55    public static IEnumerable<RunAttributeSelector> GetAllAttributeSelectors(OKBDataContext okb) {
56      OKBDataContext o = new OKBDataContext(okb.Connection.ConnectionString);
57      DataLoadOptions dlo = new DataLoadOptions();
58      dlo.LoadWith<Result>(r => r.DataType);
59      dlo.LoadWith<Parameter>(p => p.DataType);
60      dlo.LoadWith<ProblemCharacteristic>(pc => pc.DataType);
61      o.LoadOptions = dlo;
62      foreach (Selector selector in Selectors) {
63        yield return new RunAttributeSelector(o, selector.Table.Name, selector.Field);
64      }
65      foreach (Result result in okb.Results) {
66        yield return new RunAttributeSelector(typeof(Result), result.Name, true, result.DataType.Type, result.Id);
67      }
68      foreach (Parameter p in okb.Parameters) {
69        yield return new RunAttributeSelector(typeof(Parameter), p.Name, true, p.DataType.Type, p.Id);
70      }
71      foreach (ProblemCharacteristic pc in okb.ProblemCharacteristics) {
72        yield return new RunAttributeSelector(typeof(ProblemCharacteristic), pc.Name, true, pc.DataType.Type, pc.Id);
73      }
74    }
75
76    public void ConfigureDataLoadOptions(DataLoadOptions dlo) {
77      if (IsHidden)
78        return;
79      Include(TableType, dlo);
80    }
81
82    private static readonly Dictionary<Type, Type> parents = new Dictionary<Type, Type>() {
83      { typeof(Run), null },
84      { typeof(Client), typeof(Run) },
85      { typeof(User), typeof(Run) },
86      { typeof(Experiment), typeof(Run) },
87      { typeof(ExperimentCreator), typeof(Experiment) },
88      { typeof(Project), typeof(Experiment) },
89      { typeof(Algorithm), typeof(Experiment) },
90      { typeof(AlgorithmClass), typeof(Algorithm) },
91      { typeof(Platform), typeof(Algorithm) },
92      { typeof(Problem), typeof(Experiment) },
93      { typeof(ProblemClass), typeof(Problem) },
94      { typeof(SolutionRepresentation), typeof(Problem) },
95    };
96
97    public static MethodInfo Enumerable_Where =
98      typeof(Enumerable).GetMethods().Single(mi =>
99        mi.Name == "Where" &&
100        mi.GetParameters().Count() == 2 &&
101        mi.GetParameters()[1].ParameterType.GetGenericArguments().Count() == 2);
102
103    public static MethodInfo Enumerable_Cast = typeof(Enumerable).GetMethod("Cast");
104
105    private void AssociateWith<T, V>(DataLoadOptions dlo,
106      Expression<Func<T, IEnumerable>> intSelector,
107      Expression<Func<T, IEnumerable>> doubleSelector,
108      Expression<Func<T, IEnumerable>> charSelector,
109      Expression<Func<T, IEnumerable>> blobSelector,
110      Expression<Func<V, bool>> filterPredicate) {
111      Expression<Func<T, IEnumerable>> selector;
112      switch (Type.GetTypeCode(DataType)) {
113        case TypeCode.Int32: selector = intSelector; break;
114        case TypeCode.Double: selector = doubleSelector; break;
115        case TypeCode.String: selector = charSelector; break;
116        default:
117          if (blobSelector != null)
118            selector = blobSelector;
119          else
120            throw new ArgumentException("DataType");
121          break;
122      }
123      ParameterExpression param = Expression.Parameter(typeof(T), "param");
124      dlo.AssociateWith<T>((Expression<Func<T, object>>)
125        Expression.Lambda(
126          Expression.Convert(
127            Expression.Call(
128              null,
129              Enumerable_Where.MakeGenericMethod(typeof(V)),
130              Expression.Convert(Expression.Invoke(selector, param), typeof(IEnumerable<V>)),
131              filterPredicate),
132          typeof(object)), param));
133      try {
134        dlo.LoadWith(selector);
135      }
136      catch (ArgumentException) {
137        Console.WriteLine("INFO: not adding (duplicate) load option: dlo.LoadWith<{0}>({1})", typeof(T).Name, selector.ToString());
138        Console.WriteLine("INFO: clearing association filters to allow multiple associations");
139        dlo.AssociateWith<T>((Expression<Func<T, object>>)
140          Expression.Lambda(
141            Expression.Convert(
142            Expression.Invoke(selector, param),
143            typeof(object)),
144          param));
145      }
146    }
147
148    private void Include(Type type, DataLoadOptions dlo) {
149      if (parents.ContainsKey(type)) {
150        Type parentType = parents[type];
151        if (parentType == null)
152          return;
153        LoadWith(dlo, parentType, type);
154        Include(parentType, dlo);
155      } else if (type == typeof(ProblemCharacteristic)) {
156        AssociateWith<Problem, IProblemCharacteristicValue>(dlo,
157          p => p.IntProblemCharacteristicValues,
158          p => p.FloatProblemCharacteristicValues,
159          p => p.CharProblemCharacteristicValues,
160          null,
161          pc => pc.ProblemId == ParentId);
162        Include(typeof(Problem), dlo);
163      } else if (type == typeof(Parameter)) {
164        AssociateWith<Experiment, IParameterValue>(dlo,
165          x => x.IntParameterValues,
166          x => x.FloatParameterValues,
167          x => x.CharParameterValues,
168          x => x.OperatorParameterValues,
169          ipv => ipv.ParameterId == ParentId);
170        try {
171          dlo.LoadWith<OperatorParameterValue>(opv => opv.DataType);
172        }
173        catch (ArgumentException) {
174          Console.WriteLine("INFO: not adding (duplicate) load option for OperatorParameterValue.DataType");
175        }
176        Include(typeof(Experiment), dlo);
177      } else if (type == typeof(Result)) {
178        AssociateWith<Run, IResultValue>(dlo,
179          r => r.IntResultValues,
180          r => r.FloatResultValues,
181          r => r.CharResultValues,
182          r => r.BlobResultValues,
183          irv => irv.ResultId == ParentId);
184      } else
185        throw new ArgumentException("type");
186    }
187
188    protected static List<Selector> Selectors = new List<Selector>() {
189        ExpressionTools.GetSelector(run => run, r => r.Id),
190        ExpressionTools.GetSelector(run => run, r => r.FinishedDate),
191
192        ExpressionTools.GetSelector(run => run.Client, c => c.Id),
193        ExpressionTools.GetSelector(run => run.Client, c => c.Name),
194
195        ExpressionTools.GetSelector(run => run.User, u => u.Id),
196        ExpressionTools.GetSelector(run => run.User, u => u.Name),
197
198        ExpressionTools.GetSelector(run => run.Experiment, x => x.Id),
199
200        ExpressionTools.GetSelector(run => run.Experiment.ExperimentCreators.Single(), xc => xc.User.Id),
201        ExpressionTools.GetSelector(run => run.Experiment.ExperimentCreators.Single(), xc => xc.User.Name),
202
203        ExpressionTools.GetSelector(run => run.Experiment.Project, p => p.Id),
204        ExpressionTools.GetSelector(run => run.Experiment.Project, p => p.Name),
205        ExpressionTools.GetSelector(run => run.Experiment.Project, p => p.Description),
206
207        ExpressionTools.GetSelector(run => run.Experiment.Algorithm, a => a.Id),
208        ExpressionTools.GetSelector(run => run.Experiment.Algorithm, a => a.Name),
209        ExpressionTools.GetSelector(run => run.Experiment.Algorithm, a => a.Description),
210
211        ExpressionTools.GetSelector(run => run.Experiment.Algorithm.AlgorithmClass, ac => ac.Id),
212        ExpressionTools.GetSelector(run => run.Experiment.Algorithm.AlgorithmClass, ac => ac.Name),
213        ExpressionTools.GetSelector(run => run.Experiment.Algorithm.AlgorithmClass, ac => ac.Description),
214
215        ExpressionTools.GetSelector(run => run.Experiment.Algorithm.Platform, p => p.Id),
216        ExpressionTools.GetSelector(run => run.Experiment.Algorithm.Platform, p => p.Name),
217        ExpressionTools.GetSelector(run => run.Experiment.Algorithm.Platform, p => p.Description),
218
219        ExpressionTools.GetSelector(run => run.Experiment.Problem, p => p.Id),
220        ExpressionTools.GetSelector(run => run.Experiment.Problem, p => p.Name),
221        ExpressionTools.GetSelector(run => run.Experiment.Problem, p => p.Description),
222
223        ExpressionTools.GetSelector(run => run.Experiment.Problem.ProblemClass, pc => pc.Id),
224        ExpressionTools.GetSelector(run => run.Experiment.Problem.ProblemClass, pc => pc.Name),
225        ExpressionTools.GetSelector(run => run.Experiment.Problem.ProblemClass, pc => pc.Description),
226
227        ExpressionTools.GetSelector(run => run.Experiment.Problem.SolutionRepresentation, sr => sr.Id),
228        ExpressionTools.GetSelector(run => run.Experiment.Problem.SolutionRepresentation, sr => sr.Name),
229        ExpressionTools.GetSelector(run => run.Experiment.Problem.SolutionRepresentation, sr => sr.Description)
230    };
231
232    private Func<Run, object> compiledSelector;
233
234    protected void CreateCompiledSelector<T>() {
235      var genericCompiledSelector = ((Expression<Func<Run, T>>)GetSelectorExpression()).Compile();
236      compiledSelector = run => {
237        try {
238          return (object)genericCompiledSelector(run);
239        }
240        catch (InvalidOperationException x) {
241          if (x.TargetSite == ExpressionTools.Enumerable_Single)
242            return null;
243          else
244            throw;
245        }
246      };
247    }
248
249    public Func<Run, object> CompiledSelector {
250      get {
251        if (compiledSelector == null) {
252          typeof(RunAttributeSelector)
253            .GetMethod("CreateCompiledSelector", BindingFlags.Instance | BindingFlags.NonPublic)
254            .MakeGenericMethod(DataType).Invoke(this, new object[0]);
255        }
256        return compiledSelector;
257      }
258    }
259
260    public LambdaExpression GetSelectorExpression() {
261      if (TableType == typeof(Parameter))
262        return
263          GetDynamicSelector(typeof(Parameter), run => run.Experiment,
264            x => x.IntParameterValues.Single(ipv => ipv.ParameterId == ParentId).Value,
265            x => x.FloatParameterValues.Single(fpv => fpv.ParameterId == ParentId).Value,
266            x => x.CharParameterValues.Single(cpv => cpv.ParameterId == ParentId).Value,
267            x => x.OperatorParameterValues.Single(opv => opv.ParameterId == ParentId).DataType.ClrName);
268      else if (TableType == typeof(Result))
269        return
270          GetDynamicSelector(typeof(Result), run => run,
271            r => r.IntResultValues.Single(irv => irv.ResultId == ParentId).Value,
272            r => r.FloatResultValues.Single(frv => frv.ResultId == ParentId).Value,
273            r => r.CharResultValues.Single(crv => crv.ResultId == ParentId).Value,
274            null);
275      else if (TableType == typeof(ProblemCharacteristic))
276        return
277          GetDynamicSelector(typeof(ProblemCharacteristic), run => run.Experiment.Problem,
278            p => p.IntProblemCharacteristicValues.Single(ipcv => ipcv.ProblemCharacteristicId == ParentId).Value,
279            p => p.FloatProblemCharacteristicValues.Single(fpcv => fpcv.ProblemCharacteristicId == ParentId).Value,
280            p => p.CharProblemCharacteristicValues.Single(cpcv => cpcv.ProblemCharacteristicId == ParentId).Value,
281            null);
282      else
283        return Selectors.Single(s => s.Table == TableType && s.Field == FieldName).Expression;
284    }
285
286    public Expression<Func<Run, bool>> GetWhereExpression() {
287      return GetWhereExpression(GetSelectorExpression());
288    }
289
290    protected Expression<Func<Run, bool>> GetWhereExpression(Expression selector) {
291      try {
292        return (Expression<Func<Run, bool>>)typeof(RunAttributeSelector)
293          .GetMethod("GenericGetWhereExpression", BindingFlags.Instance | BindingFlags.NonPublic)
294          .MakeGenericMethod(selector.Type.GetGenericArguments()[1])
295          .Invoke(this, new[] { selector });
296      }
297      catch (TargetInvocationException x) {
298        throw x.InnerException;
299      }
300    }
301
302    protected Expression<Func<Run, bool>> GenericGetWhereExpression<T>(Expression<Func<Run, T>> selector) {
303      ParameterExpression parameter = Expression.Parameter(typeof(Run), "run");
304      Expression testExpression = Expression.Constant(true);
305      if (AllowedValues != null) {
306        testExpression = Expression.AndAlso(testExpression,
307          Expression.Call(
308            null,
309            ExpressionTools.Enumerable_Contains.MakeGenericMethod(typeof(T)),
310            Expression.Constant(AllowedValues.Cast<T>().ToArray()),
311            Expression.Invoke(selector, parameter)));
312      }
313      if (MinValue != null) {
314        testExpression = Expression.AndAlso(testExpression,
315          ExpressionTools.GetLessThanOrEqualExpression<T>(Expression.Constant(MinValue),
316          Expression.Invoke(selector, parameter)));
317      }
318      if (MaxValue != null) {
319        testExpression = Expression.AndAlso(testExpression,
320          ExpressionTools.GetGreaterOrEqualExpression<T>(Expression.Constant(MaxValue),
321          Expression.Invoke(selector, parameter)));
322      }
323      return (Expression<Func<Run, bool>>)
324        Expression.Lambda(testExpression, parameter);
325    }
326  }
327}
Note: See TracBrowser for help on using the repository browser.