Free cookie consent management tool by TermsFeed Policy Generator

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

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

Add using around ZipFile to prevent a locked file in case of a deserialization exception (#548)

File size: 5.3 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;
10
11namespace HeuristicLab.Persistence.Default.Xml {
12
13  public class XmlParser : IEnumerable<ISerializationToken> {
14
15    private readonly XmlReader reader;
16    private delegate IEnumerator<ISerializationToken> Handler();
17    private readonly Dictionary<string, Handler> handlers;
18
19    public XmlParser(TextReader input) {
20      XmlReaderSettings settings = new XmlReaderSettings {
21        ConformanceLevel = ConformanceLevel.Document,
22        IgnoreWhitespace = true,
23        IgnoreComments = true
24      };
25      reader = XmlReader.Create(input, settings);
26      handlers = new Dictionary<string, Handler> {
27                     {XmlStringConstants.PRIMITIVE, ParsePrimitive},
28                     {XmlStringConstants.COMPOSITE, ParseComposite},
29                     {XmlStringConstants.REFERENCE, ParseReference},
30                     {XmlStringConstants.NULL, ParseNull},
31                     {XmlStringConstants.METAINFO, ParseMetaInfo},
32                   };
33    }
34
35    public IEnumerator<ISerializationToken> GetEnumerator() {
36      while (reader.Read()) {
37        if (!reader.IsStartElement()) {
38          break;
39        }
40        IEnumerator<ISerializationToken> iterator;
41        try {
42          iterator = handlers[reader.Name].Invoke();
43        } catch (KeyNotFoundException) {
44          throw new PersistenceException(String.Format(
45            "Invalid XML tag \"{0}\" in persistence file.",
46            reader.Name));
47        }
48        while (iterator.MoveNext()) {
49          yield return iterator.Current;
50        }
51      }
52    }
53
54    private IEnumerator<ISerializationToken> ParsePrimitive() {
55      int? id = null;
56      string idString = reader.GetAttribute("id");
57      if (idString != null)
58        id = int.Parse(idString);
59      string name = reader.GetAttribute("name");
60      int typeId = int.Parse(reader.GetAttribute("typeId"));
61      XmlReader inner = reader.ReadSubtree();
62      inner.Read();
63      string xml = inner.ReadInnerXml();
64      inner.Close();
65      yield return new PrimitiveToken(name, typeId, id, new XmlString(xml));
66    }
67
68    private IEnumerator<ISerializationToken> ParseComposite() {
69      string name = reader.GetAttribute("name");
70      string idString = reader.GetAttribute("id");
71      int? id = null;
72      if (idString != null)
73        id = int.Parse(idString);
74      int typeId = int.Parse(reader.GetAttribute("typeId"));
75      yield return new BeginToken(name, typeId, id);
76      IEnumerator<ISerializationToken> iterator = GetEnumerator();
77      while (iterator.MoveNext())
78        yield return iterator.Current;
79      yield return new EndToken(name, typeId, id);
80    }
81
82    private IEnumerator<ISerializationToken> ParseReference() {
83      yield return new ReferenceToken(
84        reader.GetAttribute("name"),
85        int.Parse(reader.GetAttribute("ref")));
86    }
87
88    private IEnumerator<ISerializationToken> ParseNull() {
89      yield return new NullReferenceToken(reader.GetAttribute("name"));
90    }
91
92    private IEnumerator<ISerializationToken> ParseMetaInfo() {
93      yield return new MetaInfoBeginToken();
94      IEnumerator<ISerializationToken> iterator = GetEnumerator();
95      while (iterator.MoveNext())
96        yield return iterator.Current;
97      yield return new MetaInfoEndToken();
98    }
99
100    IEnumerator IEnumerable.GetEnumerator() {
101      return GetEnumerator();
102    }
103
104    public static List<TypeMapping> ParseTypeCache(TextReader reader) {
105      try {
106        var typeCache = new List<TypeMapping>();
107        XmlReader xmlReader = XmlReader.Create(reader);
108        while (xmlReader.Read()) {
109          if (xmlReader.Name == XmlStringConstants.TYPE) {
110            typeCache.Add(new TypeMapping(
111              int.Parse(xmlReader.GetAttribute("id")),
112              xmlReader.GetAttribute("typeName"),
113              xmlReader.GetAttribute("serializer")));
114          }
115        }
116        return typeCache;
117      } catch (PersistenceException) {
118        throw;
119      } catch (Exception e) {
120        throw new PersistenceException("Unexpected exception during type cache parsing.", e);
121      }
122    }
123
124    public static object Deserialize(string filename) {
125      using (ZipFile file = new ZipFile(filename)) {
126        return Deserialize(file);
127      }
128    }
129
130    public static object Deserialize(Stream stream) {
131      using (ZipFile file = new ZipFile(stream)) {
132        return Deserialize(file);
133      }
134    }
135
136    private static object Deserialize(ZipFile zipFile) {
137      try {
138        Deserializer deSerializer = new Deserializer(
139          ParseTypeCache(
140          new StreamReader(
141            zipFile.GetInputStream(zipFile.GetEntry("typecache.xml")))));
142        XmlParser parser = new XmlParser(
143          new StreamReader(zipFile.GetInputStream(zipFile.GetEntry("data.xml"))));
144        object result = deSerializer.Deserialize(parser);
145        zipFile.Close();
146        return result;
147      } catch (PersistenceException e) {
148        throw;
149      } catch (Exception e) {
150        throw new PersistenceException("Unexpected exception during deserialization", e);
151      }
152    }
153  }
154}
Note: See TracBrowser for help on using the repository browser.