Free cookie consent management tool by TermsFeed Policy Generator

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

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

Add serializer class information to type cache. (#506)

File size: 6.8 KB
Line 
1using System.Collections.Generic;
2using System;
3using HeuristicLab.Persistence.Interfaces;
4
5namespace HeuristicLab.Persistence.Core {
6
7
8  struct ParentReference { }
9  delegate void Setter(object value);
10
11
12  interface IAccessibleObject {
13    object Obj { get; }
14    Setter GetSetter(string name);
15  }
16
17
18  class CustomComposite : IAccessibleObject {
19
20    public object Obj { get; private set; }
21    public readonly List<object> customValues;
22
23    public CustomComposite(object obj) {
24      Obj = obj;
25      customValues = new List<object>();
26    }
27
28    public void AddValue(object value) {
29      customValues.Add(value);
30    }
31
32    public Setter GetSetter(string name) {
33      int index = customValues.Count - 1;
34      return value => customValues[index] = value;
35    }
36  }
37
38
39  class StorableComposite : IAccessibleObject {
40
41    public object Obj { get; private set; }
42    public readonly Dictionary<string, DataMemberAccessor> accessorDict;
43
44    public StorableComposite(object obj, Dictionary<string, DataMemberAccessor> accessorDict) {
45      Obj = obj;
46      this.accessorDict = new Dictionary<string, DataMemberAccessor>();
47      foreach (KeyValuePair<string, DataMemberAccessor> pair in accessorDict) {
48        this.accessorDict.Add(
49          pair.Value.Name,
50          pair.Value);
51      }
52    }
53
54    public void SetValue(string name, object value) {
55      accessorDict[name].Set(value);
56      accessorDict.Remove(name);
57    }
58
59    public Setter GetSetter(string name) {
60      return value => accessorDict[name].Set(value);
61    }
62
63    public void PopulateDefaultValues() {
64      foreach (var pair in accessorDict) {
65        pair.Value.Set(pair.Value.DefaultValue);
66      }
67    }
68  }
69
70
71  public class DeSerializer {
72
73    private delegate void Handler(ISerializationToken token);
74    private delegate void Thunk();
75
76    private readonly Dictionary<int, object> id2obj;
77    private readonly Dictionary<Type, object> serializerMapping;
78    private readonly Dictionary<Type, Handler> handlers;
79    private readonly Stack<IAccessibleObject> parentStack;   
80    private readonly Dictionary<int, Type> typeIds;   
81    private List<Thunk> finalFixes;
82
83    public DeSerializer(
84      IEnumerable<TypeMapping> typeCache) {     
85      id2obj = new Dictionary<int, object>();
86      parentStack = new Stack<IAccessibleObject>();
87      handlers = new Dictionary<Type, Handler> {
88                     {typeof (BeginToken), CompositeStartHandler},
89                     {typeof (EndToken), CompositeEndHandler},
90                     {typeof (PrimitiveToken), PrimitiveHandler},
91                     {typeof (ReferenceToken), ReferenceHandler},
92                     {typeof (NullReferenceToken), NullHandler}
93                   };     
94      typeIds = new Dictionary<int, Type>();
95      serializerMapping = new Dictionary<Type, object>();
96      foreach ( var typeMapping in typeCache ) {
97        Type type = Type.GetType(typeMapping.TypeName);
98        typeIds.Add(typeMapping.Id, type);
99        if (typeMapping.Serializer != null) {
100          Type serializerType = Type.GetType(typeMapping.Serializer);
101          serializerMapping.Add(type, Activator.CreateInstance(serializerType, true));
102        }
103      }
104    }
105
106    public object DeSerialize(IEnumerable<ISerializationToken> tokens) {
107      finalFixes = new List<Thunk>();
108      foreach (ISerializationToken token in tokens) {
109        handlers[token.GetType()].Invoke(token);
110      }
111      foreach (Thunk fix in finalFixes) {
112        fix();
113      }
114      return parentStack.Pop().Obj;
115    }
116
117    private void CompositeStartHandler(ISerializationToken token) {
118      BeginToken start = (BeginToken)token;
119      object instance;     
120      Type type = typeIds[(int)start.TypeId];
121      IDecomposer decomposer = null;
122      if ( serializerMapping.ContainsKey(type) )
123        decomposer = serializerMapping[type] as IDecomposer;     
124      if (decomposer != null) {
125        instance = new ParentReference();
126        parentStack.Push(new CustomComposite(instance));       
127      } else {       
128        instance = Activator.CreateInstance(type, true);
129        Dictionary<string, DataMemberAccessor> accessorDict =
130          StorableAttribute.GetAutostorableAccessors(instance);
131        parentStack.Push(new StorableComposite(instance, accessorDict));       
132      }
133      if ( start.Id != null )
134        id2obj.Add((int)start.Id, instance);
135    }
136
137    private void CompositeEndHandler(ISerializationToken token) {
138      EndToken end = (EndToken)token;
139      Type type = typeIds[(int)end.TypeId];
140      IDecomposer decomposer = null;
141      if (serializerMapping.ContainsKey(type))
142        decomposer = serializerMapping[type] as IDecomposer;           
143      if (decomposer != null) {
144        CustomComposite customComposite = (CustomComposite)parentStack.Pop();
145        object deserializedObject =
146          decomposer.Compose(customComposite.customValues, type);
147        if ( end.Id != null )
148          id2obj[(int)end.Id] = deserializedObject;       
149        SetValue(end.Name, deserializedObject);         
150      } else {
151        StorableComposite storableComposite = (StorableComposite)parentStack.Pop();
152        storableComposite.PopulateDefaultValues();
153        SetValue(end.Name, storableComposite.Obj);
154      }
155    }
156
157    private void PrimitiveHandler(ISerializationToken token) {
158      PrimitiveToken primitive = (PrimitiveToken)token;
159      Type type = typeIds[(int)primitive.TypeId];
160      object value = ((IFormatter) serializerMapping[type]).Parse(primitive.SerialData);
161      if ( ! value.GetType().IsValueType )
162        id2obj[(int)primitive.Id] = value;
163      SetValue(primitive.Name, value);
164    }
165
166    private void ReferenceHandler(ISerializationToken token) {
167      ReferenceToken reference = (ReferenceToken)token;
168      object referredObject = id2obj[reference.Id];
169      SetValue(reference.Name, id2obj[reference.Id]);
170      if (referredObject is ParentReference) {
171        Setter set = parentStack.Peek().GetSetter(reference.Name);       
172        int id = reference.Id;
173        finalFixes.Add(() => set(id2obj[id]));
174      }
175    }
176
177    private void NullHandler(ISerializationToken token) {
178      NullReferenceToken nil = (NullReferenceToken)token;
179      SetValue(nil.Name, null);
180    }   
181
182    private void SetValue(string name, object value) {
183      if (parentStack.Count == 0) {
184        parentStack.Push(new StorableComposite(value, new Dictionary<string, DataMemberAccessor>()));
185      } else {
186        object accessibleObject = parentStack.Peek();
187        if (accessibleObject is StorableComposite) {
188          ((StorableComposite)accessibleObject).SetValue(name, value);
189        } else if (accessibleObject is CustomComposite) {
190          ((CustomComposite)accessibleObject).AddValue(value);
191        }
192      }
193    }
194  }
195}
Note: See TracBrowser for help on using the repository browser.