[mapguide-commits] r4832 - in trunk/Tools/Maestro: Maestro Maestro/ResourceEditors MaestroAPI

svn_mapguide at osgeo.org svn_mapguide at osgeo.org
Wed May 5 04:07:42 EDT 2010


Author: jng
Date: 2010-05-05 04:07:38 -0400 (Wed, 05 May 2010)
New Revision: 4832

Added:
   trunk/Tools/Maestro/MaestroAPI/MgFeatureSetReader.cs
   trunk/Tools/Maestro/MaestroAPI/XmlFeatureSetReader.cs
Modified:
   trunk/Tools/Maestro/Maestro/OSGeo.MapGuide.Maestro.csproj
   trunk/Tools/Maestro/Maestro/ResourceEditors/FeatureSourceEditorBase.cs
   trunk/Tools/Maestro/MaestroAPI/FeatureSetReader.cs
   trunk/Tools/Maestro/MaestroAPI/FeatureSourceDescription.cs
   trunk/Tools/Maestro/MaestroAPI/HttpServerConnection.cs
   trunk/Tools/Maestro/MaestroAPI/LocalNativeConnection.cs
   trunk/Tools/Maestro/MaestroAPI/OSGeo.MapGuide.MaestroAPI.csproj
Log:
This submission includes the following changes:

 - Fix some glaring bugs in LocalNativeConnection which included casting the wrong MgService type and deserializing the content to the wrong type
 - Enable local feature source preview if we're using LocalNativeConnection
 - #1349: Split the FeatureSetReader into http and local implementations
 - #1345: Set Maestro.exe, MgCooker.exe and MgCookerCommandline.exe to build targeting x86. It turns out only the executables need to be explicitly set to x86. The other projects are untouched, as they will target whatever the owning process is targeting.

Modified: trunk/Tools/Maestro/Maestro/OSGeo.MapGuide.Maestro.csproj
===================================================================
--- trunk/Tools/Maestro/Maestro/OSGeo.MapGuide.Maestro.csproj	2010-05-05 00:46:05 UTC (rev 4831)
+++ trunk/Tools/Maestro/Maestro/OSGeo.MapGuide.Maestro.csproj	2010-05-05 08:07:38 UTC (rev 4832)
@@ -68,6 +68,7 @@
     <WarningLevel>4</WarningLevel>
     <DebugType>full</DebugType>
     <ErrorReport>prompt</ErrorReport>
+    <PlatformTarget>x86</PlatformTarget>
   </PropertyGroup>
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
     <OutputPath>bin\Release\</OutputPath>
@@ -91,6 +92,7 @@
     <WarningLevel>4</WarningLevel>
     <DebugType>none</DebugType>
     <ErrorReport>prompt</ErrorReport>
+    <PlatformTarget>x86</PlatformTarget>
   </PropertyGroup>
   <ItemGroup>
     <Reference Include="ICSharpCode.SharpZipLib, Version=0.85.4.369, Culture=neutral, PublicKeyToken=1b03e6acf1164f73, processorArchitecture=MSIL">

Modified: trunk/Tools/Maestro/Maestro/ResourceEditors/FeatureSourceEditorBase.cs
===================================================================
--- trunk/Tools/Maestro/Maestro/ResourceEditors/FeatureSourceEditorBase.cs	2010-05-05 00:46:05 UTC (rev 4831)
+++ trunk/Tools/Maestro/Maestro/ResourceEditors/FeatureSourceEditorBase.cs	2010-05-05 08:07:38 UTC (rev 4832)
@@ -104,6 +104,7 @@
 			}
 
             //This stuff is not applicable to raster providers
+            //TODO: Cleaner way to detect raster providers
             string provider = feature.Provider.ToUpper();
             if (!provider.StartsWith("OSGEO.GDAL") &&
                 !provider.StartsWith("OSGEO.WMS") &&
@@ -115,11 +116,18 @@
                 LocalPreviewPage.Controls.Clear();
                 LocalPreviewPage.Controls.Add(ctl);
 
-                //This feature is broken for any MG release < 2.2 so disable it.
-                Version ver = editor.CurrentConnection.SiteVersion;
-                Version supported = new Version(2, 2);
-                if (ver < supported)
-                    EditorTab.Controls.Remove(LocalPreviewPage);
+                //HACK: When we split the ServerConnectionI implementations we'll need
+                //to deal with this
+                var conn = editor.CurrentConnection as MaestroAPI.LocalNativeConnection;
+                if (conn == null) //Must be HTTP
+                {
+                    //This feature is broken for any MG release < 2.2 so disable it.
+
+                    Version ver = editor.CurrentConnection.SiteVersion;
+                    Version supported = new Version(2, 2);
+                    if (ver < supported)
+                        EditorTab.Controls.Remove(LocalPreviewPage);
+                }
             }
             else
             {

Modified: trunk/Tools/Maestro/MaestroAPI/FeatureSetReader.cs
===================================================================
--- trunk/Tools/Maestro/MaestroAPI/FeatureSetReader.cs	2010-05-05 00:46:05 UTC (rev 4831)
+++ trunk/Tools/Maestro/MaestroAPI/FeatureSetReader.cs	2010-05-05 08:07:38 UTC (rev 4832)
@@ -21,284 +21,227 @@
 using System.IO;
 using System.Xml;
 using Topology.Geometries;
+using System.Data;
+using System.Collections.Generic;
 
 namespace OSGeo.MapGuide.MaestroAPI
 {
 	/// <summary>
 	/// Represents a set of results from a query
 	/// </summary>
-	public class FeatureSetReader : IDisposable
+	public abstract class FeatureSetReader : IDisposable, IDataReader
 	{
-		private FeatureSetColumn[] m_columns;
-		private FeatureSetRow m_row;
-		private XmlTextReader m_reader;
+		protected FeatureSetColumn[] m_columns;
+		protected FeatureSetRow m_row;
 
-		private OSGeo.MapGuide.MgReader m_rd;
+        protected Dictionary<string, int> _nameOrdinalMap;
 
-		public FeatureSetReader(OSGeo.MapGuide.MgReader rd)
-		{
-			m_rd = rd;
-			m_columns = new FeatureSetColumn[rd.GetPropertyCount()];
-			for(int i = 0; i < m_columns.Length; i++)
-				m_columns[i] = new FeatureSetColumn(rd.GetPropertyName(i), rd.GetPropertyType(rd.GetPropertyName(i)));
+        protected FeatureSetReader() { }
 
+        /// <summary>
+        /// Initializes the column array for this reader. Must be called before
+        /// any reading operations commence.
+        /// </summary>
+        /// <param name="cols"></param>
+        protected void InitColumns(FeatureSetColumn[] cols)
+        {
+            m_columns = cols;
+            _nameOrdinalMap = new Dictionary<string, int>();
+            for (int i = 0; i < m_columns.Length; i++)
+            {
+                _nameOrdinalMap.Add(m_columns[i].Name, i);
+            }
+        }
+
+		public FeatureSetColumn[] Columns
+		{
+			get { return m_columns; }
 		}
 
-		//TODO: Make internal
-		public FeatureSetReader(Stream m_source)
+        public bool Read()
+        {
+            m_row = null;
+            bool next = ReadInternal();
+            if (next)
+            {
+                m_row = ProcessFeatureRow();
+            }
+            return next;
+        }
+
+        protected abstract bool ReadInternal();
+
+        protected abstract FeatureSetRow ProcessFeatureRow();
+        
+		public FeatureSetRow Row
 		{
-			m_reader = new XmlTextReader(m_source);
-			m_reader.WhitespaceHandling = WhitespaceHandling.Significant;
+			get { return m_row; }
+		}
 
-			//First we extract the response layout
-			m_reader.Read();
-			if (m_reader.Name != "xml")
-				throw new Exception("Bad document");
-			m_reader.Read();
-			if (m_reader.Name != "FeatureSet" && m_reader.Name != "PropertySet" && m_reader.Name != "RowSet")
-				throw new Exception("Bad document");
+        public virtual void Dispose() { }
 
-            m_reader.Read();
-            if (m_reader.Name != "xs:schema" && m_reader.Name != "PropertyDefinitions" && m_reader.Name != "ColumnDefinitions")
-                throw new Exception("Bad document");
+        public void Close()
+        {
+            CloseInternal();
+            this.IsClosed = true;
+        }
 
-			XmlDocument doc = new XmlDocument();
-			doc.LoadXml(m_reader.ReadOuterXml());
-			XmlNamespaceManager mgr = new XmlNamespaceManager(doc.NameTable);
-			mgr.AddNamespace("xs", "http://www.w3.org/2001/XMLSchema");
-			mgr.AddNamespace("gml", "http://www.opengis.net/gml");
-			mgr.AddNamespace("fdo", "http://fdo.osgeo.org/schemas");
+        protected abstract void CloseInternal();
 
-			//TODO: Assumes there is only one type returned... perhaps more can be returned....
-			XmlNodeList lst = doc.SelectNodes("xs:schema/xs:complexType/xs:complexContent/xs:extension/xs:sequence/xs:element", mgr);
-			if (lst.Count == 0)
-				lst = doc.SelectNodes("xs:schema/xs:complexType/xs:sequence/xs:element", mgr);
-            if (lst.Count == 0)
-                lst = doc.SelectNodes("PropertyDefinitions/PropertyDefinition");
-            if (lst.Count == 0)
-                lst = doc.SelectNodes("ColumnDefinitions/Column");
-			m_columns = new FeatureSetColumn[lst.Count];
-			for(int i = 0;i<lst.Count;i++)
-				m_columns[i] = new FeatureSetColumn(lst[i]);
+        public abstract int Depth { get; }
 
-			m_row = null;
+        public abstract DataTable GetSchemaTable();
 
-			if (m_reader.Name != "Features" && m_reader.Name != "Properties" && m_reader.Name != "Rows")
-				throw new Exception("Bad document");
+        public bool IsClosed { get; private set; }
 
-			m_reader.Read();
+        public bool NextResult()
+        {
+            return Read();
+        }
 
-            if (m_reader.NodeType != XmlNodeType.EndElement)
-            {
-                if (m_reader.Name == "Features")
-                    m_reader = null; //No features :(
-                else if (m_reader.Name == "PropertyCollection" || m_reader.Name == "Row")
-                {
-                    //OK
-                }
-                else if (m_reader.Name != "Feature")
-                    throw new Exception("Bad document");
-            }
-		}
+        public abstract int RecordsAffected { get; }
 
-		public FeatureSetColumn[] Columns
-		{
-			get { return m_columns; }
-		}
+        public int FieldCount
+        {
+            get { return m_columns.Length; }
+        }
 
-		public bool Read()
-		{
-			if (m_rd != null)
-			{
-				bool next = m_rd.ReadNext();
-                if (!next)
-                {
-                    this.Dispose();
-                    return false;
-                }
+        public virtual bool GetBoolean(int i)
+        {
+            return (bool)m_row[GetName(i)];
+        }
 
-				m_row = new FeatureSetRow(this, m_rd);
-				return next;
-			}
-			else
-			{
+        public virtual byte GetByte(int i)
+        {
+            return (byte)m_row[GetName(i)];
+        }
 
-				if (m_reader == null || (m_reader.Name != "Feature" && m_reader.Name != "PropertyCollection" && m_reader.Name != "Row"))
-				{
-					m_row = null;
-					return false;
-				}
+        public virtual long GetBytes(int i, long fieldOffset, byte[] buffer, int bufferoffset, int length)
+        {
+            throw new NotImplementedException();
+        }
 
-				string xmlfragment = m_reader.ReadOuterXml();
-				XmlDocument doc = new XmlDocument();
-				doc.LoadXml(xmlfragment);
+        public virtual char GetChar(int i)
+        {
+            return (char)m_row[GetName(i)];
+        }
 
-                if (doc["Row"] != null)
-                    m_row = new FeatureSetRow(this, doc["Row"]);
-                else if (doc["Feature"] == null)
-                    m_row = new FeatureSetRow(this, doc["PropertyCollection"]);
-                else
-				    m_row = new FeatureSetRow(this, doc["Feature"]);
+        public virtual long GetChars(int i, long fieldoffset, char[] buffer, int bufferoffset, int length)
+        {
+            throw new NotImplementedException();
+        }
 
-                if (m_reader.Name != "Feature" && m_reader.Name != "PropertyCollection" && m_reader.Name != "Row")
-				{
-					m_reader.Close();
-					m_reader = null;
-				}
+        public virtual IDataReader GetData(int i)
+        {
+            return (IDataReader)m_row[GetName(i)];
+        }
 
-				return true;
-			}
-		}
+        public virtual string GetDataTypeName(int i)
+        {
+            return m_columns[i].Type.Name;
+        }
 
-		public FeatureSetRow Row
-		{
-			get { return m_row; }
-		}
+        public virtual DateTime GetDateTime(int i)
+        {
+            return (DateTime)m_row[GetName(i)];
+        }
 
+        public virtual decimal GetDecimal(int i)
+        {
+            return (decimal)m_row[GetName(i)];
+        }
 
-        #region IDisposable Members
+        public virtual double GetDouble(int i)
+        {
+            return (double)m_row[GetName(i)];
+        }
 
-        public void Dispose()
+        public virtual Type GetFieldType(int i)
         {
-            if (m_rd != null)
-            {
-                m_rd.Close();
-                m_rd.Dispose();
-                m_rd = null;
-                m_row = null;
-            }
+            return m_columns[i].Type;
         }
 
-        #endregion
-    }
+        public float GetFloat(int i)
+        {
+            return (float)m_row[GetName(i)];
+        }
 
-	public class FeatureSetColumn
-	{
-		internal FeatureSetColumn(string name, int type)
-		{
-			m_name = name;
-			m_type = Utility.ConvertMgTypeToNetType(type);
-		}
+        public virtual Guid GetGuid(int i)
+        {
+            return (Guid)m_row[GetName(i)];
+        }
 
-		internal FeatureSetColumn(XmlNode node)
-		{
-            if (node.Name == "PropertyDefinition" || node.Name == "Column")
-            {
-                m_name = node["Name"].InnerText;
-                m_allowNull = true;
-                switch (node["Type"].InnerText.ToLower().Trim())
-                {
-                    case "string":
-                        m_type = typeof(string);
-                        break;
-                    case "byte":
-                        m_type = typeof(Byte);
-                        break;
-                    case "int32":
-                    case "int":
-                    case "integer":
-                        m_type = typeof(int);
-                        break;
-                    case "int16":
-                        m_type = typeof(short);
-                        break;
-                    case "int64":
-                    case "long":
-                        m_type = typeof(long);
-                        break;
-                    case "float":
-                    case "single":
-                        m_type = typeof(float);
-                        break;
-                    case "double":
-                    case "decimal":
-                        m_type = typeof(double);
-                        break;
-                    case "boolean":
-                    case "bool":
-                        m_type = typeof(bool);
-                        return;
-                    case "datetime":
-                    case "date":
-                        m_type = typeof(DateTime);
-                        break;
-                    case "raster":
-                        m_type = Utility.RasterType;
-                        break;
-                    case "geometry":
-                        m_type = Utility.GeometryType;
-                        break;
-                    default:
-                        //throw new Exception("Failed to find appropriate type for: " + node["xs:simpleType"]["xs:restriction"].Attributes["base"].Value);
-                        m_type = Utility.UnmappedType;
-                        break;
-                }
-            }
-            else
-            {
-                m_name = node.Attributes["name"].Value;
-                m_allowNull = node.Attributes["minOccurs"] != null && node.Attributes["minOccurs"].Value == "0";
-                if (node.Attributes["type"] != null && node.Attributes["type"].Value == "gml:AbstractGeometryType")
-                    m_type = Utility.GeometryType;
-                else if (node["xs:simpleType"] == null)
-                    m_type = Utility.RasterType;
-                else
-                    switch (node["xs:simpleType"]["xs:restriction"].Attributes["base"].Value.ToLower())
-                    {
-                        case "xs:string":
-                            m_type = typeof(string);
-                            break;
-                        case "fdo:byte":
-                            m_type = typeof(Byte);
-                            break;
-                        case "fdo:int32":
-                            m_type = typeof(int);
-                            break;
-                        case "fdo:int16":
-                            m_type = typeof(short);
-                            break;
-                        case "fdo:int64":
-                            m_type = typeof(long);
-                            break;
-                        case "xs:float":
-                        case "xs:single":
-                        case "fdo:single":
-                            m_type = typeof(float);
-                            break;
-                        case "xs:double":
-                        case "xs:decimal":
-                            m_type = typeof(double);
-                            break;
-                        case "xs:boolean":
-                            m_type = typeof(bool);
-                            return;
-                        case "xs:datetime":
-                            m_type = typeof(DateTime);
-                            break;
-                        default:
-                            //throw new Exception("Failed to find appropriate type for: " + node["xs:simpleType"]["xs:restriction"].Attributes["base"].Value);
-                            m_type = Utility.UnmappedType;
-                            break;
-                    }
-            }
-		}
+        public short GetInt16(int i)
+        {
+            return (short)m_row[GetName(i)];
+        }
 
-		private string m_name;
-		private Type m_type;
-		private bool m_allowNull;
+        public int GetInt32(int i)
+        {
+            return (int)m_row[GetName(i)];
+        }
 
+        public long GetInt64(int i)
+        {
+            return (long)m_row[GetName(i)];
+        }
+
+        public string GetName(int i)
+        {
+            return m_columns[i].Name;
+        }
+
+        public int GetOrdinal(string name)
+        {
+            return _nameOrdinalMap[name];
+        }
+
+        public string GetString(int i)
+        {
+            return (string)m_row[GetName(i)];
+        }
+
+        public object GetValue(int i)
+        {
+            return m_row[GetName(i)];
+        }
+
+        public int GetValues(object[] values)
+        {
+            throw new NotImplementedException();
+        }
+
+        public bool IsDBNull(int i)
+        {
+            return m_row.IsValueNull(i);
+        }
+
+        public object this[string name]
+        {
+            get { return m_row[name]; }
+        }
+
+        public object this[int i]
+        {
+            get { return m_row[GetName(i)]; }
+        }
+    }
+
+	public abstract class FeatureSetColumn
+	{
+		protected string m_name;
+        protected Type m_type;
+        protected bool m_allowNull;
+
 		public string Name { get { return m_name; } }
 		public Type Type { get { return m_type; } }
 	}
 
-	public class FeatureSetRow
+	public abstract class FeatureSetRow : IDataRecord
 	{
         private Topology.IO.WKTReader m_reader = null;
-        
-        private bool m_hasMgReader = true;
-        private Topology.IO.MapGuide.MgReader m_mgReader = null;
 
-        private Topology.IO.WKTReader Reader
+        protected Topology.IO.WKTReader Reader
         {
             get
             {
@@ -308,28 +251,12 @@
             }
         }
 
-        private Topology.IO.MapGuide.MgReader MgReader
-        {
-            get
-            {
-                if (m_hasMgReader)
-                {
-                    try
-                    {
-                        m_mgReader = null;
-                        m_mgReader = new Topology.IO.MapGuide.MgReader();
-                    }
-                    catch
-                    {
-                        m_hasMgReader = false;
-                    }
-                }
-
-                return m_mgReader;
-            }
-        }
-
-		private FeatureSetRow(FeatureSetReader parent)
+        protected FeatureSetReader m_parent;
+        protected object[] m_items;
+        protected bool[] m_nulls;
+        protected bool[] m_lazyloadGeometry;
+        
+		protected FeatureSetRow(FeatureSetReader parent)
 		{
 			m_parent = parent;
 			m_items = new object[parent.Columns.Length];
@@ -342,158 +269,13 @@
 			}
 		}
 
-		internal FeatureSetRow(FeatureSetReader parent, OSGeo.MapGuide.MgReader rd)
-			: this(parent)
-		{
-			for(int i = 0; i < m_parent.Columns.Length; i++)
-			{
-				string p = m_parent.Columns[i].Name;
-				int ordinal = GetOrdinal(p);
-				m_nulls[ordinal] = rd.IsNull(p);
-
-                if (!m_nulls[ordinal])
-                {
-                    if (parent.Columns[ordinal].Type == typeof(string))
-                        m_items[ordinal] = rd.GetString(p);
-                    else if (parent.Columns[ordinal].Type == typeof(int))
-                        m_items[ordinal] = rd.GetInt32(p);
-                    else if (parent.Columns[ordinal].Type == typeof(long))
-                        m_items[ordinal] = rd.GetInt64(p);
-                    else if (parent.Columns[ordinal].Type == typeof(short))
-                        m_items[ordinal] = rd.GetInt16(p);
-                    else if (parent.Columns[ordinal].Type == typeof(double))
-                        m_items[ordinal] = rd.GetDouble(p);
-                    else if (parent.Columns[ordinal].Type == typeof(float))
-                        m_items[ordinal] = rd.GetSingle(p);
-                    else if (parent.Columns[ordinal].Type == typeof(bool))
-                        m_items[ordinal] = rd.GetBoolean(p);
-                    else if (parent.Columns[ordinal].Type == typeof(DateTime))
-                    {
-                        MgDateTime t = rd.GetDateTime(p);
-                        try
-                        {
-                            m_items[ordinal] = new DateTime(t.Year, t.Month, t.Day, t.Hour, t.Minute, t.Second);
-                        }
-                        catch(Exception ex)
-                        {
-                            //Unfortunately FDO supports invalid dates, such as the 30th feb
-                            m_nulls[ordinal] = true;
-                            m_items[ordinal] = ex;
-                        }
-                    }
-                    else if (parent.Columns[ordinal].Type == Utility.GeometryType)
-                    {
-                        //TODO: Uncomment this once the Topology.Net API gets updated to 2.0.0
-                        //It is optional to include the Topology.IO.MapGuide dll
-                        /*if (this.MgReader != null)
-                            m_items[ordinal] = this.MgReader.ReadGeometry(ref rd, p);
-                        else*/
-                        {
-                            //No MapGuide dll, convert to WKT and then to internal representation
-                            System.IO.MemoryStream ms = Utility.MgStreamToNetStream(rd, rd.GetType().GetMethod("GetGeometry"), new string[] { p });
-                            OSGeo.MapGuide.MgAgfReaderWriter rdw = new OSGeo.MapGuide.MgAgfReaderWriter();
-                            OSGeo.MapGuide.MgGeometry g = rdw.Read(rd.GetGeometry(p));
-                            OSGeo.MapGuide.MgWktReaderWriter rdww = new OSGeo.MapGuide.MgWktReaderWriter();
-                            m_items[ordinal] = this.Reader.Read(rdww.Write(g));
-                        }
-                    }
-                    else if (parent.Columns[ordinal].Type == Utility.UnmappedType)
-                    {
-                        //Attempt to read it as a string
-                        try { m_items[ordinal] = rd.GetString(p); }
-                        catch { m_items[ordinal] = null; }
-                    }
-                    else
-                        throw new Exception("Unknown type: " + parent.Columns[ordinal].Type.FullName);
-                }
-			}
-		}
-
-		internal FeatureSetRow(FeatureSetReader parent, XmlNode node)
-			: this(parent)
-		{
-            string nodeName = "Property";
-            if (node.Name == "Row")
-                nodeName = "Column";
-
-            foreach (XmlNode p in node.SelectNodes(nodeName))
-            {
-                int ordinal = GetOrdinal(p["Name"].InnerText);
-                if (!m_nulls[ordinal])
-                    throw new Exception("Bad document, multiple: " + p["Name"].InnerText + " values in a single feature");
-                m_nulls[ordinal] = false;
-
-                if (parent.Columns[ordinal].Type == typeof(string) || parent.Columns[ordinal].Type == Utility.UnmappedType)
-                    m_items[ordinal] = p["Value"].InnerText;
-                else if (parent.Columns[ordinal].Type == typeof(int))
-                    m_items[ordinal] = XmlConvert.ToInt32(p["Value"].InnerText);
-                else if (parent.Columns[ordinal].Type == typeof(long))
-                    m_items[ordinal] = XmlConvert.ToInt64(p["Value"].InnerText);
-                else if (parent.Columns[ordinal].Type == typeof(short))
-                    m_items[ordinal] = XmlConvert.ToInt16(p["Value"].InnerText);
-                else if (parent.Columns[ordinal].Type == typeof(double))
-                    m_items[ordinal] = XmlConvert.ToDouble(p["Value"].InnerText);
-                else if (parent.Columns[ordinal].Type == typeof(bool))
-                    m_items[ordinal] = XmlConvert.ToBoolean(p["Value"].InnerText);
-                else if (parent.Columns[ordinal].Type == typeof(DateTime))
-                {
-                    try
-                    {
-                        //Fix for broken ODBC provider
-                        string v = p["Value"].InnerText;
-
-                        if (v.Trim().ToUpper().StartsWith("TIMESTAMP"))
-                            v = v.Trim().Substring("TIMESTAMP".Length).Trim();
-                        else if (v.Trim().ToUpper().StartsWith("DATE"))
-                            v = v.Trim().Substring("DATE".Length).Trim();
-                        else if (v.Trim().ToUpper().StartsWith("TIME"))
-                            v = v.Trim().Substring("TIME".Length).Trim();
-
-                        if (v != p["Value"].InnerText)
-                        {
-                            if (v.StartsWith("'"))
-                                v = v.Substring(1);
-                            if (v.EndsWith("'"))
-                                v = v.Substring(0, v.Length - 1);
-
-                            m_items[ordinal] = DateTime.Parse(v, System.Globalization.CultureInfo.InvariantCulture, System.Globalization.DateTimeStyles.NoCurrentDateDefault);
-                        }
-                        else
-                            m_items[ordinal] = XmlConvert.ToDateTime(v, XmlDateTimeSerializationMode.Unspecified);
-                    }
-                    catch (Exception ex)
-                    {
-                        //Unfortunately FDO supports invalid dates, such as the 30th feb
-                        m_nulls[ordinal] = true;
-                        m_items[ordinal] = ex;
-                    }
-                }
-                else if (parent.Columns[ordinal].Type == Utility.GeometryType)
-                {
-                    m_items[ordinal] = p["Value"].InnerText;
-                    if (string.IsNullOrEmpty(p["Value"].InnerText))
-                    {
-                        m_nulls[ordinal] = true;
-                        m_items[ordinal] = null;
-                    }
-                    else
-                        m_lazyloadGeometry[ordinal] = true;
-                }
-                else
-                    throw new Exception("Unknown type: " + parent.Columns[ordinal].Type.FullName);
-            }
-		}
-
-		private FeatureSetReader m_parent;
-		private object[] m_items;
-		private bool[] m_nulls;
-		private bool[] m_lazyloadGeometry;
-
+        [Obsolete("This will be gone in a future release. Use IsDBNull(int i) instead. To get the index use GetOrdinal(string name)")]
 		public bool IsValueNull(string name)
 		{
 			return IsValueNull(GetOrdinal(name));
 		}
 
+        [Obsolete("This will be gone in a future release. Use IsDBNull(int i) instead")]
 		public bool IsValueNull(int index)
 		{
 			if (index >= m_nulls.Length)
@@ -502,25 +284,6 @@
 				return m_nulls[index];
 		}
 
-		public object this[int index]
-		{
-			get 
-			{
-				if (index >= m_items.Length)
-					throw new InvalidOperationException("Index " + index.ToString() + ", was out of bounds");
-				else
-				{
-					if (m_lazyloadGeometry[index] && !m_nulls[index])
-					{
-						m_items[index] = this.Reader.Read((string)m_items[index]);
-						m_lazyloadGeometry[index] = false;
-					}
-
-					return m_items[index];
-				}
-			}
-		}
-
 		public int GetOrdinal(string name)
 		{
             if (name == null)
@@ -553,5 +316,123 @@
 				return this[GetOrdinal(name)];
 			}
 		}
-	}
+
+        public int FieldCount
+        {
+            get { return m_parent.Columns.Length; }
+        }
+
+        public bool GetBoolean(int i)
+        {
+            return (bool)m_items[i];
+        }
+
+        public byte GetByte(int i)
+        {
+            return (byte)m_items[i];
+        }
+
+        public long GetBytes(int i, long fieldOffset, byte[] buffer, int bufferoffset, int length)
+        {
+            throw new NotImplementedException();
+        }
+
+        public char GetChar(int i)
+        {
+            return (char)m_items[i];
+        }
+
+        public long GetChars(int i, long fieldoffset, char[] buffer, int bufferoffset, int length)
+        {
+            throw new NotImplementedException();
+        }
+
+        public IDataReader GetData(int i)
+        {
+            return (IDataReader)m_items[i];
+        }
+
+        public string GetDataTypeName(int i)
+        {
+            return m_parent.Columns[i].Type.Name;
+        }
+
+        public DateTime GetDateTime(int i)
+        {
+            return (DateTime)m_items[i];
+        }
+
+        public decimal GetDecimal(int i)
+        {
+            return (decimal)m_items[i];
+        }
+
+        public double GetDouble(int i)
+        {
+            return (double)m_items[i];
+        }
+
+        public Type GetFieldType(int i)
+        {
+            return m_parent.Columns[i].Type;
+        }
+
+        public float GetFloat(int i)
+        {
+            return (float)m_items[i];
+        }
+
+        public Guid GetGuid(int i)
+        {
+            return (Guid)m_items[i];
+        }
+
+        public short GetInt16(int i)
+        {
+            return (short)m_items[i];
+        }
+
+        public int GetInt32(int i)
+        {
+            return (int)m_items[i];
+        }
+
+        public long GetInt64(int i)
+        {
+            return (long)m_items[i];
+        }
+
+        public string GetName(int i)
+        {
+            return m_parent.GetName(i);
+        }
+
+        public string GetString(int i)
+        {
+            return (string)m_items[i];
+        }
+
+        public object GetValue(int i)
+        {
+            return m_items[i];
+        }
+
+        public int GetValues(object[] values)
+        {
+            throw new NotImplementedException();
+        }
+
+        public bool IsDBNull(int index)
+        {
+            if (index >= m_nulls.Length)
+                throw new InvalidOperationException("Index " + index.ToString() + ", was out of bounds");
+            else
+                return m_nulls[index];
+        }
+
+        public object this[int i]
+        {
+            get { return m_items[i]; }
+        }
+    }
 }

Modified: trunk/Tools/Maestro/MaestroAPI/FeatureSourceDescription.cs
===================================================================
--- trunk/Tools/Maestro/MaestroAPI/FeatureSourceDescription.cs	2010-05-05 00:46:05 UTC (rev 4831)
+++ trunk/Tools/Maestro/MaestroAPI/FeatureSourceDescription.cs	2010-05-05 08:07:38 UTC (rev 4832)
@@ -110,7 +110,7 @@
 
 				m_columns = new FeatureSetColumn[lst.Count];
 				for(int i = 0;i<lst.Count;i++)
-					m_columns[i] = new FeatureSetColumn(lst[i]);
+                    m_columns[i] = new ClassPropertyColumn(lst[i]);
 
                 XmlNode extension = node.SelectSingleNode("xs:complexContent/xs:extension", mgr);
                 if (extension != null && extension.Attributes["base"] != null)
@@ -137,4 +137,9 @@
 			public FeatureSetColumn[] Columns { get { return m_columns; } }
 		}
 	}
+
+    internal class ClassPropertyColumn : XmlFeatureSetColumn
+    {
+        internal ClassPropertyColumn(XmlNode node) : base(node) { }
+    }
 }

Modified: trunk/Tools/Maestro/MaestroAPI/HttpServerConnection.cs
===================================================================
--- trunk/Tools/Maestro/MaestroAPI/HttpServerConnection.cs	2010-05-05 00:46:05 UTC (rev 4831)
+++ trunk/Tools/Maestro/MaestroAPI/HttpServerConnection.cs	2010-05-05 08:07:38 UTC (rev 4832)
@@ -490,7 +490,7 @@
             ResourceIdentifier.Validate(featureSourceID, ResourceTypes.FeatureSource);
             string req = m_reqBuilder.ExecuteSqlQuery(featureSourceID, sql);
 
-            return new FeatureSetReader(this.OpenRead(req));
+            return new XmlFeatureSetReader(this.OpenRead(req));
         }
 
 		public FeatureSetReader QueryFeatureSource(string resourceID, string schema, string query)
@@ -532,7 +532,7 @@
                     rs.Flush();
                 }
 
-                return new FeatureSetReader(req.GetResponse().GetResponseStream());
+                return new XmlFeatureSetReader(req.GetResponse().GetResponseStream());
             }
             catch (Exception ex)
             {

Modified: trunk/Tools/Maestro/MaestroAPI/LocalNativeConnection.cs
===================================================================
--- trunk/Tools/Maestro/MaestroAPI/LocalNativeConnection.cs	2010-05-05 00:46:05 UTC (rev 4831)
+++ trunk/Tools/Maestro/MaestroAPI/LocalNativeConnection.cs	2010-05-05 08:07:38 UTC (rev 4832)
@@ -156,7 +156,8 @@
 			get
 			{
 				MgFeatureService fes = this.Con.CreateService(MgServiceType.FeatureService) as MgFeatureService;
-				return (FeatureProviderRegistryFeatureProviderCollection) base.DeserializeObject(typeof(ResourceList), Utility.MgStreamToNetStream(fes, fes.GetType().GetMethod("GetFeatureProviders"), new object[] { }));
+                var reg = (FeatureProviderRegistry)base.DeserializeObject(typeof(FeatureProviderRegistry), Utility.MgStreamToNetStream(fes, fes.GetType().GetMethod("GetFeatureProviders"), new object[] { }));
+                return reg.FeatureProvider;
 			}
 		}
 
@@ -188,7 +189,7 @@
 
 		public FdoProviderCapabilities GetProviderCapabilities(string provider)
 		{
-			MgFeatureService fes = this.Con.CreateService(MgServiceType.ResourceService) as MgFeatureService;
+			MgFeatureService fes = this.Con.CreateService(MgServiceType.FeatureService) as MgFeatureService;
 			return (FdoProviderCapabilities) base.DeserializeObject(typeof(FdoProviderCapabilities), Utility.MgStreamToNetStream(fes, fes.GetType().GetMethod("GetCapabilities"), new object[] { provider }));
 		}
 
@@ -205,12 +206,12 @@
 			return Utility.MgStreamToNetStream(res, res.GetType().GetMethod("GetResourceContent"), new object[] { new MgResourceIdentifier(resourceID) }).ToArray();
 		}
 
-		public override FeatureProviderRegistryFeatureProvider GetFeatureProvider(string providername)
-		{
-			MgFeatureService fes = this.Con.CreateService(MgServiceType.FeatureService) as MgFeatureService;
-			System.IO.MemoryStream ms = Utility.MgStreamToNetStream(fes, fes.GetType().GetMethod("GetCapabilities"), new object[] { providername });
-			return (FeatureProviderRegistryFeatureProvider)DeserializeObject(typeof(FeatureProviderRegistryFeatureProvider), ms);
-		}
+        //public override FeatureProviderRegistryFeatureProvider GetFeatureProvider(string providername)
+        //{
+        //    MgFeatureService fes = this.Con.CreateService(MgServiceType.FeatureService) as MgFeatureService;
+        //    System.IO.MemoryStream ms = Utility.MgStreamToNetStream(fes, fes.GetType().GetMethod("GetCapabilities"), new object[] { providername });
+        //    return (FeatureProviderRegistryFeatureProvider)DeserializeObject(typeof(FeatureProviderRegistryFeatureProvider), ms);
+        //}
 
 		public System.IO.Stream GetMapDWF(string resourceID)
 		{
@@ -245,7 +246,7 @@
         {
             MgFeatureService fes = this.Con.CreateService(MgServiceType.FeatureService) as MgFeatureService;
             MgSqlDataReader reader = fes.ExecuteSqlQuery(new MgResourceIdentifier(featureSourceID), sql);
-            return new FeatureSetReader(reader);
+            return new MgFeatureSetReader(reader);
         }
 
 		public FeatureSetReader QueryFeatureSource(string resourceID, string schema, string query)
@@ -277,8 +278,12 @@
             if (computedProperties != null && computedProperties.Count > 0)
                 foreach (string s in computedProperties.Keys)
                     mgf.AddComputedProperty(s, computedProperties[s]);
+
+            MgReader mr = fes.SelectFeatures(new MgResourceIdentifier(resourceID), schema, mgf);
+
             
-   			return new FeatureSetReader(fes.SelectFeatures(new MgResourceIdentifier(resourceID), schema, mgf));
+
+   			return new MgFeatureSetReader(mr);
 		}
 
         private FeatureSetReader AggregateQueryFeatureSourceCore(string resourceID, string schema, string query, string[] columns, System.Collections.Specialized.NameValueCollection computedProperties)
@@ -296,7 +301,7 @@
                 foreach (string s in computedProperties.Keys)
                     mgf.AddComputedProperty(s, computedProperties[s]);
 
-            return new FeatureSetReader(fes.SelectAggregate(new MgResourceIdentifier(resourceID), schema, mgf));
+            return new MgFeatureSetReader(fes.SelectAggregate(new MgResourceIdentifier(resourceID), schema, mgf));
         }
 
         public override FeatureSetReader AggregateQueryFeatureSource(string resourceID, string schema, string filter, string[] columns)

Added: trunk/Tools/Maestro/MaestroAPI/MgFeatureSetReader.cs
===================================================================
--- trunk/Tools/Maestro/MaestroAPI/MgFeatureSetReader.cs	                        (rev 0)
+++ trunk/Tools/Maestro/MaestroAPI/MgFeatureSetReader.cs	2010-05-05 08:07:38 UTC (rev 4832)
@@ -0,0 +1,187 @@
+#region Disclaimer / License
+// Copyright (C) 2010, 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;
+
+namespace OSGeo.MapGuide.MaestroAPI
+{
+    public class MgFeatureSetReader : FeatureSetReader
+    {
+        private OSGeo.MapGuide.MgReader m_rd;
+
+        public MgFeatureSetReader(OSGeo.MapGuide.MgReader mr) : base()
+		{
+			m_rd = mr;
+
+            FeatureSetColumn[] cols = new FeatureSetColumn[mr.GetPropertyCount()];
+            for (int i = 0; i < cols.Length; i++)
+                cols[i] = new MgFeatureSetColumn(mr.GetPropertyName(i), mr.GetPropertyType(mr.GetPropertyName(i)));
+
+            InitColumns(cols);
+		}
+
+        protected override bool ReadInternal()
+        {
+            return m_rd.ReadNext();
+        }
+
+        protected override FeatureSetRow ProcessFeatureRow()
+        {
+            return new MgFeatureSetRow(this, m_rd);
+        }
+
+        protected override void CloseInternal()
+        {
+            m_rd.Close();
+        }
+
+        public override int Depth
+        {
+            get
+            {
+                return -1;
+            }
+        }
+
+        public override System.Data.DataTable GetSchemaTable()
+        {
+            throw new NotImplementedException();
+        }
+
+        public override int RecordsAffected
+        {
+            get { throw new NotImplementedException(); }
+        }
+    }
+
+    public class MgFeatureSetRow : FeatureSetRow
+    {
+        private Topology.IO.MapGuide.MgReader m_mgReader = null;
+
+        private Topology.IO.MapGuide.MgReader MgReader
+        {
+            get
+            {
+                if (m_mgReader == null)
+                {
+                    m_mgReader = new Topology.IO.MapGuide.MgReader();
+                }
+
+                return m_mgReader;
+            }
+        }
+
+        internal MgFeatureSetRow(FeatureSetReader parent, OSGeo.MapGuide.MgReader rd)
+			: base(parent)
+		{
+			for(int i = 0; i < m_parent.Columns.Length; i++)
+			{
+				string p = m_parent.Columns[i].Name;
+				int ordinal = GetOrdinal(p);
+				m_nulls[ordinal] = rd.IsNull(p);
+
+                if (!m_nulls[ordinal])
+                {
+                    if (parent.Columns[ordinal].Type == typeof(string))
+                        m_items[ordinal] = rd.GetString(p);
+                    else if (parent.Columns[ordinal].Type == typeof(int))
+                        m_items[ordinal] = rd.GetInt32(p);
+                    else if (parent.Columns[ordinal].Type == typeof(long))
+                        m_items[ordinal] = rd.GetInt64(p);
+                    else if (parent.Columns[ordinal].Type == typeof(short))
+                        m_items[ordinal] = rd.GetInt16(p);
+                    else if (parent.Columns[ordinal].Type == typeof(double))
+                        m_items[ordinal] = rd.GetDouble(p);
+                    else if (parent.Columns[ordinal].Type == typeof(float))
+                        m_items[ordinal] = rd.GetSingle(p);
+                    else if (parent.Columns[ordinal].Type == typeof(bool))
+                        m_items[ordinal] = rd.GetBoolean(p);
+                    else if (parent.Columns[ordinal].Type == typeof(DateTime))
+                    {
+                        MgDateTime t = rd.GetDateTime(p);
+                        try
+                        {
+                            m_items[ordinal] = new DateTime(t.Year, t.Month, t.Day, t.Hour, t.Minute, t.Second);
+                        }
+                        catch(Exception ex)
+                        {
+                            //Unfortunately FDO supports invalid dates, such as the 30th feb
+                            m_nulls[ordinal] = true;
+                            m_items[ordinal] = ex;
+                        }
+                    }
+                    else if (parent.Columns[ordinal].Type == Utility.GeometryType)
+                    {
+                        //TODO: Uncomment this once the Topology.Net API gets updated to 2.0.0
+                        //It is optional to include the Topology.IO.MapGuide dll
+                        /*if (this.MgReader != null)
+                            m_items[ordinal] = this.MgReader.ReadGeometry(ref rd, p);
+                        else*/
+                        {
+                            //No MapGuide dll, convert to WKT and then to internal representation
+                            System.IO.MemoryStream ms = Utility.MgStreamToNetStream(rd, rd.GetType().GetMethod("GetGeometry"), new string[] { p });
+                            OSGeo.MapGuide.MgAgfReaderWriter rdw = new OSGeo.MapGuide.MgAgfReaderWriter();
+                            OSGeo.MapGuide.MgGeometry g = rdw.Read(rd.GetGeometry(p));
+                            OSGeo.MapGuide.MgWktReaderWriter rdww = new OSGeo.MapGuide.MgWktReaderWriter();
+                            m_items[ordinal] = this.Reader.Read(rdww.Write(g));
+                        }
+                    }
+                    else if (parent.Columns[ordinal].Type == Utility.UnmappedType)
+                    {
+                        //Attempt to read it as a string
+                        try { m_items[ordinal] = rd.GetString(p); }
+                        catch { m_items[ordinal] = null; }
+                    }
+                    else
+                        throw new Exception("Unknown type: " + parent.Columns[ordinal].Type.FullName);
+                }
+			}
+		}
+
+        public object this[int index]
+        {
+            get
+            {
+                if (index >= m_items.Length)
+                    throw new InvalidOperationException("Index " + index.ToString() + ", was out of bounds");
+                else
+                {
+                    if (m_lazyloadGeometry[index] && !m_nulls[index])
+                    {
+                        m_items[index] = this.Reader.Read((string)m_items[index]);
+                        m_lazyloadGeometry[index] = false;
+                    }
+
+                    return m_items[index];
+                }
+            }
+        }
+    }
+
+    public class MgFeatureSetColumn : FeatureSetColumn
+    {
+        internal MgFeatureSetColumn(string name, int type) : base()
+		{
+			m_name = name;
+			m_type = Utility.ConvertMgTypeToNetType(type);
+		}
+    }
+}

Modified: trunk/Tools/Maestro/MaestroAPI/OSGeo.MapGuide.MaestroAPI.csproj
===================================================================
--- trunk/Tools/Maestro/MaestroAPI/OSGeo.MapGuide.MaestroAPI.csproj	2010-05-05 00:46:05 UTC (rev 4831)
+++ trunk/Tools/Maestro/MaestroAPI/OSGeo.MapGuide.MaestroAPI.csproj	2010-05-05 08:07:38 UTC (rev 4832)
@@ -1,7 +1,7 @@
 <Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5">
   <PropertyGroup>
     <ProjectType>Local</ProjectType>
-    <ProductVersion>9.0.21022</ProductVersion>
+    <ProductVersion>9.0.30729</ProductVersion>
     <SchemaVersion>2.0</SchemaVersion>
     <ProjectGuid>{290B027E-3649-4A60-A9BF-0544831435E2}</ProjectGuid>
     <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
@@ -90,7 +90,7 @@
   <ItemGroup>
     <Reference Include="MapGuideDotNetApi, Version=2.0.0.2308, Culture=neutral, PublicKeyToken=f526c48929fda856, processorArchitecture=MSIL">
       <SpecificVersion>False</SpecificVersion>
-      <HintPath>MapGuideDotNetApi.dll</HintPath>
+      <HintPath>.\MapGuideDotNetApi.dll</HintPath>
     </Reference>
     <Reference Include="System">
       <Name>System</Name>
@@ -287,6 +287,7 @@
       <SubType>Code</SubType>
     </Compile>
     <Compile Include="LocalNativeCoordinateSystem.cs" />
+    <Compile Include="MgFeatureSetReader.cs" />
     <Compile Include="RequestBuilder.cs">
       <SubType>Code</SubType>
     </Compile>
@@ -313,6 +314,7 @@
     <Compile Include="Utility.cs">
       <SubType>Code</SubType>
     </Compile>
+    <Compile Include="XmlFeatureSetReader.cs" />
     <Compile Include="XmlSerializer\XmlSerializerAttribute.cs">
       <SubType>Code</SubType>
     </Compile>

Added: trunk/Tools/Maestro/MaestroAPI/XmlFeatureSetReader.cs
===================================================================
--- trunk/Tools/Maestro/MaestroAPI/XmlFeatureSetReader.cs	                        (rev 0)
+++ trunk/Tools/Maestro/MaestroAPI/XmlFeatureSetReader.cs	2010-05-05 08:07:38 UTC (rev 4832)
@@ -0,0 +1,329 @@
+#region Disclaimer / License
+// Copyright (C) 2010, 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.Xml;
+using System.IO;
+
+namespace OSGeo.MapGuide.MaestroAPI
+{
+    public class XmlFeatureSetReader : FeatureSetReader
+    {
+        private XmlTextReader m_reader;
+
+		//TODO: Make internal
+        public XmlFeatureSetReader(Stream m_source) : base()
+		{
+			m_reader = new XmlTextReader(m_source);
+			m_reader.WhitespaceHandling = WhitespaceHandling.Significant;
+
+			//First we extract the response layout
+			m_reader.Read();
+			if (m_reader.Name != "xml")
+				throw new Exception("Bad document");
+			m_reader.Read();
+			if (m_reader.Name != "FeatureSet" && m_reader.Name != "PropertySet" && m_reader.Name != "RowSet")
+				throw new Exception("Bad document");
+
+            m_reader.Read();
+            if (m_reader.Name != "xs:schema" && m_reader.Name != "PropertyDefinitions" && m_reader.Name != "ColumnDefinitions")
+                throw new Exception("Bad document");
+
+			XmlDocument doc = new XmlDocument();
+			doc.LoadXml(m_reader.ReadOuterXml());
+			XmlNamespaceManager mgr = new XmlNamespaceManager(doc.NameTable);
+			mgr.AddNamespace("xs", "http://www.w3.org/2001/XMLSchema");
+			mgr.AddNamespace("gml", "http://www.opengis.net/gml");
+			mgr.AddNamespace("fdo", "http://fdo.osgeo.org/schemas");
+
+			//TODO: Assumes there is only one type returned... perhaps more can be returned....
+			XmlNodeList lst = doc.SelectNodes("xs:schema/xs:complexType/xs:complexContent/xs:extension/xs:sequence/xs:element", mgr);
+			if (lst.Count == 0)
+				lst = doc.SelectNodes("xs:schema/xs:complexType/xs:sequence/xs:element", mgr);
+            if (lst.Count == 0)
+                lst = doc.SelectNodes("PropertyDefinitions/PropertyDefinition");
+            if (lst.Count == 0)
+                lst = doc.SelectNodes("ColumnDefinitions/Column");
+			FeatureSetColumn[] cols = new FeatureSetColumn[lst.Count];
+			for(int i = 0;i<lst.Count;i++)
+                cols[i] = new XmlFeatureSetColumn(lst[i]);
+
+            InitColumns(cols);
+
+			m_row = null;
+
+			if (m_reader.Name != "Features" && m_reader.Name != "Properties" && m_reader.Name != "Rows")
+				throw new Exception("Bad document");
+
+			m_reader.Read();
+
+            if (m_reader.NodeType != XmlNodeType.EndElement)
+            {
+                if (m_reader.Name == "Features")
+                    m_reader = null; //No features :(
+                else if (m_reader.Name == "PropertyCollection" || m_reader.Name == "Row")
+                {
+                    //OK
+                }
+                else if (m_reader.Name != "Feature")
+                    throw new Exception("Bad document");
+            }
+		}
+
+        protected override bool ReadInternal()
+        {
+            if (m_reader == null || (m_reader.Name != "Feature" && m_reader.Name != "PropertyCollection" && m_reader.Name != "Row"))
+            {
+                m_row = null;
+                return false;
+            }
+            return true;
+        }
+
+        protected override FeatureSetRow ProcessFeatureRow()
+        {
+            string xmlfragment = m_reader.ReadOuterXml();
+            XmlDocument doc = new XmlDocument();
+            doc.LoadXml(xmlfragment);
+
+            FeatureSetRow row = null;
+
+            if (doc["Row"] != null)
+                row = new XmlFeatureSetRow(this, doc["Row"]);
+            else if (doc["Feature"] == null)
+                row = new XmlFeatureSetRow(this, doc["PropertyCollection"]);
+            else
+                row = new XmlFeatureSetRow(this, doc["Feature"]);
+
+            if (m_reader.Name != "Feature" && m_reader.Name != "PropertyCollection" && m_reader.Name != "Row")
+            {
+                m_reader.Close();
+                m_reader = null;
+            }
+
+            return row;
+        }
+
+        protected override void CloseInternal()
+        {
+            throw new NotImplementedException();
+        }
+
+        public override int Depth
+        {
+            get { throw new NotImplementedException(); }
+        }
+
+        public override System.Data.DataTable GetSchemaTable()
+        {
+            throw new NotImplementedException();
+        }
+
+        public override int RecordsAffected
+        {
+            get { throw new NotImplementedException(); }
+        }
+    }
+
+    public class XmlFeatureSetRow : FeatureSetRow
+    {
+        internal XmlFeatureSetRow(FeatureSetReader parent, XmlNode node)
+			: base(parent)
+		{
+            string nodeName = "Property";
+            if (node.Name == "Row")
+                nodeName = "Column";
+
+            foreach (XmlNode p in node.SelectNodes(nodeName))
+            {
+                int ordinal = GetOrdinal(p["Name"].InnerText);
+                if (!m_nulls[ordinal])
+                    throw new Exception("Bad document, multiple: " + p["Name"].InnerText + " values in a single feature");
+                m_nulls[ordinal] = false;
+
+                if (parent.Columns[ordinal].Type == typeof(string) || parent.Columns[ordinal].Type == Utility.UnmappedType)
+                    m_items[ordinal] = p["Value"].InnerText;
+                else if (parent.Columns[ordinal].Type == typeof(int))
+                    m_items[ordinal] = XmlConvert.ToInt32(p["Value"].InnerText);
+                else if (parent.Columns[ordinal].Type == typeof(long))
+                    m_items[ordinal] = XmlConvert.ToInt64(p["Value"].InnerText);
+                else if (parent.Columns[ordinal].Type == typeof(short))
+                    m_items[ordinal] = XmlConvert.ToInt16(p["Value"].InnerText);
+                else if (parent.Columns[ordinal].Type == typeof(double))
+                    m_items[ordinal] = XmlConvert.ToDouble(p["Value"].InnerText);
+                else if (parent.Columns[ordinal].Type == typeof(bool))
+                    m_items[ordinal] = XmlConvert.ToBoolean(p["Value"].InnerText);
+                else if (parent.Columns[ordinal].Type == typeof(DateTime))
+                {
+                    try
+                    {
+                        //Fix for broken ODBC provider
+                        string v = p["Value"].InnerText;
+
+                        if (v.Trim().ToUpper().StartsWith("TIMESTAMP"))
+                            v = v.Trim().Substring("TIMESTAMP".Length).Trim();
+                        else if (v.Trim().ToUpper().StartsWith("DATE"))
+                            v = v.Trim().Substring("DATE".Length).Trim();
+                        else if (v.Trim().ToUpper().StartsWith("TIME"))
+                            v = v.Trim().Substring("TIME".Length).Trim();
+
+                        if (v != p["Value"].InnerText)
+                        {
+                            if (v.StartsWith("'"))
+                                v = v.Substring(1);
+                            if (v.EndsWith("'"))
+                                v = v.Substring(0, v.Length - 1);
+
+                            m_items[ordinal] = DateTime.Parse(v, System.Globalization.CultureInfo.InvariantCulture, System.Globalization.DateTimeStyles.NoCurrentDateDefault);
+                        }
+                        else
+                            m_items[ordinal] = XmlConvert.ToDateTime(v, XmlDateTimeSerializationMode.Unspecified);
+                    }
+                    catch (Exception ex)
+                    {
+                        //Unfortunately FDO supports invalid dates, such as the 30th feb
+                        m_nulls[ordinal] = true;
+                        m_items[ordinal] = ex;
+                    }
+                }
+                else if (parent.Columns[ordinal].Type == Utility.GeometryType)
+                {
+                    m_items[ordinal] = p["Value"].InnerText;
+                    if (string.IsNullOrEmpty(p["Value"].InnerText))
+                    {
+                        m_nulls[ordinal] = true;
+                        m_items[ordinal] = null;
+                    }
+                    else
+                        m_lazyloadGeometry[ordinal] = true;
+                }
+                else
+                    throw new Exception("Unknown type: " + parent.Columns[ordinal].Type.FullName);
+            }
+		}
+    }
+
+    public class XmlFeatureSetColumn : FeatureSetColumn
+    {
+        internal XmlFeatureSetColumn(XmlNode node) : base()
+		{
+            if (node.Name == "PropertyDefinition" || node.Name == "Column")
+            {
+                m_name = node["Name"].InnerText;
+                m_allowNull = true;
+                switch (node["Type"].InnerText.ToLower().Trim())
+                {
+                    case "string":
+                        m_type = typeof(string);
+                        break;
+                    case "byte":
+                        m_type = typeof(Byte);
+                        break;
+                    case "int32":
+                    case "int":
+                    case "integer":
+                        m_type = typeof(int);
+                        break;
+                    case "int16":
+                        m_type = typeof(short);
+                        break;
+                    case "int64":
+                    case "long":
+                        m_type = typeof(long);
+                        break;
+                    case "float":
+                    case "single":
+                        m_type = typeof(float);
+                        break;
+                    case "double":
+                    case "decimal":
+                        m_type = typeof(double);
+                        break;
+                    case "boolean":
+                    case "bool":
+                        m_type = typeof(bool);
+                        return;
+                    case "datetime":
+                    case "date":
+                        m_type = typeof(DateTime);
+                        break;
+                    case "raster":
+                        m_type = Utility.RasterType;
+                        break;
+                    case "geometry":
+                        m_type = Utility.GeometryType;
+                        break;
+                    default:
+                        //throw new Exception("Failed to find appropriate type for: " + node["xs:simpleType"]["xs:restriction"].Attributes["base"].Value);
+                        m_type = Utility.UnmappedType;
+                        break;
+                }
+            }
+            else
+            {
+                m_name = node.Attributes["name"].Value;
+                m_allowNull = node.Attributes["minOccurs"] != null && node.Attributes["minOccurs"].Value == "0";
+                if (node.Attributes["type"] != null && node.Attributes["type"].Value == "gml:AbstractGeometryType")
+                    m_type = Utility.GeometryType;
+                else if (node["xs:simpleType"] == null)
+                    m_type = Utility.RasterType;
+                else
+                    switch (node["xs:simpleType"]["xs:restriction"].Attributes["base"].Value.ToLower())
+                    {
+                        case "xs:string":
+                            m_type = typeof(string);
+                            break;
+                        case "fdo:byte":
+                            m_type = typeof(Byte);
+                            break;
+                        case "fdo:int32":
+                            m_type = typeof(int);
+                            break;
+                        case "fdo:int16":
+                            m_type = typeof(short);
+                            break;
+                        case "fdo:int64":
+                            m_type = typeof(long);
+                            break;
+                        case "xs:float":
+                        case "xs:single":
+                        case "fdo:single":
+                            m_type = typeof(float);
+                            break;
+                        case "xs:double":
+                        case "xs:decimal":
+                            m_type = typeof(double);
+                            break;
+                        case "xs:boolean":
+                            m_type = typeof(bool);
+                            return;
+                        case "xs:datetime":
+                            m_type = typeof(DateTime);
+                            break;
+                        default:
+                            //throw new Exception("Failed to find appropriate type for: " + node["xs:simpleType"]["xs:restriction"].Attributes["base"].Value);
+                            m_type = Utility.UnmappedType;
+                            break;
+                    }
+            }
+		}
+    }
+}



More information about the mapguide-commits mailing list