[mapguide-commits] r6460 - in trunk/Tools/Maestro: Maestro MaestroAPITests MaestroAPITests/UserTestData OSGeo.MapGuide.MaestroAPI/Feature OSGeo.MapGuide.MaestroAPI.Http OSGeo.MapGuide.MaestroAPI.Http/Commands

svn_mapguide at osgeo.org svn_mapguide at osgeo.org
Fri Jan 27 12:22:20 EST 2012


Author: jng
Date: 2012-01-27 09:22:20 -0800 (Fri, 27 Jan 2012)
New Revision: 6460

Added:
   trunk/Tools/Maestro/MaestroAPITests/GeoRestTests.cs
   trunk/Tools/Maestro/MaestroAPITests/UserTestData/GeoRestConfig.xml
   trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Http/Commands/GeoRestCommands.cs
   trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Http/GeoRestConnection.cs
Modified:
   trunk/Tools/Maestro/Maestro/Maestro.csproj
   trunk/Tools/Maestro/MaestroAPITests/MaestroAPITests.csproj
   trunk/Tools/Maestro/MaestroAPITests/TestControl.cs
   trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Http/HttpCapabilities.cs
   trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Http/HttpServerConnection.cs
   trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Http/OSGeo.MapGuide.MaestroAPI.Http.csproj
   trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI/Feature/PropertyValue.cs
Log:
#1913: Add insert command support for the HTTP connection. For this to work, the HTTP connection must be initialized with the following additional parameters:

 * GeoRestUrl: The URL to the GeoREST http server, or web server that exposes the GeoREST http endpoint
 * GeoRestConfigFile: The path to an XML file that describes a list of GeoREST MapGuide Sources with capabilities indicating whether insert/update/delete is supported. Only MapGuide sources can work here because Maestro's feature manipulation interfaces work off of Feature Source IDs and Feature Classes, external FDO sources cannot be resolved to Feature Source IDs, thus such sources cannot be listed in this file.

Unit tests have been added to test the insert operations for a GeoREST-enabled connection and the various pre-conditions required by the command.

Modified: trunk/Tools/Maestro/Maestro/Maestro.csproj
===================================================================
--- trunk/Tools/Maestro/Maestro/Maestro.csproj	2012-01-27 14:19:15 UTC (rev 6459)
+++ trunk/Tools/Maestro/Maestro/Maestro.csproj	2012-01-27 17:22:20 UTC (rev 6460)
@@ -64,10 +64,6 @@
       <SpecificVersion>False</SpecificVersion>
       <HintPath>..\SDK\bin\Maestro.Shared.UI.dll</HintPath>
     </Reference>
-    <Reference Include="MapGuideDotNetApi, Version=2.0.0.2308, Culture=neutral, PublicKeyToken=f526c48929fda856, processorArchitecture=MSIL">
-      <SpecificVersion>False</SpecificVersion>
-      <HintPath>..\SDK\bin\MapGuideDotNetApi.dll</HintPath>
-    </Reference>
     <Reference Include="NetTopologySuite.Merged, Version=1.8.0.0, Culture=neutral, PublicKeyToken=f526c48929fda856, processorArchitecture=MSIL">
       <SpecificVersion>False</SpecificVersion>
       <HintPath>..\Thirdparty\NTS\NetTopologySuite.Merged.dll</HintPath>
@@ -84,10 +80,6 @@
       <SpecificVersion>False</SpecificVersion>
       <HintPath>..\SDK\bin\OSGeo.MapGuide.MaestroAPI.Http.dll</HintPath>
     </Reference>
-    <Reference Include="OSGeo.MapGuide.MaestroAPI.Native, Version=3.0.0.5475, Culture=neutral, PublicKeyToken=f526c48929fda856, processorArchitecture=MSIL">
-      <SpecificVersion>False</SpecificVersion>
-      <HintPath>..\SDK\bin\OSGeo.MapGuide.MaestroAPI.Native.dll</HintPath>
-    </Reference>
     <Reference Include="System" />
     <Reference Include="System.Data" />
     <Reference Include="System.Deployment" />
@@ -395,6 +387,10 @@
       <Project>{F1E2F468-5030-4DBA-968C-9620284AFAA1}</Project>
       <Name>Maestro.Base</Name>
     </ProjectReference>
+    <ProjectReference Include="..\OSGeo.MapGuide.MaestroAPI.Native\OSGeo.MapGuide.MaestroAPI.Native32-2.2.0.csproj">
+      <Project>{F4420153-9DF3-4407-AD65-E8ABED2B6E25}</Project>
+      <Name>OSGeo.MapGuide.MaestroAPI.Native32-2.2.0</Name>
+    </ProjectReference>
     <ProjectReference Include="..\Thirdparty\SharpDevelop\ICSharpCode.Core.WinForms\ICSharpCode.Core.WinForms.csproj">
       <Project>{857CA1A3-FC88-4BE0-AB6A-D1EE772AB288}</Project>
       <Name>ICSharpCode.Core.WinForms</Name>

Added: trunk/Tools/Maestro/MaestroAPITests/GeoRestTests.cs
===================================================================
--- trunk/Tools/Maestro/MaestroAPITests/GeoRestTests.cs	                        (rev 0)
+++ trunk/Tools/Maestro/MaestroAPITests/GeoRestTests.cs	2012-01-27 17:22:20 UTC (rev 6460)
@@ -0,0 +1,133 @@
+#region Disclaimer / License
+// Copyright (C) 2012, 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 NUnit.Framework;
+using OSGeo.MapGuide.MaestroAPI.Commands;
+using OSGeo.MapGuide.MaestroAPI.Feature;
+using GisSharpBlog.NetTopologySuite.IO;
+using System.Collections.Specialized;
+
+namespace MaestroAPITests
+{
+    [TestFixture(Ignore = TestControl.IgnoreGeoRestTests)]
+    public class GeoRestTests
+    {
+        [Test]
+        public void TestInsert()
+        {
+            var conn = ConnectionUtil.CreateTestHttpConnectionWithGeoRest();
+            var insert = (IInsertFeatures)conn.CreateCommand((int)CommandType.InsertFeature);
+            insert.ClassName = "SHP_Schema:Parcels";
+            
+
+            var rec = new MutableRecord();
+            insert.RecordToInsert = rec;
+            insert.FeatureSourceId = "Library://Samples/Sheboygan/Data/Parcels.FeatureSource";
+            var dr = conn.FeatureService.AggregateQueryFeatureSource(
+                insert.FeatureSourceId,
+                "SHP_Schema:Parcels",
+                null,
+                new NameValueCollection()
+                {
+                    { "TOTAL", "COUNT(Autogenerated_SDF_ID)" }
+                });
+
+            long lBefore = 0L;
+            if (dr.ReadNext())
+            {
+                lBefore = dr.GetInt64("TOTAL");
+            }
+            dr.Close();
+
+            var wktReader = new WKTReader();
+
+            rec.PutValue("RNAME", new StringValue("Hello World"));
+            rec.PutValue("Geometry", new GeometryValue(wktReader.Read("POLYGON ((30 10, 10 20, 20 40, 40 40, 30 10))")));
+
+            var res = insert.Execute();
+            Assert.Null(res.Error);
+
+            long lAfter = lBefore;
+            dr = conn.FeatureService.AggregateQueryFeatureSource(
+                insert.FeatureSourceId,
+                "SHP_Schema:Parcels",
+                null,
+                new NameValueCollection()
+                {
+                    { "TOTAL", "COUNT(Autogenerated_SDF_ID)" }
+                });
+            if (dr.ReadNext())
+                lAfter = dr.GetInt64("TOTAL");
+            dr.Close();
+
+            Assert.AreEqual(lBefore + 1L, lAfter);
+        }
+
+        [Test]
+        public void TestInsertNotAllowed()
+        {
+            var conn = ConnectionUtil.CreateTestHttpConnectionWithGeoRest();
+            var insert = (IInsertFeatures)conn.CreateCommand((int)CommandType.InsertFeature);
+
+            insert.ClassName = "SHP_Schema:Parcels";
+            var rec = new MutableRecord();
+            insert.FeatureSourceId = "Library://Samples/Sheboygan/Data/ParcelsNotAllowed.FeatureSource";
+            insert.RecordToInsert = rec;
+
+            //This is not allowed
+            var res = insert.Execute();
+            Assert.IsAssignableFrom<InvalidOperationException>(res.Error);
+        }
+
+        [Test]
+        public void TestInsertNonConfigured()
+        {
+            var conn = ConnectionUtil.CreateTestHttpConnectionWithGeoRest();
+            var insert = (IInsertFeatures)conn.CreateCommand((int)CommandType.InsertFeature);
+
+            var rec = new MutableRecord();
+            insert.ClassName = "SHP_Schema:Rail";
+            insert.FeatureSourceId = "Library://Samples/Sheboygan/Data/Rail.FeatureSource";
+            insert.RecordToInsert = rec;
+
+            //This is not configured
+            var res = insert.Execute();
+            Assert.IsAssignableFrom<InvalidOperationException>(res.Error);
+        }
+
+        [Test]
+        public void TestInsertNonConfigured2()
+        {
+            var conn = ConnectionUtil.CreateTestHttpConnectionWithGeoRest();
+            var insert = (IInsertFeatures)conn.CreateCommand((int)CommandType.InsertFeature);
+
+            var rec = new MutableRecord();
+            insert.ClassName = "SHP_Schema:Foobar";
+            insert.FeatureSourceId = "Library://Samples/Sheboygan/Data/Parcels.FeatureSource";
+            insert.RecordToInsert = rec;
+
+            //This is not configured
+            var res = insert.Execute();
+            Assert.IsAssignableFrom<InvalidOperationException>(res.Error);
+        }
+    }
+}

Modified: trunk/Tools/Maestro/MaestroAPITests/MaestroAPITests.csproj
===================================================================
--- trunk/Tools/Maestro/MaestroAPITests/MaestroAPITests.csproj	2012-01-27 14:19:15 UTC (rev 6459)
+++ trunk/Tools/Maestro/MaestroAPITests/MaestroAPITests.csproj	2012-01-27 17:22:20 UTC (rev 6460)
@@ -74,6 +74,7 @@
     <Compile Include="ConfigurationTests.cs" />
     <Compile Include="ExpressionTests.cs" />
     <Compile Include="FeatureReaderTests.cs" />
+    <Compile Include="GeoRestTests.cs" />
     <Compile Include="HttpConnectionTests.cs" />
     <Compile Include="HttpSiteTests.cs" />
     <Compile Include="LocalNativeFeatureTests.cs" />
@@ -552,6 +553,9 @@
     <Content Include="UserTestData\1896.xml">
       <CopyToOutputDirectory>Always</CopyToOutputDirectory>
     </Content>
+    <Content Include="UserTestData\GeoRestConfig.xml">
+      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+    </Content>
     <Content Include="UserTestData\NASA_WMS_config_doc.xml">
       <CopyToOutputDirectory>Always</CopyToOutputDirectory>
     </Content>

Modified: trunk/Tools/Maestro/MaestroAPITests/TestControl.cs
===================================================================
--- trunk/Tools/Maestro/MaestroAPITests/TestControl.cs	2012-01-27 14:19:15 UTC (rev 6459)
+++ trunk/Tools/Maestro/MaestroAPITests/TestControl.cs	2012-01-27 17:22:20 UTC (rev 6460)
@@ -40,6 +40,7 @@
         public const bool IgnoreLocalNativeRuntimeMapTests = true;
         public const bool IgnoreLocalNativePerformanceTests = true;
         public const bool IgnoreLocalNativeFeatureTests = true;
+        public const bool IgnoreGeoRestTests = true;
         public const bool IgnoreLocalFeatureTests = false;
         public const bool IgnoreSchemaTests = false;
         public const bool IgnoreSerializationTests = false;
@@ -62,6 +63,28 @@
     {
         public static string Port { get { return ""; } }
 
+        public static IServerConnection CreateTestHttpConnectionWithGeoRest()
+        {
+            if (!string.IsNullOrEmpty(Port))
+            {
+                return ConnectionProviderRegistry.CreateConnection("Maestro.Http",
+                    "Url", "http://" + Environment.MachineName + ":" + Port + "/mapguide/mapagent/mapagent.fcgi",
+                    "Username", "Administrator",
+                    "Password", "admin",
+                    "GeoRestUrl", "http://localhost:99/",
+                    "GeoRestConfigPath", "UserTestData\\GeoRestConfig.xml");
+            }
+            else
+            {
+                return ConnectionProviderRegistry.CreateConnection("Maestro.Http",
+                    "Url", "http://" + Environment.MachineName + "/mapguide/mapagent/mapagent.fcgi",
+                    "Username", "Administrator",
+                    "Password", "admin",
+                    "GeoRestUrl", "http://localhost:99/",
+                    "GeoRestConfigPath", "UserTestData\\GeoRestConfig.xml");
+            }
+        }
+
         public static IServerConnection CreateTestHttpConnection()
         {
             if (!string.IsNullOrEmpty(Port))

Added: trunk/Tools/Maestro/MaestroAPITests/UserTestData/GeoRestConfig.xml
===================================================================
--- trunk/Tools/Maestro/MaestroAPITests/UserTestData/GeoRestConfig.xml	                        (rev 0)
+++ trunk/Tools/Maestro/MaestroAPITests/UserTestData/GeoRestConfig.xml	2012-01-27 17:22:20 UTC (rev 6460)
@@ -0,0 +1,19 @@
+<?xml version="1.0" ?>
+<GeoRestConfiguration>
+    <GeoRestFeatureSource>
+        <FeatureSource>Library://Samples/Sheboygan/Data/Parcels.FeatureSource</FeatureSource>
+        <FeatureClass>SHP_Schema:Parcels</FeatureClass>
+        <UriPart>mgproperty</UriPart>
+        <AllowInsert>true</AllowInsert>
+        <AllowUpdate>false</AllowUpdate>
+        <AllowDelete>false</AllowDelete>
+    </GeoRestFeatureSource>
+    <GeoRestFeatureSource>
+        <FeatureSource>Library://Samples/Sheboygan/Data/ParcelsNotAllowed.FeatureSource</FeatureSource>
+        <FeatureClass>SHP_Schema:Parcels</FeatureClass>
+        <UriPart>notallowed</UriPart>
+        <AllowInsert>false</AllowInsert>
+        <AllowUpdate>false</AllowUpdate>
+        <AllowDelete>false</AllowDelete>
+    </GeoRestFeatureSource>
+</GeoRestConfiguration>
\ No newline at end of file

Modified: trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI/Feature/PropertyValue.cs
===================================================================
--- trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI/Feature/PropertyValue.cs	2012-01-27 14:19:15 UTC (rev 6459)
+++ trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI/Feature/PropertyValue.cs	2012-01-27 17:22:20 UTC (rev 6460)
@@ -22,6 +22,7 @@
 using System.Text;
 using OSGeo.MapGuide.MaestroAPI.Schema;
 using GeoAPI.Geometries;
+using System.Globalization;
 
 namespace OSGeo.MapGuide.MaestroAPI.Feature
 {
@@ -61,6 +62,12 @@
         /// The suggsted property definition type.
         /// </value>
         public abstract PropertyDefinitionType PropertyDefType { get; }
+
+        /// <summary>
+        /// Gets the value as a string
+        /// </summary>
+        /// <returns></returns>
+        public abstract string ValueAsString();
     }
 
     /// <summary>
@@ -203,6 +210,18 @@
         {
             get { return PropertyValueType.Byte; }
         }
+
+        /// <summary>
+        /// Gets the value as a string
+        /// </summary>
+        /// <returns></returns>
+        public override string ValueAsString()
+        {
+            if (IsNull)
+                throw new Exception("Null Value"); //LOCALIZEME
+
+            return this.Value.ToString(CultureInfo.InvariantCulture);
+        }
     }
 
     /// <summary>
@@ -221,6 +240,18 @@
         {
             get { return PropertyValueType.Boolean; }
         }
+
+        /// <summary>
+        /// Gets the value as a string
+        /// </summary>
+        /// <returns></returns>
+        public override string ValueAsString()
+        {
+            if (IsNull)
+                throw new Exception("Null Value"); //LOCALIZEME
+
+            return this.Value.ToString();
+        }
     }
 
     /// <summary>
@@ -250,6 +281,15 @@
         {
             get { return PropertyDefinitionType.Data; }
         }
+
+        /// <summary>
+        /// Gets the value as a string
+        /// </summary>
+        /// <returns></returns>
+        public override string ValueAsString()
+        {
+            throw new NotSupportedException();
+        }
     }
 
     /// <summary>
@@ -279,6 +319,15 @@
         {
             get { return PropertyDefinitionType.Data; }
         }
+
+        /// <summary>
+        /// Gets the value as a string
+        /// </summary>
+        /// <returns></returns>
+        public override string ValueAsString()
+        {
+            throw new NotSupportedException();
+        }
     }
 
     /// <summary>
@@ -297,6 +346,33 @@
         {
             get { return PropertyValueType.DateTime; }
         }
+
+        static string PadLeft(string str, char ch, int totalChars)
+        {
+            var value = str;
+            while (value.Length < totalChars)
+                value = ch + value;
+            return value;
+        }
+
+        /// <summary>
+        /// Gets the value as a string
+        /// </summary>
+        /// <returns></returns>
+        public override string ValueAsString()
+        {
+            if (IsNull)
+                throw new Exception("Null Value"); //LOCALIZEME
+
+            var dt = this.Value;
+            return string.Format("TIMESTAMP '{0}-{1}-{2} {3}:{4}:{5}'",
+                PadLeft(dt.Year.ToString(), '0', 4),
+                PadLeft(dt.Month.ToString(), '0', 2),
+                PadLeft(dt.Year.ToString(), '0', 2),
+                PadLeft(dt.Hour.ToString(), '0', 2),
+                PadLeft(dt.Minute.ToString(), '0', 2),
+                PadLeft(dt.Second.ToString(), '0', 2));
+        }
     }
 
     /// <summary>
@@ -315,6 +391,18 @@
         {
             get { return PropertyValueType.Double; }
         }
+
+        /// <summary>
+        /// Gets the value as a string
+        /// </summary>
+        /// <returns></returns>
+        public override string ValueAsString()
+        {
+            if (IsNull)
+                throw new Exception("Null Value"); //LOCALIZEME
+
+            return this.Value.ToString(CultureInfo.InvariantCulture);
+        }
     }
 
     /// <summary>
@@ -344,6 +432,18 @@
         {
             get { return PropertyDefinitionType.Object; }
         }
+
+        /// <summary>
+        /// Gets the value as a string
+        /// </summary>
+        /// <returns></returns>
+        public override string ValueAsString()
+        {
+            if (IsNull)
+                throw new Exception("Null Value"); //LOCALIZEME
+
+            throw new NotSupportedException();
+        }
     }
 
     /// <summary>
@@ -373,6 +473,18 @@
         {
             get { return PropertyDefinitionType.Geometry; }
         }
+
+        /// <summary>
+        /// Gets the value as a string
+        /// </summary>
+        /// <returns></returns>
+        public override string ValueAsString()
+        {
+            if (IsNull)
+                throw new Exception("Null Value"); //LOCALIZEME
+
+            return this.Value.AsText();
+        }
     }
 
     /// <summary>
@@ -391,6 +503,18 @@
         {
             get { return PropertyValueType.Int16; }
         }
+
+        /// <summary>
+        /// Gets the value as a string
+        /// </summary>
+        /// <returns></returns>
+        public override string ValueAsString()
+        {
+            if (IsNull)
+                throw new Exception("Null Value"); //LOCALIZEME
+
+            return this.Value.ToString(CultureInfo.InvariantCulture);
+        }
     }
 
     /// <summary>
@@ -409,6 +533,18 @@
         {
             get { return PropertyValueType.Int32; }
         }
+
+        /// <summary>
+        /// Gets the value as a string
+        /// </summary>
+        /// <returns></returns>
+        public override string ValueAsString()
+        {
+            if (IsNull)
+                throw new Exception("Null Value"); //LOCALIZEME
+
+            return this.Value.ToString(CultureInfo.InvariantCulture);
+        }
     }
 
     /// <summary>
@@ -427,6 +563,18 @@
         {
             get { return PropertyValueType.Int64; }
         }
+
+        /// <summary>
+        /// Gets the value as a string
+        /// </summary>
+        /// <returns></returns>
+        public override string ValueAsString()
+        {
+            if (IsNull)
+                throw new Exception("Null Value"); //LOCALIZEME
+
+            return this.Value.ToString(CultureInfo.InvariantCulture);
+        }
     }
 
     /// <summary>
@@ -456,6 +604,15 @@
         {
             get { return PropertyDefinitionType.Raster; }
         }
+
+        /// <summary>
+        /// Gets the value as a string
+        /// </summary>
+        /// <returns></returns>
+        public override string ValueAsString()
+        {
+            throw new NotSupportedException();
+        }
     }
 
     /// <summary>
@@ -474,6 +631,18 @@
         {
             get { return PropertyValueType.Single; }
         }
+
+        /// <summary>
+        /// Gets the value as a string
+        /// </summary>
+        /// <returns></returns>
+        public override string ValueAsString()
+        {
+            if (IsNull)
+                throw new Exception("Null Value"); //LOCALIZEME
+
+            return this.Value.ToString(CultureInfo.InvariantCulture);
+        }
     }
 
     /// <summary>
@@ -503,6 +672,17 @@
         {
             get { return PropertyDefinitionType.Data; }
         }
+
+        /// <summary>
+        /// Gets the value as a string
+        /// </summary>
+        /// <returns></returns>
+        public override string ValueAsString()
+        {
+            if (IsNull)
+                throw new Exception("Null Value"); //LOCALIZEME
+
+            return this.Value;
+        }
     }
-
 }

Added: trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Http/Commands/GeoRestCommands.cs
===================================================================
--- trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Http/Commands/GeoRestCommands.cs	                        (rev 0)
+++ trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Http/Commands/GeoRestCommands.cs	2012-01-27 17:22:20 UTC (rev 6460)
@@ -0,0 +1,181 @@
+#region Disclaimer / License
+// Copyright (C) 2012, 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.Commands;
+using System.Xml;
+using OSGeo.MapGuide.MaestroAPI.Feature;
+using System.Net;
+using System.IO;
+using System.Diagnostics;
+
+namespace OSGeo.MapGuide.MaestroAPI.Http.Commands
+{
+    public class GeoRestInsertFeatures : DefaultInsertCommand<HttpServerConnection>
+    {
+        internal GeoRestInsertFeatures(HttpServerConnection conn) : base(conn) { }
+
+        protected override void ExecuteInternal()
+        {
+            var gconn = base.ConnImpl.GeoRestConnection;
+            if (gconn == null)
+                throw new InvalidOperationException("Connection does not have a valid GeoREST url or configuration"); //LOCALIZEME
+
+            if (!gconn.Configuration.IsGeoRestEnabled(this.FeatureSourceId, this.ClassName))
+                throw new InvalidOperationException(this.FeatureSourceId + " (" + this.ClassName + ") is not GeoREST configured"); //LOCALIEME
+
+            var fsConf = gconn.Configuration.GetFeatureSource(this.FeatureSourceId, this.ClassName);
+            if (!fsConf.AllowInsert)
+                throw new InvalidOperationException(this.FeatureSourceId + " (" + this.ClassName + ") is not configured for insert operations"); //LOCALIEME
+
+            //Assemble XML to POST
+            XmlDocument doc = new XmlDocument();
+            var fs = doc.AppendChild(doc.CreateElement("FeatureSet"));
+            var features = fs.AppendChild(doc.CreateElement("Features"));
+            var feat = ConvertToFeatureElement(doc);
+            features.AppendChild(feat);
+            
+            //Build GeoREST insert url
+            string insertUrl = gconn.Url;
+            if (!insertUrl.EndsWith("/"))
+                insertUrl += "/";
+            insertUrl += "rest/data/" + fsConf.UriPart + "/.xml";
+
+            HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create(insertUrl);
+            req.Method = "POST";
+            req.ContentType = "application/xml; charset=\"UTF-8\"";
+            req.Timeout = 10 * 1000;
+
+            using (Stream reqStream = req.GetRequestStream())
+            {
+                using (StreamWriter sw = new StreamWriter(reqStream))
+                {
+                    doc.Save(sw);
+                }
+            }
+
+            HttpWebResponse resp = (HttpWebResponse)req.GetResponse();
+#if DEBUG
+            using (var sr = new StreamReader(resp.GetResponseStream()))
+            {
+                Trace.TraceInformation("GeoRest Insert:\n" + sr.ReadToEnd());
+            }
+#endif
+        }
+
+        private XmlNode ConvertToFeatureElement(XmlDocument doc)
+        {
+            XmlNode feat = doc.CreateElement("Feature");
+            foreach (var propName in this.RecordToInsert.PropertyNames)
+            {
+                var prop = doc.CreateElement("Property");
+                var name = doc.CreateElement("Name");
+                name.InnerText = propName;
+                prop.AppendChild(name);
+
+                var value = doc.CreateElement("Value");
+                prop.AppendChild(value);
+
+                if (!this.RecordToInsert.IsNull(propName))
+                {
+                    var pv = this.RecordToInsert.GetValue(propName);
+                    value.InnerText = pv.ValueAsString();
+                }
+                feat.AppendChild(prop);
+            }
+            return feat;
+        }
+    }
+
+    /*
+    public class GeoRestUpdateFeatures : DefaultUpdateCommand<HttpServerConnection>
+    {
+        public override int ExecuteInternal()
+        {
+            var gconn = base.ConnImpl.GeoRestConnection;
+            if (gconn == null)
+                throw new InvalidOperationException("Connection does not have a valid GeoREST url or configuration"); //LOCALIZEME
+
+            if (!gconn.Configuration.IsGeoRestEnabled(this.FeatureSourceId))
+                throw new InvalidOperationException(this.FeatureSourceId + " is not GeoREST configured"); //LOCALIEME
+
+            var fsConf = gconn.Configuration.GetFeatureSource(this.FeatureSourceId);
+            if (!fsConf.AllowInsert)
+                throw new InvalidOperationException(this.FeatureSourceId + " is not configured for insert operations"); //LOCALIEME
+
+            XmlDocument doc = new XmlDocument();
+            var fs = doc.AppendChild(doc.CreateElement("FeatureSet"));
+            var features = fs.AppendChild(doc.CreateElement("Features"));
+            var feat = ConvertToFeatureElement(doc);
+            features.AppendChild(feat);
+
+            HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create(gconn.Url);
+            req.Method = "POST";
+            req.ContentType = "text/xml";
+
+            Stream reqStream = req.GetRequestStream();
+            doc.Save(reqStream);
+
+            HttpWebResponse resp = (HttpWebResponse)req.GetResponse();
+#if DEBUG
+            using (var sr = new StreamReader(resp.GetResponseStream()))
+            {
+                Trace.TraceInformation("GeoRest Insert:\n" + sr.ReadToEnd());
+            }
+#endif
+            return 1;
+        }
+
+        private XmlNode ConvertToFeatureElement(XmlDocument doc)
+        {
+            XmlNode feat = doc.CreateElement("Feature");
+            foreach (var propName in this.ValuesToUpdate.PropertyNames)
+            {
+                var prop = doc.CreateElement("Property");
+                var name = doc.CreateElement("Name");
+                name.InnerText = propName;
+                prop.AppendChild(name);
+
+                var value = doc.CreateElement("Value");
+                prop.AppendChild(value);
+
+                if (!this.ValuesToUpdate.IsNull(propName))
+                {
+                    var pv = this.ValuesToUpdate.GetValue(propName);
+                    value.InnerText = pv.ValueAsString();
+                }
+                feat.AppendChild(prop);
+            }
+            return feat;
+        }
+    }
+     
+    public class GeoRestDeleteFeatures : DefaultDeleteCommand<HttpServerConnection>
+    {
+        protected override int ExecuteInternal()
+        {
+            var gconn = base.ConnImpl;
+            if (gconn == null)
+                throw new InvalidOperationException("Connection does not have a valid GeoREST url or configuration");
+        }
+    }
+     */
+}

Added: trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Http/GeoRestConnection.cs
===================================================================
--- trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Http/GeoRestConnection.cs	                        (rev 0)
+++ trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Http/GeoRestConnection.cs	2012-01-27 17:22:20 UTC (rev 6460)
@@ -0,0 +1,114 @@
+#region Disclaimer / License
+// Copyright (C) 2012, 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 System.IO;
+using System.Xml;
+
+namespace OSGeo.MapGuide.MaestroAPI.Http
+{
+    internal class GeoRestConnection
+    {
+        private string _geoRestUrl;
+
+        private string _configFile;
+
+        private GeoRestFeatureSourceConfiguration _conf;
+
+        public GeoRestFeatureSourceConfiguration Configuration { get { return _conf; } }
+
+        internal GeoRestConnection(string url, string configFile)
+        {
+            _geoRestUrl = url;
+            _configFile = configFile;
+            _conf = GeoRestFeatureSourceConfiguration.LoadFrom(configFile);
+        }
+
+        public string Url { get { return _geoRestUrl; } }
+
+        public string ConfigPath { get { return _configFile; } }
+    }
+
+    internal class GeoRestFeatureSourceConfiguration
+    {
+        private Dictionary<string, GeoRestFeatureSource> _configuredFeatureSources;
+
+        private GeoRestFeatureSourceConfiguration()
+        {
+            _configuredFeatureSources = new Dictionary<string, GeoRestFeatureSource>();
+        }
+
+        private void PutConfig(string featureSource, string featureClass, GeoRestFeatureSource fs)
+        {
+            _configuredFeatureSources[featureSource + "|" + featureClass] = fs;
+        }
+
+        public bool IsGeoRestEnabled(string featureSource, string featureClass) { return _configuredFeatureSources.ContainsKey(featureSource + "|" + featureClass); }
+
+        public ICollection<string> FeatureSources { get { return _configuredFeatureSources.Keys; } }
+
+        public GeoRestFeatureSource GetFeatureSource(string featureSource, string featureClass) { return _configuredFeatureSources[featureSource + "|" + featureClass]; }
+
+        internal static GeoRestFeatureSourceConfiguration LoadFrom(string configFile)
+        {
+            var conf = new GeoRestFeatureSourceConfiguration();
+
+            if (!string.IsNullOrEmpty(configFile) && File.Exists(configFile))
+            {
+                XmlDocument doc = new XmlDocument();
+                doc.Load(configFile);
+
+                XmlNodeList fsNodes = doc.GetElementsByTagName("GeoRestFeatureSource");
+                foreach (XmlNode fsNode in fsNodes)
+                {
+                    var gfs = new GeoRestFeatureSource()
+                    {
+                        FeatureSourceId = fsNode["FeatureSource"].InnerText,
+                        FeatureClass = fsNode["FeatureClass"].InnerText,
+                        UriPart = fsNode["UriPart"].InnerText,
+                        AllowInsert = bool.Parse(fsNode["AllowInsert"].InnerText),
+                        AllowUpdate = bool.Parse(fsNode["AllowUpdate"].InnerText),
+                        AllowDelete = bool.Parse(fsNode["AllowDelete"].InnerText)
+                    };
+
+                    conf.PutConfig(gfs.FeatureSourceId, gfs.FeatureClass, gfs);
+                }
+            }
+
+            return conf;
+        }
+    }
+
+    public class GeoRestFeatureSource
+    {
+        public string FeatureSourceId { get; set; }
+
+        public string UriPart { get; set; }
+
+        public string FeatureClass { get; set; }
+
+        public bool AllowInsert { get; set; }
+
+        public bool AllowUpdate { get; set; }
+
+        public bool AllowDelete { get; set; }
+    }
+}

Modified: trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Http/HttpCapabilities.cs
===================================================================
--- trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Http/HttpCapabilities.cs	2012-01-27 14:19:15 UTC (rev 6459)
+++ trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Http/HttpCapabilities.cs	2012-01-27 17:22:20 UTC (rev 6460)
@@ -29,18 +29,40 @@
 {
     internal class HttpCapabilities : ConnectionCapabilities
     {
-        internal HttpCapabilities(IServerConnection parent) : base(parent) { }
+        private HttpServerConnection _implConn;
 
+        internal HttpCapabilities(IServerConnection parent) 
+            : base(parent) 
+        {
+            _implConn = parent as HttpServerConnection;
+        }
+
         public override int[] SupportedCommands
         {
             get 
             {
-                //TODO: Work out what this can/can't do
-                return new int[] 
+                var gconn = _implConn.GeoRestConnection;
+                if (gconn != null && gconn.Configuration.FeatureSources.Count > 0)
                 {
-                    (int)CommandType.GetResourceContents,
-                    (int)CommandType.GetFdoCacheInfo
-                };
+                    return new int[] 
+                    {
+                        (int)CommandType.GetResourceContents,
+                        (int)CommandType.GetFdoCacheInfo,
+                        //GeoREST allows us to support these
+                        //(int)CommandType.DeleteFeatures,
+                        (int)CommandType.InsertFeature,
+                        //(int)CommandType.UpdateFeatures
+                    };
+                }
+                else
+                {
+                    //TODO: Work out what this can/can't do
+                    return new int[] 
+                    {
+                        (int)CommandType.GetResourceContents,
+                        (int)CommandType.GetFdoCacheInfo
+                    };
+                }
             }
         }
 

Modified: trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Http/HttpServerConnection.cs
===================================================================
--- trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Http/HttpServerConnection.cs	2012-01-27 14:19:15 UTC (rev 6459)
+++ trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Http/HttpServerConnection.cs	2012-01-27 17:22:20 UTC (rev 6460)
@@ -86,13 +86,29 @@
             get
             {
                 var nvc = new NameValueCollection();
-                nvc["Url"] = this.BaseURL;
+                nvc[PARAM_URL] = this.BaseURL;
                 nvc[CommandLineArguments.Provider] = this.ProviderName;
                 nvc[CommandLineArguments.Session] = this.SessionID;
+                nvc[PARAM_GEORESTURL] = this.GeoRestUrl;
+                nvc[PARAM_GEORESTCONF] = this.GeoRestConfigPath;
                 return nvc;
             }
         }
 
+        private GeoRestConnection _geoRestConn;
+
+        internal GeoRestConnection GeoRestConnection { get { return _geoRestConn; } }
+
+        public string GeoRestUrl
+        {
+            get { return (_geoRestConn == null) ? string.Empty : _geoRestConn.Url; }
+        }
+
+        public string GeoRestConfigPath
+        {
+            get { return (_geoRestConn == null) ? string.Empty : _geoRestConn.ConfigPath; }
+        }
+
         public override string ProviderName
         {
             get { return "Maestro.Http"; }
@@ -120,10 +136,18 @@
         public const string PARAM_USERNAME = "Username";
         public const string PARAM_PASSWORD = "Password";
 
+        public const string PARAM_GEORESTURL = "GeoRestUrl";
+        public const string PARAM_GEORESTCONF = "GeoRestConfigPath";
+
         private ICredentials _cred;
 
-        private void InitConnection(Uri hosturl, string sessionid, string locale, bool allowUntestedVersion)
+        private void InitConnection(Uri hosturl, string sessionid, string locale, bool allowUntestedVersion, string geoRestUrl, string geoRestConfigPath)
         {
+            if (!string.IsNullOrEmpty(geoRestUrl))
+            {
+                _geoRestConn = new GeoRestConnection(geoRestUrl, geoRestConfigPath);
+            }
+
             m_reqBuilder = new RequestBuilder(hosturl, locale, sessionid);
             string req = m_reqBuilder.GetSiteVersion();
             SiteVersion sv = null;
@@ -164,8 +188,13 @@
             }
         }
 
-        private void InitConnection(Uri hosturl, string username, string password, string locale, bool allowUntestedVersion)
+        private void InitConnection(Uri hosturl, string username, string password, string locale, bool allowUntestedVersion, string geoRestUrl, string geoRestConfigPath)
         {
+            if (!string.IsNullOrEmpty(geoRestUrl))
+            {
+                _geoRestConn = new GeoRestConnection(geoRestUrl, geoRestConfigPath);
+            }
+
             m_reqBuilder = new RequestBuilder(hosturl, locale);
             mAnonymousUser = (username == "Anonymous");
 
@@ -201,16 +230,24 @@
             string locale = null;
             bool allowUntestedVersion = true;
 
+            string geoRestUrl = null;
+            string geoRestConfig = null;
+
             if (initParams[PARAM_LOCALE] != null)
                 locale = initParams[PARAM_LOCALE];
             if (initParams[PARAM_UNTESTED] != null)
                 bool.TryParse(initParams[PARAM_UNTESTED], out allowUntestedVersion);
 
+            if (initParams[PARAM_GEORESTURL] != null)
+                geoRestUrl = initParams[PARAM_GEORESTURL];
+            if (initParams[PARAM_GEORESTCONF] != null)
+                geoRestConfig = initParams[PARAM_GEORESTCONF];
+
             if (initParams[PARAM_SESSION] != null) 
             {
                 string sessionid = initParams[PARAM_SESSION];
 
-                InitConnection(new Uri(initParams[PARAM_URL]), sessionid, locale, allowUntestedVersion);
+                InitConnection(new Uri(initParams[PARAM_URL]), sessionid, locale, allowUntestedVersion, geoRestUrl, geoRestConfig);
             }
             else //Assuming username/password combination
             {
@@ -218,7 +255,7 @@
                 if (initParams[PARAM_USERNAME] == null)
                     throw new ArgumentException("Missing required connection parameter: " + PARAM_USERNAME);
 
-                InitConnection(new Uri(initParams[PARAM_URL]), initParams[PARAM_USERNAME], pwd, locale, allowUntestedVersion);
+                InitConnection(new Uri(initParams[PARAM_URL]), initParams[PARAM_USERNAME], pwd, locale, allowUntestedVersion, geoRestUrl, geoRestConfig);
             }
         }
 
@@ -226,14 +263,14 @@
 		public HttpServerConnection(Uri hosturl, string sessionid, string locale, bool allowUntestedVersion)
 			: this()
 		{
-            InitConnection(hosturl, sessionid, locale, allowUntestedVersion);
+            InitConnection(hosturl, sessionid, locale, allowUntestedVersion, null, null);
 		}
 
         [Obsolete("This will be removed in the future. Use ConnectionProviderRegistry.CreateConnection() instead")]
 		public HttpServerConnection(Uri hosturl, string username, string password, string locale, bool allowUntestedVersion)
 			: this()
 		{
-            InitConnection(hosturl, username, password, locale, allowUntestedVersion);
+            InitConnection(hosturl, username, password, locale, allowUntestedVersion, null, null);
 		}
 
 		public override string SessionID
@@ -1792,7 +1829,9 @@
         public override ICommand CreateCommand(int cmdType)
         {
             CommandType ct = (CommandType)cmdType;
-            if (ct == CommandType.GetResourceContents)
+            if (ct == CommandType.InsertFeature)
+                return new GeoRestInsertFeatures(this);
+            else if (ct == CommandType.GetResourceContents)
                 return new HttpGetResourceContents(this);
             else if (ct == CommandType.GetFdoCacheInfo)
                 return new HttpGetFdoCacheInfo(this);

Modified: trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Http/OSGeo.MapGuide.MaestroAPI.Http.csproj
===================================================================
--- trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Http/OSGeo.MapGuide.MaestroAPI.Http.csproj	2012-01-27 14:19:15 UTC (rev 6459)
+++ trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Http/OSGeo.MapGuide.MaestroAPI.Http.csproj	2012-01-27 17:22:20 UTC (rev 6460)
@@ -51,7 +51,9 @@
     <Compile Include="..\Properties\SignedAssemblyInfo.cs">
       <Link>SignedAssemblyInfo.cs</Link>
     </Compile>
+    <Compile Include="Commands\GeoRestCommands.cs" />
     <Compile Include="Commands\HttpGetFdoCacheInfo.cs" />
+    <Compile Include="GeoRestConnection.cs" />
     <Compile Include="HttpCapabilities.cs" />
     <Compile Include="HttpCoordinateSystem.cs" />
     <Compile Include="HttpCoordinateSystemCatalog.cs" />



More information about the mapguide-commits mailing list