Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.Persistence/3.3/Core/ConfigurationService.cs @ 3754

Last change on this file since 3754 was 3743, checked in by gkronber, 15 years ago

Fixed GPL license headers #893

File size: 10.1 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.IO;
24using System.Linq;
25using System.Collections.Generic;
26using System.Reflection;
27using System.Text;
28using HeuristicLab.Persistence.Default.Xml;
29using HeuristicLab.Persistence.Interfaces;
30using HeuristicLab.Tracing;
31using HeuristicLab.Persistence.Core.Tokens;
32using HeuristicLab.Persistence.Auxiliary;
33
34namespace HeuristicLab.Persistence.Core {
35
36  /// <summary>
37  /// Provides a persistable configuration of primitive and composite serializers for
38  /// all registered serial formats. Custom formats can be defined and will be saved
39  /// for future sessions. A default configuration can be generated through reflection.
40  ///
41  /// This class has only a single instance.
42  /// </summary>
43  public class ConfigurationService {
44
45    private static ConfigurationService instance;
46    private readonly Dictionary<IFormat, Configuration> customConfigurations;
47
48    /// <summary>
49    /// List of all available primitive serializers.
50    /// </summary>
51    public Dictionary<Type, List<IPrimitiveSerializer>> PrimitiveSerializers { get; private set; }
52
53    /// <summary>
54    /// List of all available composite serializers (discovered through reflection).
55    /// </summary>
56    public List<ICompositeSerializer> CompositeSerializers { get; private set; }
57
58    /// <summary>
59    /// List of all available formats (discovered through reflection).   
60    /// </summary>
61    public List<IFormat> Formats { get; private set; }
62
63    /// <summary>
64    /// Gets the singleton instance.
65    /// </summary>
66    /// <value>The singleton instance.</value>
67    public static ConfigurationService Instance {
68      get {
69        if (instance == null)
70          instance = new ConfigurationService();
71        return instance;
72      }
73    }
74
75    private ConfigurationService() {
76      PrimitiveSerializers = new Dictionary<Type, List<IPrimitiveSerializer>>();
77      CompositeSerializers = new List<ICompositeSerializer>();
78      customConfigurations = new Dictionary<IFormat, Configuration>();
79      Formats = new List<IFormat>();
80      Reset();
81      LoadSettings();
82    }
83
84    /// <summary>
85    /// Loads the settings.
86    /// </summary>
87    public void LoadSettings() {
88      LoadSettings(false);
89    }
90
91    /// <summary>
92    /// Loads the settings.
93    /// </summary>
94    /// <param name="throwOnError">if set to <c>true</c> throw on error.</param>
95    public void LoadSettings(bool throwOnError) {
96      try {
97        TryLoadSettings();
98      } catch (Exception e) {
99        if (throwOnError) {
100          throw new PersistenceException("Could not load persistence settings.", e);
101        } else {
102          Logger.Warn("Could not load settings.", e);
103        }
104      }
105    }
106
107    /// <summary>
108    /// Tries to load the settings (i.e custom configurations).
109    /// </summary>
110    protected void TryLoadSettings() {
111      if (String.IsNullOrEmpty(Properties.Settings.Default.CustomConfigurations) ||
112          String.IsNullOrEmpty(Properties.Settings.Default.CustomConfigurationsTypeCache))
113        return;
114      Deserializer deSerializer = new Deserializer(
115        XmlParser.ParseTypeCache(
116        new StringReader(
117          Properties.Settings.Default.CustomConfigurationsTypeCache)));
118      XmlParser parser = new XmlParser(
119        new StringReader(
120          Properties.Settings.Default.CustomConfigurations));
121      var newCustomConfigurations = (Dictionary<IFormat, Configuration>)
122        deSerializer.Deserialize(parser);
123      foreach (var config in newCustomConfigurations) {
124        customConfigurations[config.Key] = config.Value;
125      }
126    }
127
128    /// <summary>
129    /// Saves the settings (i.e custom configurations).
130    /// </summary>
131    protected void SaveSettings() {
132      Serializer serializer = new Serializer(
133        customConfigurations,
134        GetDefaultConfig(new XmlFormat()),
135        "CustomConfigurations");
136      XmlGenerator generator = new XmlGenerator();
137      StringBuilder configurationString = new StringBuilder();
138      foreach (ISerializationToken token in serializer) {
139        configurationString.Append(generator.Format(token));
140      }
141      StringBuilder configurationTypeCacheString = new StringBuilder();
142      foreach (string s in generator.Format(serializer.TypeCache))
143        configurationTypeCacheString.Append(s);
144      Properties.Settings.Default.CustomConfigurations =
145        configurationString.ToString();
146      Properties.Settings.Default.CustomConfigurationsTypeCache =
147        configurationTypeCacheString.ToString();
148      Properties.Settings.Default.Save();
149    }
150
151
152    /// <summary>
153    /// Rediscover available serializers and discard all custom configurations.
154    /// </summary>
155    public void Reset() {
156      customConfigurations.Clear();
157      PrimitiveSerializers.Clear();
158      CompositeSerializers.Clear();
159      Assembly defaultAssembly = Assembly.GetExecutingAssembly();
160      DiscoverFrom(defaultAssembly);
161      try {
162        foreach (Assembly a in AppDomain.CurrentDomain.GetAssemblies())
163          if (a != defaultAssembly)
164            DiscoverFrom(a);
165      } catch (AppDomainUnloadedException x) {
166        Logger.Warn("could not get list of assemblies, AppDomain has already been unloaded", x);
167      }
168      SortCompositeSerializers();
169    }
170
171    private class PriortiySorter : IComparer<ICompositeSerializer> {
172      public int Compare(ICompositeSerializer x, ICompositeSerializer y) {
173        return y.Priority - x.Priority;
174      }
175    }
176
177    /// <summary>
178    /// Sorts the composite serializers according to their priority.
179    /// </summary>
180    protected void SortCompositeSerializers() {
181      CompositeSerializers.Sort(new PriortiySorter());
182    }
183
184    /// <summary>
185    /// Discovers serializers from an assembly.
186    /// </summary>
187    /// <param name="a">An Assembly.</param>
188    protected void DiscoverFrom(Assembly a) {
189      try {
190        foreach (Type t in a.GetTypes()) {
191          if (t.GetInterface(typeof(IPrimitiveSerializer).FullName) != null &&
192              !t.IsAbstract && t.GetConstructor(Type.EmptyTypes) != null && !t.ContainsGenericParameters) {
193            IPrimitiveSerializer primitiveSerializer =
194              (IPrimitiveSerializer)Activator.CreateInstance(t, true);
195            if (!PrimitiveSerializers.ContainsKey(primitiveSerializer.SerialDataType))
196              PrimitiveSerializers.Add(primitiveSerializer.SerialDataType, new List<IPrimitiveSerializer>());
197            PrimitiveSerializers[primitiveSerializer.SerialDataType].Add(primitiveSerializer);
198          }
199          if (t.GetInterface(typeof(ICompositeSerializer).FullName) != null &&
200              !t.IsAbstract && t.GetConstructor(Type.EmptyTypes) != null && !t.ContainsGenericParameters) {
201            CompositeSerializers.Add((ICompositeSerializer)Activator.CreateInstance(t, true));
202          }
203          if (t.GetInterface(typeof(IFormat).FullName) != null &&
204             !t.IsAbstract && t.GetConstructor(Type.EmptyTypes) != null && !t.ContainsGenericParameters) {
205            IFormat format = (IFormat)Activator.CreateInstance(t, true);
206            Formats.Add(format);
207          }
208        }
209      } catch (ReflectionTypeLoadException e) {
210        Logger.Warn("could not analyse assembly: " + a.FullName, e);
211      }
212    }
213
214    /// <summary>
215    /// Get the default (automatically discovered) configuration for a certain format.
216    /// </summary>
217    /// <param name="format">The format.</param>
218    /// <returns>The default (auto discovered) configuration.</returns>
219    public Configuration GetDefaultConfig(IFormat format) {
220      Dictionary<Type, IPrimitiveSerializer> primitiveConfig = new Dictionary<Type, IPrimitiveSerializer>();
221      if (PrimitiveSerializers.ContainsKey(format.SerialDataType)) {
222        foreach (IPrimitiveSerializer f in PrimitiveSerializers[format.SerialDataType]) {
223          if (!primitiveConfig.ContainsKey(f.SourceType))
224            primitiveConfig.Add(f.SourceType, f);
225        }
226      } else {
227        Logger.Warn(String.Format(
228          "No primitive serializers found for format {0} with serial data type {1}",
229          format.GetType().AssemblyQualifiedName,
230          format.SerialDataType.AssemblyQualifiedName));
231      }
232      return new Configuration(
233        format,
234        primitiveConfig.Values,
235        CompositeSerializers.Where((d) => d.Priority > 0));
236    }
237
238
239    /// <summary>
240    /// Get a configuration for a certain format. This returns a fresh copy of a custom configuration,
241    /// if defined, otherwise returns the default (automatically discovered) configuration.
242    /// </summary>
243    /// <param name="format">The format.</param>
244    /// <returns>A Configuration</returns>
245    public Configuration GetConfiguration(IFormat format) {
246      if (customConfigurations.ContainsKey(format))
247        return customConfigurations[format].Copy();
248      return GetDefaultConfig(format);
249    }
250
251    /// <summary>
252    /// Define a new custom configuration for a ceratin format.
253    /// </summary>
254    /// <param name="configuration">The new configuration.</param>
255    public void DefineConfiguration(Configuration configuration) {
256      customConfigurations[configuration.Format] = configuration.Copy();
257      SaveSettings();
258    }
259
260  }
261
262}
Note: See TracBrowser for help on using the repository browser.