#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);
}
}
}