Free cookie consent management tool by TermsFeed Policy Generator

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

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

reset ZipEntry data to make binary objects comparable (#548)

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