#region License Information /* HeuristicLab * Copyright (C) 2002-2008 Heuristic and Evolutionary Algorithms Laboratory (HEAL) * * This file is part of HeuristicLab. * * HeuristicLab is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * HeuristicLab is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with HeuristicLab. If not, see . */ #endregion using System; using System.Collections.Generic; using System.Text; using System.Xml; using System.IO; using System.IO.Compression; using HeuristicLab.PluginInfrastructure; namespace HeuristicLab.Core { public static class PersistenceManager { public static XmlDocument CreateXmlDocument() { XmlDocument document = new XmlDocument(); document.AppendChild(document.CreateXmlDeclaration("1.0", null, null)); return document; } public static XmlNode Persist(IStorable instance, XmlDocument document, IDictionary persistedObjects) { string name = instance.GetType().Name; name = name.Replace('`', '_'); return Persist(name, instance, document, persistedObjects); } public static XmlNode Persist(string name, IStorable instance, XmlDocument document, IDictionary persistedObjects) { if(persistedObjects.ContainsKey(instance.Guid)) { XmlNode node = document.CreateNode(XmlNodeType.Element, name, null); XmlAttribute guidAttribute = document.CreateAttribute("GUID"); guidAttribute.Value = instance.Guid.ToString(); node.Attributes.Append(guidAttribute); return node; } else { persistedObjects.Add(instance.Guid, instance); XmlNode node = instance.GetXmlNode(name, document, persistedObjects); return node; } } public static IStorable Restore(XmlNode node, IDictionary restoredObjects) { Guid guid = new Guid(node.Attributes["GUID"].Value); if(restoredObjects.ContainsKey(guid)) { return restoredObjects[guid]; } else { Type type = Type.GetType(node.Attributes["Type"].Value, true); IStorable instance = (IStorable)Activator.CreateInstance(type); restoredObjects.Add(guid, instance); instance.Populate(node, restoredObjects); return instance; } } public static void Save(IStorable instance, string filename) { using(FileStream stream = File.Create(filename)) { Save(instance, stream); stream.Close(); } } public static void Save(IStorable instance, Stream stream) { XmlDocument document = PersistenceManager.CreateXmlDocument(); Dictionary dictionary = new Dictionary(); XmlNode rootNode = document.CreateElement("Root"); document.AppendChild(rootNode); XmlNode necessaryPluginsNode = document.CreateElement("NecessaryPlugins"); rootNode.AppendChild(necessaryPluginsNode); rootNode.AppendChild(Persist(instance, document, dictionary)); // determine the list of necessary plugins for this document DiscoveryService service = new DiscoveryService(); List plugins = new List(); foreach(IStorable storeable in dictionary.Values) { PluginInfo pluginInfo = service.GetDeclaringPlugin(storeable.GetType()); if(!plugins.Contains(pluginInfo)) plugins.Add(pluginInfo); } foreach(PluginInfo uniquePlugin in plugins) { XmlNode necessaryPluginNode = document.CreateElement("Plugin"); XmlAttribute nameAttr = document.CreateAttribute("Name"); nameAttr.Value = uniquePlugin.Name; XmlAttribute versionAttr = document.CreateAttribute("Version"); versionAttr.Value = uniquePlugin.Version.ToString(); necessaryPluginNode.Attributes.Append(nameAttr); necessaryPluginNode.Attributes.Append(versionAttr); necessaryPluginsNode.AppendChild(necessaryPluginNode); } document.Save(stream); } public static IStorable Load(string filename) { using(FileStream stream = File.OpenRead(filename)) { IStorable storable = Load(stream); stream.Close(); return storable; } } public static IStorable Load(Stream stream) { XmlDocument doc = new XmlDocument(); doc.Load(stream); XmlNode rootNode = doc.ChildNodes[1]; if(rootNode.Name == "Root" && rootNode.ChildNodes.Count == 2) { // load documents that have a list of necessary plugins at the top return PersistenceManager.Restore(rootNode.ChildNodes[1], new Dictionary()); } else { // compatibility to load documents without list of necessary plugins return PersistenceManager.Restore(rootNode, new Dictionary()); } } public static IStorable RestoreFromGZip(byte[] serializedStorable) { GZipStream stream = new GZipStream(new MemoryStream(serializedStorable), CompressionMode.Decompress); return Load(stream); } public static byte[] SaveToGZip(IStorable storable) { MemoryStream memStream = new MemoryStream(); GZipStream stream = new GZipStream(memStream, CompressionMode.Compress, true); Save(storable, stream); stream.Close(); return memStream.ToArray(); } public static string BuildTypeString(Type type) { string assembly = type.Assembly.FullName; assembly = assembly.Substring(0, assembly.IndexOf(", ")); StringBuilder builder = new StringBuilder(); builder.Append(type.Namespace); builder.Append("."); builder.Append(type.Name); Type[] args = type.GetGenericArguments(); if(args.Length > 0) { builder.Append("[["); builder.Append(BuildTypeString(args[0])); builder.Append("]"); for(int i = 1; i < args.Length; i++) { builder.Append(",["); builder.Append(BuildTypeString(args[i])); builder.Append("]"); } builder.Append("]"); } builder.Append(", "); builder.Append(assembly); return builder.ToString(); } } }