Free cookie consent management tool by TermsFeed Policy Generator

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

Last change on this file since 14549 was 14549, checked in by jkarder, 7 years ago

#2520: worked on persistence

File size: 5.5 KB
RevLine 
[13326]1#region License Information
2/* HeuristicLab
[13347]3 * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
[13326]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;
[13347]25using Google.ProtocolBuffers;
[13326]26
27namespace HeuristicLab.Persistence {
[13347]28  public sealed class Mapper {
[14549]29    internal class MappingEqualityComparer : IEqualityComparer<object> {
30      bool IEqualityComparer<object>.Equals(object x, object y) {
31        if (x == null && y == null) return true;
32        if (x == null ^ y == null) return false;
33        if (x.GetType() != y.GetType()) return false;
34
35        var type = x.GetType();
36        if (type.IsValueType || type == typeof(string)) return x.Equals(y);
37        return object.ReferenceEquals(x, y);
38      }
39
40      int IEqualityComparer<object>.GetHashCode(object obj) {
41        return obj == null ? 0 : obj.GetHashCode();
42      }
43    }
44
[13358]45    private static StaticCache staticCache = null;
46    private static object locker = new object();
47    public static StaticCache StaticCache {
48      get {
49        lock (locker) {
50          if (staticCache == null) staticCache = new StaticCache();
51          return staticCache;
52        }
53      }
54    }
55
[13347]56    private Index<ITransformer> transformers;
57    private Index<Type> types;
[13326]58    private Index<string> strings;
[14549]59    private Dictionary<uint, Box> boxId2Box;
[13358]60    private Dictionary<object, uint> object2BoxId;
61    private Dictionary<uint, object> boxId2object;
[13326]62
[14549]63    public uint BoxCount { get; private set; }
[13326]64
[13347]65    public Mapper() {
66      transformers = new Index<ITransformer>();
67      types = new Index<Type>();
[13326]68      strings = new Index<string>();
[14549]69      boxId2Box = new Dictionary<uint, Box>();
70      object2BoxId = new Dictionary<object, uint>(new MappingEqualityComparer());
[13358]71      boxId2object = new Dictionary<uint, object>();
[13326]72
[13347]73      BoxCount = 0;
[13326]74    }
75
[13358]76    public uint GetTransformerId(ITransformer transformer) {
77      return transformers.GetIndex(transformer);
[13326]78    }
[13358]79    public ITransformer GetTransformer(uint transformerId) {
80      return transformers.GetValue(transformerId);
[13326]81    }
82
[13347]83    public uint GetTypeId(Type type) {
[13326]84      return types.GetIndex(type);
85    }
[13347]86    public Type GetType(uint typeId) {
[13326]87      return types.GetValue(typeId);
88    }
89
90    public uint GetStringId(string str) {
91      return strings.GetIndex(str);
92    }
93    public string GetString(uint stringId) {
94      return strings.GetValue(stringId);
95    }
96
[13347]97    public uint GetBoxId(object o) {
98      uint boxId;
99
100      if (o == null)
[14549]101        boxId = 0;
[13347]102      else {
[14549]103        if (object2BoxId.TryGetValue(o, out boxId)) return boxId;
[13347]104        var type = o.GetType();
[13358]105        var typeInfo = StaticCache.GetTypeInfo(type);
[13347]106        if (typeInfo.Transformer == null) throw new ArgumentException("Cannot serialize object of type " + o.GetType());
[14549]107        boxId = ++BoxCount;
[13347]108        typeInfo.Used++;
[14549]109        object2BoxId.Add(o, boxId);
110        boxId2Box.Add(boxId, typeInfo.Transformer.ToBox(o, this));
[13347]111      }
112      return boxId;
[13326]113    }
[13347]114    public object GetObject(uint boxId) {
115      object o;
[13358]116      if (boxId2object.TryGetValue(boxId, out o)) return o;
[13326]117
[14549]118      Box box;
119      boxId2Box.TryGetValue(boxId, out box);
120
[13347]121      if (box == null)
122        o = null;
123      else {
124        var transformer = transformers.GetValue(box.TransformerId);
125        o = transformer.ToObject(box, this);
[14549]126        boxId2object.Add(boxId, o);
127        transformer.FillFromBox(o, box, this);
[13347]128      }
129      return o;
[13326]130    }
131
132    public object CreateInstance(Type type) {
[13358]133      return StaticCache.GetTypeInfo(type).GetConstructor()();
[13326]134    }
135
[13347]136    public static Bundle ToBundle(object o) {
137      var mapper = new Mapper();
138      var bundle = Bundle.CreateBuilder();
139      bundle.RootBoxId = mapper.GetBoxId(o);
140      bundle.AddRangeTransformerGuids(mapper.transformers.GetValues().Select(x => x.Guid).Select(x => ByteString.CopyFrom(x.ToByteArray())));
[14537]141      bundle.AddRangeTypeGuids(mapper.types.GetValues().Select(x => StaticCache.GetGuid(x)).Select(x => ByteString.CopyFromUtf8(x)));
[13347]142      bundle.AddRangeStrings(mapper.strings.GetValues());
[14549]143      bundle.AddRangeBoxes(mapper.boxId2Box.OrderBy(x => x.Key).Select(x => x.Value));
[13347]144      return bundle.Build();
[13326]145    }
[13347]146    public static object ToObject(Bundle bundle) {
147      var mapper = new Mapper();
[14537]148      mapper.types = new Index<Type>(bundle.TypeGuidsList.Select(x => x.ToStringUtf8()).Select(x => StaticCache.GetType(x)));
[13347]149      mapper.strings = new Index<string>(bundle.StringsList);
[14549]150      mapper.boxId2Box = bundle.BoxesList.Select((b, i) => new { Box = b, Index = i }).ToDictionary(k => (uint)k.Index + 1, v => v.Box);
[13358]151      mapper.transformers = new Index<ITransformer>(bundle.TransformerGuidsList.Select(x => new Guid(x.ToByteArray())).Select(x => StaticCache.GetTransformer(x)));
[13347]152      return mapper.GetObject(bundle.RootBoxId);
[13326]153    }
154  }
155}
Note: See TracBrowser for help on using the repository browser.