Free cookie consent management tool by TermsFeed Policy Generator

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

Last change on this file since 1652 was 1625, checked in by epitzer, 16 years ago

Added PersistenceException used consistently for all error conditions in the persistence framework (#548)

File size: 5.1 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 e) {
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      try {
126        ZipFile zipFile = new ZipFile(filename);
127        Deserializer deSerializer = new Deserializer(
128          ParseTypeCache(
129          new StreamReader(
130            zipFile.GetInputStream(zipFile.GetEntry("typecache.xml")))));
131        XmlParser parser = new XmlParser(
132          new StreamReader(zipFile.GetInputStream(zipFile.GetEntry("data.xml"))));
133        object result = deSerializer.Deserialize(parser);
134        zipFile.Close();
135        return result;
136      } catch (PersistenceException e) {
137        throw;
138      } catch (Exception e) {
139        throw new PersistenceException("Unexpected exception during deserialization", e);
140      }
141    }
142  }
143}
Note: See TracBrowser for help on using the repository browser.