[1454] | 1 | using System.Collections.Generic;
|
---|
| 2 | using System;
|
---|
| 3 | using System.Text;
|
---|
| 4 | using HeuristicLab.Persistence.Interfaces;
|
---|
| 5 | using HeuristicLab.Persistence.Core;
|
---|
| 6 | using System.IO;
|
---|
[1466] | 7 | using ICSharpCode.SharpZipLib.Zip;
|
---|
[1476] | 8 | using HeuristicLab.Tracing;
|
---|
| 9 | using log4net;
|
---|
[1556] | 10 | using HeuristicLab.Persistence.Core.Tokens;
|
---|
[1454] | 11 |
|
---|
[1615] | 12 | namespace HeuristicLab.Persistence.Default.Xml {
|
---|
[1454] | 13 |
|
---|
[1564] | 14 | public class XmlGenerator : GeneratorBase<string> {
|
---|
[1566] | 15 |
|
---|
[1454] | 16 | private int depth;
|
---|
[1570] | 17 | private int Depth {
|
---|
| 18 | get {
|
---|
| 19 | return depth;
|
---|
| 20 | }
|
---|
| 21 | set {
|
---|
| 22 | depth = value;
|
---|
| 23 | prefix = new string(' ', depth * 2);
|
---|
| 24 | }
|
---|
| 25 | }
|
---|
[1454] | 26 |
|
---|
[1570] | 27 | private string prefix;
|
---|
| 28 |
|
---|
| 29 |
|
---|
[1454] | 30 | public XmlGenerator() {
|
---|
[1570] | 31 | Depth = 0;
|
---|
[1454] | 32 | }
|
---|
| 33 |
|
---|
| 34 | private enum NodeType { Start, End, Inline } ;
|
---|
| 35 |
|
---|
[1570] | 36 | private static void AddXmlTagContent(StringBuilder sb, string name, Dictionary<string, object> attributes) {
|
---|
[1566] | 37 | sb.Append(name);
|
---|
[1454] | 38 | foreach (var attribute in attributes) {
|
---|
| 39 | if (attribute.Value != null && !string.IsNullOrEmpty(attribute.Value.ToString())) {
|
---|
[1570] | 40 | sb.Append(' ');
|
---|
[1454] | 41 | sb.Append(attribute.Key);
|
---|
| 42 | sb.Append("=\"");
|
---|
| 43 | sb.Append(attribute.Value);
|
---|
| 44 | sb.Append('"');
|
---|
| 45 | }
|
---|
| 46 | }
|
---|
[1570] | 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);
|
---|
[1454] | 64 | sb.Append(">");
|
---|
[1570] | 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");
|
---|
[1566] | 73 | return sb.ToString();
|
---|
[1454] | 74 | }
|
---|
| 75 |
|
---|
[1570] | 76 | private string CreateNodeStart(string name) {
|
---|
| 77 | return CreateNodeStart(name, new Dictionary<string, object>());
|
---|
[1454] | 78 | }
|
---|
| 79 |
|
---|
[1570] | 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 |
|
---|
[1566] | 106 | protected override string Format(BeginToken beginToken) {
|
---|
[1570] | 107 | return CreateNodeStart(
|
---|
[1612] | 108 | XmlStringConstants.COMPOSITE,
|
---|
[1570] | 109 | new Dictionary<string, object> {
|
---|
| 110 | {"name", beginToken.Name},
|
---|
| 111 | {"typeId", beginToken.TypeId},
|
---|
| 112 | {"id", beginToken.Id}});
|
---|
[1454] | 113 | }
|
---|
| 114 |
|
---|
[1566] | 115 | protected override string Format(EndToken endToken) {
|
---|
[1612] | 116 | return CreateNodeEnd(XmlStringConstants.COMPOSITE);
|
---|
[1454] | 117 | }
|
---|
| 118 |
|
---|
[1566] | 119 | protected override string Format(PrimitiveToken dataToken) {
|
---|
[1612] | 120 | return CreateNode(XmlStringConstants.PRIMITIVE,
|
---|
[1454] | 121 | new Dictionary<string, object> {
|
---|
| 122 | {"typeId", dataToken.TypeId},
|
---|
| 123 | {"name", dataToken.Name},
|
---|
[1570] | 124 | {"id", dataToken.Id}},
|
---|
| 125 | ((XmlString)dataToken.SerialData).Data);
|
---|
[1454] | 126 | }
|
---|
| 127 |
|
---|
[1566] | 128 | protected override string Format(ReferenceToken refToken) {
|
---|
[1612] | 129 | return CreateNode(XmlStringConstants.REFERENCE,
|
---|
[1570] | 130 | new Dictionary<string, object> {
|
---|
| 131 | {"ref", refToken.Id},
|
---|
| 132 | {"name", refToken.Name}});
|
---|
[1454] | 133 | }
|
---|
| 134 |
|
---|
[1566] | 135 | protected override string Format(NullReferenceToken nullRefToken) {
|
---|
[1612] | 136 | return CreateNode(XmlStringConstants.NULL,
|
---|
[1570] | 137 | new Dictionary<string, object>{
|
---|
| 138 | {"name", nullRefToken.Name}});
|
---|
[1454] | 139 | }
|
---|
| 140 |
|
---|
[1553] | 141 | protected override string Format(MetaInfoBeginToken metaInfoBeginToken) {
|
---|
[1612] | 142 | return CreateNodeStart(XmlStringConstants.METAINFO);
|
---|
[1553] | 143 | }
|
---|
| 144 |
|
---|
| 145 | protected override string Format(MetaInfoEndToken metaInfoEndToken) {
|
---|
[1612] | 146 | return CreateNodeEnd(XmlStringConstants.METAINFO);
|
---|
[1553] | 147 | }
|
---|
| 148 |
|
---|
[1454] | 149 | public IEnumerable<string> Format(List<TypeMapping> typeCache) {
|
---|
[1612] | 150 | yield return CreateNodeStart(XmlStringConstants.TYPECACHE);
|
---|
[1454] | 151 | foreach (var mapping in typeCache)
|
---|
[1570] | 152 | yield return CreateNode(
|
---|
[1612] | 153 | XmlStringConstants.TYPE,
|
---|
[1570] | 154 | mapping.GetDict());
|
---|
[1612] | 155 | yield return CreateNodeEnd(XmlStringConstants.TYPECACHE);
|
---|
[1454] | 156 | }
|
---|
| 157 |
|
---|
[1566] | 158 | public static void Serialize(object o, string filename) {
|
---|
[1564] | 159 | Serialize(o, filename, ConfigurationService.Instance.GetDefaultConfig(new XmlFormat()));
|
---|
[1454] | 160 | }
|
---|
| 161 |
|
---|
[1466] | 162 | public static void Serialize(object obj, string filename, Configuration config) {
|
---|
[1625] | 163 | try {
|
---|
| 164 | Serializer serializer = new Serializer(obj, config);
|
---|
| 165 | XmlGenerator generator = new XmlGenerator();
|
---|
| 166 | ZipOutputStream zipStream = new ZipOutputStream(File.Create(filename));
|
---|
| 167 | zipStream.SetLevel(9);
|
---|
| 168 | zipStream.PutNextEntry(new ZipEntry("data.xml"));
|
---|
| 169 | StreamWriter writer = new StreamWriter(zipStream);
|
---|
| 170 | ILog logger = Logger.GetDefaultLogger();
|
---|
| 171 | foreach (ISerializationToken token in serializer) {
|
---|
| 172 | string line = generator.Format(token);
|
---|
| 173 | writer.Write(line);
|
---|
| 174 | logger.Debug(line.TrimEnd());
|
---|
| 175 | }
|
---|
| 176 | writer.Flush();
|
---|
| 177 | zipStream.PutNextEntry(new ZipEntry("typecache.xml"));
|
---|
| 178 | writer = new StreamWriter(zipStream);
|
---|
| 179 | foreach (string line in generator.Format(serializer.TypeCache)) {
|
---|
| 180 | writer.Write(line);
|
---|
| 181 | logger.Debug(line.TrimEnd());
|
---|
| 182 | }
|
---|
| 183 | writer.Flush();
|
---|
| 184 | zipStream.Close();
|
---|
| 185 | } catch (PersistenceException e) {
|
---|
| 186 | throw;
|
---|
| 187 | } catch (Exception e) {
|
---|
| 188 | throw new PersistenceException("Unexpected exception during Serialization.", e);
|
---|
[1476] | 189 | }
|
---|
[1454] | 190 | }
|
---|
| 191 | }
|
---|
| 192 | } |
---|