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

Last change on this file since 1567 was 1567, checked in by epitzer, 12 years ago

One file per class; rename ViewOnlyFormat -> DebugStringFormat (#548)

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