source: branches/PersistenceOverhaul/HeuristicLab.Persistence/4.0/Core/PersistenceMapper.cs @ 13326

Last change on this file since 13326 was 13326, checked in by swagner, 7 years ago

#2520: Created plugin for new persistence implementation

File size: 5.5 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2012 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.Generic;
24using System.Linq;
25using HeuristicLab.Persistence.Data;
26using HeuristicLab.PluginInfrastructure;
27
28namespace HeuristicLab.Persistence {
29  public sealed class PersistenceMapper {
30    private ShortIndex<ITransformer> transformers;
31    private Dictionary<Type, TypeInfo> typeInfos;
32    private ShortIndex<Type> types;
33    private Index<string> strings;
34    private Index<PersistenceData> data;
35    private Dictionary<object, uint> dataCache;
36    private Dictionary<uint, object> objectCache;
37
38    public long Nodes { get; private set; }
39
40    public PersistenceMapper() {
41      transformers = new ShortIndex<ITransformer>();
42      typeInfos = new Dictionary<Type, TypeInfo>();
43      types = new ShortIndex<Type>();
44      strings = new Index<string>();
45      data = new Index<PersistenceData>();
46      dataCache = new Dictionary<object, uint>(new ReferenceEqualityComparer<object>());
47      objectCache = new Dictionary<uint, object>();
48
49      Nodes = 0;
50
51      foreach (var transformer in ApplicationManager.Manager.GetInstances<ITransformer>().OrderBy(x => x.Order)) {
52        ushort id = transformers.GetIndex(transformer);
53        transformer.Initialize(id);
54      }
55    }
56
57    public TypeInfo GetTypeInfo(Type type) {
58      TypeInfo typeInfo;
59      typeInfos.TryGetValue(type, out typeInfo);
60      if (typeInfo == null) {
61        var transformer = transformers.GetValues().Select(x => x.Item2).Where(x => x.CanTransformType(type)).FirstOrDefault();
62        typeInfo = new TypeInfo(type, transformer);
63        typeInfos.Add(type, typeInfo);
64      }
65      return typeInfo;
66    }
67    public IEnumerable<TypeInfo> GetTypeInfos() {
68      return typeInfos.Values;
69    }
70    public IEnumerable<Type> GetTypes() {
71      return typeInfos.Values.Select(x => x.Type);
72    }
73
74    public ushort GetTypeId(Type type) {
75      return types.GetIndex(type);
76    }
77    public Type GetType(ushort typeId) {
78      return types.GetValue(typeId);
79    }
80
81    public uint GetStringId(string str) {
82      return strings.GetIndex(str);
83    }
84    public string GetString(uint stringId) {
85      return strings.GetValue(stringId);
86    }
87
88    public void Cache(object o, PersistenceData data) {
89      dataCache.Add(o, this.data.GetIndex(data));
90    }
91    public void Cache(PersistenceData data, object o) {
92      objectCache.Add(this.data.GetIndex(data), o);
93    }
94
95    public uint GetDataId(object o) {
96      if (o == null) return 0;
97      if (dataCache.ContainsKey(o)) return dataCache[o];
98
99      var type = o.GetType();
100      var typeInfo = GetTypeInfo(type);
101      if (typeInfo.Transformer == null) throw new ArgumentException("Cannot serialize object of type " + o.GetType());
102      Nodes++;
103      typeInfo.Used++;
104      return data.GetIndex(typeInfo.Transformer.ToData(o, this));
105    }
106    public object GetObject(uint dataId) {
107      if (dataId == 0) return null;
108      if (objectCache.ContainsKey(dataId)) return objectCache[dataId];
109      var data = this.data.GetValue(dataId);
110      var transformer = transformers.GetValue(data.TransformerId);
111      return transformer.ToObject(data, this);
112    }
113
114    public object CreateInstance(Type type) {
115      return GetTypeInfo(type).GetConstructor()();
116    }
117
118    public static PersistenceMapper mapper;
119    public static PersistenceBundle ToBundle(object o) {
120      mapper = new PersistenceMapper();
121      var bundle = new PersistenceBundle();
122      bundle.RootId = mapper.GetDataId(o);
123      bundle.TransformerGuids = mapper.transformers.GetValues().Select(x => new Tuple<ushort, Guid>(x.Item1, x.Item2.Guid)).ToArray();
124      bundle.TypeNames = mapper.types.GetValues().Select(x => new Tuple<ushort, string>(x.Item1, x.Item2.AssemblyQualifiedName)).ToArray();
125      bundle.Strings = mapper.strings.GetValues().ToArray();
126      bundle.Data = mapper.data.GetValues().ToArray();
127      return bundle;
128    }
129    public static object ToObject(PersistenceBundle bundle) {
130      mapper = new PersistenceMapper();
131      mapper.types = new ShortIndex<Type>(bundle.TypeNames.Select(x => new Tuple<ushort, Type>(x.Item1, Type.GetType(x.Item2, true))));
132      mapper.strings = new Index<string>(bundle.Strings);
133      mapper.data = new Index<PersistenceData>(bundle.Data);
134      mapper.transformers = new ShortIndex<ITransformer>(
135        bundle.TransformerGuids.Select(x => new Tuple<ushort, ITransformer>(
136          x.Item1,
137          mapper.transformers.GetValues().Select(y => y.Item2).Where(y => y.Guid == x.Item2).First())
138        )
139      );
140      foreach (var type in mapper.types.GetValues().Select(x => x.Item2))
141        mapper.typeInfos.Add(type, new TypeInfo(type));
142
143      return mapper.GetObject(bundle.RootId);
144    }
145  }
146}
Note: See TracBrowser for help on using the repository browser.