source: branches/PersistenceOverhaul/HeuristicLab.Persistence/4.0/Core/Mapper.cs @ 13347

Last change on this file since 13347 was 13347, checked in by swagner, 4 years ago

#2520: Worked on persistence overhaul

File size: 5.6 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2015 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.PluginInfrastructure;
26using Google.ProtocolBuffers;
27using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
28
29namespace HeuristicLab.Persistence {
30  public sealed class Mapper {
31    private Index<ITransformer> transformers;
32    private Dictionary<Type, TypeInfo> typeInfos;
33    private Index<Type> types;
34    private Index<string> strings;
35    private Index<Box> boxes;
36    private Dictionary<object, uint> boxCache;
37    private Dictionary<uint, object> objectCache;
38
39    public long BoxCount { get; private set; }
40
41    public Mapper() {
42      transformers = new Index<ITransformer>();
43      typeInfos = new Dictionary<Type, TypeInfo>();
44      types = new Index<Type>();
45      strings = new Index<string>();
46      boxes = new Index<Box>();
47      boxCache = new Dictionary<object, uint>(new ReferenceEqualityComparer<object>());
48      objectCache = new Dictionary<uint, object>();
49
50      BoxCount = 0;
51
52      foreach (var transformer in ApplicationManager.Manager.GetInstances<ITransformer>().OrderBy(x => x.Order)) {
53        transformer.Initialize(transformers.GetIndex(transformer));
54      }
55    }
56
57    public TypeInfo GetTypeInfo(Type type) {
58      TypeInfo typeInfo;
59      if (!typeInfos.TryGetValue(type, out typeInfo)) {
60        var transformer = transformers.GetValues().Where(x => x.CanTransformType(type)).FirstOrDefault();
61        typeInfo = new TypeInfo(type, transformer);
62        typeInfos.Add(type, typeInfo);
63      }
64      return typeInfo;
65    }
66    public IEnumerable<TypeInfo> GetTypeInfos() {
67      return typeInfos.Values;
68    }
69    public IEnumerable<Type> GetTypes() {
70      return typeInfos.Values.Select(x => x.Type);
71    }
72
73    public uint GetTypeId(Type type) {
74      return types.GetIndex(type);
75    }
76    public Type GetType(uint typeId) {
77      return types.GetValue(typeId);
78    }
79
80    public uint GetStringId(string str) {
81      return strings.GetIndex(str);
82    }
83    public string GetString(uint stringId) {
84      return strings.GetValue(stringId);
85    }
86
87    public uint GetBoxId(object o) {
88      uint boxId;
89      if (boxCache.TryGetValue(o, out boxId)) return boxId;
90
91      if (o == null)
92        boxId = boxes.GetIndex(null);
93      else {
94        var type = o.GetType();
95        var typeInfo = GetTypeInfo(type);
96        if (typeInfo.Transformer == null) throw new ArgumentException("Cannot serialize object of type " + o.GetType());
97        BoxCount++;
98        typeInfo.Used++;
99        boxId = boxes.GetIndex(typeInfo.Transformer.ToBox(o, this));
100      }
101      boxCache.Add(o, boxId);
102      return boxId;
103    }
104    public object GetObject(uint boxId) {
105      object o;
106      if (objectCache.TryGetValue(boxId, out o)) return o;
107
108      var box = this.boxes.GetValue(boxId);
109      if (box == null)
110        o = null;
111      else {
112        var transformer = transformers.GetValue(box.TransformerId);
113        o = transformer.ToObject(box, this);
114      }
115      objectCache.Add(boxId, o);
116      return o;
117    }
118
119    public object CreateInstance(Type type) {
120      return GetTypeInfo(type).GetConstructor()();
121    }
122
123    public static Bundle ToBundle(object o) {
124      var mapper = new Mapper();
125      var bundle = Bundle.CreateBuilder();
126      bundle.RootBoxId = mapper.GetBoxId(o);
127      bundle.AddRangeTransformerGuids(mapper.transformers.GetValues().Select(x => x.Guid).Select(x => ByteString.CopyFrom(x.ToByteArray())));
128      bundle.AddRangeTypeGuids(mapper.types.GetValues().Select(x => mapper.typeInfos[x].StorableClassAttribute.Guid).Select(x => ByteString.CopyFrom(x.ToByteArray())));
129      bundle.AddRangeStrings(mapper.strings.GetValues());
130      bundle.AddRangeBoxes(mapper.boxes.GetValues());
131      return bundle.Build();
132    }
133    public static object ToObject(Bundle bundle) {
134      var types = new Dictionary<Guid, Type>();
135      foreach (var asm in AppDomain.CurrentDomain.GetAssemblies()) {
136        foreach (var t in asm.GetTypes().Where(x => StorableClassAttribute.IsStorableClass(x)))
137          types.Add(StorableClassAttribute.GetStorableClassAttribute(t).Guid, t);
138      }
139
140      var mapper = new Mapper();
141      mapper.types = new Index<Type>(bundle.TypeGuidsList.Select(x => new Guid(x.ToByteArray())).Select(x => types[x]));
142      mapper.strings = new Index<string>(bundle.StringsList);
143      mapper.boxes = new Index<Box>(bundle.BoxesList);
144      mapper.transformers = new Index<ITransformer>(bundle.TransformerGuidsList.Select(x => new Guid(x.ToByteArray())).Select(x => mapper.transformers.GetValues().First(y => y.Guid == x)));
145      foreach (var type in mapper.types.GetValues())
146        mapper.typeInfos.Add(type, new TypeInfo(type));
147
148      return mapper.GetObject(bundle.RootBoxId);
149    }
150  }
151}
Note: See TracBrowser for help on using the repository browser.