#region Disclaimer / License
// Copyright (C) 2009, Kenneth Skovhede
// http://www.hexad.dk, opensource@hexad.dk
//
// 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;
using System.Collections.Generic;
using System.Xml;
using System.Text;
using System.IO;
using ObjCommon = OSGeo.MapGuide.ObjectModels.Common;
using OSGeo.MapGuide.ObjectModels.Capabilities;
using OSGeo.MapGuide.MaestroAPI.Resource;
using OSGeo.MapGuide.MaestroAPI.Commands;
using OSGeo.MapGuide.MaestroAPI.Mapping;
using OSGeo.MapGuide.MaestroAPI.Serialization;
using OSGeo.MapGuide.MaestroAPI.CoordinateSystem;
using OSGeo.MapGuide.ObjectModels.MapDefinition;
using OSGeo.MapGuide.ObjectModels.Common;
using System.Collections.Specialized;
using OSGeo.MapGuide.MaestroAPI.Schema;
using OSGeo.MapGuide.MaestroAPI.Feature;
namespace OSGeo.MapGuide.MaestroAPI
{
///
/// Base class of all connection classes. Covers functionality encompassed by
/// the MapGuide Geospatial Platform API (ie. Feature Service and Resource Service)
///
public abstract class PlatformConnectionBase
{
///
/// A list of cached serializers
///
protected Hashtable m_serializers;
///
/// The current XML validator
///
protected XMLValidator m_validator;
///
/// The path of Xsd schemas
///
protected string m_schemasPath;
///
/// A lookup table for Xsd Schemas
///
protected Hashtable m_cachedSchemas;
///
/// A flag indicating if Xsd validation is perfomed
///
protected bool m_disableValidation = false;
///
/// Initializes a new instance of the class.
///
protected PlatformConnectionBase()
{
ResourceTypeRegistry.Init();
m_serializers = new Hashtable();
m_validator = new XMLValidator();
m_cachedSchemas = new Hashtable();
m_schemasPath = System.IO.Path.Combine(System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location), "Schemas");
}
#region Serialization plumbing
///
/// Deserializes an object from a stream.
///
/// The expected object type
/// The stream containing the object
/// The deserialized object
virtual public T DeserializeObject(System.IO.Stream data)
{
return (T)DeserializeObject(typeof(T), data);
}
///
/// Deserializes an object from a stream.
///
/// The expected object type
/// The stream containing the object
/// The deserialized object
virtual public object DeserializeObject(Type type, System.IO.Stream data)
{
//HACK: MGOS 2.2 outputs different capabilities xml (because it's actually the correct one!), so
//without breaking support against 2.1 and older servers, we transform the xml to its pre-2.2 form
if (type == typeof(FdoProviderCapabilities) && this.SiteVersion < new Version(2, 2))
{
StringBuilder sb = null;
using (StreamReader reader = new StreamReader(data))
{
sb = new StringBuilder(reader.ReadToEnd());
}
//Pre-2.2 the elements were suffixed with Collection, change the suffix to List
sb.Replace("", "");
sb.Replace("", "");
sb.Replace("", "");
sb.Replace("", "");
sb.Replace("", "");
sb.Replace("", "");
byte[] bytes = Encoding.UTF8.GetBytes(sb.ToString());
//Replace the original input stream
data = new MemoryStream(bytes);
}
//Must copy stream, because we will be reading it twice :(
//Once for validation, and once for deserialization
System.IO.MemoryStream ms = new System.IO.MemoryStream();
Utility.CopyStream(data, ms);
ms.Position = 0;
#if DEBUG_LASTMESSAGE
//Save us a copy for later investigation
using (System.IO.FileStream fs = System.IO.File.Open("lastResponse.xml", System.IO.FileMode.Create, System.IO.FileAccess.ReadWrite, System.IO.FileShare.None))
Utility.CopyStream(ms, fs);
ms.Position = 0;
#endif
//TODO: Find out why the "xs:include" doesn't work with validator
//Validation is quite important, as we otherwise may end up injecting malicious code
// if (!m_disableValidation)
// {
// m_validator.Validate(ms, GetSchema(type));
// ms.Position = 0;
// }
try
{
return GetSerializer(type).Deserialize(ms);
}
catch (Exception ex)
{
string s = ex.Message;
throw;
}
}
///
/// Serialize an object into a new memory stream.
///
/// The object to serialize
/// A memorystream with the serialized object
virtual public System.IO.MemoryStream SerializeObject(object o)
{
System.IO.MemoryStream ms = new System.IO.MemoryStream();
GetSerializer(o.GetType()).Serialize(new Utf8XmlWriter(ms), o);
return Utility.RemoveUTF8BOM(ms);
}
///
/// Serializes an object into a stream
///
/// The object to serialize
/// The stream to serialize into
virtual public void SerializeObject(object o, System.IO.Stream stream)
{
//The Utf8 writer makes sure the Utf8 tag is in place + sets encoding to Utf8
//This is needed because the server fails when rendering maps using non utf8 xml documents
//And the XmlSerializer sytem in .Net does not have a method to set the encoding attribute
//This does not remove the utf8 BOM marker :(
//GetSerializer(o.GetType()).Serialize(new Utf8XmlWriter(stream), o);
SerializeObject(o).WriteTo(stream);
}
///
/// Returns an XmlSerializer for the given type
///
/// The object type to serialize
/// An XmlSerializer for the given type
virtual protected System.Xml.Serialization.XmlSerializer GetSerializer(Type type)
{
if (m_serializers[type] == null)
m_serializers[type] = new System.Xml.Serialization.XmlSerializer(type);
return (System.Xml.Serialization.XmlSerializer)m_serializers[type];
}
#endregion
#region Validation
///
/// Gets or sets a flag that indicates if the Xml resources are validated before leaving and entering the server.
///
public bool DisableValidation
{
get { return m_disableValidation; }
set { m_disableValidation = value; }
}
///
/// Validates the current server version against the highest tested version.
///
/// The version to validate
virtual protected void ValidateVersion(ObjCommon.SiteVersion version)
{
ValidateVersion(new Version(version.Version));
}
///
/// Validates the current server version against the highest tested version.
///
/// The version to validate
virtual protected void ValidateVersion(Version version)
{
if (version > this.MaxTestedVersion)
throw new Exception("Untested with MapGuide Build > " + this.MaxTestedVersion.ToString());
}
#endregion
///
/// Gets the name of the provider of this implementation
///
public abstract string ProviderName { get; }
///
/// Gets a collection of name-value parameters required to create another copy
/// of this connection via the
///
///
public abstract NameValueCollection CloneParameters { get; }
///
/// Gets the current SessionID.
///
abstract public string SessionID { get; }
///
/// Gets the interface of this connection
///
///
protected abstract IServerConnection GetInterface();
///
/// Removes the version numbers from a providername
///
/// The name of the provider, with or without version numbers
/// The provider name without version numbers
virtual public string RemoveVersionFromProviderName(string providername)
{
return Utility.StripVersionFromProviderName(providername);
}
///
/// Gets the Xsd schema for a given type.
///
/// The type to get the schema for
/// The schema for the given type
virtual protected System.Xml.Schema.XmlSchema GetSchema(Type type)
{
if (m_cachedSchemas[type] == null)
{
System.Reflection.FieldInfo fi = type.GetField("SchemaName", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public );
if (fi == null)
throw new Exception("Type " + type + ", does not contain Schema Info");
string xsd = (string)fi.GetValue(null);
using (System.IO.FileStream fs = System.IO.File.Open(System.IO.Path.Combine(m_schemasPath, xsd), System.IO.FileMode.Open, System.IO.FileAccess.Read, System.IO.FileShare.Read))
m_cachedSchemas.Add(type, System.Xml.Schema.XmlSchema.Read(fs, null));
}
return (System.Xml.Schema.XmlSchema)m_cachedSchemas[type];
}
///
/// Raised when a resource is added
///
public event ResourceEventHandler ResourceAdded;
///
/// Raised when a resource is deleted. Note if a folder is deleted, this will
/// only be raised for the folder and not its children. Also note that this is
/// raised on any move operations as the original source is for all intents and
/// purposes, deleted.
///
public event ResourceEventHandler ResourceDeleted;
///
/// Raised when a resource is updated
///
public event ResourceEventHandler ResourceUpdated;
///
/// Raises the event
///
///
protected void OnResourceAdded(string resId)
{
var handler = this.ResourceAdded;
if (handler != null)
handler(this, new ResourceEventArgs(resId));
}
///
/// Raises the event
///
///
protected void OnResourceDeleted(string resId)
{
var handler = this.ResourceDeleted;
if (handler != null)
handler(this, new ResourceEventArgs(resId));
}
///
/// Raises the event
///
///
protected void OnResourceUpdated(string resId)
{
var handler = this.ResourceUpdated;
if (handler != null)
handler(this, new ResourceEventArgs(resId));
}
///
/// Gets or sets the collection of cached schemas. Use the object type for key, and an XmlSchema instance for value.
///
virtual public Hashtable CachedSchemas
{
get { return m_cachedSchemas; }
set { m_cachedSchemas = value; }
}
///
/// Releases unmanaged and - optionally - managed resources
///
abstract public void Dispose();
///
/// Clones this instance.
///
///
public abstract IServerConnection Clone();
///
/// Raised when a outbound request has been dispatched
///
public event RequestEventHandler RequestDispatched;
///
/// Called when [request dispatched].
///
/// The data.
protected void OnRequestDispatched(string data)
{
var handler = this.RequestDispatched;
if (handler != null)
handler(this, new RequestEventArgs(data));
}
#region Resource Service
///
/// Returns raw data from the server a byte array
///
/// The full resourceID to get data from
/// Raw data from the given resource
public abstract Stream GetResourceXmlData(string resourceID);
///
/// Returns an object deserialized from server data.
/// Uses the ResourceID to infer the object type.
///
/// The full resourceID of the item to retrieve.
/// A deserialized object.
virtual public IResource GetResource(string resourceID)
{
var stream = GetResourceXmlData(resourceID);
var rt = ResourceIdentifier.GetResourceType(resourceID);
IResource o = ResourceTypeRegistry.Deserialize(rt, stream);
o.CurrentConnection = GetInterface();
o.ResourceID = resourceID;
return o;
}
///
/// Deletes the resource.
///
/// The resourceid.
public abstract void DeleteResource(string resourceid);
///
/// Writes an object into a resourceID
///
/// The resource to write into
/// The resourcec to write
virtual public void WriteResource(string resourceid, object resource)
{
System.IO.MemoryStream ms = SerializeObject(resource);
ms.Position = 0;
//Validate that our data is correctly formated
/*if (!m_disableValidation)
{
m_validator.Validate(ms, GetSchema(resource.GetType()));
ms.Position = 0;
}*/
#if DEBUG_LASTMESSAGE
using (System.IO.Stream s = System.IO.File.Open("lastSave.xml", System.IO.FileMode.Create, System.IO.FileAccess.Write, System.IO.FileShare.None))
Utility.CopyStream(ms, s);
ms.Position = 0;
#endif
SetResourceXmlData(resourceid, ms);
}
///
/// Writes raw data into a resource.
///
/// The resourceID to write into
/// The stream containing the data to write.
public virtual void SetResourceXmlData(string resourceid, System.IO.Stream stream)
{
SetResourceXmlData(resourceid, stream, null);
}
///
/// Gets a full list of resources in the permanent server repository (Library).
/// This method returns the full catalog and should be used sparringly.
///
/// A list of contained resources
virtual public ObjCommon.ResourceList GetRepositoryResources()
{
return GetRepositoryResources("Library://", null, -1, true);
}
///
/// Gets a list of resources in the permanent server repository (Library).
/// This method limits folder recursion to the specified depth.
///
/// The max depth to recurse. Use -1 for no limit.
/// A list of contained resources
virtual public ObjCommon.ResourceList GetRepositoryResources(int depth)
{
return GetRepositoryResources("Library://", null, depth, true);
}
///
/// Gets a list of resources in the permanent server repository (Library).
/// This method limits folder recursion to the specified depth.
///
/// The folder from which to return items. Use null for "Library://"
/// The max depth to recurse. Use -1 for no limit.
/// A list of contained resources
virtual public ObjCommon.ResourceList GetRepositoryResources(string startingpoint, int depth)
{
return GetRepositoryResources(startingpoint, null, depth, true);
}
///
/// Gets a list of resources in the permanent server repository (Library).
/// This method limits folder recursion to the specified depth.
///
/// The folder from which to return items. Use null for "Library://"
/// A list of contained resources
virtual public ObjCommon.ResourceList GetRepositoryResources(string startingpoint)
{
return GetRepositoryResources(startingpoint, null, -1, true);
}
///
/// Gets a list of resources in the permanent server repository (Library).
/// This method limits folder recursion to the specified depth.
///
/// The folder from which to return items. Use null for "Library://"
/// The type of resource to look for. Basically this is the resource extension, like ".MapDefinition". Use null for all resources.
/// A list of contained resources
virtual public ObjCommon.ResourceList GetRepositoryResources(string startingpoint, string type)
{
return GetRepositoryResources(startingpoint, type, -1, true);
}
///
/// Gets a list of resources in the permanent server repository (Library).
/// This method limits folder recursion to the specified depth.
///
/// The folder from which to return items. Use null for "Library://"
/// The type of resource to look for. Basically this is the resource extension, like ".MapDefinition". Use null for all resources.
/// The max depth to recurse. Use -1 for no limit.
/// A list of contained resources
public ObjCommon.ResourceList GetRepositoryResources(string startingpoint, string type, int depth)
{
return GetRepositoryResources(startingpoint, type, depth, true);
}
///
/// Gets a list of resources in the permanent server repository (Library).
///
/// The folder from which to return items. Use null for "Library://"
/// The type of resource to look for. Basically this is the resource extension, like ".MapDefinition". Use null for all resources.
/// The max depth to recurse. Use -1 for no limit.
/// A flag indicating if the count of subfolders and resources should be calculated for leaf nodes
/// A list of contained resources
abstract public ObjCommon.ResourceList GetRepositoryResources(string startingpoint, string type, int depth, bool computeChildren);
///
/// Forces a timestamp update of the specified resource. This is akin to
/// setting the resource's content using its existing content.
///
///
public virtual void Touch(string resourceId)
{
if (!ResourceIdentifier.IsFolderResource(resourceId))
{
SetResourceXmlData(resourceId, GetResourceXmlData(resourceId));
}
}
///
/// Returns a boolean indicating if a given resource exists
///
/// The resource to look for
/// True if the resource exists false otherwise. Also returns false on error.
public virtual bool ResourceExists(string resourceid)
{
try
{
string sourcefolder;
if (resourceid.EndsWith("/"))
sourcefolder = resourceid.Substring(0, resourceid.Substring(0, resourceid.Length - 1).LastIndexOf("/") + 1);
else
sourcefolder = resourceid.Substring(0, resourceid.LastIndexOf("/") + 1);
ObjCommon.ResourceList lst = GetRepositoryResources(sourcefolder, 1);
foreach (object o in lst.Items)
if (o.GetType() == typeof(ObjCommon.ResourceListResourceFolder) && ((ObjCommon.ResourceListResourceFolder)o).ResourceId == resourceid)
return true;
else if (o.GetType() == typeof(ObjCommon.ResourceListResourceDocument) && ((ObjCommon.ResourceListResourceDocument)o).ResourceId == resourceid)
return true;
return false;
}
catch
{
return false;
}
}
///
/// Updates all resource references inside an object.
///
/// The object in which the resource references are to be updated
/// The current resource path, the one updating from
/// The new resource path, the one updating to
/// True if the old and new resource path identifiers are folders, false otherwise
public virtual void UpdateResourceReferences(object o, string oldresourcepath, string newresourcepath, bool folderupdates)
{
UpdateResourceReferences(o, oldresourcepath, newresourcepath, folderupdates, new Hashtable());
}
///
/// Updates all resource references inside an object.
///
/// The object in which the resource references are to be updated
/// The current resource path, the one updating from
/// The new resource path, the one updating to
/// True if the old and new resource path identifiers are folders, false otherwise
/// A hashtable with objects previously visited. Used for recursion, leave as null when calling from outside the API.
protected void UpdateResourceReferences(object o, string oldresourcepath, string newresourcepath, bool folderupdates, Hashtable visited)
{
if (o == null)
return;
if (visited == null)
visited = new Hashtable();
//Prevent infinite recursion
if (o as string == null && !o.GetType().IsPrimitive)
{
if (visited.ContainsKey(o))
return;
else
visited.Add(o, null);
}
if (folderupdates)
{
if (!oldresourcepath.EndsWith("/"))
oldresourcepath += "/";
if (!newresourcepath.EndsWith("/"))
newresourcepath += "/";
}
//If the value is a document or fragment of a document, we still wan't to repoint it
if (o as System.Xml.XmlDocument != null || o as System.Xml.XmlNode != null)
{
Queue lst = new Queue();
if (o as System.Xml.XmlDocument != null)
{
foreach (System.Xml.XmlNode n in (o as System.Xml.XmlDocument).ChildNodes)
if (n.NodeType == System.Xml.XmlNodeType.Element)
lst.Enqueue(n);
}
else
lst.Enqueue(o as System.Xml.XmlNode);
while (lst.Count > 0)
{
System.Xml.XmlNode n = lst.Dequeue();
foreach (System.Xml.XmlNode nx in n.ChildNodes)
if (nx.NodeType == System.Xml.XmlNodeType.Element)
lst.Enqueue(nx);
if (n.Name == "ResourceId")
{
string current = n.InnerXml;
if (folderupdates && current.StartsWith(oldresourcepath))
n.InnerXml = newresourcepath + current.Substring(oldresourcepath.Length);
else if (current == oldresourcepath)
n.InnerXml = newresourcepath;
}
foreach (System.Xml.XmlAttribute a in n.Attributes)
if (a.Name == "ResourceId")
{
string current = a.Value;
if (folderupdates && current.StartsWith(oldresourcepath))
n.Value = newresourcepath + current.Substring(oldresourcepath.Length);
else if (current == oldresourcepath)
n.Value = newresourcepath;
}
}
//There can be no objects in an xml document or node, so just return immediately
return;
}
//Try to find the object properties
foreach (System.Reflection.PropertyInfo pi in o.GetType().GetProperties())
{
//Only index free read-write properties are taken into account
if (!pi.CanRead || !pi.CanWrite || pi.GetIndexParameters().Length != 0 || pi.GetValue(o, null) == null)
continue;
object v = pi.GetValue(o, null);
if (v == null)
continue;
if (v is string)
//If we are at a ResourceId property, update it as needed
if (v is string)
{
bool isResId = pi.Name == "ResourceId";
if (!isResId)
{
//Search for attributes
object[] xmlAttrs = pi.GetCustomAttributes(typeof(System.Xml.Serialization.XmlElementAttribute), false);
if (xmlAttrs != null)
foreach (System.Xml.Serialization.XmlElementAttribute attr in xmlAttrs)
if (attr.Type == typeof(string) && attr.ElementName == "ResourceId")
if (pi.Name == "ResourceId")
{
isResId = true;
break;
}
}
if (isResId)
{
string current = v as string;
if (current != null)
{
if (folderupdates && current.StartsWith(oldresourcepath))
pi.SetValue(o, newresourcepath + current.Substring(oldresourcepath.Length), null);
else if (current == oldresourcepath)
pi.SetValue(o, newresourcepath, null);
}
}
}
else if (v is IEnumerable)
{
//Handle collections
System.Collections.IEnumerable srcList = (System.Collections.IEnumerable)v;
foreach (object ox in srcList)
UpdateResourceReferences(ox, oldresourcepath, newresourcepath, folderupdates, visited);
}
else if (v.GetType().IsArray)
{
//Handle arrays
System.Array sourceArr = (System.Array)v;
for (int i = 0; i < sourceArr.Length; i++)
UpdateResourceReferences(sourceArr.GetValue(i), oldresourcepath, newresourcepath, folderupdates, visited);
}
else if (v.GetType().IsClass)
{
//Handle subobjects
UpdateResourceReferences(v, oldresourcepath, newresourcepath, folderupdates, visited);
}
}
}
///
/// Moves a resource, and subsequently updates all resources pointing to the old resource path
///
/// The current resource path, the one moving from
/// The new resource path, the one moving to
/// A callback delegate, being called for non progress reporting events.
/// A callback delegate, being called for progress reporting events.
///
public virtual bool MoveResourceWithReferences(string oldpath, string newpath, LengthyOperationCallBack callback, LengthyOperationProgressCallBack progress)
{
LengthyOperationProgressArgs la = new LengthyOperationProgressArgs(Properties.Resources.MovingResource, -1);
if (progress != null)
progress(this, la);
if (la.Cancel)
return false;
MoveResource(oldpath, newpath, true);
la.Progress = 100;
if (progress != null)
progress(this, la);
if (la.Cancel)
return false;
la.Progress = -1;
if (progress != null)
progress(this, la);
if (la.Cancel)
return false;
ArrayList items = new ArrayList();
Hashtable paths = new Hashtable();
//The old path does not exist, but luckily the call works anyway
ObjCommon.ResourceReferenceList rlf = EnumerateResourceReferences(oldpath);
foreach (string s in rlf.ResourceId)
if (!paths.ContainsKey(s))
{
items.Add(new LengthyOperationCallbackArgs.LengthyOperationItem(s));
paths.Add(s, null);
}
la.Progress = 100;
if (progress != null)
progress(this, la);
if (la.Cancel)
return false;
LengthyOperationCallbackArgs args = new LengthyOperationCallbackArgs((LengthyOperationCallbackArgs.LengthyOperationItem[])items.ToArray(typeof(LengthyOperationCallbackArgs.LengthyOperationItem)));
if (callback != null)
callback(this, args);
if (args.Cancel)
return false;
if (args.Index > args.Items.Length)
return true;
if (args.Items.Length == 0)
return true;
do
{
LengthyOperationCallbackArgs.LengthyOperationItem item = args.Items[args.Index];
item.Status = LengthyOperationCallbackArgs.LengthyOperationItem.OperationStatus.Pending;
if (callback != null)
{
callback(this, args);
if (args.Cancel) return false;
}
try
{
System.Xml.XmlDocument d = new System.Xml.XmlDocument();
using (var ms = GetResourceXmlData(item.Itempath))
d.Load(ms);
UpdateResourceReferences(d, oldpath, newpath, false);
using (System.IO.MemoryStream ms = new System.IO.MemoryStream())
{
d.Save(ms);
ms.Position = 0;
SetResourceXmlData(item.Itempath, ms);
}
item.Status = LengthyOperationCallbackArgs.LengthyOperationItem.OperationStatus.Success;
}
catch (Exception ex)
{
string s = ex.Message;
item.Status = LengthyOperationCallbackArgs.LengthyOperationItem.OperationStatus.Failure;
}
if (callback != null)
{
callback(this, args);
if (args.Cancel) return false;
}
args.Index++;
} while (!args.Cancel && args.Index < args.Items.Length);
return !args.Cancel;
}
///
/// Moves a folder, and subsequently updates all resources pointing to the old resource path
///
/// The current folder path, the one moving from
/// The new folder path, the one moving to
/// A callback delegate, being called for non progress reporting events.
/// A callback delegate, being called for progress reporting events.
///
public virtual bool MoveFolderWithReferences(string oldpath, string newpath, LengthyOperationCallBack callback, LengthyOperationProgressCallBack progress)
{
oldpath = FixAndValidateFolderPath(oldpath);
newpath = FixAndValidateFolderPath(newpath);
LengthyOperationProgressArgs la = new LengthyOperationProgressArgs("Moving folder...", -1);
if (progress != null)
progress(this, la);
if (la.Cancel)
return false;
MoveFolder(oldpath, newpath, true);
la.Progress = 100;
if (progress != null)
progress(this, la);
if (la.Cancel)
return false;
int pg = 0;
la.Progress = 0;
la.StatusMessage = "Finding folder references...";
if (progress != null)
progress(this, la);
if (la.Cancel)
return false;
ObjCommon.ResourceList lst = GetRepositoryResources(newpath);
Hashtable items = new Hashtable();
foreach (object o in lst.Items)
{
if (o.GetType() == typeof(ObjCommon.ResourceListResourceDocument))
{
//The old path does not exist, but we need to enumerate references at the old location
string resource_oldpath = ((ObjCommon.ResourceListResourceDocument)o).ResourceId;
resource_oldpath = oldpath + resource_oldpath.Substring(newpath.Length);
ObjCommon.ResourceReferenceList rlf = EnumerateResourceReferences(resource_oldpath);
foreach (string s in rlf.ResourceId)
if (!items.Contains(s))
items.Add(s, new LengthyOperationCallbackArgs.LengthyOperationItem(s));
}
pg++;
la.Progress = Math.Max(Math.Min(99, (int)(((double)pg / (double)lst.Items.Count) * (double)100)), 0);
if (progress != null)
progress(this, la);
if (la.Cancel)
return false;
}
la.Progress = 100;
if (progress != null)
progress(this, la);
if (la.Cancel)
return false;
LengthyOperationCallbackArgs.LengthyOperationItem[] vi = new LengthyOperationCallbackArgs.LengthyOperationItem[items.Values.Count];
items.Values.CopyTo(vi, 0);
LengthyOperationCallbackArgs args = new LengthyOperationCallbackArgs(vi);
if (callback != null)
callback(this, args);
if (args.Cancel)
return false;
if (args.Index > args.Items.Length)
return true;
if (args.Items.Length == 0)
return true;
do
{
LengthyOperationCallbackArgs.LengthyOperationItem item = args.Items[args.Index];
item.Status = LengthyOperationCallbackArgs.LengthyOperationItem.OperationStatus.Pending;
if (callback != null)
{
callback(this, args);
if (args.Cancel)
return false;
}
try
{
System.Xml.XmlDocument d = new System.Xml.XmlDocument();
using (var ms = GetResourceXmlData(item.Itempath))
d.Load(ms);
UpdateResourceReferences(d, oldpath, newpath, true);
using (System.IO.MemoryStream ms = new System.IO.MemoryStream())
{
d.Save(ms);
ms.Position = 0;
SetResourceXmlData(item.Itempath, ms);
}
item.Status = LengthyOperationCallbackArgs.LengthyOperationItem.OperationStatus.Success;
}
catch (Exception ex)
{
string s = ex.Message;
item.Status = LengthyOperationCallbackArgs.LengthyOperationItem.OperationStatus.Failure;
}
if (callback != null)
{
callback(this, args);
if (args.Cancel)
return false;
}
args.Index++;
} while (!args.Cancel && args.Index < args.Items.Length);
return !args.Cancel;
}
///
/// Copies folder, and subsequently updates all resources within the folder to use the new folder path instead of the originating one.
///
/// The current folder path, the one copying from
/// The new folder path, the one copying to
/// A callback delegate, being called for non progress reporting events.
/// A callback delegate, being called for progress reporting events.
///
public bool CopyFolderWithReferences(string oldpath, string newpath, LengthyOperationCallBack callback, LengthyOperationProgressCallBack progress)
{
oldpath = FixAndValidateFolderPath(oldpath);
newpath = FixAndValidateFolderPath(newpath);
ObjCommon.ResourceList lst = GetRepositoryResources(oldpath);
LengthyOperationProgressArgs la = new LengthyOperationProgressArgs("Copying folder...", -1);
if (progress != null)
progress(this, la);
if (la.Cancel)
return false;
CopyFolder(oldpath, newpath, true);
la.Progress = 100;
if (progress != null)
progress(this, la);
if (la.Cancel)
return false;
la.Progress = 0;
la.StatusMessage = "Finding folder references...";
int pg = 0;
if (progress != null)
progress(this, la);
if (la.Cancel)
return false;
ArrayList items = new ArrayList();
Hashtable paths = new Hashtable();
foreach (object o in lst.Items)
{
if (o.GetType() == typeof(ObjCommon.ResourceListResourceDocument))
{
ObjCommon.ResourceReferenceList rlf = EnumerateResourceReferences(((ObjCommon.ResourceListResourceDocument)o).ResourceId);
foreach (string s in rlf.ResourceId)
if (s.StartsWith(oldpath))
{
string dest = newpath + s.Substring(oldpath.Length);
if (!paths.ContainsKey(dest))
{
items.Add(new LengthyOperationCallbackArgs.LengthyOperationItem(dest));
paths.Add(dest, null);
}
}
}
pg++;
la.Progress = Math.Max(Math.Min(99, (int)(((double)pg / (double)lst.Items.Count) * (double)100)), 0);
if (progress != null)
progress(this, la);
if (la.Cancel)
return false;
}
la.Progress = 100;
if (progress != null)
progress(this, la);
if (la.Cancel)
return false;
LengthyOperationCallbackArgs args = new LengthyOperationCallbackArgs((LengthyOperationCallbackArgs.LengthyOperationItem[])items.ToArray(typeof(LengthyOperationCallbackArgs.LengthyOperationItem)));
if (callback != null)
callback(this, args);
if (args.Cancel)
return false;
if (args.Index > args.Items.Length)
return true;
if (args.Items.Length == 0)
return true;
do
{
LengthyOperationCallbackArgs.LengthyOperationItem item = args.Items[args.Index];
item.Status = LengthyOperationCallbackArgs.LengthyOperationItem.OperationStatus.Pending;
if (callback != null)
{
callback(this, args);
if (args.Cancel) return false;
}
try
{
System.Xml.XmlDocument d = new System.Xml.XmlDocument();
using (var ms = GetResourceXmlData(item.Itempath))
d.Load(ms);
UpdateResourceReferences(d, oldpath, newpath, true);
using (System.IO.MemoryStream ms = new System.IO.MemoryStream())
{
d.Save(ms);
ms.Position = 0;
SetResourceXmlData(item.Itempath, ms);
}
item.Status = LengthyOperationCallbackArgs.LengthyOperationItem.OperationStatus.Success;
}
catch (Exception ex)
{
string s = ex.Message;
item.Status = LengthyOperationCallbackArgs.LengthyOperationItem.OperationStatus.Failure;
}
if (callback != null)
{
callback(this, args);
if (args.Cancel) return false;
}
args.Index++;
} while (!args.Cancel && args.Index < args.Items.Length);
return !args.Cancel;
}
///
/// Validates the origin of the folder, and ensures the folder path has a trailing slash.
///
/// The path to validate and fix
/// The fixed path
virtual protected string FixAndValidateFolderPath(string folderpath)
{
if (!folderpath.StartsWith("Library://") && !folderpath.StartsWith("Session:" + this.SessionID + "//"))
throw new Exception("Invalid folder path, must be either library or session");
if (!folderpath.EndsWith("/"))
folderpath += "/";
return folderpath;
}
///
/// Creates a folder on the server
///
/// The path of the folder to create
virtual public void CreateFolder(string resourceID)
{
resourceID = FixAndValidateFolderPath(resourceID);
SetResourceXmlData(resourceID, new System.IO.MemoryStream());
}
///
/// Returns a value indicating if a given folder exists
///
/// The path of the folder
/// True if the folder exists, false otherwise. Also returns false on error.
virtual public bool HasFolder(string folderpath)
{
folderpath = FixAndValidateFolderPath(folderpath);
try
{
ObjCommon.ResourceList l = this.GetRepositoryResources(folderpath, 1);
return true;
}
catch
{
return false;
}
}
///
/// Enumereates all references to a given resource
///
/// The resource to enumerate references for
/// A list of resources that reference the given resourceID
abstract public ObjCommon.ResourceReferenceList EnumerateResourceReferences(string resourceid);
///
/// Copies a resource from one location to another. This does not update any references.
///
/// The current resource path, the one copying from
/// The new resource path, the one copying to
/// True if the copy can overwrite an existing resource, false otherwise
abstract public void CopyResource(string oldpath, string newpath, bool overwrite);
///
/// Copies a folder and all its content. This does not update any references.
///
/// The current folder path, the one copying from
/// The new folder path, the one copying to
/// True if the copy can overwrite an existing folder, false otherwise
abstract public void CopyFolder(string oldpath, string newpath, bool overwrite);
///
/// Moves a resource from one location to another. This does not update any references.
///
/// The current resource path, the one moving from
/// The new resource path, the one moving to
/// True if the move can overwrite an existing resource, false otherwise
abstract public void MoveResource(string oldpath, string newpath, bool overwrite);
///
/// Moves a folder and its content from one location to another. This does not update any references.
///
/// The current folder path, the one moving from
/// The new folder path, the one moving to
/// True if the move can overwrite an existing folder, false otherwise
abstract public void MoveFolder(string oldpath, string newpath, bool overwrite);
///
/// Returns data from a resource as a memorystream
///
/// The id of the resource to fetch data from
/// The name of the associated data item
/// A stream containing the references resource data
abstract public System.IO.Stream GetResourceData(string resourceID, string dataname);
///
/// Uploads data to a resource
///
/// The id of the resource to update
/// The name of the data to update or create
/// The type of data
/// A stream containing the new content of the resource data
virtual public void SetResourceData(string resourceid, string dataname, ObjCommon.ResourceDataType datatype, System.IO.Stream stream)
{
SetResourceData(resourceid, dataname, datatype, stream, null);
}
///
/// Uploads data to a resource
///
/// The id of the resource to update
/// The name of the data to update or create
/// The type of data
/// A stream containing the new content of the resource data
/// The callback.
abstract public void SetResourceData(string resourceid, string dataname, ObjCommon.ResourceDataType datatype, System.IO.Stream stream, Utility.StreamCopyProgressDelegate callback);
///
/// Saves the resource.
///
/// The resource.
public void SaveResource(OSGeo.MapGuide.MaestroAPI.Resource.IResource resource)
{
SaveResourceAs(resource, resource.ResourceID);
}
///
/// Saves the resource with the specified resource ID
///
/// The resource.
/// The resourceid.
public void SaveResourceAs(OSGeo.MapGuide.MaestroAPI.Resource.IResource resource, string resourceid)
{
var stream = resource.SerializeToStream();
SetResourceXmlData(resourceid, stream);
}
///
/// Upload a MapGuide Package file to the server
///
/// Name of the file to upload
/// A callback argument used to display progress. May be null.
abstract public void UploadPackage(string filename, Utility.StreamCopyProgressDelegate callback);
///
/// Updates the repository.
///
/// The resource id.
/// The header.
abstract public void UpdateRepository(string resourceId, ObjCommon.ResourceFolderHeaderType header);
///
/// Gets the folder or resource header.
///
/// The resource id.
///
abstract public object GetFolderOrResourceHeader(string resourceId);
///
/// Sets the resource XML data.
///
/// The resource id.
/// The content.
/// The header.
abstract public void SetResourceXmlData(string resourceId, System.IO.Stream content, System.IO.Stream header);
///
/// Gets the resource header.
///
/// The resource ID.
///
public virtual ObjCommon.ResourceDocumentHeaderType GetResourceHeader(string resourceID)
{
return (ObjCommon.ResourceDocumentHeaderType)this.GetFolderOrResourceHeader(resourceID);
}
///
/// Gets the folder header.
///
/// The resource ID.
///
public virtual ObjCommon.ResourceFolderHeaderType GetFolderHeader(string resourceID)
{
if (resourceID.EndsWith("//"))
{
ObjCommon.ResourceList lst = this.GetRepositoryResources(resourceID, 0);
ObjCommon.ResourceListResourceFolder fld = lst.Items[0] as ObjCommon.ResourceListResourceFolder;
return fld.ResourceFolderHeader;
}
else
return (ObjCommon.ResourceFolderHeaderType)this.GetFolderOrResourceHeader(resourceID);
}
///
/// Sets the folder header.
///
/// The resource ID.
/// The header.
public virtual void SetFolderHeader(string resourceID, ObjCommon.ResourceFolderHeaderType header)
{
SetFolderOrResourceHeader(resourceID, header);
}
///
/// Sets the resource header.
///
/// The resource ID.
/// The header.
public virtual void SetResourceHeader(string resourceID, ObjCommon.ResourceDocumentHeaderType header)
{
SetFolderOrResourceHeader(resourceID, header);
}
///
/// Sets the folder or resource header.
///
/// The resource ID.
/// The header.
public virtual void SetFolderOrResourceHeader(string resourceID, object header)
{
if (header == null)
throw new ArgumentNullException("header");
ObjCommon.ResourceSecurityType sec;
if (header as ObjCommon.ResourceFolderHeaderType != null)
sec = (header as ObjCommon.ResourceFolderHeaderType).Security;
else if (header as ObjCommon.ResourceDocumentHeaderType != null)
sec = (header as ObjCommon.ResourceDocumentHeaderType).Security;
else
throw new ArgumentException("Header must be either ResourceFolderHeaderType or ResourceDocumentHeaderType", "header");
if (sec.Users != null && sec.Users.User != null && sec.Users.User.Count == 0)
sec.Users = null;
if (sec.Groups != null && sec.Groups.Group != null && sec.Groups.Group.Count == 0)
sec.Groups = null;
if (resourceID.EndsWith("//"))
{
if (header as ObjCommon.ResourceFolderHeaderType == null)
throw new Exception("The resourceId: " + resourceID + " must be updated with a folder header");
UpdateRepository(resourceID, header as ObjCommon.ResourceFolderHeaderType);
}
else
this.SetResourceXmlData(resourceID, null, this.SerializeObject(header));
}
///
/// Enumerates all unmanaged folders, meaning alias'ed folders
///
/// The type of data to return
/// A filter applied to the items
/// True if the list should contains recursive results
/// The path to retrieve the data from
/// A list of unmanaged data
abstract public ObjCommon.UnmanagedDataList EnumerateUnmanagedData(string startpath, string filter, bool recursive, UnmanagedDataTypes type);
#endregion
#region Feature Service
///
/// Returns an installed provider, given the name of the provider
///
/// The name of the provider
/// The first matching provider or null
virtual public ObjCommon.FeatureProviderRegistryFeatureProvider GetFeatureProvider(string providername)
{
string pname = RemoveVersionFromProviderName(providername).ToLower();
foreach (ObjCommon.FeatureProviderRegistryFeatureProvider p in this.FeatureProviders)
if (RemoveVersionFromProviderName(p.Name).ToLower().Equals(pname.ToLower()))
return p;
return null;
}
///
/// Tests the connection.
///
/// The featuresource.
///
public abstract string TestConnection(string featuresource);
///
/// Gets a list of installed feature providers
///
abstract public ObjCommon.FeatureProviderRegistryFeatureProvider[] FeatureProviders { get; }
///
/// Returns the spatial info for a given featuresource
///
/// The ID of the resource to query
/// Query only active items
/// A list of spatial contexts
abstract public ObjCommon.FdoSpatialContextList GetSpatialContextInfo(string resourceID, bool activeOnly);
///
/// Gets the names of the identity properties from a feature
///
/// The resourceID for the FeatureSource
/// The classname of the feature, including schema
/// A string array with the found identities
abstract public string[] GetIdentityProperties(string resourceID, string classname);
///
/// Describes the feature source.
///
/// The resource ID.
///
abstract public FeatureSourceDescription DescribeFeatureSource(string resourceID);
///
/// Describes the feature source.
///
/// The resource ID.
/// The schema.
///
abstract public FeatureSchema DescribeFeatureSource(string resourceID, string schema);
///
/// feature source description cache
///
protected Dictionary m_featureSchemaCache = new Dictionary();
///
/// a class definition cache
///
protected Dictionary m_featureSchemaNameCache = new Dictionary();
///
/// Gets the feature source description.
///
/// The resource ID.
///
public virtual FeatureSourceDescription GetFeatureSourceDescription(string resourceID)
{
if (!m_featureSchemaCache.ContainsKey(resourceID))
{
try
{
m_featureSchemaCache[resourceID] = this.DescribeFeatureSource(resourceID);
foreach (ClassDefinition scm in m_featureSchemaCache[resourceID].AllClasses)
m_featureSchemaNameCache[resourceID + "!" + scm.QualifiedName] = scm;
}
catch
{
m_featureSchemaCache[resourceID] = null;
}
}
return m_featureSchemaCache[resourceID];
}
///
/// Gets the class definition.
///
/// The resource ID.
/// The schema.
///
public virtual ClassDefinition GetClassDefinition(string resourceID, string schema)
{
/*if (schema != null && schema.IndexOf(":") > 0)
schema = schema.Substring(0, schema.IndexOf(":"));*/
//If it is missing, just get the entire schema, and hope that we will need the others
//Some providers actually return the entire list even when asked for a particular schema
if (!m_featureSchemaCache.ContainsKey(resourceID + "!" + schema))
GetFeatureSourceDescription(resourceID);
if (!m_featureSchemaNameCache.ContainsKey(resourceID + "!" + schema))
m_featureSchemaNameCache[resourceID + "!" + schema] = null;
return m_featureSchemaNameCache[resourceID + "!" + schema];
}
///
/// Resets the feature source schema cache.
///
public virtual void ResetFeatureSourceSchemaCache()
{
m_featureSchemaCache = new Dictionary();
m_featureSchemaNameCache = new Dictionary();
}
///
/// Performs an aggregate query on all columns in the datasource
///
/// The resourceID of the FeatureSource to query
/// The schema name
/// The filter to apply to the
/// A FeatureSetReader with the aggregated values
public virtual IReader AggregateQueryFeatureSource(string resourceID, string schema, string filter)
{
return AggregateQueryFeatureSource(resourceID, schema, filter, (string[])null);
}
///
/// Performs an aggregate query on columns in the datasource
///
/// The resourceID of the FeatureSource to query
/// The schema name
/// The filter to apply to the
/// The columns to aggregate
/// A IFeatureReader with the aggregated values
public abstract IReader AggregateQueryFeatureSource(string resourceID, string schema, string filter, string[] columns);
///
/// Performs an aggregate query on computed resources
///
/// The resourceID of the FeatureSource to query
/// The schema name
/// The filter to apply to the
/// A collection of column name and aggregate functions
/// A FeatureSetReader with the aggregated values
public abstract IReader AggregateQueryFeatureSource(string resourceID, string schema, string filter, System.Collections.Specialized.NameValueCollection aggregateFunctions);
///
/// Gets the spatial extent.
///
/// The resource ID.
/// The schema.
/// The geometry.
///
public virtual OSGeo.MapGuide.ObjectModels.Common.IEnvelope GetSpatialExtent(string resourceID, string schema, string geometry)
{
return GetSpatialExtent(resourceID, schema, geometry, null, false);
}
///
/// Gets the spatial extent.
///
/// The resource ID.
/// The schema.
/// The geometry.
/// The filter.
///
public virtual OSGeo.MapGuide.ObjectModels.Common.IEnvelope GetSpatialExtent(string resourceID, string schema, string geometry, string filter)
{
return GetSpatialExtent(resourceID, schema, geometry, filter, false);
}
///
/// Gets the spatial extent.
///
/// The resource ID.
/// The schema.
/// The geometry.
/// if set to true [allow fallback to context information].
///
public virtual OSGeo.MapGuide.ObjectModels.Common.IEnvelope GetSpatialExtent(string resourceID, string schema, string geometry, bool allowFallbackToContextInformation)
{
return GetSpatialExtent(resourceID, schema, geometry, null, allowFallbackToContextInformation);
}
///
/// Gets the spatial extent.
///
/// The resource ID.
/// The schema.
/// The geometry.
/// The filter.
/// if set to true [allow fallback to context information].
///
protected virtual OSGeo.MapGuide.ObjectModels.Common.IEnvelope GetSpatialExtent(string resourceID, string schema, string geometry, string filter, bool allowFallbackToContextInformation)
{
Check.NotEmpty(schema, "schema");
Check.NotEmpty(geometry, "geometry");
try
{
System.Collections.Specialized.NameValueCollection fun = new System.Collections.Specialized.NameValueCollection();
fun.Add("extent", "SpatialExtents(\"" + geometry + "\")");
using (IReader fsr = AggregateQueryFeatureSource(resourceID, schema, filter, fun))
{
if (fsr.ReadNext())
{
Topology.Geometries.IGeometry geom = fsr["extent"] as Topology.Geometries.IGeometry;
if (geom == null)
{
throw new Exception("No data found in resource: " + resourceID);
}
else
{
var env = geom.EnvelopeInternal;
return OSGeo.MapGuide.ObjectModels.ObjectFactory.CreateEnvelope(
env.MinX,
env.MinY,
env.MaxX,
env.MaxY);
}
}
else
throw new Exception("No data found in resource: " + resourceID);
}
}
catch
{
if (allowFallbackToContextInformation)
try
{
ObjCommon.FdoSpatialContextList lst = this.GetSpatialContextInfo(resourceID, false);
if (lst.SpatialContext != null && lst.SpatialContext.Count >= 1)
{
return OSGeo.MapGuide.ObjectModels.ObjectFactory.CreateEnvelope(
double.Parse(lst.SpatialContext[0].Extent.LowerLeftCoordinate.X, System.Globalization.NumberStyles.Float, System.Globalization.CultureInfo.InvariantCulture),
double.Parse(lst.SpatialContext[0].Extent.UpperRightCoordinate.X, System.Globalization.NumberStyles.Float, System.Globalization.CultureInfo.InvariantCulture),
double.Parse(lst.SpatialContext[0].Extent.LowerLeftCoordinate.Y, System.Globalization.NumberStyles.Float, System.Globalization.CultureInfo.InvariantCulture),
double.Parse(lst.SpatialContext[0].Extent.UpperRightCoordinate.Y, System.Globalization.NumberStyles.Float, System.Globalization.CultureInfo.InvariantCulture)
);
}
}
catch
{
}
throw;
}
}
///
/// Enumerates the data stores.
///
/// Name of the provider.
/// The partial conn string.
///
public abstract OSGeo.MapGuide.ObjectModels.Common.DataStoreList EnumerateDataStores(string providerName, string partialConnString);
///
/// Gets the schemas.
///
/// The resource id.
///
public abstract string[] GetSchemas(string resourceId);
///
/// Gets the class names.
///
/// The resource id.
/// Name of the schema.
///
public abstract string[] GetClassNames(string resourceId, string schemaName);
#endregion
#region Feature/Capability Discovery
///
/// Gets the highest version the API is currently tested againts
///
virtual public Version MaxTestedVersion
{
get { return SiteVersions.GetVersion(KnownSiteVersions.MapGuideOS2_1); }
}
///
/// Gets the site version.
///
/// The site version.
abstract public Version SiteVersion { get; }
///
/// Gets the custom property names.
///
///
public abstract string[] GetCustomPropertyNames();
///
/// Gets the type of the custom property.
///
/// The name.
///
public abstract Type GetCustomPropertyType(string name);
///
/// Sets the custom property.
///
/// The name.
/// The value.
public abstract void SetCustomProperty(string name, object value);
///
/// Gets the custom property.
///
/// The name.
///
public abstract object GetCustomProperty(string name);
///
/// Creates the command.
///
/// Type of the CMD.
///
public virtual ICommand CreateCommand(int cmdType)
{
CommandType ct = (CommandType)cmdType;
switch (ct)
{
default:
return null;
}
}
#endregion
#region runtime map
///
/// Infers the meters per unit value from the specified coordinate system
///
///
///
///
protected virtual double InferMPU(string csWkt, double units)
{
var cs = CoordinateSystemBase.Create(csWkt);
return cs.MetersPerUnitX * units;
}
///
/// Creates a new runtime map instance from an existing map definition. Meters per unit
/// is calculated from the Coordinate System WKT of the map definition.
///
///
/// Calculation of meters-per-unit may differ between implementations. This may have an adverse
/// effect on things such as rendering and measuring depending on the underlying implementation
///
/// If you are certain of the meters-per-unit value required, use the overloaded method that
/// accepts a metersPerUnit parameter.
///
///
///
///
public RuntimeMap CreateMap(string runtimeMapResourceId, string baseMapDefinitionId)
{
var mdf = (IMapDefinition)GetResource(baseMapDefinitionId);
var mpu = InferMPU(mdf.CoordinateSystem, 1.0);
return CreateMap(runtimeMapResourceId, mdf, mpu);
}
///
/// Creates a new runtime map instance from an existing map definition
///
///
///
///
///
public virtual RuntimeMap CreateMap(string runtimeMapResourceId, string baseMapDefinitionId, double metersPerUnit)
{
var mdf = (IMapDefinition)GetResource(baseMapDefinitionId);
return CreateMap(runtimeMapResourceId, mdf, metersPerUnit);
}
///
/// Creates a new runtime map instance from an existing map definition. Meters per unit
/// is calculated from the Coordinate System WKT of the map definition.
///
///
/// Calculation of meters-per-unit may differ between implementations. This may have an adverse
/// effect on things such as rendering and measuring depending on the underlying implementation
///
/// If you are certain of the meters-per-unit value required, use the overloaded method that
/// accepts a metersPerUnit parameter.
///
///
///
///
public RuntimeMap CreateMap(string runtimeMapResourceId, IMapDefinition mdf)
{
var mpu = InferMPU(mdf.CoordinateSystem, 1.0);
return CreateMap(runtimeMapResourceId, mdf, mpu);
}
///
/// Creates a new runtime map instance from an existing map definition
///
///
///
///
///
public virtual RuntimeMap CreateMap(string runtimeMapResourceId, IMapDefinition mdf, double metersPerUnit)
{
var map = new RuntimeMap(mdf, metersPerUnit);
map.ResourceID = runtimeMapResourceId;
return map;
}
///
/// Opens the specified runtime map
///
///
///
public virtual RuntimeMap OpenMap(string runtimeMapResourceId)
{
if (!runtimeMapResourceId.StartsWith("Session:" + this.SessionID + "//") || !runtimeMapResourceId.EndsWith(".Map"))
throw new ArgumentException("Runtime maps must be in the current session repository");
var map = new RuntimeMap(GetInterface());
map.Deserialize(new MgBinaryDeserializer(this.GetResourceData(runtimeMapResourceId, "RuntimeData"), this.SiteVersion));
if (this.SiteVersion >= SiteVersions.GetVersion(KnownSiteVersions.MapGuideOS1_2))
map.DeserializeLayerData(new MgBinaryDeserializer(this.GetResourceData(runtimeMapResourceId, "LayerGroupData"), this.SiteVersion));
return map;
}
#endregion
}
}