Free cookie consent management tool by TermsFeed Policy Generator

source: branches/OKB/HeuristicLab.Services.OKB.AttributeSelection/3.3/RunAttributeSelector.cs @ 8119

Last change on this file since 8119 was 4298, checked in by swagner, 14 years ago

Worked on OKB user authentication (#1167)

File size: 14.2 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(Project), typeof(Experiment) },
88      { typeof(Algorithm), typeof(Experiment) },
89      { typeof(AlgorithmClass), typeof(Algorithm) },
90      { typeof(Platform), typeof(Algorithm) },
91      { typeof(Problem), typeof(Experiment) },
92      { typeof(ProblemClass), typeof(Problem) },
93      { typeof(SolutionRepresentation), typeof(Problem) },
94    };
95
96    public static MethodInfo Enumerable_Where =
97      typeof(Enumerable).GetMethods().Single(mi =>
98        mi.Name == "Where" &&
99        mi.GetParameters().Count() == 2 &&
100        mi.GetParameters()[1].ParameterType.GetGenericArguments().Count() == 2);
101
102    public static MethodInfo Enumerable_Cast = typeof(Enumerable).GetMethod("Cast");
103
104    private void AssociateWith<T, V>(DataLoadOptions dlo,
105      Expression<Func<T, IEnumerable>> intSelector,
106      Expression<Func<T, IEnumerable>> doubleSelector,
107      Expression<Func<T, IEnumerable>> charSelector,
108      Expression<Func<T, IEnumerable>> blobSelector,
109      Expression<Func<V, bool>> filterPredicate) {
110      Expression<Func<T, IEnumerable>> selector;
111      switch (Type.GetTypeCode(DataType)) {
112        case TypeCode.Int32: selector = intSelector; break;
113        case TypeCode.Double: selector = doubleSelector; break;
114        case TypeCode.String: selector = charSelector; break;
115        default:
116          if (blobSelector != null)
117            selector = blobSelector;
118          else
119            throw new ArgumentException("DataType");
120          break;
121      }
122      ParameterExpression param = Expression.Parameter(typeof(T), "param");
123      dlo.AssociateWith<T>((Expression<Func<T, object>>)
124        Expression.Lambda(
125          Expression.Convert(
126            Expression.Call(
127              null,
128              Enumerable_Where.MakeGenericMethod(typeof(V)),
129              Expression.Convert(Expression.Invoke(selector, param), typeof(IEnumerable<V>)),
130              filterPredicate),
131          typeof(object)), param));
132      try {
133        dlo.LoadWith(selector);
134      }
135      catch (ArgumentException) {
136        Console.WriteLine("INFO: not adding (duplicate) load option: dlo.LoadWith<{0}>({1})", typeof(T).Name, selector.ToString());
137        Console.WriteLine("INFO: clearing association filters to allow multiple associations");
138        dlo.AssociateWith<T>((Expression<Func<T, object>>)
139          Expression.Lambda(
140            Expression.Convert(
141            Expression.Invoke(selector, param),
142            typeof(object)),
143          param));
144      }
145    }
146
147    private void Include(Type type, DataLoadOptions dlo) {
148      if (parents.ContainsKey(type)) {
149        Type parentType = parents[type];
150        if (parentType == null)
151          return;
152        LoadWith(dlo, parentType, type);
153        Include(parentType, dlo);
154      } else if (type == typeof(ProblemCharacteristic)) {
155        AssociateWith<Problem, IProblemCharacteristicValue>(dlo,
156          p => p.IntProblemCharacteristicValues,
157          p => p.FloatProblemCharacteristicValues,
158          p => p.CharProblemCharacteristicValues,
159          null,
160          pc => pc.ProblemId == ParentId);
161        Include(typeof(Problem), dlo);
162      } else if (type == typeof(Parameter)) {
163        AssociateWith<Experiment, IParameterValue>(dlo,
164          x => x.IntParameterValues,
165          x => x.FloatParameterValues,
166          x => x.CharParameterValues,
167          x => x.OperatorParameterValues,
168          ipv => ipv.ParameterId == ParentId);
169        try {
170          dlo.LoadWith<OperatorParameterValue>(opv => opv.DataType);
171        }
172        catch (ArgumentException) {
173          Console.WriteLine("INFO: not adding (duplicate) load option for OperatorParameterValue.DataType");
174        }
175        Include(typeof(Experiment), dlo);
176      } else if (type == typeof(Result)) {
177        AssociateWith<Run, IResultValue>(dlo,
178          r => r.IntResultValues,
179          r => r.FloatResultValues,
180          r => r.CharResultValues,
181          r => r.BlobResultValues,
182          irv => irv.ResultId == ParentId);
183      } else
184        throw new ArgumentException("type");
185    }
186
187    protected static List<Selector> Selectors = new List<Selector>() {
188        ExpressionTools.GetSelector(run => run, r => r.Id),
189        ExpressionTools.GetSelector(run => run, r => r.FinishedDate),
190
191        ExpressionTools.GetSelector(run => run.Client, c => c.Id),
192        ExpressionTools.GetSelector(run => run.Client, c => c.Name),
193
194        ExpressionTools.GetSelector(run => run.User, u => u.Id),
195        ExpressionTools.GetSelector(run => run.User, u => u.Name),
196
197        ExpressionTools.GetSelector(run => run.Experiment, x => x.Id),
198
199        ExpressionTools.GetSelector(run => run.Experiment.Project, p => p.Id),
200        ExpressionTools.GetSelector(run => run.Experiment.Project, p => p.Name),
201        ExpressionTools.GetSelector(run => run.Experiment.Project, p => p.Description),
202
203        ExpressionTools.GetSelector(run => run.Experiment.Algorithm, a => a.Id),
204        ExpressionTools.GetSelector(run => run.Experiment.Algorithm, a => a.Name),
205        ExpressionTools.GetSelector(run => run.Experiment.Algorithm, a => a.Description),
206
207        ExpressionTools.GetSelector(run => run.Experiment.Algorithm.AlgorithmClass, ac => ac.Id),
208        ExpressionTools.GetSelector(run => run.Experiment.Algorithm.AlgorithmClass, ac => ac.Name),
209        ExpressionTools.GetSelector(run => run.Experiment.Algorithm.AlgorithmClass, ac => ac.Description),
210
211        ExpressionTools.GetSelector(run => run.Experiment.Algorithm.Platform, p => p.Id),
212        ExpressionTools.GetSelector(run => run.Experiment.Algorithm.Platform, p => p.Name),
213        ExpressionTools.GetSelector(run => run.Experiment.Algorithm.Platform, p => p.Description),
214
215        ExpressionTools.GetSelector(run => run.Experiment.Problem, p => p.Id),
216        ExpressionTools.GetSelector(run => run.Experiment.Problem, p => p.Name),
217        ExpressionTools.GetSelector(run => run.Experiment.Problem, p => p.Description),
218
219        ExpressionTools.GetSelector(run => run.Experiment.Problem.ProblemClass, pc => pc.Id),
220        ExpressionTools.GetSelector(run => run.Experiment.Problem.ProblemClass, pc => pc.Name),
221        ExpressionTools.GetSelector(run => run.Experiment.Problem.ProblemClass, pc => pc.Description),
222
223        ExpressionTools.GetSelector(run => run.Experiment.Problem.SolutionRepresentation, sr => sr.Id),
224        ExpressionTools.GetSelector(run => run.Experiment.Problem.SolutionRepresentation, sr => sr.Name),
225        ExpressionTools.GetSelector(run => run.Experiment.Problem.SolutionRepresentation, sr => sr.Description)
226    };
227
228    private Func<Run, object> compiledSelector;
229
230    protected void CreateCompiledSelector<T>() {
231      var genericCompiledSelector = ((Expression<Func<Run, T>>)GetSelectorExpression()).Compile();
232      compiledSelector = run => {
233        try {
234          return (object)genericCompiledSelector(run);
235        }
236        catch (InvalidOperationException x) {
237          if (x.TargetSite == ExpressionTools.Enumerable_Single)
238            return null;
239          else
240            throw;
241        }
242      };
243    }
244
245    public Func<Run, object> CompiledSelector {
246      get {
247        if (compiledSelector == null) {
248          typeof(RunAttributeSelector)
249            .GetMethod("CreateCompiledSelector", BindingFlags.Instance | BindingFlags.NonPublic)
250            .MakeGenericMethod(DataType).Invoke(this, new object[0]);
251        }
252        return compiledSelector;
253      }
254    }
255
256    public LambdaExpression GetSelectorExpression() {
257      if (TableType == typeof(Parameter))
258        return
259          GetDynamicSelector(typeof(Parameter), run => run.Experiment,
260            x => x.IntParameterValues.Single(ipv => ipv.ParameterId == ParentId).Value,
261            x => x.FloatParameterValues.Single(fpv => fpv.ParameterId == ParentId).Value,
262            x => x.CharParameterValues.Single(cpv => cpv.ParameterId == ParentId).Value,
263            x => x.OperatorParameterValues.Single(opv => opv.ParameterId == ParentId).DataType.ClrName);
264      else if (TableType == typeof(Result))
265        return
266          GetDynamicSelector(typeof(Result), run => run,
267            r => r.IntResultValues.Single(irv => irv.ResultId == ParentId).Value,
268            r => r.FloatResultValues.Single(frv => frv.ResultId == ParentId).Value,
269            r => r.CharResultValues.Single(crv => crv.ResultId == ParentId).Value,
270            null);
271      else if (TableType == typeof(ProblemCharacteristic))
272        return
273          GetDynamicSelector(typeof(ProblemCharacteristic), run => run.Experiment.Problem,
274            p => p.IntProblemCharacteristicValues.Single(ipcv => ipcv.ProblemCharacteristicId == ParentId).Value,
275            p => p.FloatProblemCharacteristicValues.Single(fpcv => fpcv.ProblemCharacteristicId == ParentId).Value,
276            p => p.CharProblemCharacteristicValues.Single(cpcv => cpcv.ProblemCharacteristicId == ParentId).Value,
277            null);
278      else
279        return Selectors.Single(s => s.Table == TableType && s.Field == FieldName).Expression;
280    }
281
282    public Expression<Func<Run, bool>> GetWhereExpression() {
283      return GetWhereExpression(GetSelectorExpression());
284    }
285
286    protected Expression<Func<Run, bool>> GetWhereExpression(Expression selector) {
287      try {
288        return (Expression<Func<Run, bool>>)typeof(RunAttributeSelector)
289          .GetMethod("GenericGetWhereExpression", BindingFlags.Instance | BindingFlags.NonPublic)
290          .MakeGenericMethod(selector.Type.GetGenericArguments()[1])
291          .Invoke(this, new[] { selector });
292      }
293      catch (TargetInvocationException x) {
294        throw x.InnerException;
295      }
296    }
297
298    protected Expression<Func<Run, bool>> GenericGetWhereExpression<T>(Expression<Func<Run, T>> selector) {
299      ParameterExpression parameter = Expression.Parameter(typeof(Run), "run");
300      Expression testExpression = Expression.Constant(true);
301      if (AllowedValues != null) {
302        testExpression = Expression.AndAlso(testExpression,
303          Expression.Call(
304            null,
305            ExpressionTools.Enumerable_Contains.MakeGenericMethod(typeof(T)),
306            Expression.Constant(AllowedValues.Cast<T>().ToArray()),
307            Expression.Invoke(selector, parameter)));
308      }
309      if (MinValue != null) {
310        testExpression = Expression.AndAlso(testExpression,
311          ExpressionTools.GetLessThanOrEqualExpression<T>(Expression.Constant(MinValue),
312          Expression.Invoke(selector, parameter)));
313      }
314      if (MaxValue != null) {
315        testExpression = Expression.AndAlso(testExpression,
316          ExpressionTools.GetGreaterOrEqualExpression<T>(Expression.Constant(MaxValue),
317          Expression.Invoke(selector, parameter)));
318      }
319      return (Expression<Func<Run, bool>>)
320        Expression.Lambda(testExpression, parameter);
321    }
322  }
323}
Note: See TracBrowser for help on using the repository browser.