[mapguide-commits] r6122 - in trunk/Tools/Maestro: Maestro.Base/Properties Maestro.Base/UI Maestro.Shared.UI OSGeo.MapGuide.MaestroAPI OSGeo.MapGuide.MaestroAPI/CrossConnection OSGeo.MapGuide.MaestroAPI/Properties OSGeo.MapGuide.MaestroAPI/Resource/Conversion

svn_mapguide at osgeo.org svn_mapguide at osgeo.org
Tue Sep 6 12:08:40 EDT 2011


Author: jng
Date: 2011-09-06 09:08:40 -0700 (Tue, 06 Sep 2011)
New Revision: 6122

Added:
   trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI/CrossConnection/ResourceRebaser.cs
Modified:
   trunk/Tools/Maestro/Maestro.Base/Properties/Resources.Designer.cs
   trunk/Tools/Maestro/Maestro.Base/Properties/Resources.resx
   trunk/Tools/Maestro/Maestro.Base/UI/SiteExplorer.cs
   trunk/Tools/Maestro/Maestro.Shared.UI/ProgressDialog.cs
   trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI/CrossConnection/ResourceMigrator.cs
   trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI/OSGeo.MapGuide.MaestroAPI.csproj
   trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI/Properties/Resources.Designer.cs
   trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI/Properties/Resources.resx
   trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI/Resource/Conversion/IResourceConverter.cs
Log:
#1800: Add support for drag/drop of resources between different connections. To support preservation of folder structures, a new API was added to the ResourceMigrator class with a new ResourceRebaser class to help update internal resource id references for resources as they are copied across

Modified: trunk/Tools/Maestro/Maestro.Base/Properties/Resources.Designer.cs
===================================================================
--- trunk/Tools/Maestro/Maestro.Base/Properties/Resources.Designer.cs	2011-09-06 08:25:08 UTC (rev 6121)
+++ trunk/Tools/Maestro/Maestro.Base/Properties/Resources.Designer.cs	2011-09-06 16:08:40 UTC (rev 6122)
@@ -1588,6 +1588,15 @@
         }
         
         /// <summary>
+        ///   Looks up a localized string similar to There are {0} already existing resources that have the same name. Do you want to overwrite these resources?.
+        /// </summary>
+        internal static string PromptOverwriteOnTargetConnection {
+            get {
+                return ResourceManager.GetString("PromptOverwriteOnTargetConnection", resourceCulture);
+            }
+        }
+        
+        /// <summary>
         ///   Looks up a localized string similar to Rename to.
         /// </summary>
         internal static string RenameTo {

Modified: trunk/Tools/Maestro/Maestro.Base/Properties/Resources.resx
===================================================================
--- trunk/Tools/Maestro/Maestro.Base/Properties/Resources.resx	2011-09-06 08:25:08 UTC (rev 6121)
+++ trunk/Tools/Maestro/Maestro.Base/Properties/Resources.resx	2011-09-06 16:08:40 UTC (rev 6122)
@@ -1067,4 +1067,7 @@
   <data name="DwfHandlerAction" xml:space="preserve">
     <value>Create a Drawing Source</value>
   </data>
+  <data name="PromptOverwriteOnTargetConnection" xml:space="preserve">
+    <value>There are {0} already existing resources that have the same name. Do you want to overwrite these resources?</value>
+  </data>
 </root>
\ No newline at end of file

Modified: trunk/Tools/Maestro/Maestro.Base/UI/SiteExplorer.cs
===================================================================
--- trunk/Tools/Maestro/Maestro.Base/UI/SiteExplorer.cs	2011-09-06 08:25:08 UTC (rev 6121)
+++ trunk/Tools/Maestro/Maestro.Base/UI/SiteExplorer.cs	2011-09-06 16:08:40 UTC (rev 6122)
@@ -36,6 +36,7 @@
 using Maestro.Base.Commands;
 using System.Linq;
 using Maestro.Editors;
+using OSGeo.MapGuide.MaestroAPI.CrossConnection;
 
 namespace Maestro.Base.UI
 {
@@ -376,7 +377,7 @@
 
         private void trvResources_DragDrop(object sender, DragEventArgs e)
         {
-            var data = e.Data.GetData(typeof(RepositoryItem[])) as RepositoryItem[];
+            var data = e.Data.GetData(typeof(RepositoryHandle[])) as RepositoryHandle[];
             if (data == null)
             {
                 //See if the mouse is currently over a node
@@ -397,17 +398,20 @@
                     string connectionName = RepositoryTreeModel.GetParentConnectionName(item);
                     string folderId = item.ResourceId;
 
-                    //I think it's nice to ask for confirmation
-                    if (data.Length > 0)
-                    {
-                        if (!MessageService.AskQuestion(Properties.Resources.ConfirmMove))
-                            return;
-                    }
+                    if (data.Length < 0)
+                        return;
 
-                    if (data.First().ConnectionName == connectionName)
+                    if (data.First().Connection.DisplayName == connectionName)
                     {
-                        string[] folders = MoveResourcesWithinConnection(connectionName, data.Select(x => x.ResourceId).ToArray(), folderId);
+                        //I think it's nice to ask for confirmation
+                        if (data.Length > 0)
+                        {
+                            if (!MessageService.AskQuestion(Properties.Resources.ConfirmMove))
+                                return;
+                        }
 
+                        string[] folders = MoveResourcesWithinConnection(connectionName, data.Select(x => x.ResourceId.ToString()).ToArray(), folderId);
+
                         foreach (var fid in folders)
                         {
                             LoggingService.Info("Refreshing: " + fid + " on " + connectionName); //LOCALIZEME
@@ -416,17 +420,135 @@
                     }
                     else
                     {
-                        //TODO: Revisit later
-                        MessageService.ShowError("Moving resources between connections is currently not implemented");
-                        return;
+                        string rootSourceParent = GetCommonParent(data);
+
+                        //There is an implicit assumption here that all items dropped come from the same connection
+                        var sourceConn = data.First().Connection;
+                        var targetConn = _connManager.GetConnection(connectionName);
+                        var migrator = new ResourceMigrator(sourceConn, targetConn);
+
+                        //Collect all source ids
+                        var sourceIds = new List<string>();
+                        foreach (var resId in data.Select(x => x.ResourceId.ToString()))
+                        {
+                            if (ResourceIdentifier.IsFolderResource(resId))
+                                sourceIds.AddRange(GetFullResourceList(sourceConn, resId));
+                            else
+                                sourceIds.Add(resId);
+                        
+                        }
+
+                        /*
+                        //If we're dropping to the root, the common parent becomes our 
+                        //target root
+                        if (folderId == "Library://")
+                            folderId = rootSourceParent;
+                        */
+                        //If common parent is not root, we want the name of the folder to append
+                        //to our target
+                        if (rootSourceParent != "Library://")
+                        {
+                            ResourceIdentifier resId = new ResourceIdentifier(rootSourceParent);
+                            folderId = folderId + resId.Name + "/";
+                        }
+
+                        var targets = new List<string>();
+                        foreach (var resId in sourceIds)
+                        {
+                            var dstId = resId.Replace(rootSourceParent, folderId);
+                            System.Diagnostics.Trace.TraceInformation("{0} => {1}", resId, dstId);
+                            targets.Add(dstId);
+                        }
+
+                        bool overwrite = true;
+                        var existing = new List<string>();
+                        foreach (var resId in targets)
+                        {
+                            if (targetConn.ResourceService.ResourceExists(resId))
+                            {
+                                existing.Add(resId);
+                            }
+                        }
+                        if (existing.Count > 0)
+                            overwrite = MessageService.AskQuestion(string.Format(Properties.Resources.PromptOverwriteOnTargetConnection, existing.Count));
+
+                        var wb = Workbench.Instance;
+                        var dlg = new ProgressDialog();
+                        var worker = new ProgressDialog.DoBackgroundWork((w, evt, args) =>
+                        {
+                            LengthyOperationProgressCallBack cb = (s, cbe) =>
+                            {
+                                w.ReportProgress(cbe.Progress, cbe.StatusMessage);
+                            };
+
+                            return migrator.CopyResources(sourceIds.ToArray(), targets.ToArray(), overwrite, new RebaseOptions(rootSourceParent, folderId), cb);
+                        });
+
+                        dlg.RunOperationAsync(wb, worker);
+                        RefreshModel(targetConn.DisplayName, folderId);
+                        ExpandNode(targetConn.DisplayName, folderId);
                     }
                 }
             }
         }
 
+        private string GetCommonParent(RepositoryHandle[] data)
+        {
+            if (data.Length > 0)
+            {
+                if (data.Length == 1)
+                {
+                    if (data[0].ResourceId.IsFolder)
+                        return data[0].ResourceId.ToString();
+                    else
+                        return data[0].ResourceId.ParentFolder;
+                }
+                else
+                {
+                    int matches = 0;
+                    string[] parts = data.First().ResourceId.ToString()
+                                         .Substring("Library://".Length)
+                                         .Split('/');
+                    string test = "Library://";
+                    string parent = test;
+                    int partIndex = 0;
+                    //Use first one as a sample to see how far we can go. Keep going until we have
+                    //a parent that doesn't match all of them. The one we recorded before then will
+                    //be the common parent
+                    while (matches == data.Length)
+                    {
+                        parent = test;
+                        partIndex++;
+                        if (partIndex < parts.Length) //Shouldn't happen, but just in case
+                            break;
+
+                        test = test + parts[partIndex];
+                        matches = data.Where(x => x.ResourceId.ResourceId.StartsWith(test)).Count(); 
+                    }
+                    return parent;
+                }
+            }
+            else
+            {
+                return "Library://";
+            }
+        }
+
+        private static IEnumerable<string> GetFullResourceList(IServerConnection sourceConn, string resId)
+        {
+            var list = sourceConn.ResourceService.GetRepositoryResources(resId, -1);
+            foreach (var res in list.Children)
+            {
+                if (res.IsFolder)
+                    continue;
+
+                yield return res.ResourceId;
+            }
+        }
+
         private void trvResources_DragOver(object sender, DragEventArgs e)
         {
-            var data = e.Data.GetData(typeof(RepositoryItem[])) as RepositoryItem[];
+            var data = e.Data.GetData(typeof(RepositoryHandle[])) as RepositoryHandle[];
             if (data == null)
             {
                 SiteExplorerDragDropHandler.OnDragEnter(this, e);

Modified: trunk/Tools/Maestro/Maestro.Shared.UI/ProgressDialog.cs
===================================================================
--- trunk/Tools/Maestro/Maestro.Shared.UI/ProgressDialog.cs	2011-09-06 08:25:08 UTC (rev 6121)
+++ trunk/Tools/Maestro/Maestro.Shared.UI/ProgressDialog.cs	2011-09-06 16:08:40 UTC (rev 6122)
@@ -128,7 +128,9 @@
             }
             else if (e.Error != null)
             {
-                throw e.Error;
+                ErrorDialog.Show(e.Error);
+                this.DialogResult = DialogResult.Abort;
+                this.Close();
             }
             else
             {

Modified: trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI/CrossConnection/ResourceMigrator.cs
===================================================================
--- trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI/CrossConnection/ResourceMigrator.cs	2011-09-06 08:25:08 UTC (rev 6121)
+++ trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI/CrossConnection/ResourceMigrator.cs	2011-09-06 16:08:40 UTC (rev 6122)
@@ -21,6 +21,8 @@
 using System.Collections.Generic;
 using System.Text;
 using OSGeo.MapGuide.MaestroAPI.Resource;
+using OSGeo.MapGuide.MaestroAPI.Resource.Conversion;
+using System.IO;
 
 namespace OSGeo.MapGuide.MaestroAPI.CrossConnection
 {
@@ -33,6 +35,8 @@
         private IServerConnection _source;
         private IServerConnection _target;
 
+        private IResourceConverter _converter;
+
         /// <summary>
         /// Initializes a new instance of the <see cref="ResourceMigrator"/> class.
         /// </summary>
@@ -44,9 +48,106 @@
             Check.NotNull(target, "target");
             _source = source;
             _target = target;
+            _converter = new ResourceObjectConverter();
         }
 
         /// <summary>
+        /// Copies resource from the source connection to another connection. 
+        /// </summary>
+        /// <param name="sourceResourceIds">The array of source resource ids</param>
+        /// <param name="targetResourceIds">The array of target resource ids to copy to. Each resource id in the source array will be copied to the corresponding resource id in the target array</param>
+        /// <param name="overwrite">Indicates whether to overwrite </param>
+        /// <param name="options">Re-base options</param>
+        /// <param name="callback"></param>
+        /// <returns></returns>
+        public int CopyResources(string[] sourceResourceIds, string[] targetResourceIds, bool overwrite, RebaseOptions options, LengthyOperationProgressCallBack callback)
+        {
+            Check.NotNull(sourceResourceIds, "sourceResourceIds");
+            Check.NotNull(targetResourceIds, "targetResourceIds");
+            Check.Precondition(sourceResourceIds.Length == targetResourceIds.Length, "resourceIds.Length == targetResourceIds.Length");
+
+            var cb = callback;
+            if (cb == null)
+            {
+                cb = new LengthyOperationProgressCallBack((s, e) =>
+                {
+                    //Do nothing
+                });
+            }
+
+            var targetCaps = _target.Capabilities;
+
+            int copied = 0;
+            int unit = 100 / sourceResourceIds.Length;
+            int progress = 0;
+
+            string message = "";
+            for (int i = 0; i < sourceResourceIds.Length; i++)
+            {
+                var srcResId = sourceResourceIds[i];
+                var dstResId = targetResourceIds[i];
+                
+                //Get the source resource object
+                IResource res = _source.ResourceService.GetResource(srcResId);
+
+                //Skip if target exists and overwrite is not specified
+                if (!overwrite && _target.ResourceService.ResourceExists(dstResId))
+                {
+                    progress += unit;
+                    continue;
+                }
+                else
+                {
+                    //Check if downgrading is required
+                    var maxVer = targetCaps.GetMaxSupportedResourceVersion(res.ResourceType);
+                    if (res.ResourceVersion > maxVer)
+                    {
+                        res = _converter.Convert(res, maxVer);
+                        cb(this, new LengthyOperationProgressArgs(string.Format(Properties.Resources.DowngradedResource, srcResId, maxVer), progress));
+                    }
+
+                    //Now rebase if rebase options supplied
+                    if (options != null)
+                    {
+                        var rebaser = new ResourceRebaser(res);
+                        res = rebaser.Rebase(options.SourceFolder, options.TargetFolder);
+                    }
+
+                    //Save resource
+                    _target.ResourceService.SaveResourceAs(res, dstResId);
+                    //Copy resource data
+                    foreach (var data in res.EnumerateResourceData())
+                    {
+                        using (var stream = res.GetResourceData(data.Name))
+                        {
+                            if (!stream.CanSeek)
+                            {
+                                using (var ms = new MemoryStream())
+                                {
+                                    Utility.CopyStream(stream, ms, false);
+                                    ms.Position = 0L;
+                                    _target.ResourceService.SetResourceData(dstResId, data.Name, data.Type, ms);
+                                }
+                            }
+                            else
+                            {
+                                stream.Position = 0L;
+                                _target.ResourceService.SetResourceData(dstResId, data.Name, data.Type, stream);
+                            }
+                        }
+                    }
+
+                    copied++;
+                    message = string.Format(Properties.Resources.CopiedResourceToTarget, srcResId, dstResId);
+                }
+                progress += unit;
+                cb(this, new LengthyOperationProgressArgs(message, progress));
+            }
+
+            return copied;
+        }
+
+        /// <summary>
         /// Copies resources from the source connection to another connection. The resources in question will
         /// be copied to the specified folder. Folder structure of the source is discarded
         /// </summary>
@@ -69,6 +170,8 @@
                 });
             }
 
+            var targetCaps = _target.Capabilities;
+
             int copied = 0;
             int unit = 100 / resourceIds.Length;
             int progress = 0;
@@ -81,10 +184,19 @@
                 //Skip if target exists and overwrite is not specified
                 if (!overwrite && _target.ResourceService.ResourceExists(targetId))
                 {
+                    progress += unit;
                     continue;
                 }
                 else
                 {
+                    //Check if downgrading is required
+                    var maxVer = targetCaps.GetMaxSupportedResourceVersion(res.ResourceType);
+                    if (res.ResourceVersion > maxVer)
+                    {
+                        res = _converter.Convert(res, maxVer);
+                        cb(this, new LengthyOperationProgressArgs(string.Format(Properties.Resources.DowngradedResource, resId, maxVer), progress));
+                    }
+
                     //Save resource
                     _target.ResourceService.SaveResourceAs(res, targetId);
                     //Copy resource data
@@ -92,8 +204,20 @@
                     {
                         using (var stream = res.GetResourceData(data.Name))
                         {
-                            stream.Position = 0L;
-                            _target.ResourceService.SetResourceData(targetId, data.Name, data.Type, stream);
+                            if (!stream.CanSeek)
+                            {
+                                using (var ms = new MemoryStream())
+                                {
+                                    Utility.CopyStream(stream, ms, false);
+                                    ms.Position = 0L;
+                                    _target.ResourceService.SetResourceData(targetId, data.Name, data.Type, ms);
+                                }
+                            }
+                            else
+                            {
+                                stream.Position = 0L;
+                                _target.ResourceService.SetResourceData(targetId, data.Name, data.Type, stream);
+                            }
                         }
                     }
 
@@ -128,6 +252,8 @@
                 });
             }
 
+            var targetCaps = _target.Capabilities;
+
             int moved = 0;
             int unit = 100 / resourceIds.Length;
             int progress = 0;
@@ -140,10 +266,19 @@
                 //Skip if target exists and overwrite is not specified
                 if (!overwrite && _target.ResourceService.ResourceExists(targetId))
                 {
+                    progress += unit;
                     continue;
                 }
                 else
                 {
+                    //Check if downgrading is required
+                    var maxVer = targetCaps.GetMaxSupportedResourceVersion(res.ResourceType);
+                    if (res.ResourceVersion > maxVer)
+                    {
+                        res = _converter.Convert(res, maxVer);
+                        cb(this, new LengthyOperationProgressArgs(string.Format(Properties.Resources.DowngradedResource, resId, maxVer), progress));
+                    }
+
                     //Save resource
                     _target.ResourceService.SaveResourceAs(res, targetId);
                     //Copy resource data
@@ -151,8 +286,20 @@
                     {
                         using (var stream = res.GetResourceData(data.Name))
                         {
-                            stream.Position = 0L;
-                            _target.ResourceService.SetResourceData(targetId, data.Name, data.Type, stream);
+                            if (!stream.CanSeek)
+                            {
+                                using (var ms = new MemoryStream())
+                                {
+                                    Utility.CopyStream(stream, ms, false);
+                                    ms.Position = 0L;
+                                    _target.ResourceService.SetResourceData(targetId, data.Name, data.Type, ms);
+                                }
+                            }
+                            else
+                            {
+                                stream.Position = 0L;
+                                _target.ResourceService.SetResourceData(targetId, data.Name, data.Type, stream);
+                            }
                         }
                     }
 
@@ -194,6 +341,7 @@
                 cb = new LengthyOperationProgressCallBack((o, a) => { });
             }
 
+            var targetCaps = _target.Capabilities;
             int total = dependentResourceIds.Length + 1;
             int unit = 100 / total;
             int progress = 0;
@@ -202,6 +350,14 @@
             {
                 //Copy the specified resource
                 IResource res = _source.ResourceService.GetResource(resourceId);
+
+                //Check if downgrading is required
+                var maxVer = targetCaps.GetMaxSupportedResourceVersion(res.ResourceType);
+                if (res.ResourceVersion > maxVer)
+                {
+                    res = _converter.Convert(res, maxVer);
+                    cb(this, new LengthyOperationProgressArgs(string.Format(Properties.Resources.DowngradedResource, resourceId, maxVer), progress));
+                }
                 _target.ResourceService.SaveResource(res);
 
                 //Copy its resource data
@@ -209,8 +365,20 @@
                 {
                     using (var stream = res.GetResourceData(data.Name))
                     {
-                        stream.Position = 0L;
-                        _target.ResourceService.SetResourceData(resourceId, data.Name, data.Type, stream);
+                        if (!stream.CanSeek)
+                        {
+                            using (var ms = new MemoryStream())
+                            {
+                                Utility.CopyStream(stream, ms, false);
+                                ms.Position = 0L;
+                                _target.ResourceService.SetResourceData(resourceId, data.Name, data.Type, ms);
+                            }
+                        }
+                        else
+                        {
+                            stream.Position = 0L;
+                            _target.ResourceService.SetResourceData(resourceId, data.Name, data.Type, stream);
+                        }
                     }
                 }
 
@@ -243,8 +411,20 @@
                             {
                                 using (var stream = res.GetResourceData(data.Name))
                                 {
-                                    stream.Position = 0L;
-                                    _target.ResourceService.SetResourceData(resId, data.Name, data.Type, stream);
+                                    if (!stream.CanSeek)
+                                    {
+                                        using (var ms = new MemoryStream())
+                                        {
+                                            Utility.CopyStream(stream, ms, false);
+                                            ms.Position = 0L;
+                                            _target.ResourceService.SetResourceData(resId, data.Name, data.Type, ms);
+                                        }
+                                    }
+                                    else
+                                    {
+                                        stream.Position = 0L;
+                                        _target.ResourceService.SetResourceData(resId, data.Name, data.Type, stream);
+                                    }
                                 }
                             }
 

Added: trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI/CrossConnection/ResourceRebaser.cs
===================================================================
--- trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI/CrossConnection/ResourceRebaser.cs	                        (rev 0)
+++ trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI/CrossConnection/ResourceRebaser.cs	2011-09-06 16:08:40 UTC (rev 6122)
@@ -0,0 +1,107 @@
+#region Disclaimer / License
+// Copyright (C) 2011, Jackie Ng
+// http://trac.osgeo.org/mapguide/wiki/maestro, jumpinjackie at 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.Text;
+using OSGeo.MapGuide.MaestroAPI.Resource;
+using System.Xml;
+using System.IO;
+
+namespace OSGeo.MapGuide.MaestroAPI.CrossConnection
+{
+    /// <summary>
+    /// Resource re-basing options
+    /// </summary>
+    public class RebaseOptions
+    {
+        public RebaseOptions(string sourceFolder, string targetFolder)
+        {
+            Check.Precondition(ResourceIdentifier.IsFolderResource(sourceFolder), "ResourceIdentifier.IsFolderResource(sourceFolder)");
+            Check.Precondition(ResourceIdentifier.IsFolderResource(targetFolder), "ResourceIdentifier.IsFolderResource(targetFolder)");
+
+            this.SourceFolder = sourceFolder;
+            this.TargetFolder = targetFolder;
+        }
+
+        /// <summary>
+        /// The source folder to look for in resource ids
+        /// </summary>
+        public string SourceFolder
+        {
+            get;
+            private set;
+        }
+
+        /// <summary>
+        /// The target folder to replace with
+        /// </summary>
+        public string TargetFolder
+        {
+            get;
+            private set;
+        }
+    }
+
+    /// <summary>
+    /// A helper class to re-base referenced resource ids in a resource document
+    /// </summary>
+    public class ResourceRebaser
+    {
+        private IResource _res;
+
+        public ResourceRebaser(IResource res)
+        {
+            _res = res;
+        }
+
+        /// <summary>
+        /// Re-bases any resource id references in the resource document
+        /// </summary>
+        /// <param name="sourceRoot"></param>
+        /// <param name="targetRoot"></param>
+        /// <returns>A re-based copy of the original resource</returns>
+        public IResource Rebase(string sourceRoot, string targetRoot)
+        {
+            if (sourceRoot == targetRoot)
+                return _res;
+
+            var xml = ResourceTypeRegistry.SerializeAsString(_res);
+            var doc = new XmlDocument();
+            doc.LoadXml(xml);
+
+            var elements = doc.GetElementsByTagName("ResourceId");
+            foreach (XmlNode el in elements)
+            {
+                el.InnerText = el.InnerText.Replace(sourceRoot, targetRoot);
+            }
+
+            using (var ms = new MemoryStream())
+            {
+                doc.Save(ms);
+                ms.Position = 0L;
+                var modifiedRes = ResourceTypeRegistry.Deserialize(_res.ResourceType, ms);
+                modifiedRes.CurrentConnection = _res.CurrentConnection;
+                modifiedRes.ResourceID = _res.ResourceID;
+
+                return modifiedRes;
+            }
+        }
+    }
+}

Modified: trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI/OSGeo.MapGuide.MaestroAPI.csproj
===================================================================
--- trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI/OSGeo.MapGuide.MaestroAPI.csproj	2011-09-06 08:25:08 UTC (rev 6121)
+++ trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI/OSGeo.MapGuide.MaestroAPI.csproj	2011-09-06 16:08:40 UTC (rev 6122)
@@ -191,6 +191,7 @@
     <Compile Include="CoordinateSystem\MeterBasedCoordinateSystem.cs" />
     <Compile Include="CoordinateSystem\NsDoc.cs" />
     <Compile Include="CrossConnection\NsDoc.cs" />
+    <Compile Include="CrossConnection\ResourceRebaser.cs" />
     <Compile Include="Exceptions\CustomPropertyNotFoundException.cs" />
     <Compile Include="Exceptions\ExpressionException.cs" />
     <Compile Include="Exceptions\MaestroException.cs" />

Modified: trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI/Properties/Resources.Designer.cs
===================================================================
--- trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI/Properties/Resources.Designer.cs	2011-09-06 08:25:08 UTC (rev 6121)
+++ trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI/Properties/Resources.Designer.cs	2011-09-06 16:08:40 UTC (rev 6122)
@@ -278,6 +278,24 @@
         }
         
         /// <summary>
+        ///   Looks up a localized string similar to Copied: {0} =&gt; {1}.
+        /// </summary>
+        internal static string CopiedResourceToTarget {
+            get {
+                return ResourceManager.GetString("CopiedResourceToTarget", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Resource {0} downgraded to version {1}.
+        /// </summary>
+        internal static string DowngradedResource {
+            get {
+                return ResourceManager.GetString("DowngradedResource", resourceCulture);
+            }
+        }
+        
+        /// <summary>
         ///   Looks up a localized string similar to No coordinate system specified. The coordinate system if not specified will default to LL84.
         /// </summary>
         internal static string DS_NoCoordinateSpace {

Modified: trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI/Properties/Resources.resx
===================================================================
--- trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI/Properties/Resources.resx	2011-09-06 08:25:08 UTC (rev 6121)
+++ trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI/Properties/Resources.resx	2011-09-06 16:08:40 UTC (rev 6122)
@@ -530,4 +530,10 @@
   <data name="MDF_NoCoordinateSystem" xml:space="preserve">
     <value>Map Definition has no coordinate system</value>
   </data>
+  <data name="CopiedResourceToTarget" xml:space="preserve">
+    <value>Copied: {0} =&gt; {1}</value>
+  </data>
+  <data name="DowngradedResource" xml:space="preserve">
+    <value>Resource {0} downgraded to version {1}</value>
+  </data>
 </root>
\ No newline at end of file

Modified: trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI/Resource/Conversion/IResourceConverter.cs
===================================================================
--- trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI/Resource/Conversion/IResourceConverter.cs	2011-09-06 08:25:08 UTC (rev 6121)
+++ trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI/Resource/Conversion/IResourceConverter.cs	2011-09-06 16:08:40 UTC (rev 6122)
@@ -42,6 +42,11 @@
     {
         public IResource Convert(IResource resource, Version targetVersion)
         {
+            //How does this work? If source and target versions are known, it means the classes
+            //that represent them are also known and we just serialize from the source type to xml
+            //and deserialize that xml to the target type, with any unsupported bits falling by the
+            //wayside in the process, and any new bits flubbed with default values as part of deserialization
+
             var resVer = resource.GetResourceTypeDescriptor().Version;
             var dstVer = string.Format("{0}.{1}.{2}", targetVersion.Major, targetVersion.Minor, targetVersion.Build);
             var dstXsd = resource.ValidatingSchema.Replace(resVer, dstVer);
@@ -56,6 +61,7 @@
 
                     var convRes = ResourceTypeRegistry.Deserialize(xml.ToString());
                     convRes.CurrentConnection = resource.CurrentConnection;
+                    convRes.ResourceID = resource.ResourceID;
                     return convRes;
                 }
             }



More information about the mapguide-commits mailing list