Free cookie consent management tool by TermsFeed Policy Generator

source: branches/CEDMA-Exporter-715/sources/HeuristicLab.Persistence/3.3/Default/Xml/XmlGenerator.cs @ 2227

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

Don't take ownership of underlying stream. (#672)

File size: 8.3 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        using (FileStream stream = File.Create(tempfile)) {
175          Serialize(obj, stream, config, includeAssemblies, compression);
176        }
177        Logger.Info(String.Format("serialization took {0} seconds with compression level {1}",
178          (DateTime.Now - start).TotalSeconds, compression));
179        File.Copy(tempfile, filename, true);
180        File.Delete(tempfile);
181      } catch (Exception) {
182        Logger.Warn("Exception caught, no data has been written.");
183        throw;
184      }
185    }
186
187
188    public static void Serialize(object obj, Stream stream, Configuration config) {
189      Serialize(obj, stream, config, false);
190    }
191   
192    public static void Serialize(object obj, Stream stream, Configuration config, bool includeAssemblies) {
193      Serialize(obj, stream, config, includeAssemblies, 9);
194    }
195
196    public static void Serialize(object obj, Stream stream, Configuration config, bool includeAssemblies, int compression) {     
197      try {
198        Serializer serializer = new Serializer(obj, config);
199        XmlGenerator generator = new XmlGenerator();
200        using (ZipOutputStream zipStream = new ZipOutputStream(stream)) {
201          zipStream.IsStreamOwner = false;
202          zipStream.SetLevel(compression);
203          zipStream.PutNextEntry(new ZipEntry("data.xml"));
204          StreamWriter writer = new StreamWriter(zipStream);
205          foreach (ISerializationToken token in serializer) {
206            string line = generator.Format(token);
207            writer.Write(line);
208          }
209          writer.Flush();
210          zipStream.PutNextEntry(new ZipEntry("typecache.xml"));
211          foreach (string line in generator.Format(serializer.TypeCache)) {
212            writer.Write(line);
213          }
214          writer.Flush();
215          if (includeAssemblies) {
216            foreach (string name in serializer.RequiredFiles) {
217              Uri uri = new Uri(name);
218              if (!uri.IsFile) {
219                Logger.Warn("cannot read non-local files");
220                continue;
221              }
222              zipStream.PutNextEntry(new ZipEntry(Path.GetFileName(uri.PathAndQuery)));
223              FileStream reader = File.OpenRead(uri.PathAndQuery);
224              byte[] buffer = new byte[1024 * 1024];
225              while (true) {
226                int bytesRead = reader.Read(buffer, 0, 1024 * 1024);
227                if (bytesRead == 0)
228                  break;
229                zipStream.Write(buffer, 0, bytesRead);
230              }
231              writer.Flush();
232            }
233          }
234        }
235      } catch (PersistenceException) {
236        throw;
237      } catch (Exception e) {
238        throw new PersistenceException("Unexpected exception during Serialization.", e);
239      }     
240    }
241  }
242}
Note: See TracBrowser for help on using the repository browser.