Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.Persistence/3.3/Default/Xml/XmlGenerator.cs @ 1892

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

Configurable compression level (and lower default settings) and remove excessive logging for better saving speed. (#646)

File size: 8.2 KB
Line 
1using System.Collections.Generic;
2using System;
3using System.Text;
4using HeuristicLab.Persistence.Interfaces;
5using HeuristicLab.Persistence.Core;
6using System.IO;
7using ICSharpCode.SharpZipLib.Zip;
8using HeuristicLab.Tracing;
9using log4net;
10using HeuristicLab.Persistence.Core.Tokens;
11
12namespace HeuristicLab.Persistence.Default.Xml {
13
14  public class XmlGenerator : GeneratorBase<string> {
15
16    private int depth;
17    private int Depth {
18      get {
19        return depth;
20      }
21      set {
22        depth = value;
23        prefix = new string(' ', depth * 2);
24      }
25    }
26
27    private string prefix;
28
29
30    public XmlGenerator() {
31      Depth = 0;
32    }
33
34    private enum NodeType { Start, End, Inline } ;
35
36    private static void AddXmlTagContent(StringBuilder sb, string name, Dictionary<string, object> attributes) {
37      sb.Append(name);
38      foreach (var attribute in attributes) {
39        if (attribute.Value != null && !string.IsNullOrEmpty(attribute.Value.ToString())) {
40          sb.Append(' ');
41          sb.Append(attribute.Key);
42          sb.Append("=\"");
43          sb.Append(attribute.Value);
44          sb.Append('"');
45        }
46      }
47    }
48
49    private static void AddXmlStartTag(StringBuilder sb, string name, Dictionary<string, object> attributes) {
50      sb.Append('<');
51      AddXmlTagContent(sb, name, attributes);
52      sb.Append('>');
53    }
54
55    private static void AddXmlInlineTag(StringBuilder sb, string name, Dictionary<string, object> attributes) {
56      sb.Append('<');
57      AddXmlTagContent(sb, name, attributes);
58      sb.Append("/>");
59    }
60
61    private static void AddXmlEndTag(StringBuilder sb, string name) {
62      sb.Append("</");
63      sb.Append(name);
64      sb.Append(">");
65    }
66
67    private string CreateNodeStart(string name, Dictionary<string, object> attributes) {
68      StringBuilder sb = new StringBuilder();
69      sb.Append(prefix);
70      Depth += 1;
71      AddXmlStartTag(sb, name, attributes);
72      sb.Append("\r\n");
73      return sb.ToString();
74    }
75
76    private string CreateNodeStart(string name) {
77      return CreateNodeStart(name, new Dictionary<string, object>());
78    }
79
80    private string CreateNodeEnd(string name) {
81      Depth -= 1;
82      StringBuilder sb = new StringBuilder();
83      sb.Append(prefix);
84      AddXmlEndTag(sb, name);
85      sb.Append("\r\n");
86      return sb.ToString();
87    }
88
89    private string CreateNode(string name, Dictionary<string, object> attributes) {
90      StringBuilder sb = new StringBuilder();
91      sb.Append(prefix);
92      AddXmlInlineTag(sb, name, attributes);
93      sb.Append("\r\n");
94      return sb.ToString();
95    }
96
97    private string CreateNode(string name, Dictionary<string, object> attributes, string content) {
98      StringBuilder sb = new StringBuilder();
99      sb.Append(prefix);
100      AddXmlStartTag(sb, name, attributes);
101      sb.Append(content);
102      sb.Append("</").Append(name).Append(">\r\n");
103      return sb.ToString();
104    }
105
106    protected override string Format(BeginToken beginToken) {
107      return CreateNodeStart(
108        XmlStringConstants.COMPOSITE,
109        new Dictionary<string, object> {
110          {"name", beginToken.Name},
111          {"typeId", beginToken.TypeId},
112          {"id", beginToken.Id}});
113    }
114
115    protected override string Format(EndToken endToken) {
116      return CreateNodeEnd(XmlStringConstants.COMPOSITE);
117    }
118
119    protected override string Format(PrimitiveToken dataToken) {
120      return CreateNode(XmlStringConstants.PRIMITIVE,
121        new Dictionary<string, object> {
122            {"typeId", dataToken.TypeId},
123            {"name", dataToken.Name},
124            {"id", dataToken.Id}},
125        ((XmlString)dataToken.SerialData).Data);
126    }
127
128    protected override string Format(ReferenceToken refToken) {
129      return CreateNode(XmlStringConstants.REFERENCE,
130        new Dictionary<string, object> {
131          {"ref", refToken.Id},
132          {"name", refToken.Name}});
133    }
134
135    protected override string Format(NullReferenceToken nullRefToken) {
136      return CreateNode(XmlStringConstants.NULL,
137        new Dictionary<string, object>{
138          {"name", nullRefToken.Name}});
139    }
140
141    protected override string Format(MetaInfoBeginToken metaInfoBeginToken) {
142      return CreateNodeStart(XmlStringConstants.METAINFO);
143    }
144
145    protected override string Format(MetaInfoEndToken metaInfoEndToken) {
146      return CreateNodeEnd(XmlStringConstants.METAINFO);
147    }
148
149    public IEnumerable<string> Format(List<TypeMapping> typeCache) {
150      yield return CreateNodeStart(XmlStringConstants.TYPECACHE);
151      foreach (var mapping in typeCache)
152        yield return CreateNode(
153          XmlStringConstants.TYPE,
154          mapping.GetDict());
155      yield return CreateNodeEnd(XmlStringConstants.TYPECACHE);
156    }
157
158    public static void Serialize(object o, string filename) {
159      Serialize(o, filename, ConfigurationService.Instance.GetDefaultConfig(new XmlFormat()), false, 5);
160    }
161
162    public static void Serialize(object o, string filename, int compression) {
163      Serialize(o, filename, ConfigurationService.Instance.GetConfiguration(new XmlFormat()), false, compression);
164    }
165
166    public static void Serialize(object obj, string filename, Configuration config) {
167      Serialize(obj, filename, config, false, 5);
168    }
169
170    public static void Serialize(object obj, string filename, Configuration config, bool includeAssemblies, int compression) {     
171      try {
172        string tempfile = Path.GetTempFileName();
173        DateTime start = DateTime.Now;
174        Serialize(obj, File.Create(tempfile), config, includeAssemblies, compression);
175        Logger.Info(String.Format("serialization took {0} seconds with compression level {1}",
176          (DateTime.Now - start).TotalSeconds, compression));
177        File.Copy(tempfile, filename, true);
178        File.Delete(tempfile);
179      } catch (Exception) {
180        Logger.Warn("Exception caught, no data has been written.");
181        throw;
182      }
183    }
184
185
186    public static void Serialize(object obj, Stream stream, Configuration config) {
187      Serialize(obj, stream, config, false);
188    }
189   
190    public static void Serialize(object obj, Stream stream, Configuration config, bool includeAssemblies) {
191      Serialize(obj, stream, config, includeAssemblies, 9);
192    }
193
194    public static void Serialize(object obj, Stream stream, Configuration config, bool includeAssemblies, int compression) {     
195      try {
196        Serializer serializer = new Serializer(obj, config);
197        XmlGenerator generator = new XmlGenerator();
198        using (ZipOutputStream zipStream = new ZipOutputStream(stream)) {
199          zipStream.SetLevel(compression);
200          zipStream.PutNextEntry(new ZipEntry("data.xml"));
201          StreamWriter writer = new StreamWriter(zipStream);
202          foreach (ISerializationToken token in serializer) {
203            string line = generator.Format(token);
204            writer.Write(line);
205          }
206          writer.Flush();
207          zipStream.PutNextEntry(new ZipEntry("typecache.xml"));
208          foreach (string line in generator.Format(serializer.TypeCache)) {
209            writer.Write(line);
210          }
211          writer.Flush();
212          if (includeAssemblies) {
213            foreach (string name in serializer.RequiredFiles) {
214              Uri uri = new Uri(name);
215              if (!uri.IsFile) {
216                Logger.Warn("cannot read non-local files");
217                continue;
218              }
219              zipStream.PutNextEntry(new ZipEntry(Path.GetFileName(uri.PathAndQuery)));
220              FileStream reader = File.OpenRead(uri.PathAndQuery);
221              byte[] buffer = new byte[1024 * 1024];
222              while (true) {
223                int bytesRead = reader.Read(buffer, 0, 1024 * 1024);
224                if (bytesRead == 0)
225                  break;
226                zipStream.Write(buffer, 0, bytesRead);
227              }
228              writer.Flush();
229            }
230          }
231        }
232      } catch (PersistenceException) {
233        throw;
234      } catch (Exception e) {
235        throw new PersistenceException("Unexpected exception during Serialization.", e);
236      }     
237    }
238  }
239}
Note: See TracBrowser for help on using the repository browser.