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

Last change on this file since 14537 was 14537, checked in by jkarder, 6 years ago

#2520: worked on persistence

File size: 4.8 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 Google.ProtocolBuffers;
26
27namespace HeuristicLab.Persistence {
28  public sealed class Mapper {
29    private static StaticCache staticCache = null;
30    private static object locker = new object();
31    public static StaticCache StaticCache {
32      get {
33        lock (locker) {
34          if (staticCache == null) staticCache = new StaticCache();
35          return staticCache;
36        }
37      }
38    }
39
40    private Index<ITransformer> transformers;
41    private Index<Type> types;
42    private Index<string> strings;
43    private Index<Box> boxes;
44    private Dictionary<object, uint> object2BoxId;
45    private Dictionary<uint, object> boxId2object;
46
47    public long BoxCount { get; private set; }
48
49    public Mapper() {
50      transformers = new Index<ITransformer>();
51      types = new Index<Type>();
52      strings = new Index<string>();
53      boxes = new Index<Box>();
54      object2BoxId = new Dictionary<object, uint>(new ReferenceEqualityComparer<object>());
55      boxId2object = new Dictionary<uint, object>();
56
57      BoxCount = 0;
58    }
59
60    public uint GetTransformerId(ITransformer transformer) {
61      return transformers.GetIndex(transformer);
62    }
63    public ITransformer GetTransformer(uint transformerId) {
64      return transformers.GetValue(transformerId);
65    }
66
67    public uint GetTypeId(Type type) {
68      return types.GetIndex(type);
69    }
70    public Type GetType(uint typeId) {
71      return types.GetValue(typeId);
72    }
73
74    public uint GetStringId(string str) {
75      return strings.GetIndex(str);
76    }
77    public string GetString(uint stringId) {
78      return strings.GetValue(stringId);
79    }
80
81    public uint GetBoxId(object o) {
82      uint boxId;
83      if (object2BoxId.TryGetValue(o, out boxId)) return boxId;
84
85      if (o == null)
86        boxId = boxes.GetIndex(null);
87      else {
88        var type = o.GetType();
89        var typeInfo = StaticCache.GetTypeInfo(type);
90        if (typeInfo.Transformer == null) throw new ArgumentException("Cannot serialize object of type " + o.GetType());
91        BoxCount++;
92        typeInfo.Used++;
93        boxId = boxes.GetIndex(typeInfo.Transformer.ToBox(o, this));
94      }
95      object2BoxId.Add(o, boxId);
96      return boxId;
97    }
98    public object GetObject(uint boxId) {
99      object o;
100      if (boxId2object.TryGetValue(boxId, out o)) return o;
101
102      var box = this.boxes.GetValue(boxId);
103      if (box == null)
104        o = null;
105      else {
106        var transformer = transformers.GetValue(box.TransformerId);
107        o = transformer.ToObject(box, this);
108      }
109      boxId2object.Add(boxId, o);
110      return o;
111    }
112
113    public object CreateInstance(Type type) {
114      return StaticCache.GetTypeInfo(type).GetConstructor()();
115    }
116
117    public static Bundle ToBundle(object o) {
118      var mapper = new Mapper();
119      var bundle = Bundle.CreateBuilder();
120      bundle.RootBoxId = mapper.GetBoxId(o);
121      bundle.AddRangeTransformerGuids(mapper.transformers.GetValues().Select(x => x.Guid).Select(x => ByteString.CopyFrom(x.ToByteArray())));
122      bundle.AddRangeTypeGuids(mapper.types.GetValues().Select(x => StaticCache.GetGuid(x)).Select(x => ByteString.CopyFromUtf8(x)));
123      bundle.AddRangeStrings(mapper.strings.GetValues());
124      bundle.AddRangeBoxes(mapper.boxes.GetValues());
125      return bundle.Build();
126    }
127    public static object ToObject(Bundle bundle) {
128      var mapper = new Mapper();
129      mapper.types = new Index<Type>(bundle.TypeGuidsList.Select(x => x.ToStringUtf8()).Select(x => StaticCache.GetType(x)));
130      mapper.strings = new Index<string>(bundle.StringsList);
131      mapper.boxes = new Index<Box>(bundle.BoxesList);
132      mapper.transformers = new Index<ITransformer>(bundle.TransformerGuidsList.Select(x => new Guid(x.ToByteArray())).Select(x => StaticCache.GetTransformer(x)));
133      return mapper.GetObject(bundle.RootBoxId);
134    }
135  }
136}
Note: See TracBrowser for help on using the repository browser.