#region Disclaimer / License // Copyright (C) 2010, Jackie Ng // http://trac.osgeo.org/mapguide/wiki/maestro, jumpinjackie@gmail.com // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License, or (at your option) any later version. // // This library 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 // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA // #endregion using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Text; using System.Xml; using System.Xml.Serialization; using OSGeo.MapGuide.MaestroAPI.Exceptions; using OSGeo.MapGuide.MaestroAPI.Resource; using OSGeo.MapGuide.ObjectModels.ApplicationDefinition; using OSGeo.MapGuide.ObjectModels.Common; using OSGeo.MapGuide.ObjectModels.DrawingSource; using OSGeo.MapGuide.ObjectModels.FeatureSource; using OSGeo.MapGuide.ObjectModels.LayerDefinition; using OSGeo.MapGuide.ObjectModels.LoadProcedure; using OSGeo.MapGuide.ObjectModels.MapDefinition; using OSGeo.MapGuide.ObjectModels.PrintLayout; using OSGeo.MapGuide.ObjectModels.SymbolDefinition; using OSGeo.MapGuide.ObjectModels.SymbolLibrary; using OSGeo.MapGuide.ObjectModels.WebLayout; using OSGeo.MapGuide.ObjectModels; namespace OSGeo.MapGuide.MaestroAPI { /// /// /// public delegate IResource ResourceDeserializationCallback(string xml); /// /// /// public delegate Stream ResourceSerializationCallback(IResource res); /// /// A resource serializer /// public class ResourceSerializer { /// /// Gets or sets the serialize method. /// /// The serialize method. public ResourceSerializationCallback Serialize { get; set; } /// /// Gets or sets the deserialize method. /// /// The deserialize method. public ResourceDeserializationCallback Deserialize { get; set; } } //TODO: Expand on documentation as this is an important class /// /// A registry of serializers allowing automatic serialization/deserialization of any XML /// content based on its version and resource type. /// public static class ResourceTypeRegistry { private static Dictionary _serializers; static ResourceTypeRegistry() { _serializers = new Dictionary(); //ApplicationDefinition 1.0.0 _serializers.Add( ResourceTypeDescriptor.ApplicationDefinition, new ResourceSerializer() { Serialize = (res) => { return res.SerializeToStream(); }, Deserialize = (xml) => { return OSGeo.MapGuide.ObjectModels.ApplicationDefinition_1_0_0.ApplicationDefinitionType.Deserialize(xml); } }); //DrawingSource 1.0.0 _serializers.Add( ResourceTypeDescriptor.DrawingSource, new ResourceSerializer() { Serialize = (res) => { return res.SerializeToStream(); }, Deserialize = (xml) => { return OSGeo.MapGuide.ObjectModels.DrawingSource_1_0_0.DrawingSource.Deserialize(xml); } }); //FeatureSource 1.0.0 _serializers.Add( ResourceTypeDescriptor.FeatureSource, new ResourceSerializer() { Serialize = (res) => { return res.SerializeToStream(); }, Deserialize = (xml) => { return OSGeo.MapGuide.ObjectModels.FeatureSource_1_0_0.FeatureSourceType.Deserialize(xml); } }); //LayerDefinition 1.0.0 _serializers.Add( ResourceTypeDescriptor.LayerDefinition, new ResourceSerializer() { Serialize = (res) => { return res.SerializeToStream(); }, Deserialize = (xml) => { return OSGeo.MapGuide.ObjectModels.LayerDefinition_1_0_0.LayerDefinition.Deserialize(xml); } }); //LoadProcedure 1.0.0 _serializers.Add( ResourceTypeDescriptor.LoadProcedure, new ResourceSerializer() { Serialize = (res) => { return res.SerializeToStream(); }, Deserialize = (xml) => { return OSGeo.MapGuide.ObjectModels.LoadProcedure_1_0_0.LoadProcedure.Deserialize(xml); } }); //MapDefinition 1.0.0 _serializers.Add( ResourceTypeDescriptor.MapDefinition, new ResourceSerializer() { Serialize = (res) => { return OSGeo.MapGuide.ObjectModels.MapDefinition_1_0_0.MdfEntryPoint.Serialize(res); }, Deserialize = (xml) => { return OSGeo.MapGuide.ObjectModels.MapDefinition_1_0_0.MdfEntryPoint.Deserialize(xml); } }); //PrintLayout 1.0.0 _serializers.Add( ResourceTypeDescriptor.PrintLayout, new ResourceSerializer() { Serialize = (res) => { return res.SerializeToStream(); }, Deserialize = (xml) => { return OSGeo.MapGuide.ObjectModels.PrintLayout_1_0_0.PrintLayout.Deserialize(xml); } }); //SymbolDefinition 1.0.0 _serializers.Add( ResourceTypeDescriptor.SymbolDefinition, new ResourceSerializer() { Serialize = (res) => { return res.SerializeToStream(); }, Deserialize = (xml) => { //HACK: We have to peek at the XML to determine if this is simple or compound. var doc = new XmlDocument(); doc.LoadXml(xml); if (doc.DocumentElement.Name == "SimpleSymbolDefinition") { return OSGeo.MapGuide.ObjectModels.SymbolDefinition_1_0_0.SimpleSymbolDefinition.Deserialize(xml); } else { if (doc.DocumentElement.Name == "CompoundSymbolDefinition") return OSGeo.MapGuide.ObjectModels.SymbolDefinition_1_0_0.CompoundSymbolDefinition.Deserialize(xml); else //WTF? throw new SerializationException("Could not determine symbol type"); //LOCALIZE } } }); //SymbolLibrary 1.0.0 _serializers.Add( ResourceTypeDescriptor.SymbolLibrary, new ResourceSerializer() { Serialize = (res) => { return res.SerializeToStream(); }, Deserialize = (xml) => { return OSGeo.MapGuide.ObjectModels.SymbolLibrary_1_0_0.SymbolLibraryType.Deserialize(xml); } }); //WebLayout 1.0.0 _serializers.Add( ResourceTypeDescriptor.WebLayout, new ResourceSerializer() { Serialize = (res) => { return res.SerializeToStream(); }, Deserialize = (xml) => { return OSGeo.MapGuide.ObjectModels.WebLayout_1_0_0.WebLayoutType.Deserialize(xml); } }); } /// /// Registers a resource serializer /// /// The desc. /// The serializer. public static void RegisterResource(ResourceTypeDescriptor desc, ResourceSerializer serializer) { if (_serializers.ContainsKey(desc)) throw new ArgumentException(string.Format(Properties.Resources.ERR_SERIALIZER_ALREADY_REGISTERED, desc.ResourceType, desc.Version), "desc"); _serializers.Add(desc, serializer); } /// /// Registers a resource serializer /// /// The desc. /// The serialize method. /// The deserialize method. public static void RegisterResource(ResourceTypeDescriptor desc, ResourceSerializationCallback serializeMethod, ResourceDeserializationCallback deserializeMethod) { RegisterResource(desc, new ResourceSerializer() { Deserialize = deserializeMethod, Serialize = serializeMethod }); } internal static void Init() { //does nothing, it's just for kicking the static constructor into gear } /// /// Deserializes the specified stream for the specified resource type. /// /// Type of the resource. /// The stream. /// public static IResource Deserialize(ResourceTypes resourceType, Stream stream) { //UGLY: We have to peek inside the stream to determine the version number //House the stream inside a rewindable memory stream using (var ms = new MemoryStream()) { Utility.CopyStream(stream, ms); ms.Position = 0L; //Rewind var rd = ResourceContentVersionChecker.GetVersionFromXmlStream(ms); Debug.Assert(rd.ResourceType.Equals(resourceType.ToString())); ms.Position = 0L; //Rewind using (var reader = new StreamReader(ms)) { var xml = reader.ReadToEnd(); if (_serializers.ContainsKey(rd)) return _serializers[rd].Deserialize(xml); else return new UntypedResource(xml, resourceType, rd.Version); } } } /// /// Serializes the specified resource. /// /// The resource. /// public static Stream Serialize(IResource res) { var rd = res.GetResourceTypeDescriptor(); if (!_serializers.ContainsKey(rd)) { var utr = res as UntypedResource; if (utr == null) throw new SerializationException(Properties.Resources.ERR_NO_SERIALIZER + rd.ToString()); return utr.SerializeToStream(); } return _serializers[rd].Serialize(res); } /// /// Serializes the specified resource. /// /// /// public static string SerializeAsString(IResource res) { using (var stream = Serialize(res)) { using (var sr = new StreamReader(stream)) { return sr.ReadToEnd(); } } } /// /// Deserializes the specified XML. /// /// The XML. /// public static IResource Deserialize(string xml) { var checker = new ResourceContentVersionChecker(xml); var rd = checker.GetVersion(); if (rd == null) throw new SerializationException(Properties.Resources.ERR_NOT_RESOURCE_CONTENT_XML); if (!_serializers.ContainsKey(rd)) { var rtype = (ResourceTypes)Enum.Parse(typeof(ResourceTypes), rd.ResourceType); return new UntypedResource(xml, rtype, rd.Version); //throw new SerializationException(Properties.Resources.ERR_NO_SERIALIZER + rd.ToString()); } return _serializers[rd].Deserialize(xml); } } }