Free cookie consent management tool by TermsFeed Policy Generator

source: branches/New Persistence Exploration/Persistence/Persistence/Core/DeSerializer.cs @ 1420

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

Remove old storable persistence mechanism. (#506)

File size: 5.5 KB
Line 
1using System.Collections.Generic;
2using System;
3using HeuristicLab.Persistence.Interfaces;
4
5namespace HeuristicLab.Persistence.Core { 
6
7  struct ParentReference { }
8  delegate void Setter(object value); 
9
10  class CompositeObject {
11
12    public object Obj { get; private set; }
13    public List<Tag> customValues;
14
15    public CompositeObject(object obj) {
16      Obj = obj;
17      customValues = new List<Tag>();
18    }
19
20    public void AddValue(string name, object value) {
21      customValues.Add(new Tag(name, value));
22    }
23
24    public Setter GetSetter(string name) {           
25      Tag t = customValues[customValues.Count - 1];     
26      return value => t.Value = value;
27    }
28  } 
29
30  public class DeSerializer {
31
32    private delegate void Handler(ISerializationToken token);
33    private delegate void Thunk();
34
35    private readonly Dictionary<int, object> id2obj;
36    private readonly Dictionary<Type, object> serializerMapping;
37    private readonly Dictionary<Type, Handler> handlers;
38    private readonly Stack<CompositeObject> parentStack;   
39    private readonly Dictionary<int, Type> typeIds;   
40    private List<Thunk> finalFixes;
41
42    public DeSerializer(
43      IEnumerable<TypeMapping> typeCache) {     
44      id2obj = new Dictionary<int, object>();
45      parentStack = new Stack<CompositeObject>();
46      handlers = new Dictionary<Type, Handler> {
47                     {typeof (BeginToken), CompositeStartHandler},
48                     {typeof (EndToken), CompositeEndHandler},
49                     {typeof (PrimitiveToken), PrimitiveHandler},
50                     {typeof (ReferenceToken), ReferenceHandler},
51                     {typeof (NullReferenceToken), NullHandler}
52                   };     
53      typeIds = new Dictionary<int, Type>();
54      serializerMapping = new Dictionary<Type, object>();
55      foreach ( var typeMapping in typeCache ) {
56        Type type = Type.GetType(typeMapping.TypeName);
57        typeIds.Add(typeMapping.Id, type);
58        if (typeMapping.Serializer != null) {
59          Type serializerType = Type.GetType(typeMapping.Serializer);
60          serializerMapping.Add(type, Activator.CreateInstance(serializerType, true));
61        }
62      }
63    }
64
65    public object DeSerialize(IEnumerable<ISerializationToken> tokens) {
66      finalFixes = new List<Thunk>();     
67      foreach (ISerializationToken token in tokens) {
68        handlers[token.GetType()].Invoke(token);
69      }
70      foreach (Thunk fix in finalFixes) {
71        fix();
72      }
73      return parentStack.Pop().Obj;
74    }
75
76    private void CompositeStartHandler(ISerializationToken token) {
77      BeginToken start = (BeginToken)token;
78      object instance;     
79      Type type = typeIds[(int)start.TypeId];
80      IDecomposer decomposer = null;
81      if ( serializerMapping.ContainsKey(type) )
82        decomposer = serializerMapping[type] as IDecomposer;     
83      if (decomposer != null) {       
84        instance = decomposer.CreateInstance(type);
85        if (instance == null)
86          instance = new ParentReference();
87        parentStack.Push(new CompositeObject(instance));       
88      } else {
89        throw new ApplicationException(String.Format(
90          "No suitable method for deserialization of type \"{0}\" found.",
91          type.FullName));
92      }
93      if ( start.Id != null )
94        id2obj.Add((int)start.Id, instance);
95    }
96
97    private void CompositeEndHandler(ISerializationToken token) {
98      EndToken end = (EndToken)token;
99      Type type = typeIds[(int)end.TypeId];
100      IDecomposer decomposer = null;
101      if (serializerMapping.ContainsKey(type))
102        decomposer = serializerMapping[type] as IDecomposer;           
103      if (decomposer != null) {
104        CompositeObject customComposite = (CompositeObject)parentStack.Pop();
105        object deserializedObject =         
106          decomposer.Populate(customComposite.Obj, customComposite.customValues, type);
107        if ( end.Id != null )
108          id2obj[(int)end.Id] = deserializedObject;       
109        SetValue(end.Name, deserializedObject);         
110      } else {
111        throw new ApplicationException(String.Format(
112          "No suitable method for deserialization of type \"{0}\" found.",
113          type.FullName));
114      }
115    }
116
117    private void PrimitiveHandler(ISerializationToken token) {
118      PrimitiveToken primitive = (PrimitiveToken)token;
119      Type type = typeIds[(int)primitive.TypeId];
120      object value = ((IFormatter) serializerMapping[type]).Parse(primitive.SerialData);
121      if ( ! value.GetType().IsValueType )
122        id2obj[(int)primitive.Id] = value;
123      SetValue(primitive.Name, value);
124    }
125
126    private void ReferenceHandler(ISerializationToken token) {
127      ReferenceToken reference = (ReferenceToken)token;
128      object referredObject = id2obj[reference.Id];
129      SetValue(reference.Name, id2obj[reference.Id]);
130      if (referredObject is ParentReference) {
131        Setter set = parentStack.Peek().GetSetter(reference.Name);       
132        int id = reference.Id;
133        finalFixes.Add(() => set(id2obj[id]));
134      }
135    }
136
137    private void NullHandler(ISerializationToken token) {
138      NullReferenceToken nil = (NullReferenceToken)token;
139      SetValue(nil.Name, null);
140    }   
141
142    private void SetValue(string name, object value) {
143      if (parentStack.Count == 0) {       
144        parentStack.Push(new CompositeObject(value));
145      } else {       
146        parentStack.Peek().AddValue(name, value);       
147      }
148    }
149  }
150}
Note: See TracBrowser for help on using the repository browser.