Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.Persistence/3.3/Core/DeSerializer.cs @ 1625

Last change on this file since 1625 was 1625, checked in by epitzer, 15 years ago

Added PersistenceException used consistently for all error conditions in the persistence framework (#548)

File size: 5.7 KB
RevLine 
[1454]1using System.Collections.Generic;
2using System;
3using HeuristicLab.Persistence.Interfaces;
[1556]4using HeuristicLab.Persistence.Core.Tokens;
[1454]5
[1574]6namespace HeuristicLab.Persistence.Core {
[1454]7
[1574]8  public class Deserializer {
[1454]9
[1567]10    class Midwife {
[1566]11
[1567]12      public int? Id { get; private set; }
13      public bool MetaMode { get; set; }
14      public object Obj { get; private set; }
[1454]15
[1567]16      private List<Tag> metaInfo;
17      private List<Tag> customValues;
18      private Type type;
19      private IDecomposer decomposer;
[1553]20
[1567]21      public Midwife(object value) {
22        this.Obj = value;
23      }
[1566]24
[1567]25      public Midwife(Type type, IDecomposer decomposer, int? id) {
26        this.type = type;
27        this.decomposer = decomposer;
28        this.Id = id;
29        MetaMode = false;
30        metaInfo = new List<Tag>();
31        customValues = new List<Tag>();
32      }
[1454]33
[1567]34      public void CreateInstance() {
35        if (Obj != null)
[1625]36          throw new PersistenceException("object already instantiated");
[1567]37        Obj = decomposer.CreateInstance(type, metaInfo);
38      }
[1454]39
[1567]40      public void AddValue(string name, object value) {
41        if (MetaMode) {
42          metaInfo.Add(new Tag(name, value));
43        } else {
44          customValues.Add(new Tag(name, value));
45        }
[1553]46      }
[1454]47
[1567]48      public void Populate() {
49        decomposer.Populate(Obj, customValues, type);
50      }
[1553]51    }
[1454]52
53    private readonly Dictionary<int, object> id2obj;
[1553]54    private readonly Dictionary<Type, object> serializerMapping;
[1566]55    private readonly Stack<Midwife> parentStack;
[1553]56    private readonly Dictionary<int, Type> typeIds;
[1454]57
[1542]58    public Deserializer(
[1553]59      IEnumerable<TypeMapping> typeCache) {
[1454]60      id2obj = new Dictionary<int, object>();
[1553]61      parentStack = new Stack<Midwife>();
[1454]62      typeIds = new Dictionary<int, Type>();
[1542]63      serializerMapping = CreateSerializers(typeCache);
[1454]64    }
65
[1542]66    private Dictionary<Type, object> CreateSerializers(IEnumerable<TypeMapping> typeCache) {
[1625]67      try {
68        var map = new Dictionary<Type, object>();
69        foreach (var typeMapping in typeCache) {
70          Type type = Type.GetType(typeMapping.TypeName, true);
71          typeIds.Add(typeMapping.Id, type);
72          Type serializerType = Type.GetType(typeMapping.Serializer, true);
73          map.Add(type, Activator.CreateInstance(serializerType, true));
74        }
75        return map;
76      } catch (Exception e) {
77        throw new PersistenceException(
78          "The serialization type cache could not be loaded.\r\n" +
79          "This usualy happens when you are missing an Assembly/Plugin.", e);
80      }     
[1454]81    }
82
[1566]83    public object Deserialize(IEnumerable<ISerializationToken> tokens) {
[1454]84      foreach (ISerializationToken token in tokens) {
85        Type t = token.GetType();
[1566]86        if (t == typeof(BeginToken)) {
[1454]87          CompositeStartHandler((BeginToken)token);
[1566]88        } else if (t == typeof(EndToken)) {
89          CompositeEndHandler((EndToken)token);
90        } else if (t == typeof(PrimitiveToken)) {
91          PrimitiveHandler((PrimitiveToken)token);
92        } else if (t == typeof(ReferenceToken)) {
93          ReferenceHandler((ReferenceToken)token);
[1454]94        } else if (t == typeof(NullReferenceToken)) {
95          NullHandler((NullReferenceToken)token);
[1553]96        } else if (t == typeof(MetaInfoBeginToken)) {
97          MetaInfoBegin((MetaInfoBeginToken)token);
98        } else if (t == typeof(MetaInfoEndToken)) {
99          MetaInfoEnd((MetaInfoEndToken)token);
[1454]100        } else {
[1625]101          throw new PersistenceException("invalid token type");
[1454]102        }
103      }
104      return parentStack.Pop().Obj;
105    }
106
[1553]107    private void CompositeStartHandler(BeginToken token) {
[1454]108      Type type = typeIds[(int)token.TypeId];
109      IDecomposer decomposer = null;
[1566]110      if (serializerMapping.ContainsKey(type))
[1553]111        decomposer = serializerMapping[type] as IDecomposer;
[1454]112      if (decomposer == null)
[1625]113        throw new PersistenceException(String.Format(
[1454]114          "No suitable method for deserialization of type \"{0}\" found.",
115          type.VersionInvariantName()));
[1553]116      parentStack.Push(new Midwife(type, decomposer, token.Id));
[1454]117    }
118
[1553]119    private void CompositeEndHandler(EndToken token) {
[1454]120      Type type = typeIds[(int)token.TypeId];
[1553]121      Midwife midwife = parentStack.Pop();
[1574]122      if (midwife.Obj == null)
123        CreateInstance(midwife);
[1553]124      midwife.Populate();
125      SetValue(token.Name, midwife.Obj);
[1454]126    }
127
[1553]128    private void PrimitiveHandler(PrimitiveToken token) {
[1454]129      Type type = typeIds[(int)token.TypeId];
[1566]130      object value = ((IFormatter)serializerMapping[type]).Parse(token.SerialData);
131      if (token.Id != null)
[1454]132        id2obj[(int)token.Id] = value;
133      SetValue(token.Name, value);
134    }
135
[1553]136    private void ReferenceHandler(ReferenceToken token) {
[1454]137      object referredObject = id2obj[token.Id];
[1553]138      SetValue(token.Name, referredObject);
[1454]139    }
140
[1553]141    private void NullHandler(NullReferenceToken token) {
[1454]142      SetValue(token.Name, null);
[1553]143    }
[1454]144
[1553]145    private void MetaInfoBegin(MetaInfoBeginToken token) {
146      parentStack.Peek().MetaMode = true;
147    }
148
149    private void MetaInfoEnd(MetaInfoEndToken token) {
[1566]150      Midwife m = parentStack.Peek();
[1553]151      m.MetaMode = false;
152      CreateInstance(m);
153    }
154
155    private void CreateInstance(Midwife m) {
156      m.CreateInstance();
157      if (m.Id != null)
[1566]158        id2obj.Add((int)m.Id, m.Obj);
[1553]159    }
160
[1454]161    private void SetValue(string name, object value) {
[1566]162      if (parentStack.Count == 0) {
[1553]163        parentStack.Push(new Midwife(value));
164      } else {
165        Midwife m = parentStack.Peek();
166        if (m.MetaMode == false && m.Obj == null)
167          CreateInstance(m);
[1566]168        m.AddValue(name, value);
[1454]169      }
170    }
171  }
172}
Note: See TracBrowser for help on using the repository browser.