Free cookie consent management tool by TermsFeed Policy Generator

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

Last change on this file since 10085 was 9456, checked in by swagner, 12 years ago

Updated copyright year and added some missing license headers (#1889)

File size: 10.0 KB
RevLine 
[3742]1#region License Information
2/* HeuristicLab
[9456]3 * Copyright (C) 2002-2013 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
[3742]4 *
5 * This file is part of HeuristicLab.
6 *
7 * HeuristicLab is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * HeuristicLab is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
19 */
20#endregion
21
[1454]22using System;
23using System.Collections;
[4068]24using System.Collections.Generic;
[1454]25using System.IO;
[4068]26using System.IO.Compression;
27using System.Xml;
[1454]28using HeuristicLab.Persistence.Core;
[4068]29using HeuristicLab.Persistence.Core.Tokens;
[1454]30using HeuristicLab.Persistence.Interfaces;
[1466]31using ICSharpCode.SharpZipLib.Zip;
[1454]32
33namespace HeuristicLab.Persistence.Default.Xml {
34
[3028]35  /// <summary>
36  /// Main entry point of persistence loading from XML. Use the static
37  /// methods to load from a file or stream.
38  /// </summary>
[1454]39  public class XmlParser : IEnumerable<ISerializationToken> {
40
[3293]41    private readonly XmlTextReader reader;
[1454]42    private delegate IEnumerator<ISerializationToken> Handler();
43    private readonly Dictionary<string, Handler> handlers;
44
[3028]45    /// <summary>
46    /// Initializes a new instance of the <see cref="XmlParser"/> class.
47    /// </summary>
48    /// <param name="input">The input.</param>
[1454]49    public XmlParser(TextReader input) {
[3293]50      reader = new XmlTextReader(input);
51      reader.WhitespaceHandling = WhitespaceHandling.All;
52      reader.Normalization = false;
[1454]53      handlers = new Dictionary<string, Handler> {
[1612]54                     {XmlStringConstants.PRIMITIVE, ParsePrimitive},
55                     {XmlStringConstants.COMPOSITE, ParseComposite},
56                     {XmlStringConstants.REFERENCE, ParseReference},
57                     {XmlStringConstants.NULL, ParseNull},
58                     {XmlStringConstants.METAINFO, ParseMetaInfo},
[3005]59                     {XmlStringConstants.TYPE, ParseTypeInfo},
[1454]60                   };
61    }
62
[3028]63    /// <summary>
64    /// Returns an enumerator that iterates through the serialization tokens.
65    /// </summary>
66    /// <returns>
67    /// An that can be used to iterate through the collection of serialization tokens.
68    /// </returns>
[1454]69    public IEnumerator<ISerializationToken> GetEnumerator() {
70      while (reader.Read()) {
71        if (!reader.IsStartElement()) {
72          break;
73        }
74        IEnumerator<ISerializationToken> iterator;
75        try {
76          iterator = handlers[reader.Name].Invoke();
[4068]77        }
78        catch (KeyNotFoundException) {
[1625]79          throw new PersistenceException(String.Format(
80            "Invalid XML tag \"{0}\" in persistence file.",
[1454]81            reader.Name));
82        }
83        while (iterator.MoveNext()) {
84          yield return iterator.Current;
85        }
86      }
87    }
88
[3028]89    /// <summary>
90    /// Returns an enumerator that iterates through the serialization tokens.
91    /// </summary>
92    /// <returns>
93    /// An that can be used to iterate through the collection of serialization tokens.
94    /// </returns>
95    IEnumerator IEnumerable.GetEnumerator() {
96      return GetEnumerator();
97    }
98
[1454]99    private IEnumerator<ISerializationToken> ParsePrimitive() {
100      int? id = null;
101      string idString = reader.GetAttribute("id");
102      if (idString != null)
103        id = int.Parse(idString);
[1616]104      string name = reader.GetAttribute("name");
105      int typeId = int.Parse(reader.GetAttribute("typeId"));
[3005]106      string typeName = reader.GetAttribute("typeName");
107      string serializer = reader.GetAttribute("serializer");
108      if (typeName != null)
109        yield return new TypeToken(typeId, typeName, serializer);
[1616]110      XmlReader inner = reader.ReadSubtree();
111      inner.Read();
112      string xml = inner.ReadInnerXml();
[1703]113      inner.Close();
[1616]114      yield return new PrimitiveToken(name, typeId, id, new XmlString(xml));
[1454]115    }
116
117    private IEnumerator<ISerializationToken> ParseComposite() {
[1566]118      string name = reader.GetAttribute("name");
[1454]119      string idString = reader.GetAttribute("id");
120      int? id = null;
121      if (idString != null)
122        id = int.Parse(idString);
[1564]123      int typeId = int.Parse(reader.GetAttribute("typeId"));
[3005]124      string typeName = reader.GetAttribute("typeName");
125      string serializer = reader.GetAttribute("serializer");
126      if (typeName != null)
127        yield return new TypeToken(typeId, typeName, serializer);
[1454]128      yield return new BeginToken(name, typeId, id);
129      IEnumerator<ISerializationToken> iterator = GetEnumerator();
130      while (iterator.MoveNext())
131        yield return iterator.Current;
132      yield return new EndToken(name, typeId, id);
133    }
134
135    private IEnumerator<ISerializationToken> ParseReference() {
136      yield return new ReferenceToken(
137        reader.GetAttribute("name"),
138        int.Parse(reader.GetAttribute("ref")));
139    }
140
141    private IEnumerator<ISerializationToken> ParseNull() {
142      yield return new NullReferenceToken(reader.GetAttribute("name"));
143    }
144
[1553]145    private IEnumerator<ISerializationToken> ParseMetaInfo() {
146      yield return new MetaInfoBeginToken();
147      IEnumerator<ISerializationToken> iterator = GetEnumerator();
148      while (iterator.MoveNext())
149        yield return iterator.Current;
150      yield return new MetaInfoEndToken();
151    }
152
[3005]153    private IEnumerator<ISerializationToken> ParseTypeInfo() {
154      yield return new TypeToken(
155        int.Parse(reader.GetAttribute("id")),
156        reader.GetAttribute("typeName"),
157        reader.GetAttribute("serializer"));
158    }
159
[3028]160    /// <summary>
161    /// Parses the type cache.
162    /// </summary>
163    /// <param name="reader">The reader.</param>
164    /// <returns>A list of type mapping entries.</returns>
[1454]165    public static List<TypeMapping> ParseTypeCache(TextReader reader) {
[1625]166      try {
167        var typeCache = new List<TypeMapping>();
168        XmlReader xmlReader = XmlReader.Create(reader);
169        while (xmlReader.Read()) {
170          if (xmlReader.Name == XmlStringConstants.TYPE) {
171            typeCache.Add(new TypeMapping(
172              int.Parse(xmlReader.GetAttribute("id")),
173              xmlReader.GetAttribute("typeName"),
174              xmlReader.GetAttribute("serializer")));
175          }
[1454]176        }
[1625]177        return typeCache;
[4068]178      }
179      catch (PersistenceException) {
[1625]180        throw;
[4068]181      }
182      catch (Exception e) {
[1625]183        throw new PersistenceException("Unexpected exception during type cache parsing.", e);
[1454]184      }
185    }
186
[3028]187    /// <summary>
188    /// Deserializes an object from the specified filename.
189    /// </summary>
190    /// <param name="filename">The filename.</param>
191    /// <returns>A fresh object instance</returns>
[1734]192    public static object Deserialize(string filename) {
[3913]193      TimeSpan start = System.Diagnostics.Process.GetCurrentProcess().TotalProcessorTime;
194      try {
195        using (ZipFile file = new ZipFile(filename)) {
196          return Deserialize(file);
197        }
[4068]198      }
199      finally {
[3913]200        TimeSpan end = System.Diagnostics.Process.GetCurrentProcess().TotalProcessorTime;
201        Tracing.Logger.Info(string.Format(
202          "deserialization of {0} took {1} seconds",
203          filename, (end - start).TotalSeconds));
[2874]204      }
[1734]205    }
206
[3028]207    /// <summary>
208    /// Deserializes the specified filename.
209    /// </summary>
210    /// <typeparam name="T">object type expected from the serialized file</typeparam>
211    /// <param name="filename">The filename.</param>
212    /// <returns>A fresh object of type T</returns>
213    public static T Deserialize<T>(string filename) {
214      return (T)Deserialize(filename);
215    }
216
217
218    /// <summary>
219    /// Deserializes an object from the specified stream.
220    /// </summary>
221    /// <param name="stream">The stream.</param>
222    /// <returns>A fresh object instance.</returns>
[1734]223    public static object Deserialize(Stream stream) {
[3005]224      try {
225        using (StreamReader reader = new StreamReader(new GZipStream(stream, CompressionMode.Decompress))) {
226          XmlParser parser = new XmlParser(reader);
227          Deserializer deserializer = new Deserializer(new TypeMapping[] { });
228          return deserializer.Deserialize(parser);
229        }
[4068]230      }
231      catch (PersistenceException) {
[3005]232        throw;
[4068]233      }
234      catch (Exception x) {
[3005]235        throw new PersistenceException("Unexpected exception during deserialization", x);
[2874]236      }
[1734]237    }
238
[3028]239    /// <summary>
240    /// Deserializes an object from the specified stream.
241    /// </summary>
242    /// <typeparam name="T">object type expected from the serialized stream</typeparam>
243    /// <param name="stream">The stream.</param>
244    /// <returns>A fresh object instance.</returns>
245    public static T Deserialize<T>(Stream stream) {
246      return (T)Deserialize(stream);
247    }
248
[1734]249    private static object Deserialize(ZipFile zipFile) {
[1779]250      try {
[3005]251        ZipEntry typecache = zipFile.GetEntry("typecache.xml");
252        if (typecache == null)
253          throw new PersistenceException("file does not contain typecache.xml");
254        Deserializer deSerializer = new Deserializer(ParseTypeCache(new StreamReader(zipFile.GetInputStream(typecache))));
255        ZipEntry data = zipFile.GetEntry("data.xml");
256        if (data == null)
257          throw new PersistenceException("file does not contain data.xml");
[1625]258        XmlParser parser = new XmlParser(
[3005]259          new StreamReader(zipFile.GetInputStream(data)));
[1625]260        object result = deSerializer.Deserialize(parser);
261        zipFile.Close();
262        return result;
[4068]263      }
264      catch (PersistenceException) {
[1625]265        throw;
[4068]266      }
267      catch (Exception e) {
[1625]268        throw new PersistenceException("Unexpected exception during deserialization", e);
269      }
[1454]270    }
[1566]271  }
[1564]272}
Note: See TracBrowser for help on using the repository browser.