Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.Persistence/3.3/Default/Xml/XmlParser.cs @ 3028

Last change on this file since 3028 was 3028, checked in by epitzer, 14 years ago

add more API docs (#548)

File size: 8.9 KB
Line 
1using System.Xml;
2using System.Collections.Generic;
3using System;
4using System.Collections;
5using System.IO;
6using HeuristicLab.Persistence.Core;
7using HeuristicLab.Persistence.Interfaces;
8using ICSharpCode.SharpZipLib.Zip;
9using HeuristicLab.Persistence.Core.Tokens;
10using System.IO.Compression;
11
12namespace HeuristicLab.Persistence.Default.Xml {
13
14  /// <summary>
15  /// Main entry point of persistence loading from XML. Use the static
16  /// methods to load from a file or stream.
17  /// </summary>
18  public class XmlParser : IEnumerable<ISerializationToken> {
19
20    private readonly XmlReader reader;
21    private delegate IEnumerator<ISerializationToken> Handler();
22    private readonly Dictionary<string, Handler> handlers;
23
24    /// <summary>
25    /// Initializes a new instance of the <see cref="XmlParser"/> class.
26    /// </summary>
27    /// <param name="input">The input.</param>
28    public XmlParser(TextReader input) {
29      XmlReaderSettings settings = new XmlReaderSettings {
30        ConformanceLevel = ConformanceLevel.Document,
31        IgnoreWhitespace = true,
32        IgnoreComments = true
33      };
34      reader = XmlReader.Create(input, settings);
35      handlers = new Dictionary<string, Handler> {
36                     {XmlStringConstants.PRIMITIVE, ParsePrimitive},
37                     {XmlStringConstants.COMPOSITE, ParseComposite},
38                     {XmlStringConstants.REFERENCE, ParseReference},
39                     {XmlStringConstants.NULL, ParseNull},
40                     {XmlStringConstants.METAINFO, ParseMetaInfo},
41                     {XmlStringConstants.TYPE, ParseTypeInfo},
42                   };
43    }
44
45    /// <summary>
46    /// Returns an enumerator that iterates through the serialization tokens.
47    /// </summary>
48    /// <returns>
49    /// An that can be used to iterate through the collection of serialization tokens.
50    /// </returns>
51    public IEnumerator<ISerializationToken> GetEnumerator() {
52      while (reader.Read()) {
53        if (!reader.IsStartElement()) {
54          break;
55        }
56        IEnumerator<ISerializationToken> iterator;
57        try {
58          iterator = handlers[reader.Name].Invoke();
59        } catch (KeyNotFoundException) {
60          throw new PersistenceException(String.Format(
61            "Invalid XML tag \"{0}\" in persistence file.",
62            reader.Name));
63        }
64        while (iterator.MoveNext()) {
65          yield return iterator.Current;
66        }
67      }
68    }
69
70    /// <summary>
71    /// Returns an enumerator that iterates through the serialization tokens.
72    /// </summary>
73    /// <returns>
74    /// An that can be used to iterate through the collection of serialization tokens.
75    /// </returns>
76    IEnumerator IEnumerable.GetEnumerator() {
77      return GetEnumerator();
78    }
79
80    private IEnumerator<ISerializationToken> ParsePrimitive() {
81      int? id = null;
82      string idString = reader.GetAttribute("id");
83      if (idString != null)
84        id = int.Parse(idString);
85      string name = reader.GetAttribute("name");
86      int typeId = int.Parse(reader.GetAttribute("typeId"));
87      string typeName = reader.GetAttribute("typeName");
88      string serializer = reader.GetAttribute("serializer");
89      if (typeName != null)
90        yield return new TypeToken(typeId, typeName, serializer);
91      XmlReader inner = reader.ReadSubtree();
92      inner.Read();
93      string xml = inner.ReadInnerXml();
94      inner.Close();
95      yield return new PrimitiveToken(name, typeId, id, new XmlString(xml));
96    }
97
98    private IEnumerator<ISerializationToken> ParseComposite() {
99      string name = reader.GetAttribute("name");
100      string idString = reader.GetAttribute("id");
101      int? id = null;
102      if (idString != null)
103        id = int.Parse(idString);
104      int typeId = int.Parse(reader.GetAttribute("typeId"));
105      string typeName = reader.GetAttribute("typeName");
106      string serializer = reader.GetAttribute("serializer");
107      if (typeName != null)
108        yield return new TypeToken(typeId, typeName, serializer);
109      yield return new BeginToken(name, typeId, id);
110      IEnumerator<ISerializationToken> iterator = GetEnumerator();
111      while (iterator.MoveNext())
112        yield return iterator.Current;
113      yield return new EndToken(name, typeId, id);
114    }
115
116    private IEnumerator<ISerializationToken> ParseReference() {
117      yield return new ReferenceToken(
118        reader.GetAttribute("name"),
119        int.Parse(reader.GetAttribute("ref")));
120    }
121
122    private IEnumerator<ISerializationToken> ParseNull() {
123      yield return new NullReferenceToken(reader.GetAttribute("name"));
124    }
125
126    private IEnumerator<ISerializationToken> ParseMetaInfo() {
127      yield return new MetaInfoBeginToken();
128      IEnumerator<ISerializationToken> iterator = GetEnumerator();
129      while (iterator.MoveNext())
130        yield return iterator.Current;
131      yield return new MetaInfoEndToken();
132    }
133
134    private IEnumerator<ISerializationToken> ParseTypeInfo() {
135      yield return new TypeToken(
136        int.Parse(reader.GetAttribute("id")),
137        reader.GetAttribute("typeName"),
138        reader.GetAttribute("serializer"));
139    }
140
141    /// <summary>
142    /// Parses the type cache.
143    /// </summary>
144    /// <param name="reader">The reader.</param>
145    /// <returns>A list of type mapping entries.</returns>
146    public static List<TypeMapping> ParseTypeCache(TextReader reader) {
147      try {
148        var typeCache = new List<TypeMapping>();
149        XmlReader xmlReader = XmlReader.Create(reader);
150        while (xmlReader.Read()) {
151          if (xmlReader.Name == XmlStringConstants.TYPE) {
152            typeCache.Add(new TypeMapping(
153              int.Parse(xmlReader.GetAttribute("id")),
154              xmlReader.GetAttribute("typeName"),
155              xmlReader.GetAttribute("serializer")));
156          }
157        }
158        return typeCache;
159      } catch (PersistenceException) {
160        throw;
161      } catch (Exception e) {
162        throw new PersistenceException("Unexpected exception during type cache parsing.", e);
163      }
164    }
165
166    /// <summary>
167    /// Deserializes an object from the specified filename.
168    /// </summary>
169    /// <param name="filename">The filename.</param>
170    /// <returns>A fresh object instance</returns>
171    public static object Deserialize(string filename) {
172      using (ZipFile file = new ZipFile(filename)) {
173        return Deserialize(file);
174      }
175    }
176
177    /// <summary>
178    /// Deserializes the specified filename.
179    /// </summary>
180    /// <typeparam name="T">object type expected from the serialized file</typeparam>
181    /// <param name="filename">The filename.</param>
182    /// <returns>A fresh object of type T</returns>
183    public static T Deserialize<T>(string filename) {
184      return (T)Deserialize(filename);
185    }
186
187
188    /// <summary>
189    /// Deserializes an object from the specified stream.
190    /// </summary>
191    /// <param name="stream">The stream.</param>
192    /// <returns>A fresh object instance.</returns>
193    public static object Deserialize(Stream stream) {
194      try {
195        using (StreamReader reader = new StreamReader(new GZipStream(stream, CompressionMode.Decompress))) {
196          XmlParser parser = new XmlParser(reader);
197          Deserializer deserializer = new Deserializer(new TypeMapping[] { });
198          return deserializer.Deserialize(parser);
199        }
200      } catch (PersistenceException) {
201        throw;
202      } catch (Exception x) {
203        throw new PersistenceException("Unexpected exception during deserialization", x);
204      }
205    }
206
207    /// <summary>
208    /// Deserializes an object from the specified stream.
209    /// </summary>
210    /// <typeparam name="T">object type expected from the serialized stream</typeparam>
211    /// <param name="stream">The stream.</param>
212    /// <returns>A fresh object instance.</returns>
213    public static T Deserialize<T>(Stream stream) {
214      return (T)Deserialize(stream);
215    }
216
217    private static object Deserialize(ZipFile zipFile) {
218      try {
219        ZipEntry typecache = zipFile.GetEntry("typecache.xml");
220        if (typecache == null)
221          throw new PersistenceException("file does not contain typecache.xml");
222        Deserializer deSerializer = new Deserializer(ParseTypeCache(new StreamReader(zipFile.GetInputStream(typecache))));
223        ZipEntry data = zipFile.GetEntry("data.xml");
224        if (data == null)
225          throw new PersistenceException("file does not contain data.xml");
226        XmlParser parser = new XmlParser(
227          new StreamReader(zipFile.GetInputStream(data)));
228        object result = deSerializer.Deserialize(parser);
229        zipFile.Close();
230        return result;
231      } catch (PersistenceException) {
232        throw;
233      } catch (Exception e) {
234        throw new PersistenceException("Unexpected exception during deserialization", e);
235      }
236    }
237  }
238}
Note: See TracBrowser for help on using the repository browser.