[mapguide-commits] r6903 - in branches/2.4/MgDev/Desktop/MgDesktop: . Services Services/Feature Services/Feature/Commands

svn_mapguide at osgeo.org svn_mapguide at osgeo.org
Sun Jul 15 09:59:27 PDT 2012


Author: jng
Date: 2012-07-15 09:59:27 -0700 (Sun, 15 Jul 2012)
New Revision: 6903

Added:
   branches/2.4/MgDev/Desktop/MgDesktop/Services/CryptoDefs.h
   branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/
   branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/ApplySchema.cpp
   branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/ApplySchema.h
   branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/DeleteCommand.cpp
   branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/DeleteCommand.h
   branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/FeatureManipulationCommand.cpp
   branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/FeatureManipulationCommand.h
   branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/FeatureServiceCommand.cpp
   branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/FeatureServiceCommand.h
   branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/GetConnectionPropertyValues.cpp
   branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/GetConnectionPropertyValues.h
   branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/GetFeatureProviders.cpp
   branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/GetFeatureProviders.h
   branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/GetLongTransactions.cpp
   branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/GetLongTransactions.h
   branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/GetProviderCapabilities.cpp
   branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/GetProviderCapabilities.h
   branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/GetSchemaMapping.cpp
   branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/GetSchemaMapping.h
   branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/GetSpatialContexts.cpp
   branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/GetSpatialContexts.h
   branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/InsertCommand.cpp
   branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/InsertCommand.h
   branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/SelectAggregateCommand.cpp
   branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/SelectAggregateCommand.h
   branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/SelectCommand.cpp
   branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/SelectCommand.h
   branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/SelectFeatures.cpp
   branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/SelectFeatures.h
   branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/SqlCommand.cpp
   branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/SqlCommand.h
   branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/UpdateCommand.cpp
   branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/UpdateCommand.h
   branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/UpdateFeatures.cpp
   branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/UpdateFeatures.h
   branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/FdoFeatureReader.cpp
   branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/FdoFeatureReader.h
   branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/FdoFilterCollection.cpp
   branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/FdoFilterCollection.h
   branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/FdoReaderCollection.cpp
   branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/FdoReaderCollection.h
   branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/FeatureSetReader.cpp
   branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/FeatureSetReader.h
Removed:
   branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/FeautreNumericFunctions.h
Modified:
   branches/2.4/MgDev/Desktop/MgDesktop/MgDesktop.vcproj
   branches/2.4/MgDev/Desktop/MgDesktop/MgDesktopBuild.cpp
   branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/FeatureDefs.h
   branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/FeatureUtil.cpp
   branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/FeatureUtil.h
Log:
mg-desktop changes:
 - Graft a significant chunk of the MgServerFeatureService project (commands and supporting classes) into mg-desktop. Rather than re-implementing most of the MgFeatureService APIs from scratch with mixed results, let's just re-use the already vetted code and logic from that library. This will not only eventually fix #2074, but also shrink down the size of FeatureService.cpp

Modified: branches/2.4/MgDev/Desktop/MgDesktop/MgDesktop.vcproj
===================================================================
--- branches/2.4/MgDev/Desktop/MgDesktop/MgDesktop.vcproj	2012-07-15 15:04:11 UTC (rev 6902)
+++ branches/2.4/MgDev/Desktop/MgDesktop/MgDesktop.vcproj	2012-07-15 16:59:27 UTC (rev 6903)
@@ -400,6 +400,42 @@
 				</FileConfiguration>
 			</File>
 			<File
+				RelativePath=".\Services\Feature\Commands\ApplySchema.cpp"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|x64"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|x64"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
 				RelativePath=".\Services\Resource\ByteSourceDwfInputStreamImpl.cpp"
 				>
 				<FileConfiguration
@@ -688,6 +724,42 @@
 				</FileConfiguration>
 			</File>
 			<File
+				RelativePath=".\Services\Feature\Commands\DeleteCommand.cpp"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|x64"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|x64"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
 				RelativePath=".\Services\DrawingService.cpp"
 				>
 				<FileConfiguration
@@ -1048,6 +1120,78 @@
 				</FileConfiguration>
 			</File>
 			<File
+				RelativePath=".\Services\Feature\FdoFeatureReader.cpp"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|x64"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|x64"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath=".\Services\Feature\FdoFilterCollection.cpp"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|x64"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|x64"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
 				RelativePath=".\Services\Feature\FdoForcedOneToOneFeatureReader.cpp"
 				>
 				<FileConfiguration
@@ -1084,6 +1228,42 @@
 				</FileConfiguration>
 			</File>
 			<File
+				RelativePath=".\Services\Feature\FdoReaderCollection.cpp"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|x64"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|x64"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
 				RelativePath=".\Services\Feature\FeatureClassCacheItem.cpp"
 				>
 				<FileConfiguration
@@ -1300,6 +1480,42 @@
 				</FileConfiguration>
 			</File>
 			<File
+				RelativePath=".\Services\Feature\Commands\FeatureManipulationCommand.cpp"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|x64"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|x64"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
 				RelativePath=".\Services\Feature\FeatureNumericFunctions.cpp"
 				>
 				<FileConfiguration
@@ -1516,6 +1732,78 @@
 				</FileConfiguration>
 			</File>
 			<File
+				RelativePath=".\Services\Feature\Commands\FeatureServiceCommand.cpp"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|x64"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|x64"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath=".\Services\Feature\FeatureSetReader.cpp"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|x64"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|x64"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
 				RelativePath=".\Services\Feature\FeatureSourceCacheItem.cpp"
 				>
 				<FileConfiguration
@@ -1624,6 +1912,222 @@
 				</FileConfiguration>
 			</File>
 			<File
+				RelativePath=".\Services\Feature\Commands\GetConnectionPropertyValues.cpp"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|x64"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|x64"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath=".\Services\Feature\Commands\GetFeatureProviders.cpp"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|x64"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|x64"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath=".\Services\Feature\Commands\GetLongTransactions.cpp"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|x64"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|x64"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath=".\Services\Feature\Commands\GetProviderCapabilities.cpp"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|x64"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|x64"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath=".\Services\Feature\Commands\GetSchemaMapping.cpp"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|x64"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|x64"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath=".\Services\Feature\Commands\GetSpatialContexts.cpp"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|x64"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|x64"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
 				RelativePath=".\Services\Feature\GwsConnectionPool.cpp"
 				>
 				<FileConfiguration
@@ -1732,6 +2236,42 @@
 				</FileConfiguration>
 			</File>
 			<File
+				RelativePath=".\Services\Feature\Commands\InsertCommand.cpp"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|x64"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|x64"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
 				RelativePath=".\Exception\InvalidDwfPackageException.cpp"
 				>
 				<FileConfiguration
@@ -3320,6 +3860,114 @@
 				</FileConfiguration>
 			</File>
 			<File
+				RelativePath=".\Services\Feature\Commands\SelectAggregateCommand.cpp"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|x64"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|x64"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath=".\Services\Feature\Commands\SelectCommand.cpp"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|x64"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|x64"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath=".\Services\Feature\Commands\SelectFeatures.cpp"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|x64"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|x64"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
 				RelativePath=".\MapLayer\Selection.cpp"
 				>
 				<FileConfiguration
@@ -3464,6 +4112,42 @@
 				</FileConfiguration>
 			</File>
 			<File
+				RelativePath=".\Services\Feature\Commands\SqlCommand.cpp"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|x64"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|x64"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
 				RelativePath=".\Services\SqlReader.cpp"
 				>
 				<FileConfiguration
@@ -3896,6 +4580,78 @@
 				</FileConfiguration>
 			</File>
 			<File
+				RelativePath=".\Services\Feature\Commands\UpdateCommand.cpp"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|x64"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|x64"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath=".\Services\Feature\Commands\UpdateFeatures.cpp"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|x64"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|x64"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
 				RelativePath=".\Services\Resource\ZipFileHandler.cpp"
 				>
 				<FileConfiguration
@@ -3978,6 +4734,10 @@
 				>
 			</File>
 			<File
+				RelativePath=".\Services\Feature\Commands\ApplySchema.h"
+				>
+			</File>
+			<File
 				RelativePath=".\Services\Feature\BooleanDataReaderCreator.h"
 				>
 			</File>
@@ -4010,6 +4770,10 @@
 				>
 			</File>
 			<File
+				RelativePath=".\Services\CryptoDefs.h"
+				>
+			</File>
+			<File
 				RelativePath=".\Services\Rendering\CustomLogoInfo.h"
 				>
 			</File>
@@ -4030,6 +4794,10 @@
 				>
 			</File>
 			<File
+				RelativePath=".\Services\Feature\Commands\DeleteCommand.h"
+				>
+			</File>
+			<File
 				RelativePath=".\Services\Feature\DoubleDataReaderCreator.h"
 				>
 			</File>
@@ -4078,10 +4846,22 @@
 				>
 			</File>
 			<File
+				RelativePath=".\Services\Feature\FdoFeatureReader.h"
+				>
+			</File>
+			<File
+				RelativePath=".\Services\Feature\FdoFilterCollection.h"
+				>
+			</File>
+			<File
 				RelativePath=".\Services\Feature\FdoForcedOneToOneFeatureReader.h"
 				>
 			</File>
 			<File
+				RelativePath=".\Services\Feature\FdoReaderCollection.h"
+				>
+			</File>
+			<File
 				RelativePath=".\Services\Feature\FeatureClassCacheItem.h"
 				>
 			</File>
@@ -4110,6 +4890,10 @@
 				>
 			</File>
 			<File
+				RelativePath=".\Services\Feature\Commands\FeatureManipulationCommand.h"
+				>
+			</File>
+			<File
 				RelativePath=".\Services\Feature\FeatureNumericFunctions.h"
 				>
 			</File>
@@ -4134,6 +4918,14 @@
 				>
 			</File>
 			<File
+				RelativePath=".\Services\Feature\Commands\FeatureServiceCommand.h"
+				>
+			</File>
+			<File
+				RelativePath=".\Services\Feature\FeatureSetReader.h"
+				>
+			</File>
+			<File
 				RelativePath=".\Services\Feature\FeatureSourceCacheItem.h"
 				>
 			</File>
@@ -4146,14 +4938,34 @@
 				>
 			</File>
 			<File
-				RelativePath=".\Services\Feature\FeautreNumericFunctions.h"
+				RelativePath=".\Services\Feature\GeometryDataReaderCreator.h"
 				>
 			</File>
 			<File
-				RelativePath=".\Services\Feature\GeometryDataReaderCreator.h"
+				RelativePath=".\Services\Feature\Commands\GetConnectionPropertyValues.h"
 				>
 			</File>
 			<File
+				RelativePath=".\Services\Feature\Commands\GetFeatureProviders.h"
+				>
+			</File>
+			<File
+				RelativePath=".\Services\Feature\Commands\GetLongTransactions.h"
+				>
+			</File>
+			<File
+				RelativePath=".\Services\Feature\Commands\GetProviderCapabilities.h"
+				>
+			</File>
+			<File
+				RelativePath=".\Services\Feature\Commands\GetSchemaMapping.h"
+				>
+			</File>
+			<File
+				RelativePath=".\Services\Feature\Commands\GetSpatialContexts.h"
+				>
+			</File>
+			<File
 				RelativePath=".\Services\Feature\GwsConnectionPool.h"
 				>
 			</File>
@@ -4170,6 +4982,10 @@
 				>
 			</File>
 			<File
+				RelativePath=".\Services\Feature\Commands\InsertCommand.h"
+				>
+			</File>
+			<File
 				RelativePath=".\Services\Feature\Int16DataReaderCreator.h"
 				>
 			</File>
@@ -4386,6 +5202,18 @@
 				>
 			</File>
 			<File
+				RelativePath=".\Services\Feature\Commands\SelectAggregateCommand.h"
+				>
+			</File>
+			<File
+				RelativePath=".\Services\Feature\Commands\SelectCommand.h"
+				>
+			</File>
+			<File
+				RelativePath=".\Services\Feature\Commands\SelectFeatures.h"
+				>
+			</File>
+			<File
 				RelativePath=".\MapLayer\Selection.h"
 				>
 			</File>
@@ -4406,6 +5234,10 @@
 				>
 			</File>
 			<File
+				RelativePath=".\Services\Feature\Commands\SqlCommand.h"
+				>
+			</File>
+			<File
 				RelativePath=".\Services\SqlReader.h"
 				>
 			</File>
@@ -4462,6 +5294,14 @@
 				>
 			</File>
 			<File
+				RelativePath=".\Services\Feature\Commands\UpdateCommand.h"
+				>
+			</File>
+			<File
+				RelativePath=".\Services\Feature\Commands\UpdateFeatures.h"
+				>
+			</File>
+			<File
 				RelativePath=".\Services\Resource\ZipFileHandler.h"
 				>
 			</File>

Modified: branches/2.4/MgDev/Desktop/MgDesktop/MgDesktopBuild.cpp
===================================================================
--- branches/2.4/MgDev/Desktop/MgDesktop/MgDesktopBuild.cpp	2012-07-15 15:04:11 UTC (rev 6902)
+++ branches/2.4/MgDev/Desktop/MgDesktop/MgDesktopBuild.cpp	2012-07-15 16:59:27 UTC (rev 6903)
@@ -49,7 +49,10 @@
 #include "Services/Feature/CreateFeatureSource.cpp"
 #include "Services/Feature/FdoConnectionPool.cpp"
 #include "Services/Feature/FdoConnectionUtil.cpp"
+#include "Services/Feature/FdoFeatureReader.cpp"
+#include "Services/Feature/FdoFilterCollection.cpp"
 #include "Services/Feature/FdoForcedOneToOneFeatureReader.cpp"
+#include "Services/Feature/FdoReaderCollection.cpp"
 #include "Services/Feature/FeatureClassCacheItem.cpp"
 #include "Services/Feature/FeatureConnection.cpp"
 #include "Services/Feature/FeatureDistribution.cpp"
@@ -58,6 +61,7 @@
 #include "Services/Feature/FeatureSchemaCacheItem.cpp"
 #include "Services/Feature/FeatureServiceCacheEntry.cpp"
 #include "Services/Feature/FeatureServiceCache.cpp"
+#include "Services/Feature/FeatureSetReader.cpp"
 #include "Services/Feature/FeatureSourceCacheItem.cpp"
 #include "Services/Feature/FeatureStringFunctions.cpp"
 #include "Services/Feature/FeatureUtil.cpp"
@@ -71,6 +75,23 @@
 #include "Services/Feature/RdbmsFeatureSourceParams.cpp"
 #include "Services/Feature/SpatialContextCacheItem.cpp"
 #include "Services/Feature/TransformCache.cpp"
+#include "Services/Feature/Commands/ApplySchema.cpp"
+#include "Services/Feature/Commands/DeleteCommand.cpp"
+#include "Services/Feature/Commands/FeatureManipulationCommand.cpp"
+#include "Services/Feature/Commands/FeatureServiceCommand.cpp"
+#include "Services/Feature/Commands/GetConnectionPropertyValues.cpp"
+#include "Services/Feature/Commands/GetFeatureProviders.cpp"
+#include "Services/Feature/Commands/GetLongTransactions.cpp"
+#include "Services/Feature/Commands/GetProviderCapabilities.cpp"
+#include "Services/Feature/Commands/GetSchemaMapping.cpp"
+#include "Services/Feature/Commands/GetSpatialContexts.cpp"
+#include "Services/Feature/Commands/InsertCommand.cpp"
+#include "Services/Feature/Commands/SelectAggregateCommand.cpp"
+#include "Services/Feature/Commands/SelectCommand.cpp"
+#include "Services/Feature/Commands/SelectFeatures.cpp"
+#include "Services/Feature/Commands/SqlCommand.cpp"
+#include "Services/Feature/Commands/UpdateCommand.cpp"
+#include "Services/Feature/Commands/UpdateFeatures.cpp"
 
 #include "Services/Rendering/CustomLogoInfo.cpp"
 #include "Services/Rendering/CustomTextInfo.cpp"

Added: branches/2.4/MgDev/Desktop/MgDesktop/Services/CryptoDefs.h
===================================================================
--- branches/2.4/MgDev/Desktop/MgDesktop/Services/CryptoDefs.h	                        (rev 0)
+++ branches/2.4/MgDev/Desktop/MgDesktop/Services/CryptoDefs.h	2012-07-15 16:59:27 UTC (rev 6903)
@@ -0,0 +1,113 @@
+#ifndef DESKTOP_CRYPTO_DEFS_H
+#define DESKTOP_CRYPTO_DEFS_H
+
+#include "SecurityDefs.h"
+#include "CryptographyUtil.h"
+
+///////////////////////////////////////////////////////////////////////////////
+/// Helper macros.
+///
+#define MG_CRYPTOGRAPHY_TRY()                                                 \
+    Ptr<MgException> cryptographyException;                                   \
+                                                                              \
+    try                                                                       \
+    {                                                                         \
+
+#define MG_CRYPTOGRAPHY_CATCH(methodName)                                     \
+    }                                                                         \
+    catch (MgErrorCode errorCode)                                             \
+    {                                                                         \
+        switch (errorCode)                                                    \
+        {                                                                     \
+            case ecOk:                                                        \
+                break;                                                        \
+                                                                              \
+            case ecInvalidOperation:                                          \
+                cryptographyException = new MgInvalidOperationException(      \
+                    methodName, __LINE__, __WFILE__, NULL, L"", NULL);        \
+                break;                                                        \
+                                                                              \
+            case ecNullArgument:                                              \
+                cryptographyException = new MgNullArgumentException(          \
+                    methodName, __LINE__, __WFILE__, NULL, L"", NULL);        \
+                break;                                                        \
+                                                                              \
+            case ecInvalidArgument:                                           \
+                cryptographyException = new MgInvalidArgumentException(       \
+                    methodName, __LINE__, __WFILE__, NULL, L"", NULL);        \
+                break;                                                        \
+                                                                              \
+            case ecLengthError:                                               \
+                cryptographyException = new MgLengthException(                \
+                    methodName, __LINE__, __WFILE__, NULL, L"", NULL);        \
+                break;                                                        \
+                                                                              \
+            case ecDateTimeError:                                             \
+                cryptographyException = new MgDateTimeException(              \
+                    methodName, __LINE__, __WFILE__, NULL, L"", NULL);        \
+                break;                                                        \
+                                                                              \
+            case ecFileIoError:                                               \
+            case ecReadError:                                                 \
+            case ecWriteError:                                                \
+                cryptographyException = new MgFileIoException(                \
+                    methodName, __LINE__, __WFILE__, NULL, L"", NULL);        \
+                break;                                                        \
+                                                                              \
+            case ecEncryptionError:                                           \
+                cryptographyException = new MgEncryptionException(            \
+                    methodName, __LINE__, __WFILE__, NULL, L"", NULL);        \
+                break;                                                        \
+                                                                              \
+            case ecDecryptionError:                                           \
+                cryptographyException = new MgDecryptionException(            \
+                    methodName, __LINE__, __WFILE__, NULL, L"", NULL);        \
+                break;                                                        \
+                                                                              \
+            case ecUnclassified:                                              \
+            default:                                                          \
+                cryptographyException = new MgUnclassifiedException(          \
+                    methodName, __LINE__, __WFILE__, NULL, L"", NULL);        \
+                break;                                                        \
+        }                                                                     \
+    }                                                                         \
+    catch (MgException* e)                                                    \
+    {                                                                         \
+        cryptographyException = e;                                            \
+        cryptographyException->AddStackTraceInfo(                             \
+            methodName, __LINE__, __WFILE__);                                 \
+    }                                                                         \
+    catch (exception& e)                                                      \
+    {                                                                         \
+        cryptographyException = MgSystemException::Create(                    \
+            e, methodName, __LINE__, __WFILE__);                              \
+    }                                                                         \
+    catch (...)                                                               \
+    {                                                                         \
+        cryptographyException = new MgUnclassifiedException(                  \
+            methodName, __LINE__, __WFILE__, NULL, L"", NULL);                \
+    }                                                                         \
+
+#define MG_CRYPTOGRAPHY_THROW()                                               \
+    if (cryptographyException != NULL)                                        \
+    {                                                                         \
+        (*cryptographyException).AddRef();                                    \
+        cryptographyException->Raise();                                       \
+    }                                                                         \
+
+#define MG_CRYPTOGRAPHY_CATCH_AND_THROW(methodName)                           \
+    MG_CRYPTOGRAPHY_CATCH(methodName)                                         \
+                                                                              \
+    MG_CRYPTOGRAPHY_THROW()                                                   \
+
+#define MG_CRYPTOGRAPHY_CATCH_AND_RELEASE()                                   \
+    }                                                                         \
+    catch (MgException* e)                                                    \
+    {                                                                         \
+        cryptographyException = e;                                            \
+    }                                                                         \
+    catch (...)                                                               \
+    {                                                                         \
+    }                                                                         \
+
+#endif
\ No newline at end of file


Property changes on: branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands
___________________________________________________________________
Added: bugtraq:number
   + true

Added: branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/ApplySchema.cpp
===================================================================
--- branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/ApplySchema.cpp	                        (rev 0)
+++ branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/ApplySchema.cpp	2012-07-15 16:59:27 UTC (rev 6903)
@@ -0,0 +1,106 @@
+//
+//  Copyright (C) 2004-2011 by Autodesk, Inc.
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of version 2.1 of the GNU Lesser
+//  General Public License as published by the Free Software Foundation.
+//
+//  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 St, Fifth Floor, Boston, MA  02110-1301  USA
+//
+
+#include "Services/Feature/FeatureDefs.h"
+#include "ApplySchema.h"
+#include "Services/Feature/FeatureConnection.h"
+#include "Services/Feature/FeatureUtil.h"
+#include "Services/Feature/FeatureServiceCache.h"
+
+//////////////////////////////////////////////////////////////////
+MgServerApplySchema::MgServerApplySchema()
+{
+}
+
+//////////////////////////////////////////////////////////////////
+MgServerApplySchema::~MgServerApplySchema()
+{
+}
+
+///////////////////////////////////////////////////////////////////////////////
+void MgServerApplySchema::ApplySchema(MgResourceIdentifier* resource,
+    MgFeatureSchema* schema)
+{
+    MG_FEATURE_SERVICE_TRY()
+
+    if (NULL == resource || NULL == schema)
+    {
+        throw new MgNullArgumentException(L"MgServerApplySchema.ApplySchema", __LINE__, __WFILE__, NULL, L"", NULL);
+    }
+
+    // Connect to provider
+    Ptr<MgFeatureConnection> msfc = new MgFeatureConnection(resource);
+
+    // connection must be open
+    bool bRefresh = false;
+    if ((NULL != msfc.p) && ( msfc->IsConnectionOpen() ))
+    {
+        FdoPtr<FdoIConnection> fdoConn = msfc->GetConnection();
+
+        // Check whether command is supported by provider
+        if (!msfc->SupportsCommand((INT32)FdoCommandType_ApplySchema) ||
+            !msfc->SupportsCommand((INT32)FdoCommandType_DescribeSchema))
+        {
+            // TODO: specify which argument and message, once we have the mechanism
+            STRING message = MgFeatureUtil::GetMessage(L"MgCommandNotSupported");
+            throw new MgInvalidOperationException(L"MgServerApplySchema.ApplySchema", __LINE__, __WFILE__, NULL, L"", NULL);
+        }
+
+        FdoPtr<FdoIDescribeSchema> fdoDecribeSchemaCmd = (FdoIDescribeSchema*) fdoConn->CreateCommand(FdoCommandType_DescribeSchema);
+        CHECKNULL((FdoIDescribeSchema*)fdoDecribeSchemaCmd, L"MgServerApplySchema.ApplySchema");
+
+        FdoPtr<FdoFeatureSchemaCollection> schemas = fdoDecribeSchemaCmd->Execute();
+        CHECKNULL((FdoFeatureSchemaCollection*)schemas, L"MgServerApplySchema.ApplySchema");
+
+        FdoPtr<FdoIApplySchema> fdoApplySchemaCmd = (FdoIApplySchema*)fdoConn->CreateCommand(FdoCommandType_ApplySchema);
+        CHECKNULL((FdoIApplySchema*)fdoApplySchemaCmd, L"MgServerApplySchema.ApplySchema");
+
+        STRING schemaName = schema->GetName();
+        FdoPtr<FdoFeatureSchema> fdoOldSchema = schemas->FindItem(schemaName.c_str());
+        if (NULL == fdoOldSchema)
+        {
+            if (!schema->IsDeleted())
+            {
+                FdoPtr<FdoFeatureSchema> fdoNewSchema = MgFeatureUtil::GetFdoFeatureSchema(schema);
+                fdoApplySchemaCmd->SetFeatureSchema(fdoNewSchema);
+                fdoApplySchemaCmd->Execute();
+                bRefresh = true;
+            }
+        }
+        else
+        {
+            if (!schema->IsDeleted())
+                MgFeatureUtil::UpdateFdoFeatureSchema(schema, fdoOldSchema);
+            else
+                fdoOldSchema->Delete();
+
+            fdoApplySchemaCmd->SetFeatureSchema(fdoOldSchema);
+            fdoApplySchemaCmd->Execute();
+            bRefresh = true;
+        }
+    }
+
+    // Clear the cached schema so that MgFeatureService::DescribeSchema
+    // can return the correct schema
+    if (bRefresh)
+    {
+        MgFeatureServiceCache* m_cacheManager = MgFeatureServiceCache::GetInstance();
+        m_cacheManager->RemoveEntry(resource);
+    }
+
+    MG_FEATURE_SERVICE_CHECK_CONNECTION_CATCH_AND_THROW(resource, L"MgServerDescribeSchema.ApplySchema")
+}

Added: branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/ApplySchema.h
===================================================================
--- branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/ApplySchema.h	                        (rev 0)
+++ branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/ApplySchema.h	2012-07-15 16:59:27 UTC (rev 6903)
@@ -0,0 +1,37 @@
+//
+//  Copyright (C) 2004-2011 by Autodesk, Inc.
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of version 2.1 of the GNU Lesser
+//  General Public License as published by the Free Software Foundation.
+//
+//  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 St, Fifth Floor, Boston, MA  02110-1301  USA
+//
+
+#ifndef MG_SERVER_APPLY_SCHEMA_H_
+#define MG_SERVER_APPLY_SCHEMA_H_
+
+#include "MgDesktop.h"
+#include "System/XmlDefs.h"
+#include "System/XmlUtil.h"
+#include "Fdo.h"
+#include "FSDSAX2Parser.h"
+
+class MgServerApplySchema
+{
+/// Constructors/Destructor
+public:
+    MgServerApplySchema();
+    ~MgServerApplySchema();
+public:
+    void ApplySchema(MgResourceIdentifier* resource, MgFeatureSchema* schema);
+};
+
+#endif

Added: branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/DeleteCommand.cpp
===================================================================
--- branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/DeleteCommand.cpp	                        (rev 0)
+++ branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/DeleteCommand.cpp	2012-07-15 16:59:27 UTC (rev 6903)
@@ -0,0 +1,69 @@
+//
+//  Copyright (C) 2004-2011 by Autodesk, Inc.
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of version 2.1 of the GNU Lesser
+//  General Public License as published by the Free Software Foundation.
+//
+//  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 St, Fifth Floor, Boston, MA  02110-1301  USA
+//
+
+#include "Services/Feature/FeatureDefs.h"
+#include "MgDesktop.h"
+#include "Services/FeatureService.h"
+#include "Services/Feature/FeatureConnection.h"
+#include "FeatureManipulationCommand.h"
+#include "DeleteCommand.h"
+#include "Services/Feature/FeatureUtil.h"
+#include "Services/FeatureReader.h"
+
+MgServerDeleteCommand::MgServerDeleteCommand()
+{
+    m_srvrFeatConn = NULL;
+    m_featCommand = NULL;
+}
+
+MgServerDeleteCommand::MgServerDeleteCommand(MgFeatureCommand* command, MgFeatureConnection* connection, INT32 cmdId)
+{
+    CHECKNULL(command, L"MgServerDeleteCommand.MgServerDeleteCommand");
+    CHECKNULL(connection, L"MgServerDeleteCommand.MgServerDeleteCommand");
+
+    m_srvrFeatConn = SAFE_ADDREF((MgFeatureConnection*)connection);
+    m_featCommand = SAFE_ADDREF((MgDeleteFeatures*)command);
+    m_cmdId = cmdId;
+}
+
+MgServerDeleteCommand::~MgServerDeleteCommand()
+{
+    m_srvrFeatConn = NULL;
+}
+
+MgProperty* MgServerDeleteCommand::Execute()
+{
+    STRING clsName = m_featCommand->GetFeatureClassName();
+    STRING filterText = m_featCommand->GetFilterText();
+
+    FdoPtr<FdoIConnection> fdoConn = m_srvrFeatConn->GetConnection();
+
+    // Create the SQL command
+    FdoPtr<FdoIDelete> fdoCommand = (FdoIDelete*)fdoConn->CreateCommand(FdoCommandType_Delete);
+    CHECKNULL((FdoIDelete*)fdoCommand, L"MgServerDeleteCommand.Execute");
+
+    fdoCommand->SetFeatureClassName(clsName.c_str());
+    fdoCommand->SetFilter(filterText.c_str());
+
+    INT32 recordsDeleted = fdoCommand->Execute();
+
+    char buff[32];
+    sprintf(buff, "%d", m_cmdId);
+    STRING str = MgUtil::MultiByteToWideChar(string(buff));
+
+    return new MgInt32Property(str, recordsDeleted);
+}

Added: branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/DeleteCommand.h
===================================================================
--- branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/DeleteCommand.h	                        (rev 0)
+++ branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/DeleteCommand.h	2012-07-15 16:59:27 UTC (rev 6903)
@@ -0,0 +1,39 @@
+//
+//  Copyright (C) 2004-2011 by Autodesk, Inc.
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of version 2.1 of the GNU Lesser
+//  General Public License as published by the Free Software Foundation.
+//
+//  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 St, Fifth Floor, Boston, MA  02110-1301  USA
+//
+
+#ifndef _MG_SERVER_DELETE_COMMAND_H_
+#define _MG_SERVER_DELETE_COMMAND_H_
+
+class MgFeatureConnection;
+
+class MgServerDeleteCommand : public MgFeatureManipulationCommand
+{
+    DECLARE_CLASSNAME(MgServerDeleteCommand)
+
+public:
+    MgServerDeleteCommand(MgFeatureCommand* command, MgFeatureConnection* connection, INT32 cmdId);
+    virtual MgProperty* Execute();
+protected:
+    MgServerDeleteCommand();
+    ~MgServerDeleteCommand();
+private:
+    Ptr<MgDeleteFeatures> m_featCommand;
+    Ptr<MgFeatureConnection> m_srvrFeatConn;
+    INT32 m_cmdId;
+};
+
+#endif

Added: branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/FeatureManipulationCommand.cpp
===================================================================
--- branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/FeatureManipulationCommand.cpp	                        (rev 0)
+++ branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/FeatureManipulationCommand.cpp	2012-07-15 16:59:27 UTC (rev 6903)
@@ -0,0 +1,79 @@
+//
+//  Copyright (C) 2004-2011 by Autodesk, Inc.
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of version 2.1 of the GNU Lesser
+//  General Public License as published by the Free Software Foundation.
+//
+//  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 St, Fifth Floor, Boston, MA  02110-1301  USA
+//
+
+#include "Services/Feature/FeatureDefs.h"
+#include "MgDesktop.h"
+#include "Services/FeatureService.h"
+#include "FeatureManipulationCommand.h"
+#include "Services/Feature/FeatureConnection.h"
+#include "Services/Feature/FeatureUtil.h"
+#include "InsertCommand.h"
+#include "UpdateCommand.h"
+#include "DeleteCommand.h"
+
+MgFeatureManipulationCommand* MgFeatureManipulationCommand::CreateCommand(MgFeatureCommand* webCmd, MgFeatureConnection* connection, INT32 cmdId)
+{
+    CHECKNULL(webCmd, L"MgFeatureManipulationCommand.CreateCommand")
+    CHECKNULL(connection, L"MgFeatureManipulationCommand.CreateCommand")
+
+    INT32 cmdType = webCmd->GetCommandType();
+    bool supports = false;
+
+    Ptr<MgFeatureManipulationCommand> command;
+
+    switch(cmdType)
+    {
+        case MgFeatureCommandType::InsertFeatures:
+        {
+            supports = connection->SupportsCommand(FdoCommandType_Insert);
+            if (supports)
+            {
+                command = new MgServerInsertCommand(webCmd, connection, cmdId);
+            }
+            break;
+        }
+        case MgFeatureCommandType::UpdateFeatures:
+        {
+            supports = connection->SupportsCommand(FdoCommandType_Update);
+            if (supports)
+            {
+                command = new MgServerUpdateCommand(webCmd, connection, cmdId);
+            }
+            break;
+        }
+        case MgFeatureCommandType::DeleteFeatures:
+        {
+            supports = connection->SupportsCommand(FdoCommandType_Delete);
+            if (supports)
+            {
+                command = new MgServerDeleteCommand(webCmd, connection, cmdId);
+            }
+            break;
+        }
+    }
+
+    if (!supports)
+    {
+        STRING message = MgFeatureUtil::GetMessage(L"MgCommandNotSupported");
+
+        MgStringCollection arguments;
+        arguments.Add(message);
+        throw new MgFeatureServiceException(L"MgFeatureManipulationCommand.CreateCommand", __LINE__, __WFILE__, &arguments, L"", NULL);
+    }
+
+    return command.Detach();
+}

Added: branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/FeatureManipulationCommand.h
===================================================================
--- branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/FeatureManipulationCommand.h	                        (rev 0)
+++ branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/FeatureManipulationCommand.h	2012-07-15 16:59:27 UTC (rev 6903)
@@ -0,0 +1,35 @@
+//
+//  Copyright (C) 2004-2011 by Autodesk, Inc.
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of version 2.1 of the GNU Lesser
+//  General Public License as published by the Free Software Foundation.
+//
+//  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 St, Fifth Floor, Boston, MA  02110-1301  USA
+//
+
+#ifndef _MG_FEATURE_MANIPULATION_COMMAND_H_
+#define _MG_FEATURE_MANIPULATION_COMMAND_H_
+
+class MgFeatureConnection;
+
+class MgFeatureManipulationCommand : public MgDisposable
+{
+public:
+    static MgFeatureManipulationCommand* CreateCommand(MgFeatureCommand* command, MgFeatureConnection* connection, INT32 cmdId);
+    virtual MgProperty* Execute() = 0;
+protected:
+    virtual void Dispose()
+    {
+        delete this;
+    }
+};
+
+#endif

Added: branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/FeatureServiceCommand.cpp
===================================================================
--- branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/FeatureServiceCommand.cpp	                        (rev 0)
+++ branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/FeatureServiceCommand.cpp	2012-07-15 16:59:27 UTC (rev 6903)
@@ -0,0 +1,116 @@
+//
+//  Copyright (C) 2004-2011 by Autodesk, Inc.
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of version 2.1 of the GNU Lesser
+//  General Public License as published by the Free Software Foundation.
+//
+//  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 St, Fifth Floor, Boston, MA  02110-1301  USA
+//
+
+#include "Services/Feature/FeatureDefs.h"
+#include "MgDesktop.h"
+#include "Services/FeatureService.h"
+#include "FeatureServiceCommand.h"
+#include "SelectCommand.h"
+#include "SelectAggregateCommand.h"
+
+MgFeatureServiceCommand* MgFeatureServiceCommand::CreateCommand(MgResourceIdentifier* resource, FdoCommandType commandType)
+{
+    Ptr<MgFeatureServiceCommand> command;
+    switch(commandType)
+    {
+        case FdoCommandType_Select:
+        {
+            command = new MgSelectCommand(resource);
+            break;
+        }
+        case FdoCommandType_SelectAggregates:
+        {
+            command = new MgSelectAggregateCommand(resource);
+            break;
+        }
+    }
+    return command.Detach();
+}
+
+bool MgFeatureServiceCommand::IsFdoSupportedFunction(FdoIConnection* connection, FdoFunction* fdoFunc)
+{
+    CHECKNULL(connection, L"MgServerSelectFeatures.SupportsFunction");
+
+    FdoPtr<FdoIExpressionCapabilities> fec = connection->GetExpressionCapabilities();
+    CHECKNULL((FdoIExpressionCapabilities*)fec, L"MgServerSelectFeatures.SupportsFunction");
+
+    bool supports = false;
+
+    FdoPtr<FdoFunctionDefinitionCollection> ffdc = fec->GetFunctions();
+    if (NULL != (FdoFunctionDefinitionCollection*)ffdc)
+    {
+        FdoInt32 funcCnt = ffdc->GetCount();
+        for (FdoInt32 i=0; i < funcCnt; i++)
+        {
+            FdoPtr<FdoFunctionDefinition> ffd = ffdc->GetItem(i);
+            CHECKNULL((FdoFunctionDefinition*)ffd, L"MgServerSelectFeatures.SupportsFunction");
+
+            // TODO: Just comparing name is enough?
+            // TODO: I think, NOT, because there can be overloaded functions like one function
+            // with multiple arguments, differnet datatypes etc.
+            //
+            // Comparing argument count is not sufficient because, there can be optional arguments
+            // as well. Therefore, we should just restrict to name comparision only
+            FdoString* funcNameAllowed = ffd->GetName();
+            FdoString* funcNameSupplied = fdoFunc->GetName();
+            size_t cmp = _wcsicmp(funcNameAllowed, funcNameSupplied);
+            if (cmp == 0)
+            {
+                supports = true;
+                break;
+            }
+        }
+    }
+    return supports;
+}
+
+bool MgFeatureServiceCommand::SupportsSelectDistinct(FdoIConnection* connection)
+{
+    CHECKNULL((FdoIConnection*)connection, L"MgFeatureServiceCommand.SupportsSelectDistinct");
+
+    FdoPtr<FdoICommandCapabilities> fcc = connection->GetCommandCapabilities();
+    CHECKNULL((FdoICommandCapabilities*)fcc, L"MgFeatureServiceCommand.SupportsSelectDistinct");
+
+    bool supports = fcc->SupportsSelectDistinct();
+
+    return supports;
+}
+
+
+bool MgFeatureServiceCommand::SupportsSelectOrdering(FdoIConnection* connection)
+{
+    CHECKNULL((FdoIConnection*)connection, L"MgFeatureServiceCommand.SupportsSelectOrdering");
+
+    FdoPtr<FdoICommandCapabilities> fcc = connection->GetCommandCapabilities();
+    CHECKNULL((FdoICommandCapabilities*)fcc, L"MgFeatureServiceCommand.SupportsSelectOrdering");
+
+    bool supports = fcc->SupportsSelectOrdering();
+
+    return supports;
+}
+
+bool MgFeatureServiceCommand::SupportsSelectGrouping(FdoIConnection* connection)
+{
+    CHECKNULL((FdoIConnection*)connection, L"MgFeatureServiceCommand.SupportsSelectGrouping");
+
+    FdoPtr<FdoICommandCapabilities> fcc = connection->GetCommandCapabilities();
+    CHECKNULL((FdoICommandCapabilities*)fcc, L"MgFeatureServiceCommand.SupportsSelectGrouping");
+
+    bool supports = fcc->SupportsSelectGrouping();
+
+    return supports;
+}

Added: branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/FeatureServiceCommand.h
===================================================================
--- branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/FeatureServiceCommand.h	                        (rev 0)
+++ branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/FeatureServiceCommand.h	2012-07-15 16:59:27 UTC (rev 6903)
@@ -0,0 +1,63 @@
+//
+//  Copyright (C) 2004-2011 by Autodesk, Inc.
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of version 2.1 of the GNU Lesser
+//  General Public License as published by the Free Software Foundation.
+//
+//  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 St, Fifth Floor, Boston, MA  02110-1301  USA
+//
+
+#ifndef _MGFEATURESERVICECOMMAND_H_
+#define _MGFEATURESERVICECOMMAND_H_
+
+class MgFeatureServiceCommand : public MgDisposable
+{
+public:
+    static MgFeatureServiceCommand* CreateCommand(MgResourceIdentifier* resource, FdoCommandType commandType);
+
+    virtual FdoIdentifierCollection* GetPropertyNames() = 0;
+
+    virtual void SetDistinct( bool value ) = 0;
+    virtual bool GetDistinct( ) = 0;
+
+    virtual void SetFetchSize(FdoInt32 fetchSize) = 0;
+    virtual FdoInt32 GetFetchSize() = 0;
+
+    virtual FdoIdentifierCollection* GetOrdering() = 0;
+    virtual void SetOrderingOption( FdoOrderingOption  option ) = 0;
+    virtual FdoOrderingOption GetOrderingOption( ) = 0;
+
+    virtual FdoIdentifierCollection* GetGrouping() = 0;
+    virtual void SetGroupingFilter( FdoFilter* filter ) = 0;
+    virtual FdoFilter* GetGroupingFilter( ) = 0;
+
+    virtual void SetFeatureClassName(FdoString* value) = 0;
+    virtual void SetFilter(FdoString* value) = 0;
+    virtual void SetFilter(FdoFilter* value) = 0;
+
+    virtual FdoFilter* GetFilter() = 0;
+
+    virtual bool IsSupportedFunction(FdoFunction* fdoFunc) = 0;
+    virtual bool SupportsSelectGrouping() = 0;
+    virtual bool SupportsSelectOrdering() = 0;
+    virtual bool SupportsSelectDistinct() = 0;
+
+    virtual MgReader* Execute() = 0;
+
+protected:
+
+    virtual bool IsFdoSupportedFunction(FdoIConnection* connection, FdoFunction* fdoFunc);
+    virtual bool SupportsSelectGrouping(FdoIConnection* connection);
+    virtual bool SupportsSelectOrdering(FdoIConnection* connection);
+    virtual bool SupportsSelectDistinct(FdoIConnection* connection);
+};
+
+#endif

Added: branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/GetConnectionPropertyValues.cpp
===================================================================
--- branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/GetConnectionPropertyValues.cpp	                        (rev 0)
+++ branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/GetConnectionPropertyValues.cpp	2012-07-15 16:59:27 UTC (rev 6903)
@@ -0,0 +1,136 @@
+//
+//  Copyright (C) 2004-2011 by Autodesk, Inc.
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of version 2.1 of the GNU Lesser
+//  General Public License as published by the Free Software Foundation.
+//
+//  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 St, Fifth Floor, Boston, MA  02110-1301  USA
+//
+
+#include "Services/Feature/FeatureDefs.h"
+#include "GetConnectionPropertyValues.h"
+#include "Services/Feature/FeatureConnection.h"
+#include "Services/Feature/FeatureUtil.h"
+#include "Services/CryptoDefs.h"
+
+MgServerGetConnectionPropertyValues::MgServerGetConnectionPropertyValues()
+{
+}
+
+MgServerGetConnectionPropertyValues::~MgServerGetConnectionPropertyValues()
+{
+}
+
+// Executes the describe schema command and serializes the schema to XML
+MgStringCollection* MgServerGetConnectionPropertyValues::GetConnectionPropertyValues( CREFSTRING providerName,
+                                                                                      CREFSTRING propertyName,
+                                                                                      CREFSTRING partialConnString )
+{
+    Ptr<MgStringCollection> stringCol;
+
+    MG_FEATURE_SERVICE_TRY()
+
+    if (providerName.empty())
+    {
+        MgStringCollection arguments;
+        arguments.Add(L"1");
+        arguments.Add(MgResources::BlankArgument);
+
+        throw new MgInvalidArgumentException(L"MgServerGetConnectionPropertyValues.GetConnectionPropertyValues",
+            __LINE__, __WFILE__, &arguments, L"MgStringEmpty", NULL);
+    }
+
+    if (propertyName.empty())
+    {
+        MgStringCollection arguments;
+        arguments.Add(L"2");
+        arguments.Add(MgResources::BlankArgument);
+
+        throw new MgInvalidArgumentException(L"MgServerGetConnectionPropertyValues.GetConnectionPropertyValues",
+            __LINE__, __WFILE__, &arguments, L"MgStringEmpty", NULL);
+    }
+
+    // Decrypt the partial connection string if it was encrypted.
+
+    STRING decryptedPartialConnString;
+
+    {
+        MG_CRYPTOGRAPHY_TRY()
+
+        MgCryptographyUtil cryptoUtil;
+        string cipherText, plainText;
+
+        MgUtil::WideCharToMultiByte(partialConnString, cipherText);
+        cryptoUtil.DecryptString(cipherText, plainText);
+        MgUtil::MultiByteToWideChar(plainText, decryptedPartialConnString);
+
+        MG_CRYPTOGRAPHY_CATCH(L"MgServerGetConnectionPropertyValues.GetConnectionPropertyValues")
+
+        if (cryptographyException != NULL)
+        {
+            decryptedPartialConnString = partialConnString;
+        }
+    }
+
+    // ODBC provider returns list of DataSourceNames and does not require connection string for this.
+    // Therefore, limitation on connection string to be valid is removed. Also, as ODBC provider does
+    // provide any connection string, connection can not be opened and it will remain in closed state.
+    // Therefore validity of connection state does not apply.
+
+    // Connect to provider
+    Ptr<MgFeatureConnection> msfc = new MgFeatureConnection(providerName, decryptedPartialConnString);
+    {
+        if(NULL == msfc.p)
+        {
+            throw new MgConnectionFailedException(L"MgServerGetConnectionPropertyValues.GetConnectionPropertyValues", __LINE__, __WFILE__, NULL, L"", NULL);
+        }
+
+        // The reference to the FDO connection from the MgFeatureConnection object must be cleaned up before the parent object
+        // otherwise it leaves the FDO connection marked as still in use.
+        FdoPtr<FdoIConnection> fdoConn = msfc->GetConnection();
+        CHECKNULL((FdoIConnection*)fdoConn, L"MgServerGetConnectionPropertyValues.GetConnectionPropertyValues");
+
+        // Get Connection Info
+        FdoPtr<FdoIConnectionInfo> connInfo = fdoConn->GetConnectionInfo();
+        CHECKNULL((FdoIConnectionInfo*)connInfo, L"MgServerGetConnectionPropertyValues.GetConnectionPropertyValues");
+
+        // Get Connection Property Dictionary
+        FdoPtr<FdoIConnectionPropertyDictionary> fdoConnPropDict = connInfo->GetConnectionProperties();
+        CHECKNULL((FdoIConnectionPropertyDictionary*)fdoConnPropDict, L"MgServerGetConnectionPropertyValues.GetConnectionPropertyValues");
+
+        bool enumerable = fdoConnPropDict->IsPropertyEnumerable((FdoString*)propertyName.c_str());
+        if (!enumerable)
+        {
+            MgStringCollection arguments;
+            arguments.Add(L"2");
+            arguments.Add(propertyName);
+
+            throw new MgInvalidArgumentException(L"MgServerGetConnectionPropertyValues.GetConnectionPropertyValues",
+                __LINE__, __WFILE__, &arguments, L"MgPropertyNotEnumerable", NULL);
+        }
+
+        FdoInt32 cnt = 0;
+        FdoString** propertyValues = fdoConnPropDict->EnumeratePropertyValues((FdoString*)propertyName.c_str(), cnt);
+
+        if (propertyValues != NULL && cnt > 0)
+        {
+            stringCol = new MgStringCollection();
+            for( FdoInt32 i=0; i < cnt; i++ )
+            {
+                stringCol->Add(propertyValues[i]);
+            }
+        }
+    }
+
+    MG_FEATURE_SERVICE_CATCH_AND_THROW(L"MgServerGetConnectionPropertyValues.GetConnectionPropertyValues")
+
+    return stringCol.Detach();
+}

Added: branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/GetConnectionPropertyValues.h
===================================================================
--- branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/GetConnectionPropertyValues.h	                        (rev 0)
+++ branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/GetConnectionPropertyValues.h	2012-07-15 16:59:27 UTC (rev 6903)
@@ -0,0 +1,39 @@
+//
+//  Copyright (C) 2004-2011 by Autodesk, Inc.
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of version 2.1 of the GNU Lesser
+//  General Public License as published by the Free Software Foundation.
+//
+//  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 St, Fifth Floor, Boston, MA  02110-1301  USA
+//
+
+#ifndef _MG_SERVER_GETCONNECTIONPROPERTYVALUES_H_
+#define _MG_SERVER_GETCONNECTIONPROPERTYVALUES_H_
+
+#include "MgDesktop.h"
+#include "System/XmlDefs.h"
+#include "System/XmlUtil.h"
+#include "Fdo.h"
+
+class MgServerGetConnectionPropertyValues
+{
+public:
+    MgServerGetConnectionPropertyValues();
+    ~MgServerGetConnectionPropertyValues();
+    MgStringCollection* GetConnectionPropertyValues( CREFSTRING providerName,
+                                                     CREFSTRING propertyName,
+                                                     CREFSTRING partialConnString );
+
+private:
+    STRING  m_providerName;
+};
+
+#endif

Added: branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/GetFeatureProviders.cpp
===================================================================
--- branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/GetFeatureProviders.cpp	                        (rev 0)
+++ branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/GetFeatureProviders.cpp	2012-07-15 16:59:27 UTC (rev 6903)
@@ -0,0 +1,217 @@
+//
+//  Copyright (C) 2004-2011 by Autodesk, Inc.
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of version 2.1 of the GNU Lesser
+//  General Public License as published by the Free Software Foundation.
+//
+//  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 St, Fifth Floor, Boston, MA  02110-1301  USA
+//
+
+#include "Services/Feature/FeatureDefs.h"
+#include "GetFeatureProviders.h"
+
+MgServerGetFeatureProviders::MgServerGetFeatureProviders()
+{
+    FdoPtr<IProviderRegistry> providerReg = FdoFeatureAccessManager::GetProviderRegistry();
+    CHECKNULL(providerReg, L"MgServerGetFeatureProviders.MgServerGetFeatureProviders()");
+
+    FdoPtr<IConnectionManager> connManager = FdoFeatureAccessManager::GetConnectionManager();
+    CHECKNULL(connManager, L"MgServerGetFeatureProviders.MgServerGetFeatureProviders()");
+
+    m_fdoProviderCol = providerReg->GetProviders();
+    CHECKNULL(m_fdoProviderCol, L"MgServerGetFeatureProviders.MgServerGetFeatureProviders()");
+
+    // this XML follows the FeatureProviderRegistry-1.0.0.xsd schema
+    m_xmlUtil = new MgXmlUtil("FeatureProviderRegistry" /* NOXLATE */);
+    CHECKNULL(m_xmlUtil, L"MgServerGetFeatureProviders.MgServerGetFeatureProviders()");
+
+    // no more risk of exceptions, so we can now assign these
+    m_providerReg = providerReg.Detach();
+    m_connManager = connManager.Detach();
+}
+
+MgServerGetFeatureProviders::~MgServerGetFeatureProviders()
+{
+    FDO_SAFE_RELEASE(m_providerReg);
+    FDO_SAFE_RELEASE(m_connManager);
+
+    // do not release this one
+    m_fdoProviderCol = NULL;
+
+    delete m_xmlUtil;
+}
+
+
+MgByteReader* MgServerGetFeatureProviders::GetFeatureProviders()
+{
+    Ptr<MgByteReader> byteReader;
+
+    MG_FEATURE_SERVICE_TRY()
+
+    CreateFeatureProvidersDocument();
+    byteReader = m_xmlUtil->ToReader();
+
+    MG_FEATURE_SERVICE_CATCH_AND_THROW(L"MgServerGetFeatureProviders.GetFeatureProviders")
+
+    return byteReader.Detach();
+}
+
+void MgServerGetFeatureProviders::CreateFeatureProvidersDocument()
+{
+    CHECKNULL(m_fdoProviderCol, L"MgServerGetFeatureProviders.CreateFeatureProvidersDocument");
+
+    INT32 cnt = m_fdoProviderCol->GetCount();
+    for (INT32 i = 0; i < cnt; i++)
+    {
+        FdoPtr<FdoProvider> fdoProvider = m_fdoProviderCol->GetItem(i);
+
+        // Get ProviderName
+        FdoString* providerName = fdoProvider->GetName();
+
+        const char *name        = MgUtil::WideCharToMultiByte(providerName);
+        const char *dispname    = MgUtil::WideCharToMultiByte(fdoProvider->GetDisplayName());
+        const char *description = MgUtil::WideCharToMultiByte(fdoProvider->GetDescription());
+        const char *version     = MgUtil::WideCharToMultiByte(fdoProvider->GetVersion());
+        const char *fdoversion  = MgUtil::WideCharToMultiByte(fdoProvider->GetFeatureDataObjectsVersion());
+
+        // Add Feature Provider element
+        DOMElement* rootElem = m_xmlUtil->GetRootNode();
+        DOMElement* featureProviderElem = m_xmlUtil->AddChildNode(rootElem, "FeatureProvider" /* NOXLATE */);
+
+        // Add Provider Name
+        m_xmlUtil->AddTextNode(featureProviderElem, "Name" /* NOXLATE */, name);
+        // Display Name
+        m_xmlUtil->AddTextNode(featureProviderElem, "DisplayName" /* NOXLATE */, dispname);
+        // Description
+        m_xmlUtil->AddTextNode(featureProviderElem, "Description" /* NOXLATE */, description);
+        // Version
+        m_xmlUtil->AddTextNode(featureProviderElem, "Version" /* NOXLATE */, version);
+        // FDO version
+        m_xmlUtil->AddTextNode(featureProviderElem, "FeatureDataObjectsVersion" /* NOXLATE */, fdoversion);
+
+        delete[] name;
+        delete[] dispname;
+        delete[] description;
+        delete[] version;
+        delete[] fdoversion;
+
+        AddConnectionProperties(featureProviderElem, providerName);
+    }
+}
+
+void MgServerGetFeatureProviders::AddConnectionProperties(DOMElement* providerElem, FdoString* providerName)
+{
+    CHECKNULL(providerElem, L"MgServerGetFeatureProviders.AddConnectionProperties");
+
+    // Get Properties
+    FdoInt32 totalProperties = 0;
+
+    // Add ConnnectionProperties element (mandatory element)
+    DOMElement* connPropRootElem = m_xmlUtil->AddChildNode(providerElem, "ConnectionProperties" /* NOXLATE */ );
+    CHECKNULL(connPropRootElem, L"MgServerGetFeatureProviders.AddConnectionProperties");
+
+    // We ignore any exception thrown here so that even if client dll/so is missing, GetFeatureProviders
+    // will continue to work.
+    MG_FEATURE_SERVICE_TRY()
+
+    // Get FdoIConnection instance
+    // TODO: Should this connection be cached?
+    FdoPtr<FdoIConnection> fdoConn = m_connManager->CreateConnection(providerName);
+    CHECKNULL((FdoIConnection*)fdoConn, L"MgServerGetFeatureProviders.AddConnectionProperties");
+
+    // Get FdoIConnectionInfo
+    FdoPtr<FdoIConnectionInfo> fdoConnInfo = fdoConn->GetConnectionInfo();
+    CHECKNULL((FdoIConnectionInfo*)fdoConnInfo, L"MgServerGetFeatureProviders.AddConnectionProperties");
+
+    // Get FdoIConnectionPropertyDictionary
+    FdoPtr<FdoIConnectionPropertyDictionary> fdoConnPropertyDict = fdoConnInfo->GetConnectionProperties();
+    CHECKNULL((FdoIConnectionPropertyDictionary*)fdoConnPropertyDict, L"MgServerGetFeatureProviders.AddConnectionProperties");
+
+    // Get list of all properties
+    FdoString** properties = fdoConnPropertyDict->GetPropertyNames(totalProperties);
+    CHECKNULL(properties, L"MgServerGetFeatureProviders.AddConnectionProperties");
+
+    for ( FdoInt32 i=0; i < totalProperties; i++ )
+    {
+        AddConnectionProperty(connPropRootElem, properties[i], fdoConnPropertyDict);
+    }
+
+    MG_FEATURE_SERVICE_CATCH(L"MgServerGetFeatureProviders.GetFeatureProviders") // do not rethrow so that GetFeatureProviders works
+}
+
+void MgServerGetFeatureProviders::AddConnectionProperty(DOMElement* connPropRootElem,
+                                                   FdoString* propertyName,
+                                                   FdoIConnectionPropertyDictionary* fdoConnPropertyDict)
+{
+    CHECKNULL(connPropRootElem,     L"MgServerGetFeatureProviders.AddConnectionProperty");
+    CHECKNULL(propertyName,         L"MgServerGetFeatureProviders.AddConnectionProperty");
+    CHECKNULL(fdoConnPropertyDict,  L"MgServerGetFeatureProviders.AddConnectionProperty");
+
+    DOMElement* connPropElem = m_xmlUtil->AddChildNode(connPropRootElem, "ConnectionProperty"  /* NOXLATE */ );
+
+    bool isEnumerable = fdoConnPropertyDict->IsPropertyEnumerable(propertyName);
+    bool isProtected  = fdoConnPropertyDict->IsPropertyProtected(propertyName);
+    bool isRequired   = fdoConnPropertyDict->IsPropertyRequired(propertyName);
+
+    // Set Required attribute
+    if (isRequired)
+        connPropElem->setAttribute(X("Required"), X("true") /* NOXLATE */);
+    else
+        connPropElem->setAttribute(X("Required"), X("false") /* NOXLATE */);
+
+    // Set protected attribute
+    if (isProtected)
+        connPropElem->setAttribute(X("Protected"), X("true") /* NOXLATE */);
+    else
+        connPropElem->setAttribute(X("Protected"), X("false") /* NOXLATE */);
+
+    // Set enumerable attribute
+    if (isEnumerable)
+        connPropElem->setAttribute(X("Enumerable"), X("true") /* NOXLATE */);
+    else
+        connPropElem->setAttribute(X("Enumerable"), X("false") /* NOXLATE */);
+
+    // Add property name
+    const char *propName = MgUtil::WideCharToMultiByte(propertyName);
+    m_xmlUtil->AddTextNode(connPropElem, "Name" /* NOXLATE */, propName);
+    delete[] propName;
+
+    // Add Localized Name
+    FdoString* propLocalizedName = fdoConnPropertyDict->GetLocalizedName(propertyName);
+    if (propLocalizedName)
+    {
+        const char *localname = MgUtil::WideCharToMultiByte(propLocalizedName);
+        m_xmlUtil->AddTextNode(connPropElem, "LocalizedName" /* NOXLATE */, localname);
+        delete[] localname;
+    }
+
+    // Add Default value
+    FdoString* propDefaultValue = fdoConnPropertyDict->GetPropertyDefault(propertyName);
+    if (propDefaultValue)
+    {
+        const char *defvalue = MgUtil::WideCharToMultiByte(propDefaultValue);
+        m_xmlUtil->AddTextNode(connPropElem, "DefaultValue" /* NOXLATE */, defvalue);
+        delete[] defvalue;
+    }
+
+    // Add the values of enumerable properties if we can
+    if (isEnumerable)
+    {
+        FdoInt32 propCnt;
+        FdoString** propValues = fdoConnPropertyDict->EnumeratePropertyValues(propertyName, propCnt);
+        for ( FdoInt32 j = 0; j < propCnt; j++ )
+        {
+            const char *value = MgUtil::WideCharToMultiByte(propValues[j]);
+            m_xmlUtil->AddTextNode(connPropElem, "Value" /* NOXLATE */, value);
+            delete[] value;
+        }
+    }
+}

Added: branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/GetFeatureProviders.h
===================================================================
--- branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/GetFeatureProviders.h	                        (rev 0)
+++ branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/GetFeatureProviders.h	2012-07-15 16:59:27 UTC (rev 6903)
@@ -0,0 +1,54 @@
+//
+//  Copyright (C) 2004-2011 by Autodesk, Inc.
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of version 2.1 of the GNU Lesser
+//  General Public License as published by the Free Software Foundation.
+//
+//  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 St, Fifth Floor, Boston, MA  02110-1301  USA
+//
+
+#ifndef _MG_SERVER_GET_FEATURE_PROVIDERS_H_
+#define _MG_SERVER_GET_FEATURE_PROVIDERS_H_
+
+#include "MgDesktop.h"
+#include "System/XmlDefs.h"
+#include "System/XmlUtil.h"
+#include "Fdo.h"
+
+class MgServerGetFeatureProviders
+{
+public:
+    MgServerGetFeatureProviders();
+    ~MgServerGetFeatureProviders();
+
+
+    MgByteReader* GetFeatureProviders();
+
+private:
+
+    void CreateFeatureProvidersDocument();
+
+    void AddConnectionProperties( DOMElement* providerElem,
+                                  FdoString* providerName);
+
+    void AddConnectionProperty( DOMElement* connPropRootElem,
+                                FdoString* propertyName,
+                                FdoIConnectionPropertyDictionary* fdoConnPropertyDict);
+
+    IProviderRegistry*      m_providerReg;
+    IConnectionManager*     m_connManager;
+    MgXmlUtil*              m_xmlUtil;
+
+    const FdoProviderCollection*  m_fdoProviderCol;
+
+};
+
+#endif

Added: branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/GetLongTransactions.cpp
===================================================================
--- branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/GetLongTransactions.cpp	                        (rev 0)
+++ branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/GetLongTransactions.cpp	2012-07-15 16:59:27 UTC (rev 6903)
@@ -0,0 +1,157 @@
+//
+//  Copyright (C) 2004-2011 by Autodesk, Inc.
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of version 2.1 of the GNU Lesser
+//  General Public License as published by the Free Software Foundation.
+//
+//  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 St, Fifth Floor, Boston, MA  02110-1301  USA
+//
+
+#include "Services/Feature/FeatureDefs.h"
+#include "GetLongTransactions.h"
+#include "Services/Feature/FeatureConnection.h"
+#include "Services/Feature/FeatureUtil.h"
+#include <math.h>
+
+MgServerGetLongTransactions::MgServerGetLongTransactions()
+{
+}
+
+MgServerGetLongTransactions::~MgServerGetLongTransactions()
+{
+}
+
+// Executes the get long transactions command and serializes the schema to XML
+MgLongTransactionReader* MgServerGetLongTransactions::GetLongTransactions(MgResourceIdentifier* resId, bool bActiveOnly)
+{
+    Ptr<MgLongTransactionReader> mgLongTransactionReader;
+    mgLongTransactionReader = NULL;
+
+    MG_FEATURE_SERVICE_TRY()
+
+    if (NULL == resId)
+    {
+        throw new MgNullArgumentException(L"MgServerGetLongTransactions.GetLongTransactions", __LINE__, __WFILE__, NULL, L"", NULL);
+    }
+
+    // Connect to provider
+    Ptr<MgFeatureConnection> msfc = new MgFeatureConnection(resId);
+
+    // connection must be open to retrieve list of active contexts
+    if ((NULL != msfc.p) && ( msfc->IsConnectionOpen() ))
+    {
+        // The reference to the FDO connection from the MgFeatureConnection object must be cleaned up before the parent object
+        // otherwise it leaves the FDO connection marked as still in use.
+        FdoPtr<FdoIConnection> fdoConn = msfc->GetConnection();
+        m_providerName = msfc->GetProviderName();
+
+        // Check whether command is supported by provider
+        if (!msfc->SupportsCommand((INT32)FdoCommandType_GetLongTransactions))
+        {
+            // TODO: specify which argument and message, once we have the mechanism
+            STRING message = MgFeatureUtil::GetMessage(L"MgCommandNotSupported");
+            throw new MgInvalidOperationException(L"MgServerGetLongTransactions.GetLongTransactions", __LINE__, __WFILE__, NULL, L"", NULL);
+        }
+
+        FdoPtr<FdoIGetLongTransactions> fdoCommand = (FdoIGetLongTransactions*)fdoConn->CreateCommand(FdoCommandType_GetLongTransactions);
+        CHECKNULL((FdoIGetLongTransactions*)fdoCommand, L"MgServerGetLongTransactions.GetLongTransactions");
+
+        // Execute the command
+        FdoPtr<FdoILongTransactionReader> longTransactionReader = fdoCommand->Execute();
+        CHECKNULL((FdoILongTransactionReader*)longTransactionReader, L"MgServerGetLongTransactions.GetLongTransactions");
+
+        mgLongTransactionReader = new MgLongTransactionReader();
+        while (longTransactionReader->ReadNext())
+        {
+            // If only active long transaction is required skip all others
+            if (bActiveOnly)
+            {
+                if (!longTransactionReader->IsActive())
+                    continue;
+            }
+
+            // Set providername for which long transaction reader is executed
+            mgLongTransactionReader->SetProviderName(m_providerName);
+
+            // Add transaction data to the long transaction reader
+            Ptr<MgLongTransactionData> longTransactionData = GetLongTransactionData(longTransactionReader);
+            CHECKNULL((MgLongTransactionData*)longTransactionData, L"MgServerGetLongTransactions.GetLongTransactions");
+            mgLongTransactionReader->AddLongTransactionData(longTransactionData);
+
+            // If only active long transaction is required skip all others
+            if (bActiveOnly)
+            {
+                if (longTransactionReader->IsActive())
+                    break;
+            }
+        }
+    }
+    else
+    {
+        throw new MgConnectionFailedException(L"MgServerGetLongTransactions::GetLongTransactions()", __LINE__, __WFILE__, NULL, L"", NULL);
+    }
+
+    MG_FEATURE_SERVICE_CHECK_CONNECTION_CATCH_AND_THROW(resId, L"MgServerGetLongTransactions.GetLongTransactions")
+
+    return mgLongTransactionReader.Detach();
+}
+
+MgLongTransactionData* MgServerGetLongTransactions::GetLongTransactionData(FdoILongTransactionReader* longTransactionReader)
+{
+    Ptr<MgLongTransactionData> longTransactionData = new MgLongTransactionData();
+
+    // Name must exist
+    FdoString* name = longTransactionReader->GetName();
+    CHECKNULL((FdoString*)name, L"MgServerGetLongTransactions.GetLongTransactions");
+    longTransactionData->SetName(STRING(name));
+
+    // Desc for long transaction
+    FdoString* desc = longTransactionReader->GetDescription();
+    if (desc != NULL)
+    {
+        longTransactionData->SetDescription(STRING(desc));
+    }
+
+    // Owner for long transaction
+    FdoString* owner = longTransactionReader->GetOwner();
+    if (owner != NULL)
+    {
+        longTransactionData->SetOwner(STRING(owner));
+    }
+
+    // Creation date
+    Ptr<MgDateTime> mgDateTime;
+
+    FdoDateTime dateTime = longTransactionReader->GetCreationDate();
+    if(dateTime.IsDateTime())
+    {
+        // Valid datetime
+        double seconds;
+        double microsecs = modf(dateTime.seconds, &seconds);
+
+        mgDateTime = new MgDateTime(dateTime.year, dateTime.month, dateTime.day, dateTime.hour, dateTime.minute, (INT8)(int)seconds, (INT32)microsecs);
+    }
+    else
+    {
+        // Invalid datetime, so use current date
+        mgDateTime = new MgDateTime();
+    }
+
+    // Whether it is active or not
+    bool isActive = longTransactionReader->IsActive();
+    longTransactionData->SetActiveStatus(isActive);
+
+    // Whether it is frozen or not
+    bool isFrozen = longTransactionReader->IsFrozen();
+    longTransactionData->SetFrozenStatus(isFrozen);
+
+    return longTransactionData.Detach();
+}

Added: branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/GetLongTransactions.h
===================================================================
--- branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/GetLongTransactions.h	                        (rev 0)
+++ branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/GetLongTransactions.h	2012-07-15 16:59:27 UTC (rev 6903)
@@ -0,0 +1,38 @@
+//
+//  Copyright (C) 2004-2011 by Autodesk, Inc.
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of version 2.1 of the GNU Lesser
+//  General Public License as published by the Free Software Foundation.
+//
+//  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 St, Fifth Floor, Boston, MA  02110-1301  USA
+//
+
+#ifndef _MG_SERVERGETLONGTRANSACTIONS_H_
+#define _MG_SERVERGETLONGTRANSACTIONS_H_
+
+#include "MgDesktop.h"
+#include "System/XmlDefs.h"
+#include "System/XmlUtil.h"
+#include "Fdo.h"
+
+class MgServerGetLongTransactions
+{
+public:
+    MgServerGetLongTransactions();
+    ~MgServerGetLongTransactions();
+    MgLongTransactionReader* GetLongTransactions(MgResourceIdentifier* resId, bool bActiveOnly);
+    MgLongTransactionData* GetLongTransactionData(FdoILongTransactionReader* longTransactionReader);
+
+private:
+    STRING  m_providerName;
+};
+
+#endif

Added: branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/GetProviderCapabilities.cpp
===================================================================
--- branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/GetProviderCapabilities.cpp	                        (rev 0)
+++ branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/GetProviderCapabilities.cpp	2012-07-15 16:59:27 UTC (rev 6903)
@@ -0,0 +1,1036 @@
+//
+//  Copyright (C) 2004-2011 by Autodesk, Inc.
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of version 2.1 of the GNU Lesser
+//  General Public License as published by the Free Software Foundation.
+//
+//  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 St, Fifth Floor, Boston, MA  02110-1301  USA
+//
+
+#include "Services/Feature/FeatureDefs.h"
+#include "GetProviderCapabilities.h"
+#include "Services/Feature/FeatureConnection.h"
+#include "Services/Feature/FeatureUtil.h"
+
+/*
+static std::map<FdoThreadCapability, std::string>          s_FdoThreadCapability;
+static std::map<FdoSpatialContextExtentType, std::string>  s_FdoSpatialContextExtentType;
+static std::map<FdoClassType, std::string>                 s_FdoClassType;
+static std::map<FdoDataType,  std::string>                 s_FdoDataType;
+static std::map<FdoPropertyType,  std::string>             s_FdoPropertyTypeAsString;
+static std::map<FdoFunctionCategoryType,  std::string>     s_FdoFunctionCategoryType;
+static std::map<FdoCommandType,  std::string>              s_FdoCommandType;
+static std::map<FdoConditionType,  std::string>            s_FdoConditionType;
+static std::map<FdoSpatialOperations,  std::string>        s_FdoSpatialOperations;
+static std::map<FdoDistanceOperations,  std::string>       s_FdoDistanceOperations;
+static std::map<FdoExpressionType,  std::string>           s_FdoExpressionType;
+static std::map<FdoGeometryType,  std::string>             s_FdoGeometryType;
+static std::map<FdoGeometryComponentType,  std::string>    s_FdoGeometryComponentType;
+*/
+
+bool MgServerGetProviderCapabilities::m_isInitialized = MgServerGetProviderCapabilities::Initialize();
+
+
+MgServerGetProviderCapabilities::MgServerGetProviderCapabilities(CREFSTRING providerName, CREFSTRING connectionString)
+{
+    if (providerName.empty())
+    {
+        MgStringCollection arguments;
+        arguments.Add(L"1");
+        arguments.Add(MgResources::BlankArgument);
+
+        throw new MgInvalidArgumentException(L"MgServerGetProviderCapabilities.MgServerGetProviderCapabilities",
+            __LINE__, __WFILE__, &arguments, L"MgStringEmpty", NULL);
+    }
+
+    FdoPtr<IConnectionManager> connManager = FdoFeatureAccessManager::GetConnectionManager();
+    CHECKNULL(connManager, L"MgServerGetProviderCapabilities.MgServerGetProviderCapabilities");
+
+    // Remove the version from the provider name
+    FdoPtr<FdoProviderNameTokens> tokens = FdoProviderNameTokens::Create(providerName.c_str());
+    FdoStringsP strTokens = tokens->GetNameTokens();
+
+    FdoPtr<FdoStringElement> companyName = strTokens->GetItem(0);
+    FdoPtr<FdoStringElement> prvName = strTokens->GetItem(1);
+
+    STRING providerNoVersion;
+    providerNoVersion = companyName->GetString();
+    providerNoVersion += L".";
+    providerNoVersion += prvName->GetString();
+
+    FdoPtr<FdoIConnection> fdoConn = connManager->CreateConnection(providerNoVersion.c_str());
+
+    // Note: WFS doesn't return the proper capabilities if a connection is not opened to the actual server using a connection string.
+
+    // Check if a connection string was specified
+    if(!connectionString.empty())
+    {
+        fdoConn->SetConnectionString(connectionString.c_str());
+        fdoConn->Open();
+    }
+
+    CHECKNULL(fdoConn, L"MgServerGetProviderCapabilities.MgServerGetProviderCapabilities");
+
+    m_xmlUtil = new MgXmlUtil();
+    CHECKNULL(m_xmlUtil, L"MgServerGetProviderCapabilities.MgServerGetProviderCapabilities");
+
+    m_xmlCap = NULL;
+
+    // no more risk of exceptions, so we can now assign these
+    m_fdoConn = fdoConn.Detach();
+    m_providerName = providerNoVersion;
+}
+
+MgServerGetProviderCapabilities::~MgServerGetProviderCapabilities()
+{
+    // Check if the connection needs to be closed
+    if(m_fdoConn->GetConnectionState() == FdoConnectionState_Open)
+    {
+        m_fdoConn->Close();
+    }
+
+    m_fdoConn = NULL;
+
+    delete m_xmlUtil;
+    delete m_xmlCap;
+}
+
+
+MgByteReader* MgServerGetProviderCapabilities::GetProviderCapabilities()
+{
+    CHECKNULL(m_xmlUtil, L"MgServerGetProviderCapabilities.GetProviderCapabilities");
+    Ptr<MgByteReader> byteReader;
+
+    MG_FEATURE_SERVICE_TRY()
+
+    // Generate the capability document
+    CreateCapabilitiesDocument();
+
+    if (m_xmlCap != NULL)
+    {
+        byteReader = m_xmlCap->ToReader();
+    }
+
+    MG_FEATURE_SERVICE_CATCH_AND_THROW(L"MgServerGetProviderCapabilities.GetProviderCapabilities")
+
+    return byteReader.Detach();
+}
+
+void MgServerGetProviderCapabilities::CreateCapabilitiesDocument()
+{
+    // Root node element created
+    // this XML follows the FdoProviderCapabilities-1.0.0.xsd schema
+    m_xmlCap = new MgXmlUtil("FeatureProviderCapabilities");
+    CHECKNULL(m_xmlCap, L"MgServerGetProviderCapabilities::CreateCapabilitiesDocument");
+    DOMElement* root = m_xmlCap->GetRootNode();
+
+    // Provide name element and its attribute
+    DOMElement* providerNode = m_xmlCap->AddChildNode(root, "Provider");
+    m_xmlCap->SetAttribute(providerNode, "Name", m_providerName.c_str());
+
+    // Connection capabilities
+    CreateConnectionCapabilities();
+
+    CreateSchemaCapabilities();
+    CreateCommandCapabilities();
+    CreateFilterCapabilities();
+    //if (m_version == VERSION_SUPPORTED(1,0))
+    //    CreateExpressionCapabilities();
+    //else
+        CreateExpressionCapabilities2();
+    CreateRasterCapabilities();
+    CreateTopologyCapabilities();
+    CreateGeometryCapabilities();
+}
+
+
+
+void MgServerGetProviderCapabilities::CreateConnectionCapabilities()
+{
+    CHECKNULL(m_xmlCap, L"MgServerGetProviderCapabilities::CreateConnectionCapabilities");
+    CHECKNULL(m_fdoConn, L"MgServerGetProviderCapabilities::CreateConnectionCapabilities");
+
+    DOMElement* root = m_xmlCap->GetRootNode();
+    CHECKNULL(root, L"MgServerGetProviderCapabilities::CreateConnectionCapabilities");
+
+    DOMElement* connNode = m_xmlCap->AddChildNode(root, "Connection");
+    CHECKNULL(connNode, L"MgServerGetProviderCapabilities::CreateConnectionCapabilities");
+
+    FdoPtr<FdoIConnectionCapabilities> ficc = m_fdoConn->GetConnectionCapabilities();
+    CHECKNULL((FdoIConnectionCapabilities*)ficc, L"MgServerGetProviderCapabilities::CreateConnectionCapabilities");
+
+    // Thread
+    FdoThreadCapability ftc = ficc->GetThreadCapability();
+    string str = s_FdoThreadCapability[ftc];
+    m_xmlCap->AddTextNode(connNode, "ThreadCapability", str.c_str());
+
+    // Spatial Context
+    FdoInt32 cnt;
+    FdoSpatialContextExtentType* fscet = ficc->GetSpatialContextTypes(cnt);
+    if (cnt > 0 && fscet != NULL)
+    {
+        DOMElement* scNode = m_xmlCap->AddChildNode(connNode, "SpatialContextExtent");
+        CHECKNULL(scNode, L"MgServerGetProviderCapabilities::CreateConnectionCapabilities");
+
+        for (FdoInt32 i = 0; i < cnt; i++)
+        {
+            string scStr = s_FdoSpatialContextExtentType[fscet[i]];
+            m_xmlCap->AddTextNode(scNode, "Type", scStr.c_str());
+        }
+    }
+
+    // Locking
+    bool supportsLocking = ficc->SupportsLocking();
+    m_xmlCap->AddTextNode(connNode, "SupportsLocking", supportsLocking);
+
+    bool supportsTimeout = ficc->SupportsTimeout();
+    m_xmlCap->AddTextNode(connNode, "SupportsTimeout", supportsTimeout);
+
+    bool supportsTransactions = ficc->SupportsTransactions();
+    m_xmlCap->AddTextNode(connNode, "SupportsTransactions", supportsTransactions);
+
+    bool supportsSavePoint = ficc->SupportsSavePoint();
+    m_xmlCap->AddTextNode(connNode, "SupportsSavePoint", supportsSavePoint);
+
+    bool supportsLongTransactions = ficc->SupportsLongTransactions();
+    m_xmlCap->AddTextNode(connNode, "SupportsLongTransactions", supportsLongTransactions);
+
+    bool supportsSQL = ficc->SupportsSQL();
+    m_xmlCap->AddTextNode(connNode, "SupportsSQL", supportsSQL);
+
+    bool supportsConfiguration = ficc->SupportsConfiguration();
+    m_xmlCap->AddTextNode(connNode, "SupportsConfiguration", supportsConfiguration);
+}
+
+
+void MgServerGetProviderCapabilities::CreateSchemaCapabilities()
+{
+    CHECKNULL(m_xmlCap, L"MgServerGetProviderCapabilities::CreateSchemaCapabilities");
+    CHECKNULL(m_fdoConn, L"MgServerGetProviderCapabilities::CreateSchemaCapabilities");
+
+    FdoPtr<FdoISchemaCapabilities> fsc = m_fdoConn->GetSchemaCapabilities();
+    CHECKNULL((FdoISchemaCapabilities*)fsc, L"MgServerGetProviderCapabilities::CreateSchemaCapabilities");
+
+    DOMElement* root = m_xmlCap->GetRootNode();
+    CHECKNULL(root, L"MgServerGetProviderCapabilities::CreateSchemaCapabilities");
+
+    DOMElement* schemaNode = m_xmlCap->AddChildNode(root, "Schema");
+    CHECKNULL(schemaNode, L"MgServerGetProviderCapabilities::CreateSchemaCapabilities");
+
+    // Add all class types
+    FdoInt32 cnt = 0;
+    FdoClassType* fct = fsc->GetClassTypes(cnt);
+    if (cnt > 0 && fct != NULL)
+    {
+        DOMElement* classNode = m_xmlCap->AddChildNode(schemaNode, "Class");
+        CHECKNULL(classNode, L"MgServerGetProviderCapabilities::CreateSchemaCapabilities");
+
+        for (FdoInt32 i=0; i < cnt; i++)
+        {
+            string scStr = s_FdoClassType[fct[i]];
+            m_xmlCap->AddTextNode(classNode, "Type", scStr.c_str());
+        }
+    }
+
+    // Add all data types
+    cnt = 0;
+    FdoDataType* fdt = fsc->GetDataTypes(cnt);
+    if (cnt > 0 && fdt != NULL)
+    {
+        DOMElement* dataNode = m_xmlCap->AddChildNode(schemaNode, "Data");
+        CHECKNULL(dataNode, L"MgServerGetProviderCapabilities::CreateSchemaCapabilities");
+
+        for (FdoInt32 i=0; i < cnt; i++)
+        {
+            string dtStr = s_FdoDataType[fdt[i]];
+            m_xmlCap->AddTextNode(dataNode, "Type", dtStr.c_str());
+        }
+    }
+
+    // Supports Inheritance
+    bool supportsInheritance        = fsc->SupportsInheritance();
+    m_xmlCap->AddTextNode(schemaNode, "SupportsInheritance", supportsInheritance);
+
+    // Supports Multiple Schemas
+    bool supportsMultipleSchemas    = fsc->SupportsMultipleSchemas();
+    m_xmlCap->AddTextNode(schemaNode, "SupportsMultipleSchemas", supportsMultipleSchemas);
+
+    bool supportsObjectProperties   = fsc->SupportsObjectProperties();
+    m_xmlCap->AddTextNode(schemaNode, "SupportsObjectProperties", supportsObjectProperties);
+
+    bool supportsAssociationProperties = fsc->SupportsAssociationProperties();
+    m_xmlCap->AddTextNode(schemaNode, "SupportsAssociationProperties", supportsAssociationProperties);
+
+    bool supportsSchemaOverrides =  fsc->SupportsSchemaOverrides();
+    m_xmlCap->AddTextNode(schemaNode, "SupportsSchemaOverrides", supportsSchemaOverrides);
+
+    bool supportsNetworkModel  = fsc->SupportsNetworkModel();
+    m_xmlCap->AddTextNode(schemaNode, "SupportsNetworkModel", supportsNetworkModel);
+
+    bool supportsAutoIdGeneration  = fsc->SupportsAutoIdGeneration();
+    m_xmlCap->AddTextNode(schemaNode, "SupportsAutoIdGeneration", supportsAutoIdGeneration);
+
+    bool supportsDataStoreScopeUniqueIdGeneration  = fsc->SupportsDataStoreScopeUniqueIdGeneration();
+    m_xmlCap->AddTextNode(schemaNode, "SupportsDataStoreScopeUniqueIdGeneration", supportsDataStoreScopeUniqueIdGeneration);
+
+    FdoDataType* sagt = fsc->GetSupportedAutoGeneratedTypes(cnt);
+    if (cnt > 0 && sagt != NULL)
+    {
+        DOMElement* sagtNode = m_xmlCap->AddChildNode(schemaNode, "SupportedAutoGeneratedTypes");
+        CHECKNULL(sagtNode, L"MgServerGetProviderCapabilities::CreateSchemaCapabilities");
+
+        for (FdoInt32 i=0; i < cnt; i++)
+        {
+            string sagtStr = s_FdoDataType[sagt[i]];
+            m_xmlCap->AddTextNode(sagtNode, "Type", sagtStr.c_str());
+        }
+    }
+
+    bool supportsSchemaModification  = fsc->SupportsSchemaModification();
+    m_xmlCap->AddTextNode(schemaNode, "SupportsSchemaModification", supportsSchemaModification);
+}
+
+void MgServerGetProviderCapabilities::CreateCommandCapabilities()
+{
+    CHECKNULL(m_xmlCap, L"MgServerGetProviderCapabilities::CreateCommandCapabilities");
+    CHECKNULL(m_fdoConn, L"MgServerGetProviderCapabilities::CreateCommandCapabilities");
+
+    FdoPtr<FdoICommandCapabilities> fcc = m_fdoConn->GetCommandCapabilities();
+    CHECKNULL((FdoICommandCapabilities*)fcc, L"MgServerGetProviderCapabilities::CreateCommandCapabilities");
+
+    DOMElement* root = m_xmlCap->GetRootNode();
+    CHECKNULL(root, L"MgServerGetProviderCapabilities::CreateCommandCapabilities");
+
+    DOMElement* cmdNode = m_xmlCap->AddChildNode(root, "Command");
+    CHECKNULL(cmdNode, L"MgServerGetProviderCapabilities::CreateCommandCapabilities");
+
+    // Add all command types
+    FdoInt32 cnt = 0;
+    FdoInt32* fcmd = fcc->GetCommands(cnt);
+    if (cnt > 0 && fcmd != NULL)
+    {
+        DOMElement* scNode = m_xmlCap->AddChildNode(cmdNode, "SupportedCommands");
+        CHECKNULL(scNode, L"MgServerGetProviderCapabilities::CreateCommandCapabilities");
+
+        for (FdoInt32 i=0; i < cnt; i++)
+        {
+            string cmdStr = s_FdoCommandType[(FdoCommandType)fcmd[i]];
+            if (!cmdStr.empty())
+            {
+                switch (fcmd[i])
+                {
+                    case FdoCommandType_DescribeSchemaMapping:
+                    case FdoCommandType_NetworkShortestPath:
+                    case FdoCommandType_NetworkAllPaths:
+                    case FdoCommandType_NetworkReachableNodes:
+                    case FdoCommandType_NetworkReachingNodes:
+                    case FdoCommandType_NetworkNearestNeighbors:
+                    case FdoCommandType_NetworkWithinCost:
+                    case FdoCommandType_NetworkTSP:
+                    case FdoCommandType_ActivateTopologyArea:
+                    case FdoCommandType_DeactivateTopologyArea:
+                    case FdoCommandType_ActivateTopologyInCommandResult:
+                    case FdoCommandType_DeactivateTopologyInCommandResults:
+                    case FdoCommandType_SelectAggregates:
+                    case FdoCommandType_CreateDataStore:
+                    case FdoCommandType_DestroyDataStore:
+                    case FdoCommandType_ListDataStores:
+                        //if (m_version == VERSION_SUPPORTED(1,0))
+                        break;
+                        // these enumerates were added for version 2
+                        // fall thru to write this command
+                    default:
+                        m_xmlCap->AddTextNode(scNode, "Name", cmdStr.c_str());
+                        break;
+                }
+            }
+        }
+    }
+
+    // Supports Parameters
+    bool supportsParameters = fcc->SupportsParameters();
+    m_xmlCap->AddTextNode(cmdNode, "SupportsParameters", supportsParameters);
+
+    // Supports Timeout
+    bool supportsTimeout = fcc->SupportsTimeout();
+    m_xmlCap->AddTextNode(cmdNode, "SupportsTimeout", supportsTimeout);
+
+    // Supports SupportsSelectExpressions
+    bool supportsSelectExpressions = fcc->SupportsSelectExpressions();
+    m_xmlCap->AddTextNode(cmdNode, "SupportsSelectExpressions", supportsSelectExpressions);
+
+    // Supports SupportsSelectFunctions
+    bool supportsSelectFunctions = fcc->SupportsSelectFunctions();
+    m_xmlCap->AddTextNode(cmdNode, "SupportsSelectFunctions", supportsSelectFunctions);
+
+    // Supports SupportsSelectDistinct
+    bool supportsSelectDistinct = fcc->SupportsSelectDistinct();
+    m_xmlCap->AddTextNode(cmdNode, "SupportsSelectDistinct", supportsSelectDistinct);
+
+    // Supports SupportsSelectOrdering
+    bool supportsSelectOrdering = fcc->SupportsSelectOrdering();
+    m_xmlCap->AddTextNode(cmdNode, "SupportsSelectOrdering", supportsSelectOrdering);
+
+    // Supports SupportsSelectGrouping
+    bool supportsSelectGrouping = fcc->SupportsSelectGrouping();
+    m_xmlCap->AddTextNode(cmdNode, "SupportsSelectGrouping", supportsSelectGrouping);
+}
+
+void MgServerGetProviderCapabilities::CreateFilterCapabilities()
+{
+    CHECKNULL(m_xmlCap, L"MgServerGetProviderCapabilities::CreateFilterCapabilities");
+    CHECKNULL(m_fdoConn, L"MgServerGetProviderCapabilities::CreateFilterCapabilities");
+
+    FdoPtr<FdoIFilterCapabilities> ffc = m_fdoConn->GetFilterCapabilities();
+    CHECKNULL((FdoIFilterCapabilities*)ffc, L"MgServerGetProviderCapabilities::CreateFilterCapabilities");
+
+    DOMElement* root = m_xmlCap->GetRootNode();
+    CHECKNULL(root, L"MgServerGetProviderCapabilities::CreateFilterCapabilities");
+
+    DOMElement* filterNode = m_xmlCap->AddChildNode(root, "Filter");
+    CHECKNULL(filterNode, L"MgServerGetProviderCapabilities::CreateFilterCapabilities");
+
+    // Add all condition types
+    FdoInt32 cnt = 0;
+    FdoConditionType* fct = ffc->GetConditionTypes(cnt);
+    if (cnt > 0 && fct != NULL)
+    {
+        DOMElement* condNode = m_xmlCap->AddChildNode(filterNode, "Condition");
+        CHECKNULL(condNode, L"MgServerGetProviderCapabilities::CreateFilterCapabilities");
+
+        for (FdoInt32 i=0; i < cnt; i++)
+        {
+            string condStr = s_FdoConditionType[fct[i]];
+            m_xmlCap->AddTextNode(condNode, "Type", condStr.c_str());
+        }
+    }
+
+    // All spatial operations
+    cnt = 0;
+    FdoSpatialOperations* fso = ffc->GetSpatialOperations(cnt);
+    if (cnt > 0 && fso != NULL)
+    {
+        DOMElement* fsoNode = m_xmlCap->AddChildNode(filterNode, "Spatial");
+        CHECKNULL(fsoNode, L"MgServerGetProviderCapabilities::CreateFilterCapabilities");
+
+        for (FdoInt32 i=0; i < cnt; i++)
+        {
+            string operStr = s_FdoSpatialOperations[fso[i]];
+            m_xmlCap->AddTextNode(fsoNode, "Operation", operStr.c_str());
+        }
+    }
+
+    // All distance operations
+    cnt = 0;
+    FdoDistanceOperations* fdo = ffc->GetDistanceOperations(cnt);
+    if (cnt > 0 && fdo != NULL)
+    {
+        DOMElement* distNode = m_xmlCap->AddChildNode(filterNode, "Distance");
+        CHECKNULL(distNode, L"MgServerGetProviderCapabilities::CreateFilterCapabilities");
+
+        for (FdoInt32 i=0; i < cnt; i++)
+        {
+            string fdoStr = s_FdoDistanceOperations[fdo[i]];
+            m_xmlCap->AddTextNode(distNode, "Operation", fdoStr.c_str());
+        }
+    }
+
+    // supports Geodesic Distance
+    bool supportsGeodesicDistance = ffc->SupportsGeodesicDistance();
+    m_xmlCap->AddTextNode(filterNode, "SupportsGeodesicDistance", supportsGeodesicDistance);
+
+    // supports NonLiteral Geometric Operations
+    bool supportsNonLiteralGeometricOperations = ffc->SupportsNonLiteralGeometricOperations();
+    m_xmlCap->AddTextNode(filterNode, "SupportsNonLiteralGeometricOperations", supportsNonLiteralGeometricOperations);
+}
+
+void MgServerGetProviderCapabilities::CreateExpressionCapabilities()
+{
+    CHECKNULL(m_xmlCap, L"MgServerGetProviderCapabilities::CreateExpressionCapabilities");
+    CHECKNULL(m_fdoConn, L"MgServerGetProviderCapabilities::CreateExpressionCapabilities");
+
+    FdoPtr<FdoIExpressionCapabilities> fec = m_fdoConn->GetExpressionCapabilities();
+    CHECKNULL((FdoIExpressionCapabilities*)fec, L"MgServerGetProviderCapabilities::CreateExpressionCapabilities");
+
+    DOMElement* root = m_xmlCap->GetRootNode();
+    CHECKNULL(root, L"MgServerGetProviderCapabilities::CreateExpressionCapabilities");
+
+    DOMElement* expressionNode = m_xmlCap->AddChildNode(root, "Expression");
+    CHECKNULL(expressionNode, L"MgServerGetProviderCapabilities::CreateExpressionCapabilities");
+
+    // Add all expression types
+    FdoInt32 cnt = 0;
+    FdoExpressionType* fet = fec->GetExpressionTypes(cnt);
+    if (cnt > 0 && fet != NULL)
+    {
+        DOMElement* typeNode = m_xmlCap->AddChildNode(expressionNode, "Type");
+        CHECKNULL(typeNode, L"MgServerGetProviderCapabilities::CreateExpressionCapabilities");
+
+        for (FdoInt32 i=0; i < cnt; i++)
+        {
+            string typeStr = s_FdoExpressionType[fet[i]];
+            m_xmlCap->AddTextNode(typeNode, "Name", typeStr.c_str());
+        }
+    }
+
+    // Add all functions available
+    cnt = 0;
+    FdoPtr<FdoFunctionDefinitionCollection> ffdc = fec->GetFunctions();
+    if (NULL != (FdoFunctionDefinitionCollection*)ffdc)
+    {
+        FdoInt32 funcCnt = ffdc->GetCount();
+        if (funcCnt > 0)
+        {
+            // Add function definition collection element if there are any functions available
+            DOMElement* funcDefColNode = m_xmlCap->AddChildNode(expressionNode, "FunctionDefinitionList");
+            CHECKNULL(funcDefColNode, L"MgServerGetProviderCapabilities::CreateExpressionCapabilities");
+
+            for (FdoInt32 i=0; i < funcCnt; i++)
+            {
+                // Add function definition element
+                FdoPtr<FdoFunctionDefinition> ffd = ffdc->GetItem(i);
+                CHECKNULL((FdoFunctionDefinition*)ffd, L"MgServerGetProviderCapabilities::CreateExpressionCapabilities");
+
+                DOMElement* funcDefNode = m_xmlCap->AddChildNode(funcDefColNode, "FunctionDefinition");
+                CHECKNULL(funcDefNode, L"MgServerGetProviderCapabilities::CreateExpressionCapabilities");
+
+                const char* strName = MgUtil::WideCharToMultiByte(ffd->GetName());
+                const char* strDesc = MgUtil::WideCharToMultiByte(ffd->GetDescription());
+
+                FdoDataType eDataType = ffd->GetReturnType();
+                string strDataType = s_FdoDataType[eDataType];
+
+                m_xmlCap->AddTextNode(funcDefNode, "Name", strName);
+                m_xmlCap->AddTextNode(funcDefNode, "Description", strDesc);
+                m_xmlCap->AddTextNode(funcDefNode, "ReturnType",  strDataType.c_str());
+
+                delete[] strName;
+                delete[] strDesc;
+
+                // Add argument of each functions if there are any
+                FdoPtr<FdoReadOnlyArgumentDefinitionCollection> argCol = ffd->GetArguments();
+                if (NULL != (FdoReadOnlyArgumentDefinitionCollection*)argCol)
+                {
+                    FdoInt32 argCnt = argCol->GetCount();
+                    if (argCnt > 0)
+                    {
+                        // Add ArgumentDefinitionCollection if there are arguments
+                        DOMElement* argDefColNode = m_xmlCap->AddChildNode(funcDefNode, "ArgumentDefinitionList");
+                        CHECKNULL(argDefColNode, L"MgServerGetProviderCapabilities::CreateExpressionCapabilities");
+
+                        for (FdoInt32 j=0; j < argCnt; j++)
+                        {
+                            // Add ArgumentDefinition for each argument
+                            FdoPtr<FdoArgumentDefinition> fad = argCol->GetItem(j);
+                            CHECKNULL((FdoArgumentDefinition*)fad, L"MgServerGetProviderCapabilities::CreateExpressionCapabilities");
+
+                            DOMElement* argDefNode = m_xmlCap->AddChildNode(argDefColNode, "ArgumentDefinition");
+                            CHECKNULL(argDefNode, L"MgServerGetProviderCapabilities::CreateExpressionCapabilities");
+
+                            const char* strArgName = MgUtil::WideCharToMultiByte(fad->GetName());
+                            const char* strArgDesc = MgUtil::WideCharToMultiByte(fad->GetDescription());
+
+                            FdoDataType eArgDataType = fad->GetDataType();
+                            string strArgDataType = s_FdoDataType[eArgDataType];
+
+                            m_xmlCap->AddTextNode(argDefNode, "Name", strArgName);
+                            m_xmlCap->AddTextNode(argDefNode, "Description", strArgDesc);
+                            m_xmlCap->AddTextNode(argDefNode, "ReturnType",  strArgDataType.c_str());
+
+                            delete[] strArgName;
+                            delete[] strArgDesc;
+                        }
+                    }
+                }
+            }
+        }
+    }
+}
+
+
+void MgServerGetProviderCapabilities::CreateExpressionCapabilities2()
+{
+    CHECKNULL(m_xmlCap, L"MgServerGetProviderCapabilities::CreateExpressionCapabilities");
+    CHECKNULL(m_fdoConn, L"MgServerGetProviderCapabilities::CreateExpressionCapabilities");
+
+    FdoPtr<FdoIExpressionCapabilities> fec = m_fdoConn->GetExpressionCapabilities();
+    CHECKNULL((FdoIExpressionCapabilities*)fec, L"MgServerGetProviderCapabilities::CreateExpressionCapabilities");
+
+    DOMElement* root = m_xmlCap->GetRootNode();
+    CHECKNULL(root, L"MgServerGetProviderCapabilities::CreateExpressionCapabilities");
+
+    DOMElement* expressionNode = m_xmlCap->AddChildNode(root, "Expression");
+    CHECKNULL(expressionNode, L"MgServerGetProviderCapabilities::CreateExpressionCapabilities");
+
+    // Add all expression types
+    FdoInt32 cnt = 0;
+    FdoExpressionType* fet = fec->GetExpressionTypes(cnt);
+    if (cnt > 0 && fet != NULL)
+    {
+        DOMElement* typeNode = m_xmlCap->AddChildNode(expressionNode, "Type");
+        CHECKNULL(typeNode, L"MgServerGetProviderCapabilities::CreateExpressionCapabilities");
+
+        for (FdoInt32 i=0; i < cnt; i++)
+        {
+            string typeStr = s_FdoExpressionType[fet[i]];
+            m_xmlCap->AddTextNode(typeNode, "Name", typeStr.c_str());
+        }
+    }
+
+    // Add all functions available
+    cnt = 0;
+    FdoPtr<FdoFunctionDefinitionCollection> ffdc = fec->GetFunctions();
+    if (NULL != (FdoFunctionDefinitionCollection*)ffdc)
+    {
+        FdoInt32 funcCnt = ffdc->GetCount();
+        if (funcCnt > 0)
+        {
+            // Add function definition collection element if there are any functions available
+            DOMElement* funcDefColNode = m_xmlCap->AddChildNode(expressionNode, "FunctionDefinitionList");
+            CHECKNULL(funcDefColNode, L"MgServerGetProviderCapabilities::CreateExpressionCapabilities");
+
+            for (FdoInt32 i=0; i < funcCnt; i++)
+            {
+                // Add function definition element
+                FdoPtr<FdoFunctionDefinition> ffd = ffdc->GetItem(i);
+                CHECKNULL((FdoFunctionDefinition*)ffd, L"MgServerGetProviderCapabilities::CreateExpressionCapabilities");
+
+                DOMElement* funcDefNode = m_xmlCap->AddChildNode(funcDefColNode, "FunctionDefinition");
+                CHECKNULL(funcDefNode, L"MgServerGetProviderCapabilities::CreateExpressionCapabilities");
+
+                const char* strName = MgUtil::WideCharToMultiByte(ffd->GetName());
+                const char* strDesc = MgUtil::WideCharToMultiByte(ffd->GetDescription());
+
+                FdoFunctionCategoryType eFdoFunctionCategoryType = ffd->GetFunctionCategoryType();
+                string strFunctionCategoryType = s_FdoFunctionCategoryType[eFdoFunctionCategoryType];
+
+                m_xmlCap->AddTextNode(funcDefNode, "Name", strName);
+                m_xmlCap->AddTextNode(funcDefNode, "Description", strDesc);
+                m_xmlCap->AddTextNode(funcDefNode, "CategoryType",  strFunctionCategoryType.c_str());
+                m_xmlCap->AddTextNode(funcDefNode, "IsAggregate",  ffd->IsAggregate());
+                m_xmlCap->AddTextNode(funcDefNode, "IsSupportsVariableArgumentsList",  ffd->SupportsVariableArgumentsList());
+
+                delete[] strName;
+                delete[] strDesc;
+
+                // Add argument of each functions if there are any
+                FdoPtr<FdoReadOnlySignatureDefinitionCollection> signatures = ffd->GetSignatures();
+                if (NULL != (FdoReadOnlySignatureDefinitionCollection*)signatures)
+                {
+                    FdoInt32 signaturesCnt = signatures->GetCount();
+                    if (signaturesCnt > 0)
+                    {
+
+                        DOMElement* signDefColNode = m_xmlCap->AddChildNode(funcDefNode, "SignatureDefinitionCollection");
+                        CHECKNULL(signDefColNode, L"MgServerGetProviderCapabilities::CreateExpressionCapabilities");
+                        for (FdoInt32 j=0; j < signaturesCnt; j++)
+                        {
+
+                            // Add SignatureDefinition for each signature
+                            FdoPtr<FdoSignatureDefinition> fsd = signatures->GetItem(j);
+                            CHECKNULL((FdoSignatureDefinition*)fsd, L"MgServerGetProviderCapabilities::CreateExpressionCapabilities");
+
+                            DOMElement* signDefNode = m_xmlCap->AddChildNode(signDefColNode, "SignatureDefinition");
+                            CHECKNULL(signDefNode, L"MgServerGetProviderCapabilities::CreateExpressionCapabilities");
+
+                            FdoPropertyType eSignPropertyDataType = fsd->GetReturnPropertyType();
+                            string strSignPropertyType = s_FdoPropertyTypeAsString[eSignPropertyDataType];
+                            string strSignDataType;
+                            if (eSignPropertyDataType == FdoPropertyType_DataProperty)
+                            {
+                                FdoDataType eSignDataType = fsd->GetReturnType();
+                                strSignDataType = s_FdoDataType[eSignDataType];
+                            }
+
+                            m_xmlCap->AddTextNode(signDefNode, "PropertyType", strSignPropertyType.c_str());
+                            if (eSignPropertyDataType == FdoPropertyType_DataProperty)
+                                m_xmlCap->AddTextNode(signDefNode, "DataType",  strSignDataType.c_str());
+
+                            DOMElement* argDefColNode = m_xmlCap->AddChildNode(signDefNode, "ArgumentDefinitionList");
+                            CHECKNULL(argDefColNode, L"MgServerGetProviderCapabilities::CreateExpressionCapabilities");
+
+                            FdoPtr<FdoReadOnlyArgumentDefinitionCollection> fads = fsd->GetArguments();
+                            if (NULL != (FdoReadOnlyArgumentDefinitionCollection *) fads)
+                            {
+                                FdoInt32 argCnt = fads->GetCount();
+                                if (argCnt > 0)
+                                {
+                                    for (int k=0; k<argCnt; k++)
+                                    {
+                                        FdoPtr<FdoArgumentDefinition> fad = fads->GetItem(k);
+                                        CHECKNULL((FdoArgumentDefinition*)fad, L"MgServerGetProviderCapabilities::CreateExpressionCapabilities");
+
+                                        DOMElement* argDefNode = m_xmlCap->AddChildNode(argDefColNode, "ArgumentDefinition");
+                                        CHECKNULL(argDefNode, L"MgServerGetProviderCapabilities::CreateExpressionCapabilities");
+
+                                        const char* strArgName = MgUtil::WideCharToMultiByte(fad->GetName());
+                                        const char* strArgDesc = MgUtil::WideCharToMultiByte(fad->GetDescription());
+
+                                        FdoPropertyType eArgPropertyDataType = fad->GetPropertyType();
+                                        string strArgPropertyType = s_FdoPropertyTypeAsString[eArgPropertyDataType];
+                                        string strArgDataType;
+                                        if (eArgPropertyDataType == FdoPropertyType_DataProperty)
+                                        {
+                                            FdoDataType eArgDataType = fad->GetDataType();
+                                            strArgDataType = s_FdoDataType[eArgDataType];
+                                        }
+
+                                        m_xmlCap->AddTextNode(argDefNode, "Name", strArgName);
+                                        m_xmlCap->AddTextNode(argDefNode, "Description", strArgDesc);
+                                        m_xmlCap->AddTextNode(argDefNode, "PropertyType", strArgPropertyType.c_str());
+                                        if (eArgPropertyDataType == FdoPropertyType_DataProperty)
+                                            m_xmlCap->AddTextNode(argDefNode, "DataType",  strArgDataType.c_str());
+
+                                        delete[] strArgName;
+                                        delete[] strArgDesc;
+
+                                        FdoPtr<FdoPropertyValueConstraintList> fpvc = fad->GetArgumentValueList();
+                                        if (NULL != (FdoPropertyValueConstraintList *) fpvc)
+                                        {
+                                            if (fpvc->GetConstraintType() == FdoPropertyValueConstraintType_List)
+                                            {
+                                                DOMElement* propValueConstListNode = m_xmlCap->AddChildNode(argDefNode, "PropertyValueConstraintList");
+                                                CHECKNULL(propValueConstListNode, L"MgServerGetProviderCapabilities::CreateExpressionCapabilities");
+
+                                                FdoPropertyValueConstraintType eConstraintType = fpvc->GetConstraintType();
+
+                                                FdoPtr<FdoDataValueCollection> dvc = fpvc->GetConstraintList();
+                                                if (NULL != (FdoDataValueCollection *) dvc)
+                                                {
+                                                    FdoInt32 dvCnt = dvc->GetCount();
+                                                    if (dvCnt > 0)
+                                                    {
+                                                        for (int l=0; l<dvCnt; l++)
+                                                        {
+                                                            FdoPtr<FdoDataValue> dv = dvc->GetItem(l);
+                                                            CHECKNULL((FdoDataValue*)dv, L"MgServerGetProviderCapabilities::CreateExpressionCapabilities");
+                                                            FdoDataType dataType = dv->GetDataType();
+                                                            // FdoDataType_String is the only supported type
+                                                            if (dataType == FdoDataType_String)
+                                                            {
+                                                                FdoStringValue *stringValue = (FdoStringValue *) dv.p;
+                                                                FdoString* xmlValue = stringValue->GetString();
+                                                                const char* strDataValue = MgUtil::WideCharToMultiByte(stringValue->GetString());
+                                                                m_xmlCap->AddTextNode(propValueConstListNode, "Value", xmlValue);
+                                                                delete[] strDataValue;
+                                                            }
+                                                        }
+                                                    }
+                                                }
+                                            }
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+}
+
+void MgServerGetProviderCapabilities::CreateRasterCapabilities()
+{
+    CHECKNULL(m_xmlCap, L"MgServerGetProviderCapabilities::CreateRasterCapabilities");
+    CHECKNULL(m_fdoConn, L"MgServerGetProviderCapabilities::CreateRasterCapabilities");
+
+    FdoPtr<FdoIRasterCapabilities> frc = m_fdoConn->GetRasterCapabilities();
+    CHECKNULL((FdoIRasterCapabilities*)frc, L"MgServerGetProviderCapabilities::CreateRasterCapabilities");
+
+    DOMElement* root = m_xmlCap->GetRootNode();
+    CHECKNULL(root, L"MgServerGetProviderCapabilities::CreateRasterCapabilities");
+
+    DOMElement* rasterNode = m_xmlCap->AddChildNode(root, "Raster");
+    CHECKNULL(rasterNode, L"MgServerGetProviderCapabilities::CreateRasterCapabilities");
+
+    // Supports Raster
+    bool supportsRaster = frc->SupportsRaster();
+    m_xmlCap->AddTextNode(rasterNode, "SupportsRaster", supportsRaster);
+
+    // Supports Stitching
+    bool supportsStitching = frc->SupportsStitching();
+    m_xmlCap->AddTextNode(rasterNode, "SupportsStitching", supportsStitching);
+
+    bool supportsSubsampling = frc->SupportsSubsampling();
+    m_xmlCap->AddTextNode(rasterNode, "SupportsSubsampling", supportsSubsampling);
+
+}
+
+void MgServerGetProviderCapabilities::CreateTopologyCapabilities()
+{
+    CHECKNULL(m_xmlCap, L"MgServerGetProviderCapabilities::CreateTopologyCapabilities");
+    CHECKNULL(m_fdoConn, L"MgServerGetProviderCapabilities::CreateTopologyCapabilities");
+
+    MG_FEATURE_SERVICE_TRY()
+
+    FdoPtr<FdoITopologyCapabilities> frc = m_fdoConn->GetTopologyCapabilities();
+
+    // Provider has no topology capabilities
+    if (NULL == (FdoITopologyCapabilities*)frc)
+    {
+        return;
+    }
+
+    DOMElement* root = m_xmlCap->GetRootNode();
+    CHECKNULL(root, L"MgServerGetProviderCapabilities::CreateTopologyCapabilities");
+
+    DOMElement* topologyNode = m_xmlCap->AddChildNode(root, "Topology");
+    CHECKNULL(topologyNode, L"MgServerGetProviderCapabilities::CreateTopologyCapabilities");
+
+    // Supports Topology
+    bool supportsTopology = frc->SupportsTopology();
+    m_xmlCap->AddTextNode(topologyNode, "SupportsTopology", supportsTopology);
+
+    // Supports Stitching
+    bool supportsTopologicalHierarchy = frc->SupportsTopologicalHierarchy();
+    m_xmlCap->AddTextNode(topologyNode, "SupportsTopologicalHierarchy", supportsTopologicalHierarchy);
+
+    bool breaksCurveCrossingsAutomatically = frc->BreaksCurveCrossingsAutomatically();
+    m_xmlCap->AddTextNode(topologyNode, "BreaksCurveCrossingsAutomatically", breaksCurveCrossingsAutomatically);
+
+    bool activatesTopologyByArea = frc->ActivatesTopologyByArea();
+    m_xmlCap->AddTextNode(topologyNode, "ActivatesTopologyByArea", activatesTopologyByArea);
+
+    bool constrainsFeatureMovements = frc->ConstrainsFeatureMovements();
+    m_xmlCap->AddTextNode(topologyNode, "ConstrainsFeatureMovements", constrainsFeatureMovements);
+
+    // TODO: Change this to CATCH_AND_THROW when SimpleDB stops throwing exception of not implemented
+    MG_FEATURE_SERVICE_CATCH(L"MgServerGetProviderCapabilities.CreateTopologyCapabilities")
+
+}
+
+void MgServerGetProviderCapabilities::CreateGeometryCapabilities()
+{
+    CHECKNULL(m_xmlCap, L"MgServerGetProviderCapabilities.CreateGeometryCapabilities");
+    CHECKNULL(m_fdoConn, L"MgServerGetProviderCapabilities.CreateGeometryCapabilities");
+
+    MG_FEATURE_SERVICE_TRY()
+
+    FdoPtr<FdoIGeometryCapabilities> fgc = m_fdoConn->GetGeometryCapabilities();
+
+    // Provider has no geometric capabilities
+    if (NULL == (FdoIGeometryCapabilities*)fgc)
+    {
+        return;
+    }
+
+    DOMElement* root = m_xmlCap->GetRootNode();
+    CHECKNULL(root, L"MgServerGetProviderCapabilities.CreateGeometryCapabilities");
+
+    DOMElement* geometryNode = m_xmlCap->AddChildNode(root, "Geometry");
+    CHECKNULL(geometryNode, L"MgServerGetProviderCapabilities.CreateGeometryCapabilities");
+
+    FdoInt32 cnt = 0;
+    FdoGeometryType* geomType = fgc->GetGeometryTypes(cnt);
+    if (cnt > 0 && geomType != NULL)
+    {
+        DOMElement* geometryTypeNode = m_xmlCap->AddChildNode(geometryNode, "Types");
+        CHECKNULL(geometryTypeNode, L"MgServerGetProviderCapabilities.CreateGeometryCapabilities");
+
+        for (FdoInt32 i=0; i < cnt; i++)
+        {
+            string geomTypeStr = s_FdoGeometryType[geomType[i]];
+            m_xmlCap->AddTextNode(geometryTypeNode, "Type", geomTypeStr.c_str());
+        }
+    }
+
+    FdoGeometryComponentType* geomCompType = fgc->GetGeometryComponentTypes(cnt);
+    if (cnt > 0 && geomCompType != NULL)
+    {
+        DOMElement* geometryCompNode = m_xmlCap->AddChildNode(geometryNode, "Components");
+        CHECKNULL(geometryCompNode, L"MgServerGetProviderCapabilities.CreateGeometryCapabilities");
+
+        for (FdoInt32 i=0; i < cnt; i++)
+        {
+            string geomCompStr = s_FdoGeometryComponentType[geomCompType[i]];
+            m_xmlCap->AddTextNode(geometryCompNode, "Type", geomCompStr.c_str());
+        }
+    }
+
+    FdoInt32 dim = fgc->GetDimensionalities();
+
+    char buff[8]; buff[0] = 0;
+    sprintf(buff, "%d", dim);
+
+    m_xmlCap->AddTextNode(geometryNode, "Dimensionality", &buff[0]);
+
+    MG_FEATURE_SERVICE_CATCH_AND_THROW(L"MgServerGetProviderCapabilities.CreateGeometryCapabilities")
+}
+
+bool MgServerGetProviderCapabilities::IsConnectionOpen()
+{
+    CHECKNULL(m_fdoConn, L"MgServerGetProviderCapabilities.IsConnectionOpen");
+
+    FdoConnectionState state = m_fdoConn->GetConnectionState();
+    if (state != FdoConnectionState_Open)
+        return false;
+
+    return true;
+}
+
+bool MgServerGetProviderCapabilities::Initialize()
+{
+    // Thread Capability
+    s_FdoThreadCapability[FdoThreadCapability_SingleThreaded]           = "SingleThreaded";
+    s_FdoThreadCapability[FdoThreadCapability_PerConnectionThreaded]    = "PerConnectionThreaded";
+    s_FdoThreadCapability[FdoThreadCapability_PerCommandThreaded]       = "PerCommandThreaded";
+    s_FdoThreadCapability[FdoThreadCapability_MultiThreaded]            = "MultiThreaded";
+
+    // Spatial Extent type
+    s_FdoSpatialContextExtentType[FdoSpatialContextExtentType_Static]   = "Static";
+    s_FdoSpatialContextExtentType[FdoSpatialContextExtentType_Dynamic]  = "Dynamic";
+
+    // Class Types
+    s_FdoClassType[FdoClassType_Class]                  = "Class";
+    s_FdoClassType[FdoClassType_FeatureClass]           = "FeatureClass";
+    s_FdoClassType[FdoClassType_NetworkClass]           = "NetworkClass";
+    s_FdoClassType[FdoClassType_NetworkLayerClass]      = "NetworkLayerClass";
+    s_FdoClassType[FdoClassType_NetworkNodeClass]       = "NetworkNodeClass";
+
+    // Data types
+    s_FdoDataType[FdoDataType_Boolean]     = "Boolean";
+    s_FdoDataType[FdoDataType_Byte]        = "Byte";
+    s_FdoDataType[FdoDataType_DateTime]    = "DateTime";
+    // Implementation Note:  FdoDataType_Decimal is currently mapped to MgPropertyType::Double.
+    // An MgDecimalProperty class should be implemented in a future release.
+    s_FdoDataType[FdoDataType_Decimal]     = "Double";
+    s_FdoDataType[FdoDataType_Double]      = "Double";
+    s_FdoDataType[FdoDataType_Int16]       = "Int16";
+    s_FdoDataType[FdoDataType_Int32]       = "Int32";
+    s_FdoDataType[FdoDataType_Int64]       = "Int64";
+    s_FdoDataType[FdoDataType_Single]      = "Single";
+    s_FdoDataType[FdoDataType_String]      = "String";
+    s_FdoDataType[FdoDataType_BLOB]        = "BLOB";
+    s_FdoDataType[FdoDataType_CLOB]        = "CLOB";
+
+    s_FdoPropertyTypeAsString[FdoPropertyType_DataProperty]     = "Data";
+    s_FdoPropertyTypeAsString[FdoPropertyType_GeometricProperty]        = "Geometry";
+    s_FdoPropertyTypeAsString[FdoPropertyType_ObjectProperty]        = "Object";
+    s_FdoPropertyTypeAsString[FdoPropertyType_AssociationProperty]        = "Association";
+    s_FdoPropertyTypeAsString[FdoPropertyType_RasterProperty]        = "Raster";
+
+    s_FdoFunctionCategoryType[FdoFunctionCategoryType_Aggregate] = "Aggregate";
+    s_FdoFunctionCategoryType[FdoFunctionCategoryType_Conversion] = "Conversion";
+    s_FdoFunctionCategoryType[FdoFunctionCategoryType_Custom] = "Custom";
+    s_FdoFunctionCategoryType[FdoFunctionCategoryType_Date] = "Date";
+    s_FdoFunctionCategoryType[FdoFunctionCategoryType_Geometry] = "Geometry";
+    s_FdoFunctionCategoryType[FdoFunctionCategoryType_Math] = "Math";
+    s_FdoFunctionCategoryType[FdoFunctionCategoryType_Numeric] = "Numeric";
+    s_FdoFunctionCategoryType[FdoFunctionCategoryType_String] = "String";
+    s_FdoFunctionCategoryType[FdoFunctionCategoryType_Unspecified] = "Unspecified";
+
+    // Commands
+    s_FdoCommandType[FdoCommandType_Select]                             = "Select";
+    s_FdoCommandType[FdoCommandType_Insert]                             = "Insert";
+    s_FdoCommandType[FdoCommandType_Delete]                             = "Delete";
+    s_FdoCommandType[FdoCommandType_Update]                             = "Update";
+    s_FdoCommandType[FdoCommandType_DescribeSchema]                     = "DescribeSchema";
+    s_FdoCommandType[FdoCommandType_DescribeSchemaMapping]              = "DescribeSchemaMapping";
+    s_FdoCommandType[FdoCommandType_ApplySchema]                        = "ApplySchema";
+    s_FdoCommandType[FdoCommandType_DestroySchema]                      = "DestroySchema";
+    s_FdoCommandType[FdoCommandType_ActivateSpatialContext]             = "ActivateSpatialContext";
+    s_FdoCommandType[FdoCommandType_CreateSpatialContext]               = "CreateSpatialContext";
+    s_FdoCommandType[FdoCommandType_DestroySpatialContext]              = "DestroySpatialContext";
+    s_FdoCommandType[FdoCommandType_GetSpatialContexts]                 = "GetSpatialContexts";
+    s_FdoCommandType[FdoCommandType_CreateMeasureUnit]                  = "CreateMeasureUnit";
+    s_FdoCommandType[FdoCommandType_DestroyMeasureUnit]                 = "DestroyMeasureUnit";
+    s_FdoCommandType[FdoCommandType_GetMeasureUnits]                    = "GetMeasureUnits";
+    s_FdoCommandType[FdoCommandType_SQLCommand]                         = "SQLCommand";
+    s_FdoCommandType[FdoCommandType_AcquireLock]                        = "AcquireLock";
+    s_FdoCommandType[FdoCommandType_GetLockInfo]                        = "GetLockInfo";
+    s_FdoCommandType[FdoCommandType_GetLockedObjects]                   = "GetLockedObjects";
+    s_FdoCommandType[FdoCommandType_GetLockOwners]                      = "GetLockOwners";
+    s_FdoCommandType[FdoCommandType_ReleaseLock]                        = "ReleaseLock";
+    s_FdoCommandType[FdoCommandType_ActivateLongTransaction]            = "ActivateLongTransaction";
+    s_FdoCommandType[FdoCommandType_DeactivateLongTransaction]          = "DeactivateLongTransaction";
+    s_FdoCommandType[FdoCommandType_CommitLongTransaction]              = "CommitLongTransaction";
+    s_FdoCommandType[FdoCommandType_CreateLongTransaction]              = "CreateLongTransaction";
+    s_FdoCommandType[FdoCommandType_GetLongTransactions]                = "GetLongTransactions";
+    s_FdoCommandType[FdoCommandType_FreezeLongTransaction]              = "FreezeLongTransaction";
+    s_FdoCommandType[FdoCommandType_RollbackLongTransaction]            = "RollbackLongTransaction";
+    s_FdoCommandType[FdoCommandType_ActivateLongTransactionCheckpoint]  = "ActivateLongTransactionCheckpoint";
+    s_FdoCommandType[FdoCommandType_CreateLongTransactionCheckpoint]    = "CreateLongTransactionCheckpoint";
+    s_FdoCommandType[FdoCommandType_GetLongTransactionCheckpoints]      = "GetLongTransactionCheckpoints";
+    s_FdoCommandType[FdoCommandType_RollbackLongTransactionCheckpoint]  = "RollbackLongTransactionCheckpoint";
+    s_FdoCommandType[FdoCommandType_ChangeLongTransactionPrivileges]    = "ChangeLongTransactionPrivileges";
+    s_FdoCommandType[FdoCommandType_GetLongTransactionPrivileges]       = "GetLongTransactionPrivileges";
+    s_FdoCommandType[FdoCommandType_ChangeLongTransactionSet]           = "ChangeLongTransactionSet";
+    s_FdoCommandType[FdoCommandType_GetLongTransactionsInSet]           = "GetLongTransactionsInSet";
+    s_FdoCommandType[FdoCommandType_NetworkShortestPath]                = "NetworkShortestPath";
+    s_FdoCommandType[FdoCommandType_NetworkAllPaths]                    = "NetworkAllPaths";
+    s_FdoCommandType[FdoCommandType_NetworkReachableNodes]              = "NetworkReachableNodes";
+    s_FdoCommandType[FdoCommandType_NetworkReachingNodes]               = "NetworkReachingNodes";
+    s_FdoCommandType[FdoCommandType_NetworkNearestNeighbors]            = "NetworkNearestNeighbors";
+    s_FdoCommandType[FdoCommandType_NetworkWithinCost]                  = "NetworkWithinCost";
+    s_FdoCommandType[FdoCommandType_NetworkTSP]                         = "NetworkTSP";
+    s_FdoCommandType[FdoCommandType_ActivateTopologyArea]               = "ActivateTopologyArea";
+    s_FdoCommandType[FdoCommandType_DeactivateTopologyArea]             = "DeactivateTopologyArea";
+    s_FdoCommandType[FdoCommandType_ActivateTopologyInCommandResult]    = "ActivateTopologyInCommandResult";
+    s_FdoCommandType[FdoCommandType_DeactivateTopologyInCommandResults] = "DeactivateTopologyInCommandResults";
+    s_FdoCommandType[FdoCommandType_SelectAggregates]                   = "SelectAggregates";
+    s_FdoCommandType[FdoCommandType_CreateDataStore]                    = "CreateDataStore";
+    s_FdoCommandType[FdoCommandType_DestroyDataStore]                   = "DestroyDataStore";
+    s_FdoCommandType[FdoCommandType_ListDataStores]                     = "ListDataStores";
+    s_FdoCommandType[FdoCommandType_FirstProviderCommand]               = "FirstProviderCommand";
+
+    // Condition types
+    s_FdoConditionType[FdoConditionType_Comparison]                     = "Comparison";
+    s_FdoConditionType[FdoConditionType_Like]                           = "Like";
+    s_FdoConditionType[FdoConditionType_In]                             = "In";
+    s_FdoConditionType[FdoConditionType_Null]                           = "Null";
+    s_FdoConditionType[FdoConditionType_Spatial]                        = "Spatial";
+    s_FdoConditionType[FdoConditionType_Distance]                       = "Distance";
+
+    // Spatial Operations
+    s_FdoSpatialOperations[FdoSpatialOperations_Contains]               = "Contains";
+    s_FdoSpatialOperations[FdoSpatialOperations_Crosses]                = "Crosses";
+    s_FdoSpatialOperations[FdoSpatialOperations_Disjoint]               = "Disjoint";
+    s_FdoSpatialOperations[FdoSpatialOperations_Equals]                 = "Equals";
+    s_FdoSpatialOperations[FdoSpatialOperations_Intersects]             = "Intersects";
+    s_FdoSpatialOperations[FdoSpatialOperations_Overlaps]               = "Overlaps";
+    s_FdoSpatialOperations[FdoSpatialOperations_Touches]                = "Touches";
+    s_FdoSpatialOperations[FdoSpatialOperations_Within]                 = "Within";
+    s_FdoSpatialOperations[FdoSpatialOperations_CoveredBy]              = "CoveredBy";
+    s_FdoSpatialOperations[FdoSpatialOperations_Inside]                 = "Inside";
+    s_FdoSpatialOperations[FdoSpatialOperations_EnvelopeIntersects]     = "EnvelopeIntersects";
+
+    // Distance Operation
+    s_FdoDistanceOperations[FdoDistanceOperations_Beyond]               = "Beyond";
+    s_FdoDistanceOperations[FdoDistanceOperations_Within]               = "Within";
+
+    // Expression Type
+    s_FdoExpressionType[FdoExpressionType_Basic]                        = "Basic";
+    s_FdoExpressionType[FdoExpressionType_Function]                     = "Function";
+    s_FdoExpressionType[FdoExpressionType_Parameter]                    = "Parameter";
+
+    // Geometry Type
+    s_FdoGeometryType[FdoGeometryType_None]                     = "None";
+    s_FdoGeometryType[FdoGeometryType_Point]                    = "Point";
+    s_FdoGeometryType[FdoGeometryType_LineString]               = "LineString";
+    s_FdoGeometryType[FdoGeometryType_Polygon]                  = "Polygon";
+    s_FdoGeometryType[FdoGeometryType_MultiPoint]               = "MultiPoint";
+    s_FdoGeometryType[FdoGeometryType_MultiLineString]          = "MultiLineString";
+    s_FdoGeometryType[FdoGeometryType_MultiPolygon]             = "MultiPolygon";
+    s_FdoGeometryType[FdoGeometryType_MultiGeometry]            = "MultiGeometry";
+    s_FdoGeometryType[FdoGeometryType_CurveString]              = "CurveString";
+    s_FdoGeometryType[FdoGeometryType_CurvePolygon]             = "CurvePolygon";
+    s_FdoGeometryType[FdoGeometryType_MultiCurveString]         = "MultiCurveString";
+    s_FdoGeometryType[FdoGeometryType_MultiCurvePolygon]        = "MultiCurvePolygon";
+
+    // Geometry component type
+    s_FdoGeometryComponentType[FdoGeometryComponentType_LinearRing]         = "LinearRing";
+    s_FdoGeometryComponentType[FdoGeometryComponentType_CircularArcSegment] = "ArcSegment";
+    s_FdoGeometryComponentType[FdoGeometryComponentType_LineStringSegment]  = "LinearSegment";
+    s_FdoGeometryComponentType[FdoGeometryComponentType_Ring]               = "CurveRing";
+
+    return true;
+}

Added: branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/GetProviderCapabilities.h
===================================================================
--- branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/GetProviderCapabilities.h	                        (rev 0)
+++ branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/GetProviderCapabilities.h	2012-07-15 16:59:27 UTC (rev 6903)
@@ -0,0 +1,56 @@
+//
+//  Copyright (C) 2004-2011 by Autodesk, Inc.
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of version 2.1 of the GNU Lesser
+//  General Public License as published by the Free Software Foundation.
+//
+//  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 St, Fifth Floor, Boston, MA  02110-1301  USA
+//
+
+#ifndef _MG_SERVER_GET_PROVIDER_CAPABILITIES_H_
+#define _MG_SERVER_GET_PROVIDER_CAPABILITIES_H_
+
+#include "MgDesktop.h"
+#include "System/XmlDefs.h"
+#include "System/XmlUtil.h"
+#include "Fdo.h"
+
+class MgServerGetProviderCapabilities
+{
+public:
+    MgServerGetProviderCapabilities(CREFSTRING providerName, CREFSTRING connectionString);
+    ~MgServerGetProviderCapabilities();
+    MgByteReader* GetProviderCapabilities();
+
+private:
+
+    void CreateCapabilitiesDocument();
+    void CreateConnectionCapabilities();
+    void CreateSchemaCapabilities();
+    void CreateCommandCapabilities();
+    void CreateFilterCapabilities();
+    void CreateExpressionCapabilities();
+    void CreateExpressionCapabilities2();
+    void CreateRasterCapabilities();
+    void CreateTopologyCapabilities();
+    void CreateGeometryCapabilities();
+
+    bool IsConnectionOpen();
+    static bool Initialize();
+
+    MgXmlUtil*              m_xmlUtil;
+    STRING                  m_providerName;
+    FdoPtr<FdoIConnection>  m_fdoConn;
+    MgXmlUtil*              m_xmlCap;
+    static bool             m_isInitialized;
+};
+
+#endif

Added: branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/GetSchemaMapping.cpp
===================================================================
--- branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/GetSchemaMapping.cpp	                        (rev 0)
+++ branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/GetSchemaMapping.cpp	2012-07-15 16:59:27 UTC (rev 6903)
@@ -0,0 +1,119 @@
+//
+//  Copyright (C) 2004-2011 by Autodesk, Inc.
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of version 2.1 of the GNU Lesser
+//  General Public License as published by the Free Software Foundation.
+//
+//  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 St, Fifth Floor, Boston, MA  02110-1301  USA
+//
+
+#include "Services/Feature/FeatureDefs.h"
+#include "GetSchemaMapping.h"
+#include "Services/Resource/UnmanagedDataManager.h"
+
+MgServerGetSchemaMapping::MgServerGetSchemaMapping() :
+    m_bytes(NULL)
+{
+}
+
+MgServerGetSchemaMapping::~MgServerGetSchemaMapping()
+{
+    delete [] m_bytes;
+    m_bytes = NULL;
+}
+
+
+MgByteReader* MgServerGetSchemaMapping::GetSchemaMapping(CREFSTRING providerName, CREFSTRING partialConnString)
+{
+    Ptr<MgByteReader> byteReader;
+
+    MG_FEATURE_SERVICE_TRY()
+
+    STRING data = partialConnString;
+    MgUnmanagedDataManager::SubstituteDataPathAliases(data);
+
+    // Connect to the provider
+    Ptr<MgFeatureConnection> msfc = new MgFeatureConnection(providerName, data);
+    if ((NULL != msfc.p) && (( msfc->IsConnectionOpen() ) || ( msfc->IsConnectionPending() )))
+    {
+        // The reference to the FDO connection from the MgFeatureConnection object must be cleaned up before the parent object
+        // otherwise it leaves the FDO connection marked as still in use.
+        FdoPtr<FdoIConnection> fdoConnection;
+        fdoConnection = msfc->GetConnection();
+
+        // Create the memory stream
+        FdoIoMemoryStreamP fmis = FdoIoMemoryStream::Create();
+        CHECKNULL((FdoIoMemoryStream*)fmis, L"MgServerGetSchemaMapping.GetSchemaMapping");
+
+        FdoXmlWriterP writer = FdoXmlWriter::Create(fmis);
+
+        FdoPtr<FdoXmlSpatialContextFlags> flags = FdoXmlSpatialContextFlags::Create();
+        flags->SetIncludeDefault(true);
+
+        // Serialize the spatial contexts
+        FdoXmlSpatialContextSerializer::XmlSerialize(
+            fdoConnection,
+            FdoXmlSpatialContextWriterP(
+                FdoXmlSpatialContextWriter::Create(writer)
+            ),
+            flags
+        );
+
+        // Get the schema
+        FdoPtr<FdoIDescribeSchema> fdoDescribeSchemaCommand = (FdoIDescribeSchema*)fdoConnection->CreateCommand(FdoCommandType_DescribeSchema);
+        CHECKNULL((FdoIDescribeSchema*)fdoDescribeSchemaCommand, L"MgServerGetSchemaMapping.GetSchemaMapping");
+
+        // Execute the command
+        FdoPtr<FdoFeatureSchemaCollection> fdoFeatureSchemaCollection;
+        fdoFeatureSchemaCollection = fdoDescribeSchemaCommand->Execute();
+        CHECKNULL((FdoFeatureSchemaCollection*)fdoFeatureSchemaCollection, L"MgServerGetSchemaMapping.GetSchemaMapping");
+
+        // Write to memory stream
+        fdoFeatureSchemaCollection->WriteXml(writer);
+
+        // Get the schema mapping
+        FdoPtr<FdoIDescribeSchemaMapping> fdoDescribeSchemaMappingCommand = (FdoIDescribeSchemaMapping*)fdoConnection->CreateCommand(FdoCommandType_DescribeSchemaMapping);
+        CHECKNULL((FdoIDescribeSchemaMapping*)fdoDescribeSchemaMappingCommand, L"MgServerGetSchemaMapping.GetSchemaMapping");
+
+        fdoDescribeSchemaMappingCommand->SetIncludeDefaults(true);
+
+        // Execute the command
+        FdoPtr<FdoPhysicalSchemaMappingCollection> fdoPhysicalSchemaMappingCollection;
+        fdoPhysicalSchemaMappingCollection = fdoDescribeSchemaMappingCommand->Execute();
+        CHECKNULL((FdoPhysicalSchemaMappingCollection*)fdoPhysicalSchemaMappingCollection, L"MgServerGetSchemaMapping.GetSchemaMapping");
+
+        // Write to memory stream
+        fdoPhysicalSchemaMappingCollection->WriteXml(writer);
+
+        // Close the XML writer
+        writer->Close();
+
+        fmis->Reset(); // TODO: We should not be calling reset here. A defect in FDO should be fixed.
+
+        FdoInt64 len = fmis->GetLength();
+        m_bytes = new FdoByte[(size_t)len];
+        CHECKNULL(m_bytes, L"MgServerGetSchemaMapping.GetSchemaMapping");
+
+        fmis->Read(m_bytes, (FdoSize)len);
+
+        Ptr<MgByteSource> byteSource = new MgByteSource((BYTE_ARRAY_IN)m_bytes, (INT32)len);
+        byteSource->SetMimeType(MgMimeType::Xml);
+        byteReader = byteSource->GetReader();
+    }
+    else
+    {
+        throw new MgConnectionFailedException(L"MgServerGetSchemaMapping::GetSchemaMapping()", __LINE__, __WFILE__, NULL, L"", NULL);
+    }
+
+    MG_FEATURE_SERVICE_CATCH_AND_THROW(L"MgServerGetSchemaMapping.GetSchemaMapping")
+
+    return byteReader.Detach();
+}

Added: branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/GetSchemaMapping.h
===================================================================
--- branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/GetSchemaMapping.h	                        (rev 0)
+++ branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/GetSchemaMapping.h	2012-07-15 16:59:27 UTC (rev 6903)
@@ -0,0 +1,39 @@
+//
+//  Copyright (C) 2004-2011 by Autodesk, Inc.
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of version 2.1 of the GNU Lesser
+//  General Public License as published by the Free Software Foundation.
+//
+//  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 St, Fifth Floor, Boston, MA  02110-1301  USA
+//
+
+#ifndef _MG_SERVER_GET_SCHEMA_MAPPING_H_
+#define _MG_SERVER_GET_SCHEMA_MAPPING_H_
+
+#include "MgDesktop.h"
+#include "System/XmlDefs.h"
+#include "System/XmlUtil.h"
+#include "Fdo.h"
+
+class MgServerGetSchemaMapping
+{
+public:
+    MgServerGetSchemaMapping();
+    ~MgServerGetSchemaMapping();
+
+
+    MgByteReader* GetSchemaMapping(CREFSTRING providerName, CREFSTRING partialConnString);
+
+private:
+    FdoByte* m_bytes;
+};
+
+#endif

Added: branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/GetSpatialContexts.cpp
===================================================================
--- branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/GetSpatialContexts.cpp	                        (rev 0)
+++ branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/GetSpatialContexts.cpp	2012-07-15 16:59:27 UTC (rev 6903)
@@ -0,0 +1,293 @@
+//
+//  Copyright (C) 2004-2011 by Autodesk, Inc.
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of version 2.1 of the GNU Lesser
+//  General Public License as published by the Free Software Foundation.
+//
+//  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 St, Fifth Floor, Boston, MA  02110-1301  USA
+//
+
+#include "Services/Feature/FeatureDefs.h"
+#include "GetSpatialContexts.h"
+#include "Services/Feature/FeatureConnection.h"
+#include "Services/Feature/FeatureUtil.h"
+#include "Services/Feature/FeatureServiceCache.h"
+#include "GeometryCommon.h"
+
+MgServerGetSpatialContexts::MgServerGetSpatialContexts()
+{
+    m_featureServiceCache = MgFeatureServiceCache::GetInstance();
+}
+
+MgServerGetSpatialContexts::~MgServerGetSpatialContexts()
+{
+}
+
+// Executes the GetSpatialContext command and creates a reader
+
+MgSpatialContextReader* MgServerGetSpatialContexts::GetSpatialContexts(MgResourceIdentifier* resId)
+{
+    Ptr<MgSpatialContextReader> mgSpatialContextReader;
+
+    MG_FEATURE_SERVICE_TRY()
+
+    mgSpatialContextReader = m_featureServiceCache->GetSpatialContextReader(resId);
+
+    if (NULL == mgSpatialContextReader.p)
+    {
+        // Connect to provider
+        Ptr<MgFeatureConnection> msfc = new MgFeatureConnection(resId);
+
+        // Connection must be open to retrieve a list of available contexts.
+        if ((NULL != msfc.p) && ( msfc->IsConnectionOpen() ))
+        {
+            // The reference to the FDO connection from the MgFeatureConnection object must be cleaned up before the parent object
+            // otherwise it leaves the FDO connection marked as still in use.
+            FdoPtr<FdoIConnection> fdoConn = msfc->GetConnection();
+            m_providerName = msfc->GetProviderName();
+
+            Ptr<MgSpatialContextCacheItem> cacheItem = m_featureServiceCache->GetSpatialContextInfo(resId);
+            MgSpatialContextInfo* spatialContextInfo = cacheItem->Get();
+
+            // Check whether command is supported by provider
+            if (!msfc->SupportsCommand((INT32)FdoCommandType_GetSpatialContexts))
+            {
+                // TODO: specify which argument and message, once we have the mechanism
+                STRING message = MgFeatureUtil::GetMessage(L"MgCommandNotSupported");
+                throw new MgInvalidOperationException(L"MgServerGetSpatialContexts.GetSpatialContexts", __LINE__, __WFILE__, NULL, L"", NULL);
+            }
+
+            FdoPtr<FdoIGetSpatialContexts> fdoCommand = (FdoIGetSpatialContexts*)fdoConn->CreateCommand(FdoCommandType_GetSpatialContexts);
+            CHECKNULL((FdoIGetSpatialContexts*)fdoCommand, L"MgServerGetSpatialContexts.GetSpatialContexts");
+
+            // Execute the command
+            FdoPtr<FdoISpatialContextReader> spatialReader = fdoCommand->Execute();
+            CHECKNULL((FdoISpatialContextReader*)spatialReader, L"MgServerGetSpatialContexts.GetSpatialContexts");
+
+            mgSpatialContextReader = new MgSpatialContextReader();
+            while (spatialReader->ReadNext())
+            {
+                // Set providername for which spatial reader is executed
+                mgSpatialContextReader->SetProviderName(m_providerName);
+
+                Ptr<MgSpatialContextData> spatialData = GetSpatialContextData(spatialReader, spatialContextInfo);
+                CHECKNULL((MgSpatialContextData*)spatialData, L"MgServerGetSpatialContexts.GetSpatialContexts");
+
+                // Add spatial data to the spatialcontext reader
+                mgSpatialContextReader->AddSpatialData(spatialData);
+            }
+
+            m_featureServiceCache->SetSpatialContextReader(resId, mgSpatialContextReader.p);
+        }
+        else
+        {
+            throw new MgConnectionFailedException(L"MgServerGetSpatialContexts.GetSpatialContexts()", __LINE__, __WFILE__, NULL, L"", NULL);
+        }
+    }
+    else
+    {
+        //MgCacheManager::GetInstance()->CheckPermission(resId, MgResourcePermission::ReadOnly);
+    }
+
+    MG_FEATURE_SERVICE_CHECK_CONNECTION_CATCH_AND_THROW(resId, L"MgServerGetSpatialContexts.GetSpatialContexts")
+
+    return mgSpatialContextReader.Detach();
+}
+
+MgSpatialContextData* MgServerGetSpatialContexts::GetSpatialContextData(
+    FdoISpatialContextReader* spatialReader, MgSpatialContextInfo* spatialContextInfo)
+{
+    Ptr<MgSpatialContextData> spatialData = new MgSpatialContextData();
+
+    // Name must exist
+    FdoString* name = spatialReader->GetName();
+    CHECKNULL((FdoString*)name, L"MgServerGetSpatialContexts.GetSpatialContexts");
+    spatialData->SetName(STRING(name));
+
+    STRING coordSysName = L"";
+    FdoString* csName = spatialReader->GetCoordinateSystem();
+
+    Ptr<MgCoordinateSystemFactory> csFactory;
+    // WKT for co-ordinate system
+    FdoString* csWkt = NULL;
+    STRING srsWkt = L"";
+
+    bool haveValidCoordSys = false;
+    if(NULL != csName && *csName != '\0')
+    {
+        coordSysName = STRING(csName);
+    }
+    else
+    {
+        csWkt = spatialReader->GetCoordinateSystemWkt();
+        if (csWkt != NULL && *csWkt != '\0')
+        {
+            srsWkt = csWkt;
+            try
+            {
+                csFactory = new MgCoordinateSystemFactory();
+                coordSysName = csFactory->ConvertWktToCoordinateSystemCode(srsWkt);
+                haveValidCoordSys = (coordSysName.size() != 0);
+            }
+            catch (MgException* e)
+            {
+                SAFE_RELEASE(e);
+            }
+            catch(...)
+            {
+            }
+        }
+    }
+
+    bool spatialContextDefined = !coordSysName.empty();
+    bool coordSysOverridden = false;
+
+    // look for coordinate system override
+    if (NULL != spatialContextInfo)
+    {
+        // Perform substitution of missing coordinate system with
+        // the spatial context mapping defined in feature source document
+        MgSpatialContextInfo::const_iterator iter = spatialContextInfo->find(name);
+
+        if (spatialContextInfo->end() != iter)
+        {
+            csName = (iter->second).c_str();
+            coordSysOverridden = true;
+        }
+    }
+
+    if (csName != NULL && *csName != '\0')
+    {
+        spatialData->SetCoordinateSystem(STRING(csName));
+    }
+
+    // Desc for spatial context
+    STRING desc = L"";
+
+    // This flag is obsolete and will be deprecated.
+    bool isActive = spatialReader->IsActive();
+
+    if (coordSysOverridden)
+    {
+        srsWkt = csName;
+        desc = MgFeatureUtil::GetMessage(L"MgCoordinateSystemOverridden");
+    }
+    else if (spatialContextDefined && !coordSysOverridden)
+    {
+        // avoid looking one more time after CS in case we have a valid one...
+        if (!haveValidCoordSys)
+        {
+            csWkt = spatialReader->GetCoordinateSystemWkt();
+            if(NULL != csWkt && *csWkt != '\0')
+                srsWkt = csWkt;
+
+            if (srsWkt.empty())
+            {
+                try
+                {
+                    if (csFactory == NULL)
+                        csFactory = new MgCoordinateSystemFactory();
+
+                    // Check if the spatial context coordinate system data represents an EPSG
+                    // code. If this is the case the WKT data for the EPSG code has to be
+                    // retrieved.
+                    if (IsEpsgCodeRepresentation(csName))
+                    {
+                        // This is an EPSG code
+                        FdoString* p = NULL;
+                        if ((csName[0] == L'E') || (csName[0] == L'e'))
+                            p = csName+5;
+                        else
+                            p = csName;
+
+                        INT32 epsgCode = (INT32)wcstol(p, NULL, 10);
+
+                        // Convert the EPSG numerical code to WKT
+                        srsWkt = csFactory->ConvertEpsgCodeToWkt(epsgCode);
+                    }
+                    else
+                    {
+                        srsWkt = csFactory->ConvertCoordinateSystemCodeToWkt(STRING(csName));
+                    }
+                }
+                catch (MgException* e)
+                {
+                    SAFE_RELEASE(e);
+                }
+                catch(...)
+                {
+                    // Just use the empty WKT.
+                }
+            }
+        }
+        FdoString* fdoDesc = spatialReader->GetDescription();
+        if(NULL != fdoDesc)
+            desc = STRING(fdoDesc);
+    }
+
+    // retrieve other values from spatialReader
+    FdoSpatialContextExtentType extentType = spatialReader->GetExtentType();
+    FdoPtr<FdoByteArray> byteArray = spatialReader->GetExtent();
+    double xyTol = spatialReader->GetXYTolerance();
+    double zTol = spatialReader->GetZTolerance();
+
+    spatialData->SetCoordinateSystemWkt(srsWkt);
+    spatialData->SetDescription(desc);
+    spatialData->SetExtentType((INT32)extentType);
+
+    if (byteArray.p != NULL)
+    {
+        INT32 size = (INT32)byteArray->GetCount();
+        BYTE_ARRAY_IN bytes = (BYTE_ARRAY_IN)byteArray->GetData();
+        Ptr<MgByte> extent = new MgByte(bytes, size);
+        spatialData->SetExtent(extent);
+    }
+
+    // XY Tolerance
+    spatialData->SetXYTolerance(xyTol);
+
+    // Z Tolerance
+    spatialData->SetZTolerance(zTol);
+
+    // This flag is obsolete and will be deprecated.
+    spatialData->SetActiveStatus(isActive);
+
+    return spatialData.Detach();
+}
+
+bool MgServerGetSpatialContexts::IsEpsgCodeRepresentation (FdoString *coordSysName)
+{
+    // If the given coordinate system name is NULL or not NULL but empty
+    // return false as those cases do not represent an EPSG code.
+    if ((coordSysName == NULL) || (coordSysName[0] == L'\0'))
+        return false;
+
+    // Check if the string contains a coded EPSG number ("EPSG:<num>"). If this
+    // is the case return true;
+    size_t coordSysNameLength  = wcslen(coordSysName);
+    if (coordSysNameLength  > 5)
+        if (((coordSysName[0] == L'E') || (coordSysName[0] == L'e')) &&
+            ((coordSysName[1] == L'P') || (coordSysName[1] == L'p')) &&
+            ((coordSysName[2] == L'S') || (coordSysName[2] == L's')) &&
+            ((coordSysName[3] == L'G') || (coordSysName[3] == L'g')) &&
+            (coordSysName[4] == L':')                                   )
+            return true;
+
+    // The string does not contain a coded EPSG number. Next, check if the
+    // string represents a numeric value. If this is the case then the value
+    // represents an EPSG code and the routine has to return true.
+    for (size_t i = 0; i < coordSysNameLength; i++)
+        if (!iswdigit(coordSysName[i]))
+            return false;
+
+    // This is an EPSG code. Indicate so.
+    return true;
+}

Added: branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/GetSpatialContexts.h
===================================================================
--- branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/GetSpatialContexts.h	                        (rev 0)
+++ branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/GetSpatialContexts.h	2012-07-15 16:59:27 UTC (rev 6903)
@@ -0,0 +1,50 @@
+//
+//  Copyright (C) 2004-2011 by Autodesk, Inc.
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of version 2.1 of the GNU Lesser
+//  General Public License as published by the Free Software Foundation.
+//
+//  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 St, Fifth Floor, Boston, MA  02110-1301  USA
+//
+
+#ifndef MG_SERVERGETSPATIALCONTEXTS_H_
+#define MG_SERVERGETSPATIALCONTEXTS_H_
+
+#include "MgDesktop.h"
+#include "System/XmlDefs.h"
+#include "System/XmlUtil.h"
+#include "Fdo.h"
+
+class MgFeatureServiceCache;
+
+class MgServerGetSpatialContexts
+{
+public:
+    MgServerGetSpatialContexts();
+    ~MgServerGetSpatialContexts();
+    MgSpatialContextReader* GetSpatialContexts(MgResourceIdentifier* resId);
+
+private:
+    MgSpatialContextData* GetSpatialContextData(FdoISpatialContextReader* spatialReader,
+        MgSpatialContextInfo* spatialContextInfo);
+
+    // ==========================================================================
+    // ===================== EPSG RELATED UTILITY FUNCTIONS =====================
+    // ==========================================================================
+    // Checks whether or not the coordinate system name represents an EPSG code.
+    // If this is the case the routine returns TRUE, FALSE otherwise.
+    bool IsEpsgCodeRepresentation (FdoString *coordSysName);
+
+    STRING m_providerName;
+    MgFeatureServiceCache* m_featureServiceCache;
+};
+
+#endif

Added: branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/InsertCommand.cpp
===================================================================
--- branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/InsertCommand.cpp	                        (rev 0)
+++ branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/InsertCommand.cpp	2012-07-15 16:59:27 UTC (rev 6903)
@@ -0,0 +1,256 @@
+//
+//  Copyright (C) 2004-2011 by Autodesk, Inc.
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of version 2.1 of the GNU Lesser
+//  General Public License as published by the Free Software Foundation.
+//
+//  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 St, Fifth Floor, Boston, MA  02110-1301  USA
+//
+
+#include "Services/Feature/FeatureDefs.h"
+#include "MgDesktop.h"
+#include "Services/FeatureService.h"
+#include "Services/Feature/FeatureConnection.h"
+#include "FeatureManipulationCommand.h"
+#include "InsertCommand.h"
+#include "Services/Feature/FeatureUtil.h"
+#include "Services/FeatureReader.h"
+#include "Services/Feature/FeatureSetReader.h"
+
+MgServerInsertCommand::MgServerInsertCommand()
+{
+    m_srvrFeatConn = NULL;
+    m_featCommand = NULL;
+}
+
+MgServerInsertCommand::MgServerInsertCommand(MgFeatureCommand* command, MgFeatureConnection* connection, INT32 cmdId)
+{
+    CHECKNULL(command, L"MgServerInsertCommand.MgServerInsertCommand");
+    CHECKNULL(connection, L"MgServerInsertCommand.MgServerInsertCommand");
+
+    m_srvrFeatConn = SAFE_ADDREF((MgFeatureConnection*)connection);
+    m_featCommand = SAFE_ADDREF((MgInsertFeatures*)command);
+    m_cmdId = cmdId;
+}
+
+MgServerInsertCommand::~MgServerInsertCommand()
+{
+    m_srvrFeatConn = NULL;
+}
+
+MgProperty* MgServerInsertCommand::Execute()
+{
+    Ptr<MgFeatureProperty> prop;
+
+    STRING clsName = m_featCommand->GetFeatureClassName();
+    Ptr<MgBatchPropertyCollection> srcCol = m_featCommand->GetBatchPropertyValues();
+
+    if ((srcCol == NULL) || srcCol->GetCount() == 0)
+    {
+        STRING message = MgFeatureUtil::GetMessage(L"MgNoFeaturesForInsert");
+
+        MgStringCollection arguments;
+        arguments.Add(message);
+        throw new MgFeatureServiceException(L"MgServerInsertCommand::Execute", __LINE__, __WFILE__, &arguments, L"", NULL);
+    }
+
+    FdoPtr<FdoIConnection> fdoConn = m_srvrFeatConn->GetConnection();
+
+    // Create the SQL command
+    FdoPtr<FdoIInsert> fdoCommand = (FdoIInsert*)fdoConn->CreateCommand(FdoCommandType_Insert);
+    CHECKNULL((FdoIInsert*)fdoCommand, L"MgServerInsertCommand.Execute");
+
+    fdoCommand->SetFeatureClassName(clsName.c_str());
+
+    // TODO: Fdo returns NULL here for Oracle and SDF, ArcSDE supports it.
+    FdoPtr<FdoBatchParameterValueCollection> bParamValCol = fdoCommand->GetBatchParameterValues();
+    if (bParamValCol != NULL && bParamValCol->GetCount() > 1)
+    {
+        prop = BatchInsert(srcCol, bParamValCol, fdoCommand, fdoConn);
+    }
+    else
+    {
+        FdoPtr<FdoPropertyValueCollection> propValCol = fdoCommand->GetPropertyValues();
+        prop = SingleInsert(srcCol, propValCol, fdoCommand, fdoConn);
+    }
+
+    return prop.Detach();
+}
+
+MgFeatureProperty* MgServerInsertCommand::BatchInsert( MgBatchPropertyCollection* srcCol,
+                                                       FdoBatchParameterValueCollection* bParamValCol,
+                                                       FdoIInsert* fdoCommand,
+                                                       FdoIConnection* fdoConn)
+{
+    INT32 cnt = srcCol->GetCount();
+    for (INT32 i = 0; i < cnt; i++)
+    {
+        Ptr<MgPropertyCollection> propCol = srcCol->GetItem(i);
+        FdoPtr<FdoParameterValueCollection> paramCol = MgFeatureUtil::CreateFdoParameterCollection(propCol);
+        bParamValCol->Add(paramCol);
+    }
+    FdoPtr<FdoIFeatureReader> reader = fdoCommand->Execute();
+    CHECKNULL((FdoIFeatureReader*)reader, L"MgServerInsertCommand.BatchInsert");
+
+    // TODO: This is FDO defect, they should not require ReadNext() for class definition
+    bool available = false;
+    try
+    {
+        available = reader->ReadNext();
+    }
+    catch(FdoException* e)
+    {
+        FDO_SAFE_RELEASE(e);
+        available = false;
+    }
+    catch (...)
+    {
+        available = false;
+    }
+
+    if (!available)
+    {
+        STRING message = MgFeatureUtil::GetMessage(L"MgInsertError");
+
+        MgStringCollection arguments;
+        arguments.Add(message);
+        throw new MgFeatureServiceException(L"MgServerGwsGetFeatures.BatchInsert", __LINE__, __WFILE__, &arguments, L"", NULL);
+    }
+
+    char buff[32];
+    sprintf(buff, "%d", m_cmdId);
+    STRING str = MgUtil::MultiByteToWideChar(string(buff));
+
+    Ptr<MgFeatureReader> mgFeatureReader = new MgdFeatureReader(m_srvrFeatConn, reader);
+    return new MgFeatureProperty(str, mgFeatureReader);
+}
+
+MgFeatureProperty* MgServerInsertCommand::SingleInsert( MgBatchPropertyCollection* srcCol,
+                                                        FdoPropertyValueCollection* propValCol,
+                                                        FdoIInsert* fdoCommand,
+                                                        FdoIConnection* fdoConn )
+{
+    Ptr<MgFeatureSet> featureSet = new MgFeatureSet();
+    featureSet->SetClassDefinition(NULL);
+    Ptr<MgPropertyDefinitionCollection> keyProps;
+
+    INT32 cnt = srcCol->GetCount();
+    for (INT32 i=0; i<cnt; i++)
+    {
+        Ptr<MgPropertyCollection> propCol = srcCol->GetItem(i);
+
+        propValCol->Clear();
+        MgFeatureUtil::FillFdoPropertyCollection(propCol, propValCol);
+
+        FdoPtr<FdoIFeatureReader> reader = fdoCommand->Execute();
+        CHECKNULL((FdoIFeatureReader*)reader, L"MgServerInsertCommand.SingleInsert");
+
+        if (keyProps == NULL)
+        {
+            FdoPtr<FdoClassDefinition> classDef = reader->GetClassDefinition();
+            FdoPtr<FdoDataPropertyDefinitionCollection> idProps = classDef->GetIdentityProperties();
+            if (idProps->GetCount() > 0)
+            {
+                keyProps = new MgPropertyDefinitionCollection();
+                MgFeatureUtil::GetClassProperties(keyProps, idProps);
+            }
+        }
+
+        if (keyProps == NULL)
+        {
+            STRING message = MgFeatureUtil::GetMessage(L"MgInsertError");
+
+            MgStringCollection arguments;
+            arguments.Add(message);
+            throw new MgFeatureServiceException(L"MgServerInsertCommand.SingleInsert", __LINE__, __WFILE__, &arguments, L"", NULL);
+        }
+
+        bool available = false;
+        try
+        {
+            available = reader->ReadNext();
+        }
+        catch(FdoException* e)
+        {
+            FDO_SAFE_RELEASE(e);
+            available = false;
+        }
+        catch (...)
+        {
+            available = false;
+        }
+
+        if (!available)
+        {
+            STRING message = MgFeatureUtil::GetMessage(L"MgInsertError");
+
+            MgStringCollection arguments;
+            arguments.Add(message);
+            throw new MgFeatureServiceException(L"MgServerInsertCommand.SingleInsert", __LINE__, __WFILE__, &arguments, L"", NULL);
+        }
+
+        // Performance improvement: Only return the key values
+        Ptr<MgPropertyCollection> idProperties = new MgPropertyCollection();
+        INT32 nProps = keyProps->GetCount();
+        for (int j=0; j<nProps; j++)
+        {
+            Ptr<MgDataPropertyDefinition> propDef = dynamic_cast<MgDataPropertyDefinition*>(keyProps->GetItem(j));
+            if (propDef == NULL) continue;
+
+            //TODO: should we use qualified name here?
+            STRING propName = propDef->GetName();
+            INT32 propType = propDef->GetDataType();
+            switch (propType)
+            {
+                case MgPropertyType::Int16:
+                {
+                    Ptr<MgInt16Property> intProp = new MgInt16Property(propName, reader->GetInt16(propName.c_str()));
+                    idProperties->Add(intProp);
+                }
+                break;
+
+                case MgPropertyType::Int32:
+                {
+                    Ptr<MgInt32Property> intProp = new MgInt32Property(propName, reader->GetInt32(propName.c_str()));
+                    idProperties->Add(intProp);
+                }
+                break;
+
+                case MgPropertyType::Int64:
+                {
+                    Ptr<MgInt64Property> intProp = new MgInt64Property(propName, reader->GetInt64(propName.c_str()));
+                    idProperties->Add(intProp);
+                }
+                break;
+
+                case MgPropertyType::String:
+                {
+                    Ptr<MgStringProperty> strProp = new MgStringProperty(propName, reader->GetString(propName.c_str()));
+                    idProperties->Add(strProp);
+                }
+                break;
+
+                default:
+                break;
+            }
+        }
+
+        featureSet->AddFeature(idProperties);
+    }
+
+    Ptr<MgFeatureReader> featureSetReader = new MgdFeatureSetReader(featureSet);
+
+    char buff[32];
+    sprintf(buff, "%d", m_cmdId);
+    STRING str = MgUtil::MultiByteToWideChar(string(buff));
+
+    return new MgFeatureProperty(str, featureSetReader);
+}

Added: branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/InsertCommand.h
===================================================================
--- branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/InsertCommand.h	                        (rev 0)
+++ branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/InsertCommand.h	2012-07-15 16:59:27 UTC (rev 6903)
@@ -0,0 +1,50 @@
+//
+//  Copyright (C) 2004-2011 by Autodesk, Inc.
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of version 2.1 of the GNU Lesser
+//  General Public License as published by the Free Software Foundation.
+//
+//  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 St, Fifth Floor, Boston, MA  02110-1301  USA
+//
+
+#ifndef _MG_SERVER_INSERT_COMMAND_H_
+#define _MG_SERVER_INSERT_COMMAND_H_
+
+class MgFeatureConnection;
+
+class MgServerInsertCommand : public MgFeatureManipulationCommand
+{
+    DECLARE_CLASSNAME(MgServerInsertCommand)
+
+public:
+    MgServerInsertCommand(MgFeatureCommand* command, MgFeatureConnection* connection, INT32 cmdId);
+    virtual MgProperty* Execute();
+protected:
+    MgServerInsertCommand();
+    ~MgServerInsertCommand();
+
+    MgFeatureProperty* BatchInsert(  MgBatchPropertyCollection* srcCol,
+                                     FdoBatchParameterValueCollection* bParamValCol,
+                                     FdoIInsert* fdoCommand,
+                                     FdoIConnection* fdoConn );
+
+    MgFeatureProperty* SingleInsert( MgBatchPropertyCollection* srcCol,
+                                     FdoPropertyValueCollection* bParamValCol,
+                                     FdoIInsert* fdoCommand,
+                                     FdoIConnection* fdoConn );
+
+private:
+    Ptr<MgInsertFeatures> m_featCommand;
+    Ptr<MgFeatureConnection> m_srvrFeatConn;
+    INT32 m_cmdId;
+};
+
+#endif

Added: branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/SelectAggregateCommand.cpp
===================================================================
--- branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/SelectAggregateCommand.cpp	                        (rev 0)
+++ branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/SelectAggregateCommand.cpp	2012-07-15 16:59:27 UTC (rev 6903)
@@ -0,0 +1,340 @@
+//
+//  Copyright (C) 2004-2011 by Autodesk, Inc.
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of version 2.1 of the GNU Lesser
+//  General Public License as published by the Free Software Foundation.
+//
+//  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 St, Fifth Floor, Boston, MA  02110-1301  USA
+//
+
+#include "Services/Feature/FeatureDefs.h"
+#include "MgDesktop.h"
+#include "Services/FeatureService.h"
+#include "FeatureServiceCommand.h"
+#include "SelectCommand.h"
+#include "SelectAggregateCommand.h"
+#include "Services/DataReader.h"
+#include "Services/Feature/FeatureConnection.h"
+#include "Services/Feature/FdoForcedOneToOneFeatureReader.h"
+#include "Services/Feature/FeatureUtil.h"
+#include "FdoExpressionEngine.h"
+#include "Util/FdoExpressionEngineUtilDataReader.h"
+
+
+MgSelectAggregateCommand::MgSelectAggregateCommand(MgResourceIdentifier* resource)
+{
+    CHECKNULL((MgResourceIdentifier*)resource, L"MgSelectAggregateCommand.MgSelectAggregateCommand");
+
+    // Connect to provider
+    m_connection = new MgFeatureConnection(resource);
+    if ((NULL != m_connection.p) && ( m_connection->IsConnectionOpen() ))
+    {
+        m_providerName = m_connection->GetProviderName();
+    }
+    else
+    {
+        throw new MgConnectionFailedException(L"MgSelectAggregateCommand.MgSelectAggregateCommand", __LINE__, __WFILE__, NULL, L"", NULL);
+    }
+    // Create FdoISelectAggregates command
+    FdoPtr<FdoIConnection> fdoConn = m_connection->GetConnection();
+    m_command = (FdoISelectAggregates*)fdoConn->CreateCommand(FdoCommandType_SelectAggregates);
+    CHECKNULL((FdoISelectAggregates*)m_command, L"MgSelectAggregateCommand.MgSelectAggregateCommand");
+}
+
+MgSelectAggregateCommand::~MgSelectAggregateCommand()
+{
+    m_command = NULL;
+    m_filter = NULL;
+}
+
+FdoIdentifierCollection* MgSelectAggregateCommand::GetPropertyNames()
+{
+    CHECKNULL((FdoISelectAggregates*)m_command, L"MgSelectAggregateCommand.GetPropertyNames");
+    return m_command->GetPropertyNames();
+}
+
+void MgSelectAggregateCommand::SetDistinct(bool value)
+{
+    CHECKNULL((FdoISelectAggregates*)m_command, L"MgSelectAggregateCommand.SetDistinct");
+    m_command->SetDistinct(value);
+}
+
+bool MgSelectAggregateCommand::GetDistinct()
+{
+    CHECKNULL((FdoISelectAggregates*)m_command, L"MgSelectAggregateCommand.GetDistinct");
+    return m_command->GetDistinct();
+}
+
+void MgSelectAggregateCommand::SetFetchSize(FdoInt32 fetchSize)
+{
+    CHECKNULL((FdoISelectAggregates*)m_command, L"MgSelectAggregateCommand.SetFetchSize");
+    m_command->SetFetchSize(fetchSize);
+}
+
+FdoInt32 MgSelectAggregateCommand::GetFetchSize()
+{
+    CHECKNULL((FdoISelectAggregates*)m_command, L"MgSelectAggregateCommand.GetFetchSize");
+    return m_command->GetFetchSize();
+}
+
+FdoIdentifierCollection* MgSelectAggregateCommand::GetOrdering()
+{
+    CHECKNULL((FdoISelectAggregates*)m_command, L"MgSelectAggregateCommand.GetOrdering");
+    return m_command->GetOrdering();
+}
+
+void MgSelectAggregateCommand::SetOrderingOption(FdoOrderingOption option)
+{
+    CHECKNULL((FdoISelectAggregates*)m_command, L"MgSelectAggregateCommand.SetOrderingOption");
+    m_command->SetOrderingOption(option);
+}
+
+FdoOrderingOption MgSelectAggregateCommand::GetOrderingOption()
+{
+    CHECKNULL((FdoISelectAggregates*)m_command, L"MgSelectAggregateCommand.GetOrderingOption");
+    return m_command->GetOrderingOption();
+}
+
+FdoIdentifierCollection* MgSelectAggregateCommand::GetGrouping()
+{
+    CHECKNULL((FdoISelectAggregates*)m_command, L"MgSelectAggregateCommand.GetGrouping");
+    return m_command->GetGrouping();
+}
+
+void MgSelectAggregateCommand::SetGroupingFilter(FdoFilter* filter)
+{
+    CHECKNULL((FdoISelectAggregates*)m_command, L"MgSelectAggregateCommand.SetGroupingFilter");
+    m_command->SetGroupingFilter(filter);
+}
+
+FdoFilter* MgSelectAggregateCommand::GetGroupingFilter()
+{
+    CHECKNULL((FdoISelectAggregates*)m_command, L"MgSelectAggregateCommand.GetGroupingFilter");
+    return m_command->GetGroupingFilter();
+}
+
+void MgSelectAggregateCommand::SetFeatureClassName(FdoString* value)
+{
+    CHECKNULL((FdoISelectAggregates*)m_command, L"MgSelectAggregateCommand.SetFeatureClassName");
+    m_command->SetFeatureClassName(value);
+}
+
+void MgSelectAggregateCommand::SetFilter(FdoString* value)
+{
+    CHECKNULL((FdoISelectAggregates*)m_command, L"MgSelectAggregateCommand.SetFilter");
+    m_command->SetFilter(value);
+}
+
+void MgSelectAggregateCommand::SetFilter(FdoFilter* value)
+{
+    CHECKNULL((FdoISelectAggregates*)m_command, L"MgSelectAggregateCommand.SetFilter");
+    m_command->SetFilter(value);
+
+    m_filter = FDO_SAFE_ADDREF(value);
+}
+
+MgReader* MgSelectAggregateCommand::Execute()
+{
+    // Execute the command
+    CHECKNULL((FdoISelectAggregates*)m_command, L"MgSelectAggregateCommand.Execute");
+    FdoPtr<FdoIDataReader> dataReader = m_command->Execute();
+    CHECKNULL((FdoIDataReader*)dataReader, L"MgSelectAggregateCommand.Execute");
+
+    // Create a feature reader identifier
+    return new MgdDataReader(m_connection, dataReader); //, m_providerName);
+}
+
+bool MgSelectAggregateCommand::IsSupportedFunction(FdoFunction* fdoFunc)
+{
+    FdoPtr<FdoIConnection> fdoConn = m_connection->GetConnection();
+    return this->IsFdoSupportedFunction(fdoConn, fdoFunc);
+}
+
+bool MgSelectAggregateCommand::SupportsSelectGrouping()
+{
+    FdoPtr<FdoIConnection> fdoConn = m_connection->GetConnection();
+    return MgFeatureServiceCommand::SupportsSelectGrouping(fdoConn);
+}
+
+bool MgSelectAggregateCommand::SupportsSelectOrdering()
+{
+    FdoPtr<FdoIConnection> fdoConn = m_connection->GetConnection();
+    return MgFeatureServiceCommand::SupportsSelectOrdering(fdoConn);
+}
+
+bool MgSelectAggregateCommand::SupportsSelectDistinct()
+{
+    FdoPtr<FdoIConnection> fdoConn = m_connection->GetConnection();
+    return MgFeatureServiceCommand::SupportsSelectDistinct(fdoConn);
+}
+
+FdoFilter* MgSelectAggregateCommand::GetFilter()
+{
+    return FDO_SAFE_ADDREF(m_filter.p);
+}
+
+FdoJoinCriteriaCollection* MgSelectAggregateCommand::GetJoinCriteria()
+{
+    CHECKNULL((FdoISelectAggregates*)m_command, L"MgSelectAggregateCommand.GetJoinCriteria");
+    return m_command->GetJoinCriteria();
+}
+
+void MgSelectAggregateCommand::SetAlias(FdoString* alias)
+{
+    CHECKARGUMENTNULL(alias, L"MgSelectAggregateCommand.SetAlias");
+    CHECKNULL((FdoISelectAggregates*)m_command, L"MgSelectAggregateCommand.SetAlias");
+    m_command->SetAlias(alias);
+}
+
+MgReader* MgSelectAggregateCommand::ExecuteJoined(MgStringCollection* idPropNames, bool bForceOneToOne)
+{
+    Ptr<MgReader> ret;
+
+    FdoPtr<FdoIConnection> fdoConn = m_connection->GetConnection();
+    FdoPtr<FdoISelect> select = static_cast<FdoISelect*>(fdoConn->CreateCommand(FdoCommandType_Select));
+
+    FdoPtr<FdoIdentifier> clsName = m_command->GetFeatureClassName();
+    select->SetFeatureClassName(clsName);
+
+    
+    STRING clsNameStr = clsName->GetText();
+    STRING schemaName;
+    STRING className;
+    MgUtil::ParseQualifiedClassName(clsNameStr, schemaName, className);
+
+    FdoPtr<FdoIdentifierCollection> selectedIds = GetPropertyNames();
+    FdoPtr<FdoIdentifierCollection> computedIds = FdoIdentifierCollection::Create();
+    for (FdoInt32 i = 0; i < selectedIds->GetCount(); i++)
+    {
+        FdoPtr<FdoIdentifier> identifier = selectedIds->GetItem(i);
+        if (identifier->GetExpressionType() == FdoExpressionItemType_ComputedIdentifier)
+        {
+            FdoComputedIdentifier* comp = static_cast<FdoComputedIdentifier*>(identifier.p);
+            FdoPtr<FdoExpression> expr = comp->GetExpression();
+            if (expr->GetExpressionType() == FdoExpressionItemType_Function)
+                computedIds->Add(identifier);
+        }
+    }
+    FdoPtr<FdoClassDefinition> originalClassDef;
+
+    FdoPtr<FdoIDescribeSchema> descSchema = static_cast<FdoIDescribeSchema*>(fdoConn->CreateCommand(FdoCommandType_DescribeSchema));
+    if (!schemaName.empty())
+    {
+        descSchema->SetSchemaName(schemaName.c_str());
+    }
+    if (!className.empty())
+    {
+        FdoPtr<FdoStringCollection> classNames = FdoStringCollection::Create();
+        classNames->Add(className.c_str());
+        descSchema->SetClassNames(classNames);
+    }
+
+    FdoPtr<FdoClassDefinition> classDef;
+    FdoPtr<FdoFeatureSchemaCollection> schemas = descSchema->Execute();
+    for (FdoInt32 i = 0; i < schemas->GetCount(); i++)
+    {
+        FdoPtr<FdoFeatureSchema> schema = schemas->GetItem(i);
+        if (wcscmp(schema->GetName(), schemaName.c_str()) == 0) 
+        {
+            FdoPtr<FdoClassCollection> classes = schema->GetClasses();
+            for (FdoInt32 j = 0; j < classes->GetCount(); j++) 
+            {
+                FdoPtr<FdoClassDefinition> klassDef = classes->GetItem(j);
+                if (wcscmp(klassDef->GetName(), className.c_str()) == 0)
+                {
+                    originalClassDef = SAFE_ADDREF(klassDef.p);
+                    break;
+                }
+            }
+        }
+    }
+    
+
+    if (NULL != (FdoFilter*)m_filter)
+        select->SetFilter(m_filter);
+
+    FdoCommonExpressionType exprType;
+    FdoPtr<FdoFunctionDefinitionCollection> functions = FdoExpressionEngine::GetStandardFunctions();
+    FdoPtr<FdoArray<FdoFunction*> > aggrIdents = FdoExpressionEngineUtilDataReader::GetAggregateFunctions(functions, computedIds, exprType);
+
+    FdoPtr<FdoIFeatureReader> reader;
+    FdoPtr<FdoIdentifierCollection> ids;
+    FdoPtr<FdoIdentifierCollection> orderBy = m_command->GetOrdering();
+    FdoOrderingOption orderOpt = m_command->GetOrderingOption();
+
+    //n00bism: String goes in, garbage comes out. Anyway, we know the alias we want to set
+    select->SetAlias(PRIMARY_ALIAS);
+    //select->SetAlias(m_command->GetAlias());
+
+    FdoPtr<FdoJoinCriteriaCollection> srcCriteria = GetJoinCriteria();
+    FdoPtr<FdoJoinCriteriaCollection> dstCriteria = select->GetJoinCriteria();
+    for (FdoInt32 i = 0; i < srcCriteria->GetCount(); i++)
+    {
+        FdoPtr<FdoJoinCriteria> criteria = srcCriteria->GetItem(i);
+        dstCriteria->Add(criteria);
+    }
+
+    if ((aggrIdents != NULL) && (aggrIdents->GetCount() > 0))
+    {
+        reader = select->Execute();
+    }
+    else
+    {
+        // transfer over the identifiers to the basic select command:
+        ids = select->GetPropertyNames();
+        ids->Clear();
+        if (0 == selectedIds->GetCount())
+        {
+            FdoPtr<FdoPropertyDefinitionCollection> propDefs = originalClassDef->GetProperties();
+            for (int i=0; i<propDefs->GetCount(); i++)
+            {
+                FdoPtr<FdoPropertyDefinition> propDef = propDefs->GetItem(i);
+                FdoPtr<FdoIdentifier> localId = FdoIdentifier::Create(propDef->GetName());
+                ids->Add(localId);
+            }
+            FdoPtr<FdoReadOnlyPropertyDefinitionCollection> basePropDefs = originalClassDef->GetBaseProperties();
+            for (int i=0; i<basePropDefs->GetCount(); i++)
+            {
+                FdoPtr<FdoPropertyDefinition> basePropDef = basePropDefs->GetItem(i);
+                FdoPtr<FdoIdentifier> localId = FdoIdentifier::Create(basePropDef->GetName());
+                ids->Add(localId);
+            }
+        }
+        else
+        {
+            for (int i=0; i<selectedIds->GetCount(); i++)
+            {
+                FdoPtr<FdoIdentifier> localId = selectedIds->GetItem(i);
+                ids->Add(localId);
+            }
+        }
+
+        // Execute the basic select command:
+        reader = select->Execute();
+    }
+
+    if (bForceOneToOne)
+    {
+        FdoPtr<FdoStringCollection> names = MgFeatureUtil::MgToFdoStringCollection(idPropNames, false);
+        FdoPtr<FdoIFeatureReader> forcedReader = new MgFdoForcedOneToOneFeatureReader(reader, names);
+        FdoPtr<FdoIDataReader> dataReader = new FdoExpressionEngineUtilDataReader(functions, forcedReader, originalClassDef, computedIds, GetDistinct(), orderBy, orderOpt, ids, aggrIdents);
+
+        ret = new MgdDataReader(m_connection, dataReader); //, m_providerName);
+    }
+    else
+    {
+        FdoPtr<FdoIDataReader> dataReader = new FdoExpressionEngineUtilDataReader(functions, reader, originalClassDef, computedIds, GetDistinct(), orderBy, orderOpt, ids, aggrIdents);
+
+        ret = new MgdDataReader(m_connection, dataReader); //, m_providerName);
+    }
+
+    return ret.Detach();
+}

Added: branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/SelectAggregateCommand.h
===================================================================
--- branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/SelectAggregateCommand.h	                        (rev 0)
+++ branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/SelectAggregateCommand.h	2012-07-15 16:59:27 UTC (rev 6903)
@@ -0,0 +1,74 @@
+//
+//  Copyright (C) 2004-2011 by Autodesk, Inc.
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of version 2.1 of the GNU Lesser
+//  General Public License as published by the Free Software Foundation.
+//
+//  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 St, Fifth Floor, Boston, MA  02110-1301  USA
+//
+
+#ifndef _MGSELECTAGGREGATECOMMAND_H_
+#define _MGSELECTAGGREGATECOMMAND_H_
+
+class MgSelectAggregateCommand : public MgFeatureServiceCommand
+{
+    DECLARE_CLASSNAME(MgSelectAggregateCommand)
+
+public:
+    MgSelectAggregateCommand(MgResourceIdentifier* resource);
+    virtual ~MgSelectAggregateCommand();
+
+    virtual FdoIdentifierCollection* GetPropertyNames();
+
+    virtual void SetDistinct( bool value );
+    virtual bool GetDistinct( );
+
+    virtual void SetFetchSize(FdoInt32 fetchSize);
+    virtual FdoInt32 GetFetchSize();
+
+    virtual FdoIdentifierCollection* GetOrdering();
+    virtual void SetOrderingOption( FdoOrderingOption  option );
+    virtual FdoOrderingOption GetOrderingOption( );
+
+    virtual FdoIdentifierCollection* GetGrouping();
+    virtual void SetGroupingFilter( FdoFilter* filter );
+    virtual FdoFilter* GetGroupingFilter( );
+
+    virtual void SetFeatureClassName(FdoString* value);
+    virtual void SetFilter(FdoString* value);
+    virtual void SetFilter(FdoFilter* value);
+
+    virtual FdoFilter* GetFilter();
+
+    virtual MgReader* Execute();
+    MgReader* ExecuteJoined(MgStringCollection* idPropNames, bool bForceOneToOne);
+    virtual bool IsSupportedFunction(FdoFunction* fdoFunc);
+    virtual bool SupportsSelectGrouping();
+    virtual bool SupportsSelectOrdering();
+    virtual bool SupportsSelectDistinct();
+
+    virtual void Dispose()
+    {
+        delete this;
+    }
+
+    virtual FdoJoinCriteriaCollection* GetJoinCriteria();
+    virtual void SetAlias(FdoString* alias);
+
+private:
+    Ptr<MgFeatureConnection> m_connection;
+    STRING m_providerName;
+    FdoPtr<FdoISelectAggregates> m_command;
+
+    FdoPtr<FdoFilter> m_filter;
+};
+
+#endif

Added: branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/SelectCommand.cpp
===================================================================
--- branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/SelectCommand.cpp	                        (rev 0)
+++ branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/SelectCommand.cpp	2012-07-15 16:59:27 UTC (rev 6903)
@@ -0,0 +1,432 @@
+//
+//  Copyright (C) 2004-2011 by Autodesk, Inc.
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of version 2.1 of the GNU Lesser
+//  General Public License as published by the Free Software Foundation.
+//
+//  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 St, Fifth Floor, Boston, MA  02110-1301  USA
+//
+
+#include "Services/Feature/FeatureDefs.h"
+#include "MgDesktop.h"
+#include "Services/FeatureService.h"
+#include "FeatureServiceCommand.h"
+#include "SelectCommand.h"
+#include "SelectAggregateCommand.h"
+#include "Services/FeatureReader.h"
+#include "Services/Feature/FeatureConnection.h"
+#include "Services/Feature/FdoFeatureReader.h"
+#include "Services/Feature/FdoFilterCollection.h"
+#include "Services/Feature/FdoReaderCollection.h"
+
+// The maximum size of the subfilter for a selection query.  Tune this value for optimal selection perfomance.
+#define MG_MAX_SUBFILTER_SIZE  250
+
+MgSelectCommand::MgSelectCommand(MgResourceIdentifier* resource)
+{
+    CHECKNULL((MgResourceIdentifier*)resource, L"MgSelectCommand.MgSelectCommand");
+
+    // Connect to provider
+    m_connection = new MgFeatureConnection(resource);
+    if ((NULL != m_connection.p) && ( m_connection->IsConnectionOpen() ))
+    {
+        m_providerName = m_connection->GetProviderName();
+    }
+    else
+    {
+        throw new MgConnectionFailedException(L"MgSelectCommand.MgSelectCommand", __LINE__, __WFILE__, NULL, L"", NULL);
+    }
+    // Create FdoISelect command
+    FdoPtr<FdoIConnection> fdoConn = m_connection->GetConnection();
+    m_command = (FdoISelect*)fdoConn->CreateCommand(FdoCommandType_Select);
+    CHECKNULL((FdoISelect*)m_command, L"MgSelectCommand.MgSelectCommand");
+}
+
+MgSelectCommand::~MgSelectCommand()
+{
+    m_command = NULL;
+    m_filter = NULL;
+}
+
+FdoIdentifierCollection* MgSelectCommand::GetPropertyNames()
+{
+    CHECKNULL((FdoISelect*)m_command, L"MgSelectCommand.GetPropertyNames");
+    return m_command->GetPropertyNames();
+}
+
+void MgSelectCommand::SetDistinct(bool value)
+{
+    CHECKNULL((FdoISelect*)m_command, L"MgSelectCommand.SetDistinct");
+    // This operation is not supported by FdoISelect
+    // m_command->SetDistinct(value);
+
+    // throw new MgInvalidOperationException(L"MgSelectCommand.SetDistinct", __LINE__, __WFILE__, NULL, L"", NULL);
+}
+
+bool MgSelectCommand::GetDistinct()
+{
+    CHECKNULL((FdoISelect*)m_command, L"MgSelectCommand.GetDistinct");
+    // This operation is not supported by FdoISelect
+    // return m_command->GetDistinct();
+
+    // throw new MgInvalidOperationException(L"MgSelectCommand.GetDistinct", __LINE__, __WFILE__, NULL, L"", NULL);
+
+    return false;
+}
+
+void MgSelectCommand::SetFetchSize(FdoInt32 fetchSize)
+{
+    CHECKNULL((FdoISelect*)m_command, L"MgSelectCommand.SetFetchSize");
+    m_command->SetFetchSize(fetchSize);
+}
+
+FdoInt32 MgSelectCommand::GetFetchSize()
+{
+    CHECKNULL((FdoISelect*)m_command, L"MgSelectCommand.GetFetchSize");
+    return m_command->GetFetchSize();
+}
+
+FdoIdentifierCollection* MgSelectCommand::GetOrdering()
+{
+    CHECKNULL((FdoISelect*)m_command, L"MgSelectCommand.GetOrdering");
+    return m_command->GetOrdering();
+}
+
+void MgSelectCommand::SetOrderingOption(FdoOrderingOption option)
+{
+    CHECKNULL((FdoISelect*)m_command, L"MgSelectCommand.SetOrderingOption");
+    m_command->SetOrderingOption(option);
+}
+
+FdoOrderingOption MgSelectCommand::GetOrderingOption()
+{
+    CHECKNULL((FdoISelect*)m_command, L"MgSelectCommand.GetOrderingOption");
+    return m_command->GetOrderingOption();
+}
+
+FdoIdentifierCollection* MgSelectCommand::GetGrouping()
+{
+    CHECKNULL((FdoISelect*)m_command, L"MgSelectCommand.GetGrouping");
+    // This operation is not supported by FdoISelect
+    // return m_command->GetGrouping();
+
+    // throw new MgInvalidOperationException(L"MgSelectCommand.GetGrouping", __LINE__, __WFILE__, NULL, L"", NULL);
+    return NULL;
+}
+
+void MgSelectCommand::SetGroupingFilter(FdoFilter* filter)
+{
+    CHECKNULL((FdoISelect*)m_command, L"MgSelectCommand.SetGroupingFilter");
+    // This operation is not supported by FdoISelect
+    // m_command->SetGroupingFilter(filter);
+
+    // throw new MgInvalidOperationException(L"MgSelectCommand.SetGroupingFilter", __LINE__, __WFILE__, NULL, L"", NULL);
+}
+
+FdoFilter* MgSelectCommand::GetGroupingFilter()
+{
+    CHECKNULL((FdoISelect*)m_command, L"MgSelectCommand.GetGroupingFilter");
+    // This operation is not supported by FdoISelect
+    // return m_command->GetGroupingFilter(filter);
+
+    // throw new MgInvalidOperationException(L"MgSelectCommand.GetGroupingFilter", __LINE__, __WFILE__, NULL, L"", NULL);
+    return NULL;
+}
+
+void MgSelectCommand::SetFeatureClassName(FdoString* value)
+{
+    CHECKNULL((FdoISelect*)m_command, L"MgSelectCommand.SetFeatureClassName");
+    m_command->SetFeatureClassName(value);
+}
+
+void MgSelectCommand::SetFilter(FdoString* value)
+{
+    CHECKNULL((FdoISelect*)m_command, L"MgSelectCommand.SetFilter");
+    m_command->SetFilter(value);
+}
+
+void MgSelectCommand::SetFilter(FdoFilter* value)
+{
+    CHECKNULL((FdoISelect*)m_command, L"MgSelectCommand.SetFilter");
+    m_command->SetFilter(value);
+
+    m_filter = FDO_SAFE_ADDREF(value);
+}
+
+MgReader* MgSelectCommand::Execute()
+{
+    FdoPtr<FdoIFeatureReader> reader;
+
+    // Break up the filter into smaller chunks
+    FdoPtr<MgFdoFilterCollection> subFilters = this->GetSubFilters();
+
+    CHECKNULL((FdoISelect*)m_command, L"MgSelectCommand.Execute");
+
+    // Execute queries using the smaller filters and collect the results of the queries into a reader collection.
+    FdoPtr<MgFdoReaderCollection> frc = MgFdoReaderCollection::Create();
+
+    for (FdoInt32 filterIndex = 0; filterIndex < subFilters->GetCount(); filterIndex++)
+    {
+        FdoPtr<FdoFilter> filter = subFilters->GetItem(filterIndex);
+        m_command->SetFilter(filter);
+        reader = m_command->Execute();
+
+        frc->Add(reader);
+    }
+
+    FdoPtr<MgFdoFeatureReader> featureReader = new MgFdoFeatureReader(frc);
+    CHECKNULL((FdoIFeatureReader*)featureReader, L"MgSelectCommand.Execute");
+
+    return new MgdFeatureReader(m_connection, featureReader);
+}
+
+bool MgSelectCommand::IsSupportedFunction(FdoFunction* fdoFunc)
+{
+    FdoPtr<FdoIConnection> fdoConn = m_connection->GetConnection();
+    return this->IsFdoSupportedFunction(fdoConn, fdoFunc);
+}
+
+bool MgSelectCommand::SupportsSelectGrouping()
+{
+    FdoPtr<FdoIConnection> fdoConn = m_connection->GetConnection();
+    return MgFeatureServiceCommand::SupportsSelectGrouping(fdoConn);
+}
+
+bool MgSelectCommand::SupportsSelectOrdering()
+{
+    FdoPtr<FdoIConnection> fdoConn = m_connection->GetConnection();
+    return MgFeatureServiceCommand::SupportsSelectOrdering(fdoConn);
+}
+
+bool MgSelectCommand::SupportsSelectDistinct()
+{
+    FdoPtr<FdoIConnection> fdoConn = m_connection->GetConnection();
+    return MgFeatureServiceCommand::SupportsSelectDistinct(fdoConn);
+}
+
+FdoFilter* MgSelectCommand::GetFilter()
+{
+    return FDO_SAFE_ADDREF(m_filter.p);
+}
+
+MgFdoFilterCollection* MgSelectCommand::GetSubFilters()
+{
+    // Break up a filter into a bunch of smaller filters
+
+    // For now we just reduce a simple case with datastore limitations in handling the number of OR conditions.
+    // This is the case where a filter has only OR spatial conditions that can be broken up into a collection
+    // of smaller OR filters.
+
+    class FdoCommonFilterFragmenter :  public virtual FdoIFilterProcessor
+    {
+    private:
+        FdoPtr<FdoFilter>    m_newFilter;
+        FdoPtr<FdoIGeometry> m_geomRight;
+        FdoPtr<FdoIGeometry> m_geomLeft;
+
+        int m_OrCount;
+        std::vector<FdoFilter*> m_filters;
+        bool m_isFragmented;
+
+    protected:
+        void HandleFilter( FdoFilter *filter )
+        {
+            filter->Process( this );
+        }
+    public:
+
+        FdoCommonFilterFragmenter( ):m_isFragmented(true)
+        {
+            m_OrCount = 0;
+            m_filters.clear();
+        }
+
+        int GetOrCount() { return m_OrCount; }
+        std::vector<FdoFilter*>& GetFilters() { return m_filters; }
+        bool IsFragmented() { return m_isFragmented; }
+        FdoFilter* GetNewFilter() { return m_newFilter ? FDO_SAFE_ADDREF(m_newFilter.p) : NULL; }
+
+        virtual void Dispose()
+        {
+            delete this;
+        }
+
+        virtual void ProcessBinaryLogicalOperator(FdoBinaryLogicalOperator& filter)
+        {
+            if( filter.GetOperation() != FdoBinaryLogicalOperations_Or )
+            {
+                m_isFragmented = false;
+                return;
+            }
+
+            HandleFilter( FdoPtr<FdoFilter>(filter.GetRightOperand()) );
+            m_newFilter = filter.GetLeftOperand();
+
+            m_OrCount++;
+        }
+        virtual void ProcessComparisonCondition(FdoComparisonCondition& filter)
+        {
+            // Add filter to collection
+            m_filters.push_back(&filter);
+            return;
+        }
+        virtual void ProcessDistanceCondition(FdoDistanceCondition& filter)
+        {
+            m_isFragmented = false;
+            return;
+        }
+
+        virtual void ProcessInCondition(FdoInCondition& filter)
+        {
+            m_isFragmented = false;
+            return;
+        }
+        virtual void ProcessNullCondition(FdoNullCondition& filter)
+        {
+            m_isFragmented = false;
+            return;
+        }
+        virtual void ProcessSpatialCondition(FdoSpatialCondition& filter)
+        {
+            m_isFragmented = false;
+            return;
+        }
+
+        virtual void ProcessUnaryLogicalOperator(FdoUnaryLogicalOperator& filter)
+        {
+            m_isFragmented = false;
+            return;
+        }
+    };
+
+
+    FdoCommonFilterFragmenter  fragmenter;
+    if (m_filter)
+        m_filter->Process( &fragmenter );
+
+    FdoPtr<FdoFilter> newFilter = fragmenter.GetNewFilter();
+    while (newFilter != NULL)
+    {
+        newFilter->Process( &fragmenter );
+        FdoPtr<FdoFilter> tempFilter = fragmenter.GetNewFilter();
+        if (tempFilter != newFilter)
+        {
+            newFilter = tempFilter;
+        }
+        else
+        {
+            newFilter = NULL;
+        }
+    }
+
+#ifdef _DEBUG
+    int nCount = fragmenter.GetOrCount();
+    if ( nCount > 0)
+    {
+        char temp[1024];
+        sprintf(temp, "Or_Count = %d", nCount);  // NOXLATE
+        printf("%s\n", temp);
+    }
+#endif
+
+    FdoPtr<MgFdoFilterCollection> filters = MgFdoFilterCollection::Create();
+
+    if (fragmenter.IsFragmented() && fragmenter.GetOrCount() > 0)
+    {
+        int nSelectionCount = 0;
+
+        std::vector<FdoFilter*>::iterator filterIter;
+        bool bFirst = true;
+
+        FdoStringP filterString;
+        std::vector<FdoFilter*>& fragmentedFilters = fragmenter.GetFilters();
+
+
+        bool bIsAddedToCollection = false;
+
+        for (filterIter = fragmentedFilters.begin(); filterIter != fragmentedFilters.end(); filterIter++)
+        {
+            FdoStringP tempString = (*filterIter)->ToString();
+            FdoStringP orString = L" OR ";  // NOXLATE
+            if (bFirst)
+            {
+                filterString = tempString;
+                bFirst = false;
+            }
+            else
+            {
+                filterString = filterString + orString + tempString;
+                nSelectionCount++;
+            }
+
+            if (nSelectionCount >= MG_MAX_SUBFILTER_SIZE)
+            {
+                FdoPtr<FdoFilter> filter = FdoFilter::Parse(filterString);
+                filters->Add(filter);
+                bFirst = true;
+                filterString = L"";
+                nSelectionCount = 0;
+                bIsAddedToCollection = true;
+            }
+            else
+            {
+                bIsAddedToCollection = false;
+            }
+        }
+
+        if ( !bIsAddedToCollection )
+        {
+            FdoPtr<FdoFilter> filter = FdoFilter::Parse(filterString);
+            filters->Add(filter);
+        }
+
+    }
+    else
+    {
+        filters->Add(m_filter);
+    }
+
+    return filters.Detach();
+}
+
+FdoJoinCriteriaCollection* MgSelectCommand::GetJoinCriteria()
+{
+    CHECKNULL((FdoISelect*)m_command, L"MgSelectCommand.GetJoinCriteria");
+    return m_command->GetJoinCriteria();
+}
+
+void MgSelectCommand::SetAlias(FdoString* alias)
+{
+    CHECKNULL((FdoISelect*)m_command, L"MgSelectCommand.SetDistinct");
+    m_command->SetAlias(alias);
+}
+
+MgReader* MgSelectCommand::ExecuteJoined(MgStringCollection* idPropNames, bool bForceOneToOne)
+{
+    Ptr<MgReader> ret;
+
+    MG_FEATURE_SERVICE_TRY()
+
+    FdoPtr<FdoIFeatureReader> fdoReader = m_command->Execute();
+    if (bForceOneToOne)
+    {
+        FdoPtr<FdoStringCollection> names = MgFeatureUtil::MgToFdoStringCollection(idPropNames, false);
+        FdoPtr<FdoIFeatureReader> forcedReader = new MgFdoForcedOneToOneFeatureReader(fdoReader, names); 
+        ret = new MgdFeatureReader(m_connection, forcedReader);
+    }
+    else
+    {
+        ret = new MgdFeatureReader(m_connection, fdoReader);
+    }
+    MG_FEATURE_SERVICE_CATCH_AND_THROW(L"MgSelectCommand.ExecuteJoined")
+
+    return ret.Detach();
+}

Added: branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/SelectCommand.h
===================================================================
--- branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/SelectCommand.h	                        (rev 0)
+++ branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/SelectCommand.h	2012-07-15 16:59:27 UTC (rev 6903)
@@ -0,0 +1,82 @@
+//
+//  Copyright (C) 2004-2011 by Autodesk, Inc.
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of version 2.1 of the GNU Lesser
+//  General Public License as published by the Free Software Foundation.
+//
+//  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 St, Fifth Floor, Boston, MA  02110-1301  USA
+//
+
+#ifndef _MGSELECTCOMMAND_H_
+#define _MGSELECTCOMMAND_H_
+
+class MgFdoFeatureReader;
+class MgFdoReaderCollection;
+class MgFdoFilterCollection;
+
+class MgSelectCommand : public MgFeatureServiceCommand
+{
+    DECLARE_CLASSNAME(MgServerSqlProcessor)
+
+public:
+    MgSelectCommand(MgResourceIdentifier* resource);
+    virtual ~MgSelectCommand();
+
+    virtual FdoIdentifierCollection* GetPropertyNames();
+
+    virtual void SetDistinct( bool value );
+    virtual bool GetDistinct( );
+
+    virtual void SetFetchSize(FdoInt32 fetchSize);
+    virtual FdoInt32 GetFetchSize();
+
+    virtual FdoIdentifierCollection* GetOrdering();
+    virtual void SetOrderingOption( FdoOrderingOption  option );
+    virtual FdoOrderingOption GetOrderingOption( );
+
+    virtual FdoIdentifierCollection* GetGrouping();
+    virtual void SetGroupingFilter( FdoFilter* filter );
+    virtual FdoFilter* GetGroupingFilter( );
+
+    virtual void SetFeatureClassName(FdoString* value);
+    virtual void SetFilter(FdoString* value);
+    virtual void SetFilter(FdoFilter* value);
+
+    virtual FdoFilter* GetFilter();
+
+    virtual MgReader* Execute();
+
+    virtual bool IsSupportedFunction(FdoFunction* fdoFunc);
+
+    virtual bool SupportsSelectGrouping();
+    virtual bool SupportsSelectOrdering();
+    virtual bool SupportsSelectDistinct();
+
+    virtual void Dispose()
+    {
+        delete this;
+    }
+
+    MgReader* ExecuteJoined(MgStringCollection* idPropNames, bool bForceOneToOne);
+    virtual FdoJoinCriteriaCollection* GetJoinCriteria();
+    virtual void SetAlias(FdoString* alias);
+
+private:
+    Ptr<MgFeatureConnection> m_connection;
+    STRING m_providerName;
+    FdoPtr<FdoISelect> m_command;
+
+    FdoPtr<FdoFilter> m_filter;
+
+    MgFdoFilterCollection* GetSubFilters();
+};
+
+#endif

Added: branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/SelectFeatures.cpp
===================================================================
--- branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/SelectFeatures.cpp	                        (rev 0)
+++ branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/SelectFeatures.cpp	2012-07-15 16:59:27 UTC (rev 6903)
@@ -0,0 +1,2218 @@
+//
+//  Copyright (C) 2004-2011 by Autodesk, Inc.
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of version 2.1 of the GNU Lesser
+//  General Public License as published by the Free Software Foundation.
+//
+//  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 St, Fifth Floor, Boston, MA  02110-1301  USA
+//
+
+#include "Services/Feature/FeatureDefs.h"
+#include "MgDesktop.h"
+#include "Services/FeatureService.h"
+#include "SelectFeatures.h"
+#include "Services/Feature/FeatureConnection.h"
+#include "Services/FeatureReader.h"
+#include "Services/Feature/FeatureUtil.h"
+#include "FeatureServiceCommand.h"
+#include "SelectCommand.h"
+#include "SelectAggregateCommand.h"
+#include "Services/Feature/FeatureDistribution.h"
+#include "Services/Feature/GwsFeatureReader.h"
+#include "Services/Feature/GwsConnectionPool.h"
+#include "GwsCommonImp.h"
+#include "GwsMutableFeature.h"
+#include "GwsQuery.h"
+#include "FdoExpressionEngineCopyFilter.h"
+#include "Services/Feature/FeatureServiceCache.h"
+
+//Uncomment for extra console chatter to debug FDO joins
+//#define DEBUG_FDO_JOIN
+
+MgSelectFeatures::MgSelectFeatures()
+{
+    m_command = NULL;
+    m_options = NULL;
+    m_customPropertyFound = false;
+    m_customFunction = NULL;
+    m_customPropertyName = L"";
+    m_featureSourceCacheItem = NULL;
+
+    // Set a default join query batch size
+    m_nJoinQueryBatchSize = MgConfigProperties::DefaultFeatureServicePropertyJoinQueryBatchSize;
+
+    MgConfiguration* config = MgConfiguration::GetInstance();
+    if(config)
+    {
+        // Get the join batch size
+        config->GetIntValue(MgConfigProperties::FeatureServicePropertiesSection,
+                            MgConfigProperties::FeatureServicePropertyJoinQueryBatchSize,
+                            m_nJoinQueryBatchSize,
+                            MgConfigProperties::DefaultFeatureServicePropertyJoinQueryBatchSize);
+        // Get data cache size
+        config->GetIntValue(MgConfigProperties::FeatureServicePropertiesSection,
+                            MgConfigProperties::FeatureServicePropertyDataCacheSize,
+                            m_nDataCacheSize,
+                            MgConfigProperties::DefaultFeatureServicePropertyDataCacheSize);
+    }
+}
+
+MgSelectFeatures::~MgSelectFeatures()
+{
+}
+
+// Executes the select features command and serializes the reader
+MgReader* MgSelectFeatures::SelectFeatures(MgResourceIdentifier* resource,
+                                                 CREFSTRING className,
+                                                 MgFeatureQueryOptions* options,
+                                                 bool executeSelectAggregate)
+{
+    Ptr<MgReader> mgReader;
+    bool isSelectAggregate = executeSelectAggregate;
+
+    MG_FEATURE_SERVICE_TRY()
+
+    // Validate parameters
+    ValidateParam(resource,className);
+
+    // Retrieve the feature source
+    if (NULL == m_featureSourceCacheItem.p)
+    {
+        MgFeatureServiceCache* cacheManager = MgFeatureServiceCache::GetInstance();
+        m_featureSourceCacheItem = cacheManager->GetFeatureSource(resource);
+    }
+
+    // Set options (NULL is a valid value)
+    m_options = SAFE_ADDREF(options);
+    // Check if a feature join is to be performed by inspecting the resource for join properties
+    bool bFeatureJoinProperties = FindFeatureJoinProperties(resource, className);
+    // Check if a feature join is only a calculation
+    bool bFeatureCalculation = FindFeatureCalculation(resource, className);
+    //Test for the FDO join optimization, because performance is **substantially** better
+    bool bSupportsFdoJoin = SupportsFdoJoin(resource, className, isSelectAggregate);
+
+    // HACK: Sorry, we have to do this for now. Only SQLite provider satisifes the original
+    // FDO join optimization in both regular select and select aggregate modes
+    //
+    // SQL Server has problems in aggregate mode. So we'll say the FDO join optimization is 
+    // not supported when this is in aggregate mode. This means the join is handled by the
+    // GWS query engine. SQL Server on SQL Server join will use the best algorithm (sort merge)
+    // as both sides are sortable so we won't suffer too much of a performance penalty.
+    if (isSelectAggregate)
+    {
+        MdfModel::FeatureSource* featureSource = m_featureSourceCacheItem->Get();
+        const MdfModel::MdfString& providerName = featureSource->GetProvider();
+        if (providerName.find(L"OSGeo.SQLite") == MdfString::npos) //NOXLATE
+            bSupportsFdoJoin = false;
+    }
+
+#ifdef DEBUG_FDO_JOIN
+    STRING fsIdStr = resource->ToString();
+    ACE_DEBUG((LM_INFO, ACE_TEXT("\n(%t) Testing Feature Source (%W, %W) for FDO join optimization"), fsIdStr.c_str(), className.c_str()));
+#endif  
+    if (!isSelectAggregate && bFeatureJoinProperties)
+    {
+        if (bSupportsFdoJoin)
+        {
+#ifdef DEBUG_FDO_JOIN
+            ACE_DEBUG((LM_INFO, ACE_TEXT("\n(%t) Feature Source (%W) supports FDO join optimization"), fsIdStr.c_str()));
+#endif
+            m_command = MgFeatureServiceCommand::CreateCommand(resource, FdoCommandType_Select);
+            mgReader = SelectFdoJoin(resource, className, false);
+        }
+        else 
+        {
+#ifdef DEBUG_FDO_JOIN
+            ACE_DEBUG((LM_INFO, ACE_TEXT("\n(%t) Feature Source (%W) does not support the FDO join optimization. Using GwsQueryEngine"), fsIdStr.c_str()));
+#endif
+            // Get the FdoFilter from the options
+            // Create Command
+            CreateCommand(resource, isSelectAggregate);
+
+            // Apply options to FDO command
+            ApplyQueryOptions(isSelectAggregate);
+            FdoPtr<FdoFilter> filter = m_command->GetFilter();
+            // Perform feature join
+            mgReader = JoinFeatures(resource, className, filter);
+        }
+    }
+    else if (isSelectAggregate && bFeatureJoinProperties && bSupportsFdoJoin)
+    {
+        // NOTE: If this is FDO join capable, but contains functions over prefixed secondary properties
+        // We have to go through the GWS Query Engine because we haven't implemented reverse mapping
+        // of prefixed secondary class properties. Fortunately, the common case for this is distict value
+        // queries (eg. Generating themeable values), and GWS Query Engine is surprisingly performant in this case
+#ifdef DEBUG_FDO_JOIN
+        ACE_DEBUG((LM_INFO, ACE_TEXT("\n(%t) Feature Source (%W) supports aggregate FDO join optimization"), fsIdStr.c_str()));
+#endif
+        // Perform the same select query as above, but route this through the FDO expression engine
+        // Slow maybe, but anything is faster than going via the GWS query engine.
+        m_command = MgFeatureServiceCommand::CreateCommand(resource, FdoCommandType_Select);
+        mgReader = SelectFdoJoin(resource, className, true);
+    }
+    else
+    {
+        // Custom function specified from Select command is not allowed
+        if (!isSelectAggregate && ContainsCustomFunction(options))
+        {
+            STRING message = MgFeatureUtil::GetMessage(L"MgCustomFunctionNotSupported");
+
+            MgStringCollection arguments;
+            arguments.Add(message);
+            throw new MgFeatureServiceException(L"MgServerSelectFeatures.SelectFeatures", __LINE__, __WFILE__, &arguments, L"", NULL);
+        }
+
+        // Custom function specified using SelectAggregate,
+        // we execute as standard Select command on single property
+        // then apply function on top of it.
+        bool useClassName = true;
+        if (isSelectAggregate && ContainsCustomFunction(options))
+        {
+            isSelectAggregate = false;
+            useClassName = false;
+        }
+        else if (bFeatureJoinProperties)
+            useClassName = false;
+
+        Ptr<MgReader> reader;
+
+        // Create Command
+        CreateCommand(resource, isSelectAggregate);
+
+        // Set the FeatureClass Name
+        if (useClassName && !bFeatureCalculation)
+        {
+            m_command->SetFeatureClassName((FdoString*)className.c_str());
+        }
+
+        // Apply options to FDO command
+        ApplyQueryOptions(isSelectAggregate);
+
+        // Check if the specified className is an extension (join) in the feature source
+        if (bFeatureJoinProperties && !bSupportsFdoJoin)
+        {
+            // Perform feature join to obtain the joined properties
+            // Note: this gwsFeatureReader is just for temporary use. it will not be returned
+            // to the web-tier. Therefore this object must be closed to avoid connection leak
+            // I put the following code in a try-catch block just to make sure the gwsFeaturereader
+            // gets chance to be closed in case that an exception is thrown from underneath
+            Ptr<MgdGwsFeatureReader> gwsFeatureReader = JoinFeatures(resource, className, NULL);
+            try
+            {
+                // Get the requested property name from the MgFeatureServiceCommandObject.  This property name may be
+                // prefixed by the relation name if it is from a secondary resource.
+                FdoPtr<FdoIdentifierCollection> fic = m_command->GetPropertyNames();
+                int nFicCnt = fic->GetCount();
+                if (nFicCnt <= 0)
+                {
+                    // throw invalid argument exception because the properties the m_command is empty
+                    MgStringCollection arguments;
+                    arguments.Add(L"1");
+                    arguments.Add(L"MgFeatureServiceCommand");
+
+                    throw new MgInvalidArgumentException(L"MgSelectFeatures::SelectFeatures()",
+                        __LINE__, __WFILE__, &arguments, L"MgCollectionEmpty", NULL);
+
+                }
+
+                FdoPtr<FdoIdentifier> fi = fic->GetItem(0);
+                STRING propName = fi->GetName();
+
+                // Parse the relation name from the property name by determining which source the property is from
+                STRING relationName;
+                STRING secClassName;
+                STRING parsedPropertyName;
+                IGWSFeatureIterator* gwsFeatureIter = NULL;
+                gwsFeatureReader->ReadNext();
+                gwsFeatureReader->DeterminePropertyFeatureSource(propName, &gwsFeatureIter, relationName, secClassName, parsedPropertyName);
+
+                Ptr<MgResourceIdentifier> resId;
+
+                // Get the resource id associated with the relation name
+                if (relationName.empty())
+                {
+                    // this is the primary resource
+                    resId = SAFE_ADDREF(resource);
+                }
+                else
+                {
+                    // this is a secondary resource
+                    resId = GetSecondaryResourceIdentifier(resource, className, relationName);
+                }
+
+                // Create new command to execute against the desired resource in defined by the join
+                m_customPropertyFound = false;
+                CreateCommand(resId, isSelectAggregate);
+                // Set feature class name (either primary or secondary class)
+                m_command->SetFeatureClassName((FdoString*)secClassName.c_str());
+                // Set options
+                m_options = SAFE_ADDREF(options);
+
+                // Update the value of the computed property.  Since the joined property may be prefixed by the relation name
+                // i.e. Join1PropA, this needs to be parsed into it individual relation and property components.
+                Ptr<MgStringPropertyCollection> computedProperties = m_options->GetComputedProperties();
+
+                // Can only have one computed property for custom functions
+                assert(computedProperties->GetCount() == 1);
+                STRING aliasName = computedProperties->GetName(0);
+                STRING expression = computedProperties->GetValue(0);
+
+                STRING::size_type nPropLength = propName.length();
+                STRING::size_type nPropStart = expression.rfind(propName);
+                if(nPropStart != STRING::npos)
+                {
+                    STRING::size_type nPropEnd = expression.find(L")", nPropStart + 1);
+
+                    STRING newExpression = expression.substr(0, nPropStart);
+                    newExpression += parsedPropertyName;
+                    newExpression += expression.substr(nPropStart + nPropLength);
+                    computedProperties->SetValue(aliasName, newExpression);
+                }
+
+                // Apply options to FDO command
+                ApplyQueryOptions(isSelectAggregate);
+                if (bFeatureCalculation)
+                    UpdateCommandOnJoinCalculation(resource, className);
+            }
+            catch(...)
+            {
+                // Close the reader to avoid connection leak
+                gwsFeatureReader->Close();
+                throw;
+            }
+
+            // gwsFeatureReader will not be returned to the webtier. Therefore, we have to close it here since
+            // it is no longer neened. If we don't do this, the connection it owns will leak.
+            gwsFeatureReader->Close();
+        }
+        else if (bFeatureCalculation && !bFeatureJoinProperties)
+            UpdateCommandOnCalculation(resource, className);
+        else
+            m_command->SetFeatureClassName((FdoString*)className.c_str());
+
+        // If custom function is found, then validate that no more than one function/property is specified
+        ValidateConstraintsOnCustomFunctions();
+
+        // Execute the command
+        reader = m_command->Execute();
+
+        CHECKNULL((MgReader*)reader, L"MgServerSelectFeatures.SelectFeatures");
+
+        if (executeSelectAggregate && m_customPropertyFound)
+        {
+            mgReader = this->GetCustomReader(reader);
+            // Ticket 1051 MapGuide exhausts FDO connections during Fusion selection
+            // We are done with "reader" but Close() is not called during the release
+            // Close it here to avoid the connection leak
+            reader->Close();
+        }
+        else
+        {
+            // Increment the refcount as it will be decremented when we go out of  try...catch
+            mgReader = SAFE_ADDREF((MgReader*)reader);
+        }
+    }
+
+    MG_FEATURE_SERVICE_CHECK_CONNECTION_CATCH_AND_THROW(resource, L"MgServerSelectFeatures.SelectFeatures")
+
+    return mgReader.Detach();
+}
+
+
+void MgSelectFeatures::ApplyQueryOptions(bool isSelectAggregate)
+{
+    CHECKNULL(m_command, L"MgServerSelectFeatures.ApplyQueryOptions");
+
+    if (m_options != NULL)
+    {
+        ApplyClassProperties();
+        ApplyComputedProperties();
+        ApplyFilter();
+        // ApplySpatialFilter();
+        ApplyOrderingOptions();
+        ApplyAggregateOptions(isSelectAggregate);
+        ApplyFetchSize();
+    }
+}
+
+// ClassProperties
+void MgSelectFeatures::ApplyClassProperties()
+{
+    CHECKNULL(m_options, L"MgServerSelectFeatures.ApplyClassProperties");
+    CHECKNULL(m_command, L"MgServerSelectFeatures.ApplyClassProperties");
+
+    Ptr<MgStringCollection> properties = m_options->GetClassProperties();
+
+    if (properties == NULL)
+        return; // Nothing to do
+
+    INT32 cnt = properties->GetCount();
+    if (cnt <= 0)
+        return; // Nothing to do
+
+    //TODO: Need to check if FDO join optimization is supported, and whether this contains prefixed
+    //secondary properties.
+
+    FdoPtr<FdoIdentifierCollection> fic = m_command->GetPropertyNames();
+    CHECKNULL((FdoIdentifierCollection*)fic, L"MgServerSelectFeatures.ApplyClassProperties");
+
+    for (INT32 i=0; i < cnt; i++)
+    {
+        STRING propertyName = properties->GetItem(i);
+
+        FdoPtr<FdoIdentifier> fdoIden = FdoIdentifier::Create((FdoString*)propertyName.c_str());
+        CHECKNULL((FdoIdentifier*)fdoIden, L"MgServerSelectFeatures.ApplyClassProperties");
+
+        fic->Add(fdoIden);
+    }
+}
+
+
+// Computed properties
+void MgSelectFeatures::ApplyComputedProperties()
+{
+    CHECKNULL(m_options, L"MgServerSelectFeatures.ApplyComputedProperties");
+    CHECKNULL(m_command, L"MgServerSelectFeatures.ApplyComputedProperties");
+
+    Ptr<MgStringPropertyCollection> properties = m_options->GetComputedProperties();
+
+    if (properties == NULL)
+        return; // Nothing to do
+
+    INT32 cnt = properties->GetCount();
+    if (cnt <= 0)
+        return; // Nothing to do
+
+    //TODO: Need to check if FDO join optimization is supported, and whether this contains prefixed
+    //secondary properties in any expressions
+
+    // TODO: Add support for custom functions
+
+    for (INT32 i=0; i < cnt; i++)
+    {
+        STRING aliasName = properties->GetName(i);
+        STRING expression = properties->GetValue(i);
+
+        FdoString* str = (FdoString*)expression.c_str();
+        if (str != NULL)
+        {
+            FdoPtr<FdoExpression> expression = FdoExpression::Parse(str);
+            CHECKNULL((FdoExpression*)expression, L"MgServerSelectFeatures.ApplyComputedProperties");
+
+            bool udf = ContainsUdf(expression);
+            if (!udf)
+            {
+                AddFdoComputedProperty(aliasName, expression);
+            }
+            else
+            {
+                AddCustomComputedProperty(aliasName, expression);
+            }
+        }
+    }
+}
+
+//// Filter text
+//void MgSelectFeatures::ApplyFilter()
+//{
+//    CHECKNULL(m_options, L"MgServerSelectFeatures.ApplyFilter");
+//    CHECKNULL(m_command, L"MgServerSelectFeatures.ApplyFilter");
+//
+//    STRING filterText = m_options->GetFilter();
+//    if (filterText.empty()) { return; } // Nothing to do
+//
+//    m_command->SetFilter(filterText.c_str());
+//}
+
+// Fetch size
+void MgSelectFeatures::ApplyFetchSize()
+{
+    CHECKNULL(m_command, L"MgServerSelectFeatures.ApplyFetchSize");
+    if(m_options)
+        m_command->SetFetchSize(m_options->GetFetchSize());
+    else
+        m_command->SetFetchSize(m_nDataCacheSize);
+}
+
+// Spatial Filter
+void MgSelectFeatures::ApplyFilter()
+{
+    CHECKNULL(m_options, L"MgServerSelectFeatures.ApplyFilter");
+    CHECKNULL(m_command, L"MgServerSelectFeatures.ApplyFilter");
+
+    FdoPtr<FdoFilter> regularFilter;
+    FdoPtr<FdoSpatialCondition> spatialFilter;
+    FdoPtr<FdoFilter> combineFilter;
+    FdoBinaryLogicalOperations bOper = FdoBinaryLogicalOperations_And;
+
+    // Build regular filter
+    STRING filterText = m_options->GetFilter();
+    if (!filterText.empty())
+    {
+        regularFilter = FdoFilter::Parse(filterText.c_str());
+        #ifdef _DEBUG
+        ACE_DEBUG((LM_ERROR, ACE_TEXT("FILTER(size=%d):\n%W\n\n"), filterText.length(), filterText.c_str()));
+        #endif
+    }
+
+    // Build spatial filter
+    bool isAnd = m_options->GetBinaryOperator();
+    Ptr<MgGeometry> geom = m_options->GetGeometry();
+    INT32 spatialOp = m_options->GetSpatialOperation();
+
+    STRING geomProp = m_options->GetGeometryProperty();
+
+    if (!isAnd) // Apply OR operator
+    {
+        bOper = FdoBinaryLogicalOperations_Or;
+    }
+
+    // Check whether we have valid geometric filter
+    if (!geomProp.empty() && (geom != NULL))
+    {
+        MgAgfReaderWriter agfWriter;
+
+        Ptr<MgByteReader> reader = agfWriter.Write(geom);
+        Ptr<MgByteSink> sink = new MgByteSink(reader);
+        Ptr<MgByte> bytes = sink->ToBuffer();
+
+        FdoByte* gisBytes = bytes->Bytes();
+        INT32 len = bytes->GetLength();
+
+        FdoPtr<FdoByteArray> byteArray = FdoByteArray::Create(gisBytes, (FdoInt32)len);
+
+        #ifdef _DEBUG
+        // Get the spatial filter geometry text
+        FdoPtr<FdoFgfGeometryFactory> geometryFactory = FdoFgfGeometryFactory::GetInstance();
+        if(geometryFactory)
+        {
+            FdoPtr<FdoIGeometry> geometry = geometryFactory->CreateGeometryFromFgf(byteArray);
+            STRING geomText = geometry->GetText();
+            ACE_DEBUG((LM_INFO, ACE_TEXT("(%t) SPATIAL FILTER:\n%W\n\n"), geomText.c_str()));
+        }
+        #endif
+
+        FdoPtr<FdoGeometryValue> geomValue = FdoGeometryValue::Create(byteArray);
+        if (geomValue != NULL)
+        {
+            FdoSpatialOperations fdoSpatialOp = MgFeatureUtil::GetFdoSpatialOperation(spatialOp);
+            spatialFilter = FdoSpatialCondition::Create((FdoString*)geomProp.c_str(), fdoSpatialOp, (FdoExpression*)geomValue);
+        }
+    }
+
+    // Determine which one to apply
+    if ((regularFilter != NULL) && (spatialFilter != NULL))
+    {
+        // Both filter exists, combine them
+        combineFilter = FdoFilter::Combine(regularFilter, bOper, spatialFilter);
+    }
+    else
+    {
+        if (regularFilter != NULL)
+        {
+            // Only regular filter exists
+            combineFilter = FDO_SAFE_ADDREF((FdoFilter*)regularFilter);
+        }
+        else if (spatialFilter != NULL)
+        {
+            // Only spatial filter exists
+            combineFilter = FDO_SAFE_ADDREF((FdoFilter*)spatialFilter);
+        }
+    }
+
+    // Apply the filter
+    if (combineFilter != NULL)
+    {
+        m_command->SetFilter(combineFilter);
+    }
+}
+
+// Ordering options
+void MgSelectFeatures::ApplyOrderingOptions()
+{
+    CHECKNULL(m_options, L"MgServerSelectFeatures.ApplyOrderingOptions");
+    CHECKNULL(m_command, L"MgServerSelectFeatures.ApplyOrderingOptions");
+
+    Ptr<MgStringCollection> properties = m_options->GetOrderingProperties();
+
+    if (properties == NULL)
+        return; // Nothing to do
+
+    INT32 cnt = properties->GetCount();
+    if (cnt <= 0)
+        return; // Nothing to do
+
+    // Ordering options are supplied but provider does not support it
+    if (!m_command->SupportsSelectOrdering())
+    {
+        STRING message = MgFeatureUtil::GetMessage(L"MgOrderingOptionNotSupported");
+
+        MgStringCollection arguments;
+        arguments.Add(message);
+        throw new MgFeatureServiceException(L"MgServerSelectFeatures.ApplyOrderingOptions", __LINE__, __WFILE__, &arguments, L"", NULL);
+    }
+
+    FdoPtr<FdoIdentifierCollection> fic = m_command->GetOrdering();
+    CHECKNULL((FdoIdentifierCollection*)fic, L"MgServerSelectFeatures.ApplyOrderingOptions");
+
+    // Order option Asc or Desc (default is Asc)
+    FdoOrderingOption option = MgFeatureUtil::GetFdoOrderingOption(m_options->GetOrderOption());
+    m_command->SetOrderingOption(option);
+
+    for (INT32 i=0; i < cnt; i++)
+    {
+        STRING propertyName = properties->GetItem(i);
+
+        if (!propertyName.empty())
+        {
+            FdoPtr<FdoIdentifier> fdoIden = FdoIdentifier::Create((FdoString*)propertyName.c_str());
+            CHECKNULL((FdoIdentifier*)fdoIden, L"MgServerSelectFeatures.ApplyOrderingOptions");
+
+            fic->Add(fdoIden);
+        }
+    }
+}
+
+
+bool MgSelectFeatures::ContainsUdf(FdoExpression* expression)
+{
+    bool isUdf = false;
+    bool fdoSupported = false;
+
+    // Downcast to FdoFunction
+    FdoFunction* function = dynamic_cast<FdoFunction*>(expression);
+
+    // If we are unable to downcast, it means it is not a function, it is just
+    // an expression. We do not do anything with this. We just pass it to FDO
+    if (function != NULL)
+    {
+        if (m_command != NULL)
+        {
+            // Check if FDO supports this function, if so, let FDO handle it
+            fdoSupported = m_command->IsSupportedFunction(function);
+        }
+
+        if (!fdoSupported)
+        {
+            // If function is not supported, then check if it is a custom function.
+            isUdf = IsCustomFunction(function);
+        }
+    }
+
+    return isUdf;
+}
+
+
+bool MgSelectFeatures::IsCustomFunction(FdoFunction* fdoFunc)
+{
+    bool customFunc = false;
+
+    FdoString* funcNameAllowed = fdoFunc->GetName();
+    if (funcNameAllowed != NULL)
+    {
+        INT32 funcIndex = -1;
+        customFunc = MgFeatureUtil::FindCustomFunction(STRING(funcNameAllowed),funcIndex);
+    }
+
+    return customFunc;
+}
+
+void MgSelectFeatures::AddFdoComputedProperty(CREFSTRING aliasName, FdoExpression* expression)
+{
+    FdoPtr<FdoIdentifierCollection> fic = m_command->GetPropertyNames();
+    CHECKNULL((FdoIdentifierCollection*)fic, L"MgServerSelectFeatures.AddFdoComputedProperty");
+
+    FdoString* expName = aliasName.c_str();
+    if (expName != NULL)
+    {
+        FdoPtr<FdoComputedIdentifier> fdoIden = FdoComputedIdentifier::Create(expName, expression);
+        CHECKNULL((FdoComputedIdentifier*)fdoIden, L"MgServerSelectFeatures.AddFdoComputedProperty");
+
+        fic->Add(fdoIden);
+    }
+}
+
+void MgSelectFeatures::AddCustomComputedProperty(CREFSTRING aliasName, FdoExpression* expression)
+{
+    CHECKNULL((FdoExpression*)expression, L"MgServerSelectFeatures.AddCustomComputedProperty");
+
+    FdoPtr<FdoIdentifierCollection> fic = m_command->GetPropertyNames();
+    CHECKNULL((FdoIdentifierCollection*)fic, L"MgServerSelectFeatures.AddCustomComputedProperty");
+
+    // If property is already found, two custom properties are not supported and therefore throw exception
+    if (m_customPropertyFound)
+    {
+        STRING message = MgFeatureUtil::GetMessage(L"MgOnlyOnePropertyAllowed");
+
+        MgStringCollection arguments;
+        arguments.Add(message);
+        throw new MgFeatureServiceException(L"MgServerSelectFeatures.AddCustomComputedProperty", __LINE__, __WFILE__, &arguments, L"", NULL);
+    }
+
+    // Downcast to FdoFunction
+    FdoFunction* function = dynamic_cast<FdoFunction*>(expression);
+
+    if (function != NULL)
+    {
+        FdoString* expName = aliasName.c_str();
+        if (expName != NULL)
+        {
+            FdoPtr<FdoExpressionCollection> exprCol = function->GetArguments();
+            FdoInt32 cnt = exprCol->GetCount();
+            FdoPtr<FdoExpression> expr;
+            if (cnt > 0)
+            {
+                expr = exprCol->GetItem(0);   // Property Name
+            }
+
+            // Just pass in the property name
+            // FdoPtr<FdoComputedIdentifier> fdoIden = FdoComputedIdentifier::Create(expName, expr);
+
+            // NOTE: Each provider has its own rule for supporting computed properties, select and select aggregate
+            // functionality. Therefore we just work with simple select command, fetch the property and do the needed
+            // calculations. Therefore, we are not adding them as computed properties.
+
+            FdoIdentifier* propName = dynamic_cast<FdoIdentifier*>(expr.p);
+
+            if (propName != NULL)
+                fic->Add(propName);
+
+            m_customPropertyName = aliasName;
+            m_customPropertyFound = true;
+            m_customFunction = FDO_SAFE_ADDREF(function);
+        }
+    }
+}
+
+void MgSelectFeatures::ValidateConstraintsOnCustomFunctions()
+{
+    // Custom function should only be allowed stand alone. This means, no other property along withit
+    // will be supported. Therefore
+    // 1. ClassProperties should be zero.
+    // 2. Computed properties (custom) should not be more than one
+    // 3. No GroupBy clause allowed
+    if (m_options != NULL)
+    {
+        Ptr<MgStringCollection> strCol = m_options->GetClassProperties();
+        INT32 classPropCnt = strCol->GetCount();
+
+        if (m_customPropertyFound)
+        {
+            if (classPropCnt > 0)
+            {
+                STRING message = MgFeatureUtil::GetMessage(L"MgOnlyOnePropertyAllowed");
+
+                MgStringCollection arguments;
+                arguments.Add(message);
+                throw new MgFeatureServiceException(L"MgServerSelectFeatures.ValidateConstraintsOnCustomFunctions",
+                    __LINE__, __WFILE__, &arguments, L"", NULL);
+            }
+            MgFeatureUtil::ValidateCustomConstraints(m_customFunction);
+        }
+    }
+}
+
+
+void MgSelectFeatures::CreateCommand(MgResourceIdentifier* resource, bool isSelectAggregate)
+{
+    if (!isSelectAggregate)
+    {
+        m_command = MgFeatureServiceCommand::CreateCommand(resource, FdoCommandType_Select);
+    }
+    else
+    {
+        m_command = MgFeatureServiceCommand::CreateCommand(resource, FdoCommandType_SelectAggregates);
+    }
+    CHECKNULL((MgFeatureServiceCommand*)m_command, L"MgServerSelectFeatures.CreateCommand");
+}
+
+void MgSelectFeatures::ValidateParam(MgResourceIdentifier* resource, CREFSTRING className)
+{
+    // className and resource identifier can not be NULL
+    if (resource == NULL)
+    {
+        throw new MgNullArgumentException(L"MgSelectFeatures::ValidateParam()", __LINE__, __WFILE__, NULL, L"", NULL);
+    }
+
+    if (className.empty())
+    {
+        MgStringCollection arguments;
+        arguments.Add(L"2");
+        arguments.Add(MgResources::BlankArgument);
+
+        throw new MgInvalidArgumentException(L"MgSelectFeatures::ValidateParam()",
+            __LINE__, __WFILE__, &arguments, L"MgStringEmpty", NULL);
+    }
+}
+
+void MgSelectFeatures::ApplyAggregateOptions(bool isSelectAggregate)
+{
+    // If not select aggregate, just return
+    if (!isSelectAggregate)
+        return;
+
+    // Downcast to see if it is an instance of MgFeatureAggregateOptions.
+    MgFeatureAggregateOptions* options = dynamic_cast<MgFeatureAggregateOptions*>((MgFeatureQueryOptions*)m_options);
+
+    // If it is not MgFeatureAggregateOptions, we simply return
+    if (options == NULL)
+        return;
+
+    STRING groupFilter = options->GetGroupFilter();
+    Ptr<MgStringCollection> strCol = options->GetGroupingProperties();
+    bool distinct = options->GetDistinct();
+
+    // Provider may throw exception if distinct operation is not supported.
+    // We delegate to provider instead of determining and throwing exception
+    // of our own
+    if (distinct)
+    {
+        // Set distinct requirements
+        ((MgFeatureServiceCommand*)m_command)->SetDistinct(distinct);
+    }
+
+    // Set all properties for grouping
+    ApplyFdoGroupingProperties(strCol);
+
+    // Set Grouping Filter
+    FdoPtr<FdoFilter> filter;
+    if (!groupFilter.empty())
+    {
+        filter = FdoFilter::Parse((FdoString*)groupFilter.c_str());
+        if (filter != NULL)
+        {
+            ((MgFeatureServiceCommand*)m_command)->SetGroupingFilter(filter);
+        }
+    }
+}
+
+void MgSelectFeatures::ApplyFdoGroupingProperties(MgStringCollection* propertyNames)
+{
+    CHECKNULL(m_options, L"MgServerSelectFeatures.ApplyFdoGroupingProperties");
+    CHECKNULL(m_command, L"MgServerSelectFeatures.ApplyFdoGroupingProperties");
+
+    Ptr<MgStringCollection> properties = SAFE_ADDREF(propertyNames);
+
+    if (properties == NULL)
+        return; // Nothing to do
+
+    INT32 cnt = properties->GetCount();
+    if (cnt <= 0)
+        return; // Nothing to do
+
+    // Grouping options are supplied but provider does not support it
+    if (!m_command->SupportsSelectGrouping())
+    {
+        STRING message = MgFeatureUtil::GetMessage(L"MgGroupingNotSupported");
+
+        MgStringCollection arguments;
+        arguments.Add(message);
+        throw new MgFeatureServiceException(L"MgServerSelectFeatures.ApplyFdoGroupingProperties", __LINE__, __WFILE__, &arguments, L"", NULL);
+    }
+
+    FdoPtr<FdoIdentifierCollection> fic = ((MgFeatureServiceCommand*)m_command)->GetGrouping();
+    CHECKNULL((FdoIdentifierCollection*)fic, L"MgServerSelectFeatures.ApplyFdoGroupingProperties");
+
+    for (INT32 i=0; i < cnt; i++)
+    {
+        STRING propertyName = properties->GetItem(i);
+
+        FdoPtr<FdoIdentifier> fdoIden = FdoIdentifier::Create((FdoString*)propertyName.c_str());
+        CHECKNULL((FdoIdentifier*)fdoIden, L"MgServerSelectFeatures.ApplyFdoGroupingProperties");
+
+        fic->Add(fdoIden);
+    }
+}
+
+// Check whether user is requesting custom operations
+bool MgSelectFeatures::ContainsCustomFunction(MgFeatureQueryOptions* options)
+{
+    bool hasCustomFunction = false;
+
+    if (options == NULL)
+        return false;
+
+    Ptr<MgStringPropertyCollection> properties = options->GetComputedProperties();
+
+    if (properties == NULL)
+        return false;   // Nothing to do
+
+    INT32 cnt = properties->GetCount();
+    if (cnt <= 0)
+        return false;   // Nothing to do
+
+    for (INT32 i=0; i < cnt; i++)
+    {
+        STRING aliasName = properties->GetName(i);
+        STRING expression = properties->GetValue(i);
+
+        FdoString* str = (FdoString*)expression.c_str();
+        if (str != NULL)
+        {
+            FdoPtr<FdoExpression> expression = FdoExpression::Parse(str);
+            CHECKNULL((FdoExpression*)expression, L"MgServerSelectFeatures.ContainsCustomFunction");
+
+            hasCustomFunction = ContainsUdf(expression);
+        }
+    }
+
+    if (hasCustomFunction && (cnt != 1))
+    {
+        // Only one custom function with no property is allowed
+        STRING message = MgFeatureUtil::GetMessage(L"MgOnlyOnePropertyAllowed");
+
+        MgStringCollection arguments;
+        arguments.Add(message);
+        throw new MgFeatureServiceException(L"MgServerSelectFeatures.ContainsCustomFunction",
+            __LINE__, __WFILE__, &arguments, L"", NULL);
+    }
+
+    return hasCustomFunction;
+}
+
+// Convert reader into a custom MgDataReader
+MgReader* MgSelectFeatures::GetCustomReader(MgReader* reader)
+{
+    Ptr<MgReader> distReader;
+    if (m_customPropertyFound)
+    {
+        Ptr<MgFeatureDistribution> featureDist =
+            MgFeatureDistribution::CreateDistributionFunction(reader, m_customFunction, m_customPropertyName);
+
+        distReader = featureDist->Execute();
+    }
+
+    return distReader.Detach();
+}
+
+// Look for extension which have calculations but no joins
+bool MgSelectFeatures::FindFeatureCalculation(MgResourceIdentifier* resourceId, CREFSTRING extensionName)
+{
+    bool bCalculationExists = false;
+
+    CHECKNULL(m_featureSourceCacheItem.p, L"MgServerSelectFeatures.FindFeatureCalculation");
+    MdfModel::FeatureSource* featureSource = m_featureSourceCacheItem->Get();
+    MdfModel::ExtensionCollection* extensions = featureSource->GetExtensions();
+    CHECKNULL(extensions, L"MgServerSelectFeatures.FindFeatureCalculation");
+
+    for (int i = 0; i < extensions->GetCount(); i++)
+    {
+        MdfModel::Extension* extension = extensions->GetAt(i);
+        CHECKNULL(extension, L"MgServerSelectFeatures.FindFeatureCalculation");
+        STRING name = (STRING)extension->GetName();
+
+        STRING parsedSchemaName, parsedExtensionName;
+        MgUtil::ParseQualifiedClassName(extensionName, parsedSchemaName, parsedExtensionName);
+
+        if (parsedExtensionName != name)
+        {
+            continue;
+        }
+        else
+        {
+            CalculatedPropertyCollection* calcProps = extension->GetCalculatedProperties();
+            // we don't have joins but we have calculations
+            bCalculationExists = (calcProps != NULL && calcProps->GetCount() != 0);
+            break;
+        }
+    }
+
+    return bCalculationExists;
+}
+
+// Look for extension (feature join) properties in the feature source document
+bool MgSelectFeatures::FindFeatureJoinProperties(MgResourceIdentifier* resourceId, CREFSTRING extensionName)
+{
+    bool bJoinPropertiesExists = false;
+
+    CHECKNULL(m_featureSourceCacheItem.p, L"MgServerSelectFeatures.FindFeatureJoinProperties");
+    MdfModel::FeatureSource* featureSource = m_featureSourceCacheItem->Get();
+    MdfModel::ExtensionCollection* extensions = featureSource->GetExtensions();
+    CHECKNULL(extensions, L"MgServerSelectFeatures.FindFeatureJoinProperties");
+
+    for (int i = 0; i < extensions->GetCount(); i++)
+    {
+        MdfModel::Extension* extension = extensions->GetAt(i);
+        CHECKNULL(extension, L"MgServerSelectFeatures.FindFeatureJoinProperties");
+        STRING name = (STRING)extension->GetName();
+
+        STRING parsedSchemaName, parsedExtensionName;
+        MgUtil::ParseQualifiedClassName(extensionName, parsedSchemaName, parsedExtensionName);
+
+        if (parsedExtensionName != name)
+        {
+            continue;
+        }
+        else
+        {
+            AttributeRelateCollection* relates = extension->GetAttributeRelates();
+            bJoinPropertiesExists = (relates != NULL && relates->GetCount() != 0);
+            break;
+        }
+    }
+
+    return bJoinPropertiesExists;
+}
+
+void MgSelectFeatures::UpdateCommandOnJoinCalculation(MgResourceIdentifier* featureSourceId, CREFSTRING extensionName)
+{
+    MG_FEATURE_SERVICE_TRY()
+
+    CHECKNULL(m_featureSourceCacheItem.p, L"MgServerSelectFeatures.UpdateCommandOnJoinCalculation");
+    MdfModel::FeatureSource* featureSource = m_featureSourceCacheItem->Get();
+    MdfModel::ExtensionCollection* extensions = featureSource->GetExtensions();
+    CHECKNULL(extensions, L"MgServerSelectFeatures.UpdateCommandOnJoinCalculation");
+
+    for (int i = 0; i < extensions->GetCount(); i++)
+    {
+        MdfModel::Extension* extension = extensions->GetAt(i);
+        CHECKNULL(extension, L"MgServerSelectFeatures.UpdateCommandOnJoinCalculation");
+        STRING name = (STRING)extension->GetName();
+
+        STRING parsedSchemaName, parsedExtensionName;
+        ParseQualifiedClassNameForCalculation(extension, extensionName, parsedSchemaName, parsedExtensionName);
+
+        if (parsedExtensionName != name)
+        {
+            continue;
+        }
+        else
+        {
+            CalculatedPropertyCollection* calcProps = extension->GetCalculatedProperties();
+            if (calcProps == NULL || calcProps->GetCount() == 0)
+                break;
+            FdoPtr<FdoIdentifierCollection> idList = FdoIdentifierCollection::Create();
+            for (int idx = 0; idx < calcProps->GetCount(); idx++)
+            {
+                CalculatedProperty* calcProp = calcProps->GetAt(idx);
+                FdoPtr<FdoExpression> expressionCalc = FdoExpression::Parse(calcProp->GetExpression().c_str());
+                FdoPtr<FdoComputedIdentifier> idfCalc = FdoComputedIdentifier::Create(calcProp->GetName().c_str(), expressionCalc);
+                idList->Add(idfCalc);
+            }
+            FdoPtr<FdoFilter> filter = m_command->GetFilter();
+            if (filter != NULL)
+            {
+                FdoPtr<FdoFilter> newFilter = FdoExpressionEngineCopyFilter::Copy(filter, idList);
+                m_command->SetFilter(newFilter);
+            }
+
+            FdoPtr<FdoIdentifierCollection> fic = m_command->GetPropertyNames();
+            if (fic->GetCount() != 0)
+            {
+                // replace calculated properties provided as identifiers to computed identifiers
+                for (int idx = 0; idx < calcProps->GetCount(); idx++)
+                {
+                    CalculatedProperty* calcProp = calcProps->GetAt(idx);
+                    FdoPtr<FdoIdentifier> idf = fic->FindItem(calcProp->GetName().c_str());
+                    if (idf != NULL)
+                    {
+                        FdoPtr<FdoComputedIdentifier> idfCalc = static_cast<FdoComputedIdentifier*>(idList->GetItem(idf->GetName()));
+                        FdoPtr<FdoExpression> expressionCalc = idfCalc->GetExpression();
+                        FdoPtr<FdoExpression> expandedExpression = FdoExpressionEngineCopyFilter::Copy(expressionCalc, idList);
+
+                        int idfIndex = fic->IndexOf(idf);
+                        FdoPtr<FdoComputedIdentifier> newIdf = FdoComputedIdentifier::Create(idf->GetName(), expandedExpression);
+                        fic->SetItem(idfIndex, newIdf);
+                    }
+                }
+            }
+            break;
+        }
+    }
+    MG_FEATURE_SERVICE_CHECK_CONNECTION_CATCH_AND_THROW(featureSourceId, L"MgServerSelectFeatures.UpdateCommandOnJoinCalculation")
+}
+
+void MgSelectFeatures::UpdateCommandOnCalculation(MgResourceIdentifier* featureSourceId, CREFSTRING extensionName)
+{
+    MG_FEATURE_SERVICE_TRY()
+
+    CHECKNULL(m_featureSourceCacheItem.p, L"MgServerSelectFeatures.UpdateCommandOnCalculation");
+    MdfModel::FeatureSource* featureSource = m_featureSourceCacheItem->Get();
+    MdfModel::ExtensionCollection* extensions = featureSource->GetExtensions();
+    CHECKNULL(extensions, L"MgServerSelectFeatures.UpdateCommandOnCalculation");
+
+    for (int i = 0; i < extensions->GetCount(); i++)
+    {
+        MdfModel::Extension* extension = extensions->GetAt(i);
+        CHECKNULL(extension, L"MgServerSelectFeatures.UpdateCommandOnCalculation");
+        STRING name = (STRING)extension->GetName();
+
+        STRING parsedSchemaName, parsedExtensionName;
+        ParseQualifiedClassNameForCalculation(extension, extensionName, parsedSchemaName, parsedExtensionName);
+
+        if (parsedExtensionName != name)
+        {
+            continue;
+        }
+        else
+        {
+            m_command->SetFeatureClassName(extension->GetFeatureClass().c_str());
+            CalculatedPropertyCollection* calcProps = extension->GetCalculatedProperties();
+            if (calcProps == NULL || calcProps->GetCount() == 0)
+                break;
+            FdoPtr<FdoIdentifierCollection> idList = FdoIdentifierCollection::Create();
+            for (int idx = 0; idx < calcProps->GetCount(); idx++)
+            {
+                CalculatedProperty* calcProp = calcProps->GetAt(idx);
+                FdoPtr<FdoExpression> expressionCalc = FdoExpression::Parse(calcProp->GetExpression().c_str());
+                FdoPtr<FdoComputedIdentifier> idfCalc = FdoComputedIdentifier::Create(calcProp->GetName().c_str(), expressionCalc);
+                idList->Add(idfCalc);
+            }
+            FdoPtr<FdoFilter> filter = m_command->GetFilter();
+            if (filter != NULL)
+            {
+                FdoPtr<FdoFilter> newFilter = FdoExpressionEngineCopyFilter::Copy(filter, idList);
+                m_command->SetFilter(newFilter);
+            }
+
+            FdoPtr<FdoIdentifierCollection> fic = m_command->GetPropertyNames();
+            bool addAllProps = (fic->GetCount() == 0);
+            for (int idx = 0; idx < calcProps->GetCount(); idx++)
+            {
+                CalculatedProperty* calcProp = calcProps->GetAt(idx);
+                FdoPtr<FdoIdentifier> idf = fic->FindItem(calcProp->GetName().c_str());
+                if (idf != NULL)
+                {
+                    // replace calculated properties provided as identifiers to computed identifiers
+                    FdoPtr<FdoComputedIdentifier> idfCalc = static_cast<FdoComputedIdentifier*>(idList->GetItem(idf->GetName()));
+                    FdoPtr<FdoExpression> expressionCalc = idfCalc->GetExpression();
+                    FdoPtr<FdoExpression> expandedExpression = FdoExpressionEngineCopyFilter::Copy(expressionCalc, idList);
+
+                    int idfIndex = fic->IndexOf(idf);
+                    FdoPtr<FdoComputedIdentifier> newIdf = FdoComputedIdentifier::Create(idf->GetName(), expandedExpression);
+                    fic->SetItem(idfIndex, newIdf);
+                }
+                else
+                {
+                    if (addAllProps)
+                    {
+                        FdoPtr<FdoComputedIdentifier> idfCalc = static_cast<FdoComputedIdentifier*>(idList->GetItem(calcProp->GetName().c_str()));
+                        FdoPtr<FdoExpression> expressionCalc = idfCalc->GetExpression();
+                        FdoPtr<FdoExpression> expandedExpression = FdoExpressionEngineCopyFilter::Copy(expressionCalc, idList);
+
+                        FdoPtr<FdoComputedIdentifier> newIdf = FdoComputedIdentifier::Create(calcProp->GetName().c_str(), expandedExpression);
+                        fic->Add(newIdf);
+                    }
+                }
+                if (addAllProps)
+                {
+                    Ptr<MgFeatureConnection> fcConnection = new MgFeatureConnection(featureSourceId);
+                    if ((NULL != fcConnection.p) && ( fcConnection->IsConnectionOpen() ))
+                    {
+                        // The reference to the FDO connection from the MgFeatureConnection object must be cleaned up before the parent object
+                        // otherwise it leaves the FDO connection marked as still in use.
+                        FdoPtr<FdoIConnection> conn = fcConnection->GetConnection();
+                        FdoPtr<FdoIDescribeSchema>  descSchema = (FdoIDescribeSchema *) conn->CreateCommand (FdoCommandType_DescribeSchema);
+
+                        STRING fullClassName = extension->GetFeatureClass();
+                        STRING schemaName, className;
+                        MgUtil::ParseQualifiedClassName(fullClassName, schemaName, className);
+
+                        if (!parsedSchemaName.empty())
+                        {
+                            descSchema->SetSchemaName(parsedSchemaName.c_str());
+                        }
+
+                        if (!className.empty())
+                        {
+                            FdoPtr<FdoStringCollection> classNames = FdoStringCollection::Create();
+
+                            classNames->Add(className.c_str());
+                            descSchema->SetClassNames(classNames.p);
+                        }
+
+                        FdoPtr <FdoFeatureSchemaCollection> schemas = (FdoFeatureSchemaCollection *) descSchema->Execute ();
+                        FdoPtr<FdoFeatureSchema> schema = (FdoFeatureSchema *)schemas->GetItem (parsedSchemaName.c_str());
+                        FdoPtr<FdoClassCollection> classes = schema->GetClasses();
+
+                        FdoPtr<FdoClassDefinition> activeClass = classes->GetItem(className.c_str());
+                        FdoPtr<FdoPropertyDefinitionCollection> properties = activeClass->GetProperties();
+                        for(int i = 0; i < properties->GetCount(); i++)
+                        {
+                            FdoPtr<FdoPropertyDefinition> activeProperty = properties->GetItem(i);
+                            FdoPtr<FdoIdentifier> idf = fic->FindItem(activeProperty->GetName());
+                            if (idf == NULL)
+                            {
+                                idf = FdoIdentifier::Create(activeProperty->GetName());
+                                fic->Add(idf);
+                            }
+                        }
+                        FdoPtr<FdoReadOnlyPropertyDefinitionCollection> baseProps = activeClass->GetBaseProperties();
+                        if (baseProps != NULL)
+                        {
+                            for(int i = 0; i < baseProps->GetCount(); i++)
+                            {
+                                FdoPtr<FdoPropertyDefinition>prop = baseProps->GetItem(i);
+                                if( prop->GetIsSystem() )
+                                    continue;
+                                fic->Add( FdoPtr<FdoIdentifier>(FdoIdentifier::Create( prop->GetName() ) ) );
+                            }
+                        }
+                    }
+                }
+            }
+            break;
+        }
+    }
+    MG_FEATURE_SERVICE_CHECK_CONNECTION_CATCH_AND_THROW(featureSourceId, L"MgServerSelectFeatures.UpdateCommandOnCalculation")
+}
+
+MgdGwsFeatureReader* MgSelectFeatures::JoinFeatures(MgResourceIdentifier* featureSourceIdentifier, CREFSTRING extensionName, FdoFilter* filter)
+{
+    Ptr<MgdGwsFeatureReader> gwsFeatureReader;
+
+    MG_FEATURE_SERVICE_TRY()
+
+    FdoPtr<IGWSQueryDefinition> qd;
+    FdoPtr<MgGwsConnectionPool> pool = MgGwsConnectionPool::Create();
+
+    CHECKNULL(m_featureSourceCacheItem.p, L"MgServerSelectFeatures.JoinFeatures");
+    MdfModel::FeatureSource* featureSource = m_featureSourceCacheItem->Get();
+    MdfModel::ExtensionCollection* extensions = featureSource->GetExtensions();
+    CHECKNULL(extensions, L"MgServerSelectFeatures.JoinFeatures");
+
+    for (int i = 0; i < extensions->GetCount(); i++)
+    {
+        MdfModel::Extension* extension = extensions->GetAt(i);
+        CHECKNULL(extension, L"MgServerSelectFeatures.JoinFeatures");
+        STRING name = (STRING)extension->GetName();
+
+        STRING parsedSchemaName, parsedExtensionName;
+        MgUtil::ParseQualifiedClassName(extensionName, parsedSchemaName, parsedExtensionName);
+
+        if (parsedExtensionName != name)
+        {
+            continue;
+        }
+        else
+        {
+            // Establish connection to provider for primary feature source
+            STRING primaryConnectionName;
+            MgUtil::GenerateUuid(primaryConnectionName);
+            Ptr<MgFeatureConnection> msfcLeft = new MgFeatureConnection(featureSourceIdentifier);
+            if ((NULL != msfcLeft.p) && ( msfcLeft->IsConnectionOpen() ))
+            {
+                pool->AddConnection(primaryConnectionName.c_str(), msfcLeft);
+            }
+            else
+            {
+                throw new MgConnectionFailedException(L"MgServerSelectFeatures.JoinFeatures",
+                    __LINE__, __WFILE__, NULL, L"", NULL);
+            }
+
+            // Retrieve the primary feature class
+            STRING featureClass = (STRING)extension->GetFeatureClass();
+
+            // Parse the qualifed classname
+            STRING primaryFsSchema, primaryFsClassName;
+            MgUtil::ParseQualifiedClassName(featureClass, primaryFsSchema, primaryFsClassName);
+
+            // Create primary query definition
+            FdoPtr<FdoIdentifierCollection> lsellist;
+            FdoPtr<FdoFilter> lfilter;
+
+            // in case we have calculations we must add all properties + computed properties to the selection list
+            MdfModel::CalculatedPropertyCollection* calcProps = extension->GetCalculatedProperties();
+            if (calcProps != NULL && calcProps->GetCount() != 0)
+            {
+                FdoPtr<FdoIdentifierCollection> idList = FdoIdentifierCollection::Create();
+                for (int idx = 0; idx < calcProps->GetCount(); idx++)
+                {
+                    CalculatedProperty* calcProp = calcProps->GetAt(idx);
+                    FdoPtr<FdoExpression> expressionCalc = FdoExpression::Parse(calcProp->GetExpression().c_str());
+                    FdoPtr<FdoComputedIdentifier> idfCalc = FdoComputedIdentifier::Create(calcProp->GetName().c_str(), expressionCalc);
+                    idList->Add(idfCalc);
+                }
+                lsellist = FdoIdentifierCollection::Create();
+                for (int idx = 0; idx < calcProps->GetCount(); idx++)
+                {
+                    CalculatedProperty* calcProp = calcProps->GetAt(idx);
+                    FdoPtr<FdoComputedIdentifier> idfCalc = static_cast<FdoComputedIdentifier*>(idList->GetItem(calcProp->GetName().c_str()));
+                    FdoPtr<FdoExpression> expressionCalc = idfCalc->GetExpression();
+                    FdoPtr<FdoExpression> expandedExpression = FdoExpressionEngineCopyFilter::Copy(expressionCalc, idList);
+
+                    FdoPtr<FdoComputedIdentifier> newIdf = FdoComputedIdentifier::Create(calcProp->GetName().c_str(), expandedExpression);
+                    lsellist->Add(newIdf);
+                }
+                FdoPtr<FdoIConnection> conn = msfcLeft->GetConnection();
+                FdoPtr<FdoIDescribeSchema>  descSchema = (FdoIDescribeSchema *) conn->CreateCommand (FdoCommandType_DescribeSchema);
+
+                STRING fullClassName = extension->GetFeatureClass();
+                STRING schemaName, className;
+                MgUtil::ParseQualifiedClassName(fullClassName, schemaName, className);
+
+                if (!parsedSchemaName.empty())
+                {
+                    descSchema->SetSchemaName(parsedSchemaName.c_str());
+                }
+
+                if (!className.empty())
+                {
+                    FdoPtr<FdoStringCollection> classNames = FdoStringCollection::Create();
+
+                    classNames->Add(className.c_str());
+                    descSchema->SetClassNames(classNames.p);
+                }
+
+                FdoPtr <FdoFeatureSchemaCollection> schemas = (FdoFeatureSchemaCollection *) descSchema->Execute ();
+                FdoPtr<FdoFeatureSchema> schema = (FdoFeatureSchema *)schemas->GetItem (parsedSchemaName.c_str());
+                FdoPtr<FdoClassCollection> classes = schema->GetClasses();
+
+                FdoPtr<FdoClassDefinition> activeClass = classes->GetItem(className.c_str());
+                FdoPtr<FdoPropertyDefinitionCollection> properties = activeClass->GetProperties();
+                for(int i = 0; i < properties->GetCount(); i++)
+                {
+                    FdoPtr<FdoPropertyDefinition> activeProperty = properties->GetItem(i);
+                    FdoPtr<FdoIdentifier> idf = FdoIdentifier::Create(activeProperty->GetName());
+                    lsellist->Add(idf);
+                }
+                FdoPtr<FdoReadOnlyPropertyDefinitionCollection> baseProps = activeClass->GetBaseProperties();
+                if (baseProps != NULL)
+                {
+                    for(int i = 0; i < baseProps->GetCount(); i++)
+                    {
+                        FdoPtr<FdoPropertyDefinition>prop = baseProps->GetItem(i);
+                        if( prop->GetIsSystem() )
+                            continue;
+                        lsellist->Add( FdoPtr<FdoIdentifier>(FdoIdentifier::Create( prop->GetName() ) ) );
+                    }
+                }
+            }
+
+            FdoPtr<IGWSQueryDefinition> lqd = IGWSFeatureQueryDefinition::Create(
+                lsellist,
+                GWSQualifiedName(primaryConnectionName.c_str(), primaryFsSchema.c_str(), primaryFsClassName.c_str()),
+                lfilter);
+            CHECKNULL(lqd, L"MgServerSelectFeatures.JoinFeatures");
+            qd = lqd;
+
+            IGWSJoinQueryDefinition* jqd = NULL;
+
+            MdfModel::AttributeRelateCollection* attributeRelates = extension->GetAttributeRelates();
+            CHECKNULL(attributeRelates, L"MgServerSelectFeatures.JoinFeatures");
+
+            bool bForceOneToOne = true;
+            Ptr<MgStringCollection> attributeNameDelimiters = new MgStringCollection();
+
+            //Store all the secondary's name, and if the filter property doesn't contain secondary's name,
+            //it applies only to the primary.
+            Ptr<MgStringCollection> secondaryNames = new MgStringCollection();
+
+            // For each join (attributeRelate) to a secondary source need to do the following
+            for (int attributeRelateIndex = 0; attributeRelateIndex < attributeRelates->GetCount(); attributeRelateIndex++)
+            {
+                MdfModel::AttributeRelate* attributeRelate = attributeRelates->GetAt(attributeRelateIndex);
+                CHECKNULL(attributeRelate, L"MgServerSelectFeatures.JoinFeatures");
+
+                // Get the secondary resource id
+                STRING secondaryResourceId = (STRING)attributeRelate->GetResourceId();
+
+                // Get the name for the join relationship
+                STRING attributeRelateName = (STRING)attributeRelate->GetName();
+                STRING secondaryConnectionName = attributeRelateName;
+
+                if(!secondaryNames->Contains(attributeRelateName))
+                    secondaryNames->Add(attributeRelateName);
+
+                // Get the RelateType (join type).  Default is Left Outer join.
+                MdfModel::AttributeRelate::RelateType relateType = attributeRelate->GetRelateType();
+
+                // Get the ForceOneToOne field, which specifies if multiple matching secondary features
+                // are retrieved via a 1-to-1 or 1-to-many relationship.  Default is 1-to-1 relationship.
+                bool forceOneToOne = attributeRelate->GetForceOneToOne();
+                // If there is at least one relation is defined as one-to-many, then the one-to-many result will apply to all join results.
+                if (!forceOneToOne)
+                {
+                    bForceOneToOne = false;
+                }
+
+                // Get the AttributeNameDelimiter field, which specifies the delimiter between the JoinName (attribute relate name)
+                // and the property name for an extended property.  Default delimiter is "" (blank).
+                STRING attributeNameDelimiter = (STRING)attributeRelate->GetAttributeNameDelimiter();
+                attributeNameDelimiters->Add(attributeNameDelimiter);
+
+                // Establish connection to provider for secondary feature source
+                Ptr<MgResourceIdentifier> secondaryFeatureSource = new MgResourceIdentifier(secondaryResourceId);
+
+                if (NULL != secondaryFeatureSource)
+                {
+                    Ptr<MgFeatureConnection> msfcRight = new MgFeatureConnection(secondaryFeatureSource);
+                    if ((NULL != msfcRight.p) && ( msfcRight->IsConnectionOpen() ))
+                    {
+                        pool->AddConnection(secondaryConnectionName.c_str(), msfcRight);
+                    }
+                    else
+                    {
+                        throw new MgConnectionFailedException(L"MgServerSelectFeatures.JoinFeatures",
+                            __LINE__, __WFILE__, NULL, L"", NULL);
+                    }
+                }
+
+                // Get the secondary featureClassName (qualified className)
+                STRING secondaryClassName = (STRING)attributeRelate->GetAttributeClass();
+
+                // Parse the qualified classname
+                STRING secondaryFsSchema, secondaryFsClassName;
+                MgUtil::ParseQualifiedClassName(secondaryClassName, secondaryFsSchema, secondaryFsClassName);
+
+                // Create secondary query definition
+                FdoPtr<FdoIdentifierCollection> rsellist;
+                FdoPtr<FdoFilter> rfilter;
+
+                FdoPtr<IGWSQueryDefinition> rqd  = IGWSFeatureQueryDefinition::Create(
+                    rsellist,
+                    GWSQualifiedName(secondaryConnectionName.c_str(), secondaryFsSchema.c_str(), secondaryFsClassName.c_str()),
+                    rfilter);
+                CHECKNULL(rqd, L"MgServerSelectFeatures.JoinFeatures");
+
+                // Get Join Attributes
+                FdoPtr<FdoStringCollection> lattrs = FdoStringCollection::Create();
+                FdoPtr<FdoStringCollection> rattrs = FdoStringCollection::Create();
+
+                // Determine the number of RelateProperties (attributes)
+                MdfModel::RelatePropertyCollection* relateProperties = attributeRelate->GetRelateProperties();
+                CHECKNULL(relateProperties, L"MgServerSelectFeatures.JoinFeatures");
+                int nRelatePropertyCount = relateProperties->GetCount();
+
+                // For each RelateProperty need to do the following
+                for (int relatePropertyIndex = 0; relatePropertyIndex < nRelatePropertyCount; relatePropertyIndex++)
+                {
+                    MdfModel::RelateProperty* relateProperty = relateProperties->GetAt(relatePropertyIndex);
+                    CHECKNULL(relateProperty, L"MgServerSelectFeatures.JoinFeatures");
+
+                    // Get the FeatureClassProperty (primary attribute)
+                    STRING primaryAttribute = (STRING)relateProperty->GetFeatureClassProperty();
+
+                    // Add to the primary attribute String collection
+                    lattrs->Add(primaryAttribute.c_str());
+
+                    // Get the AttributeClassProperty (secondary attribute)
+                    STRING secondaryAttribute = (STRING)relateProperty->GetAttributeClassProperty();
+
+                    // Add to the secondary attribute String collection
+                    rattrs->Add(secondaryAttribute.c_str());
+                }
+
+                // Create the QueryDefinition
+                if (NULL != rqd)
+                {
+                    FdoString* joinName = attributeRelateName.c_str();
+                    FdoString* joinDelimiter = L".";
+                    if (MdfModel::AttributeRelate::Inner == relateType)
+                    {
+                        jqd = IGWSEqualJoinQueryDefinition::Create(joinName, joinDelimiter, bForceOneToOne, lqd, rqd, lattrs, rattrs);
+                    }
+                    else  // if (RelateType::LeftOuter == relateType)
+                    {
+                        jqd = IGWSLeftJoinQueryDefinition::Create(joinName, joinDelimiter, bForceOneToOne, lqd, rqd, lattrs, rattrs);
+                    }
+                    lqd = jqd;
+                }
+
+            }  // Repeat for each secondary source
+            qd = lqd;
+
+            FdoPtr<IGWSQuery> query = IGWSQuery::Create(pool, qd, NULL);
+            FdoPtr<IGWSFeatureIterator> iter;
+            FdoPtr<IGWSFeatureIterator> iterCopy;
+
+            // Set batch size as it may be needed
+            CGwsBatchSortedBlockJoinQueryResults::sm_nBatchSize = m_nJoinQueryBatchSize;
+
+            // Prepare and Execute Query
+            query->Prepare();
+
+            // Search the filter to see if it contains the extension name
+            // If the extension name is not found it means that the filter involves attribute(s) only from the primary
+            if(NULL != filter)
+            {
+                FdoString* filterText = filter->ToString();
+                if(NULL != filterText)
+                {
+                    bool match = false;
+                    for(int i = 0; i < secondaryNames->GetCount(); i ++)
+                    {
+                        STRING secondaryName = secondaryNames->GetItem(i);
+                        if(NULL != wcsstr(filterText, secondaryName.c_str()))
+                        {
+                            match = true;
+                            break;
+                        }
+                    }
+                    if(!match)
+                    {
+                        // Add the filter to the query because it only applies to the primary
+                        query->SetFilter(filter);
+                    }
+                }
+            }
+
+            // Execute the query
+            query->Execute(&iter, true);
+            query->Execute(&iterCopy, true);
+
+            FdoPtr<FdoStringCollection> fsNames = qd->FeatureSourceNames();
+
+            gwsFeatureReader = new MgdGwsFeatureReader(pool, iter, iterCopy, parsedExtensionName, fsNames, bForceOneToOne, attributeNameDelimiters);
+            gwsFeatureReader->SetFilter(filter);
+            break;
+        }
+    }
+
+    MG_FEATURE_SERVICE_CHECK_CONNECTION_CATCH_AND_THROW(featureSourceIdentifier, L"MgServerSelectFeatures.JoinFeatures")
+
+    // Now that the reader has been created we will need to mark all of the connections it uses as OwnReader() because the GWS reader will be
+    // taking ownership of the connections. We have to do it this late in the code in case an exception is thrown somewhere before this.
+    // We want to avoid a deadlock of the connection :)
+    gwsFeatureReader->OwnsConnections();
+
+    return gwsFeatureReader.Detach();
+}
+
+void MgSelectFeatures::ParseQualifiedClassNameForCalculation(MdfModel::Extension* extension, CREFSTRING qualifiedClassName, STRING& schemaName, STRING& className)
+{
+    CHECKNULL(extension, L"MgServerSelectFeatures.ParseQualifiedClassNameForCalculation");
+
+    MgUtil::ParseQualifiedClassName(qualifiedClassName, schemaName, className);
+
+    if (schemaName.empty())
+    {
+        STRING dummyStr;
+
+        MgUtil::ParseQualifiedClassName(extension->GetFeatureClass(), schemaName, dummyStr);
+    }
+}
+
+MgResourceIdentifier* MgSelectFeatures::GetSecondaryResourceIdentifier(MgResourceIdentifier* primResId, CREFSTRING extensionName, CREFSTRING relationName)
+{
+    Ptr<MgResourceIdentifier> secResId;
+
+    CHECKNULL(m_featureSourceCacheItem.p, L"MgServerSelectFeatures.GetSecondaryResourceIdentifier");
+    MdfModel::FeatureSource* featureSource = m_featureSourceCacheItem->Get();
+    MdfModel::ExtensionCollection* extensions = featureSource->GetExtensions();
+    CHECKNULL(extensions, L"MgServerSelectFeatures.GetSecondaryResourceIdentifier");
+
+    for (int i = 0; i < extensions->GetCount(); i++)
+    {
+        MdfModel::Extension* extension = extensions->GetAt(i);
+        CHECKNULL(extension, L"MgServerSelectFeatures.GetSecondaryResourceIdentifier");
+
+        // Get the extension name
+        STRING name = (STRING)extension->GetName();
+
+        STRING parsedSchemaName, parsedExtensionName;
+        MgUtil::ParseQualifiedClassName(extensionName, parsedSchemaName, parsedExtensionName);
+
+        if (parsedExtensionName != name)
+        {
+            continue;
+        }
+        else
+        {
+            // Determine the number of secondary sources (AttributeRelates)
+            MdfModel::AttributeRelateCollection* attributeRelates = extension->GetAttributeRelates();
+            CHECKNULL(attributeRelates, L"MgServerSelectFeatures.GetSecondaryResourceIdentifier");
+            int nAttributeRelateCount = attributeRelates->GetCount();
+
+            // Find the specified relation name
+            {
+                for (int attributeRelateIndex = 0; attributeRelateIndex < nAttributeRelateCount; attributeRelateIndex++)
+                {
+                    MdfModel::AttributeRelate* attributeRelate = attributeRelates->GetAt(attributeRelateIndex);
+                    CHECKNULL(attributeRelate, L"MgServerSelectFeatures.GetSecondaryResourceIdentifier");
+
+                    // Get the name for the join relationship
+                    STRING attributeRelateName = (STRING)attributeRelate->GetName();
+
+                    if (attributeRelateName != relationName)
+                    {
+                        continue;
+                    }
+                    else
+                    {
+                        // Get the secondary resource id
+                        STRING secondaryResourceId = (STRING)attributeRelate->GetResourceId();
+                        secResId = new MgResourceIdentifier(secondaryResourceId);
+                        break;
+                    }
+                }
+            }
+        }
+    }
+
+    return secResId.Detach();
+}
+
+bool MgSelectFeatures::SupportsFdoJoin(MgResourceIdentifier* featureSourceId, CREFSTRING extensionName, bool isAggregate)
+{
+    bool bSupported = false;
+
+    MG_FEATURE_SERVICE_TRY()
+
+    //This could be qualified, so parse it to be sure
+    STRING schemaName;
+    STRING extName;
+    MgUtil::ParseQualifiedClassName(extensionName, schemaName, extName);
+
+    CHECKNULL(m_featureSourceCacheItem.p, L"MgServerSelectFeatures.SupportsFdoJoin");
+    MdfModel::FeatureSource* featureSource = m_featureSourceCacheItem->Get();
+    MdfModel::ExtensionCollection* extensions = featureSource->GetExtensions();
+    CHECKNULL(extensions, L"MgServerSelectFeatures.SupportsFdoJoin");
+
+    MdfModel::Extension* extension = NULL;
+    for (INT32 i = 0; i < extensions->GetCount(); i++) 
+    {
+        MdfModel::Extension* ext = extensions->GetAt(i);
+        if (ext->GetName() == extName)
+        {
+            extension = ext;
+            break;
+        }
+    }
+
+    if (NULL == extension) //Extension in question not found
+    {
+#ifdef DEBUG_FDO_JOIN
+        ACE_DEBUG((LM_INFO, ACE_TEXT("\n\t(%t) [FDO Join Test] Could not find extension named: %W"), extensionName.c_str()));
+#endif
+        return false;
+    }
+
+    Ptr<MgFeatureConnection> conn = new MgFeatureConnection(featureSourceId);
+    {
+        if (!conn->IsConnectionOpen())
+        {
+            throw new MgConnectionFailedException(L"MgServerSelectFeatures.SupportsFdoJoin", __LINE__, __WFILE__, NULL, L"", NULL);
+        }
+
+        FdoPtr<FdoIConnection> fdoConn = conn->GetConnection();
+        FdoPtr<FdoIConnectionCapabilities> connCaps = fdoConn->GetConnectionCapabilities();
+        
+        MdfModel::AttributeRelateCollection* relates = extension->GetAttributeRelates();
+
+        //Get the easy checks out of the way
+        if (!connCaps->SupportsJoins())
+        {
+#ifdef DEBUG_FDO_JOIN
+            ACE_DEBUG((LM_INFO, ACE_TEXT("\n\t(%t) [FDO Join Test] The provider does not support the FDO join APIs")));
+#endif
+            return false;
+        }
+
+        FdoJoinType jtypes = (FdoJoinType)connCaps->GetJoinTypes();
+
+        //Now ascertain if all participating feature classes originate from the same feature source
+        
+        //We've yet to figure out chained joins. TODO: Revisit later
+        if (relates->GetCount() > 1)
+        {
+#ifdef DEBUG_FDO_JOIN
+            ACE_DEBUG((LM_INFO, ACE_TEXT("\n\t(%t) [FDO Join Test] Chained/Multiple FDO Joins not supported yet")));
+#endif
+            return false;
+        }
+
+        //Need to check the filter here to see if it involves secondary class properties and/or
+        //expressions involving such properties. We don't support this yet
+        if (m_options != NULL && relates->GetCount())
+        {
+            MdfModel::AttributeRelate* relate = relates->GetAt(0);
+            STRING filterText = m_options->GetFilter();
+            STRING qualifiedName = relate->GetAttributeClass();
+            STRING schemaName;
+            STRING clsName;
+            MgUtil::ParseQualifiedClassName(qualifiedName, schemaName, clsName);
+            if (FilterContainsSecondaryProperties(featureSourceId, filterText, schemaName, clsName, relate->GetName()))
+            {
+    #ifdef DEBUG_FDO_JOIN
+                ACE_DEBUG((LM_INFO, ACE_TEXT("\n\t(%t) [FDO Join Test] Filter contains secondary class properties")));
+    #endif
+                return false;
+            }
+        }
+
+        for (INT32 i = 0; i < relates->GetCount(); i++)
+        {
+            MdfModel::AttributeRelate* relate = relates->GetAt(i);
+            const MdfModel::MdfString& fsId = relate->GetResourceId();
+
+            //Different feature sources
+            if (featureSourceId->ToString() != fsId)
+            {
+#ifdef DEBUG_FDO_JOIN
+                ACE_DEBUG((LM_INFO, ACE_TEXT("\n\t(%t) [FDO Join Test] The extension does not join with another class from the same data store")));
+#endif
+                return false;
+            }
+
+            //TODO: Review when we lift the one join limit
+            if (NULL != (MgFeatureQueryOptions*)m_options)
+            {
+                //Is this costly? Should we cache it?
+                //FdoPtr<FdoFunctionDefinitionCollection> functions = FdoExpressionEngine::GetStandardFunctions();
+                Ptr<MgStringPropertyCollection> expressions = m_options->GetComputedProperties();
+                for (INT32 i = 0; i < expressions->GetCount(); i++)
+                {
+                    Ptr<MgStringProperty> compProp = expressions->GetItem(i);
+                    STRING exprText = compProp->GetValue();
+                    FdoPtr<FdoExpression> fdoExpr = FdoExpression::Parse(exprText.c_str());
+
+                    if (fdoExpr->GetExpressionType() == FdoExpressionItemType_Function)
+                    {
+                        FdoFunction* func = static_cast<FdoFunction*>(fdoExpr.p);
+                        FdoString* funcName = func->GetName();
+
+                        // We don't support functions on prefixed secondary properties (yet)
+                        // so we have to check these functions to ensure they are only operating on the 
+                        // primary side properties
+                        STRING primarySchemaName;
+                        STRING primaryClassName;
+                        MgUtil::ParseQualifiedClassName(extension->GetFeatureClass(), primarySchemaName, primaryClassName);
+                        bool bValidFunction = IsFunctionOnPrimaryProperty(func, fdoConn, primarySchemaName, primaryClassName);
+                        if (!bValidFunction)
+                        {
+#ifdef DEBUG_FDO_JOIN
+                            ACE_DEBUG((LM_INFO, ACE_TEXT("\n\t(%t) [FDO Join Test] FDO Function %W contains a non-primary or unrecognised identifier"), funcName));
+#endif
+                            return false;
+                        }
+                    }
+                }
+            }
+
+            MdfModel::RelatePropertyCollection* relProps = relate->GetRelateProperties();
+
+            //Check if the join type is supported. Given FDO exposes more join types than
+            //the ones specified here, the chances are real good that we'll have a match
+            MdfModel::AttributeRelate::RelateType rtype = relate->GetRelateType();
+            switch(rtype)
+            {
+            case MdfModel::AttributeRelate::Inner:
+                if ((jtypes & FdoJoinType_Inner) != FdoJoinType_Inner)
+                {
+#ifdef DEBUG_FDO_JOIN
+                    ACE_DEBUG((LM_INFO, ACE_TEXT("\n\t(%t) [FDO Join Test] The provider does not support Inner Join")));
+#endif
+                    return false;
+                }
+                break;
+            case MdfModel::AttributeRelate::LeftOuter:
+                if ((jtypes & FdoJoinType_LeftOuter) != FdoJoinType_LeftOuter)
+                {
+#ifdef DEBUG_FDO_JOIN
+                    ACE_DEBUG((LM_INFO, ACE_TEXT("\n\t(%t) [FDO Join Test] The provider does not support Left Outer Join")));
+#endif
+                    return false;
+                }
+                break;
+            case MdfModel::AttributeRelate::RightOuter:
+                if ((jtypes & FdoJoinType_RightOuter) != FdoJoinType_RightOuter)
+                {
+#ifdef DEBUG_FDO_JOIN
+                    ACE_DEBUG((LM_INFO, ACE_TEXT("\n\t(%t) [FDO Join Test] The provider does not support Right Outer Join")));
+#endif
+                    return false;
+                }
+                break;
+            default:
+                {
+#ifdef DEBUG_FDO_JOIN
+                    ACE_DEBUG((LM_INFO, ACE_TEXT("\n\t(%t) [FDO Join Test] The join type is not recognised")));
+#endif
+                    return false;
+                }
+            }
+        }
+
+        //Still here? You pass the test
+        bSupported = true;
+    }
+
+    MG_FEATURE_SERVICE_CATCH_AND_THROW(L"MgServerSelectFeatures.SupportsFdoJoin")
+
+    return bSupported;
+}
+
+bool MgSelectFeatures::IsFunctionOnPrimaryProperty(FdoFunction* function, FdoIConnection* fdoConn, CREFSTRING schemaName, CREFSTRING className)
+{
+    FdoPtr<FdoIdentifierCollection> identifiers = MgFeatureUtil::ExtractIdentifiers(function);
+    if (identifiers->GetCount() == 0)
+        return true; //Inconsequential
+
+    FdoPtr<FdoIDescribeSchema> descSchema = dynamic_cast<FdoIDescribeSchema*>(fdoConn->CreateCommand(FdoCommandType_DescribeSchema));
+    CHECKNULL((FdoIDescribeSchema*)descSchema, L"MgServerSelectFeatures.SelectFdoJoin");
+
+    if (!schemaName.empty())
+    {
+        descSchema->SetSchemaName(schemaName.c_str());
+    }
+    if (!className.empty())
+    {
+        FdoPtr<FdoStringCollection> classNames = FdoStringCollection::Create();
+        classNames->Add(className.c_str());
+        descSchema->SetClassNames(classNames);
+    }
+
+    FdoPtr<FdoClassDefinition> classDef;
+    FdoPtr<FdoFeatureSchemaCollection> schemas = descSchema->Execute();
+    for (FdoInt32 i = 0; i < schemas->GetCount(); i++)
+    {
+        FdoPtr<FdoFeatureSchema> schema = schemas->GetItem(i);
+        if (wcscmp(schema->GetName(), schemaName.c_str()) == 0) 
+        {
+            FdoPtr<FdoClassCollection> classes = schema->GetClasses();
+            for (FdoInt32 j = 0; j < classes->GetCount(); j++) 
+            {
+                FdoPtr<FdoClassDefinition> klassDef = classes->GetItem(j);
+                if (wcscmp(klassDef->GetName(), className.c_str()) == 0)
+                {
+                    classDef = SAFE_ADDREF(klassDef.p);
+                    break;
+                }
+            }
+        }
+    }
+
+    if (NULL == (FdoClassDefinition*)classDef)
+    {
+        //TODO: Refine message if available
+        throw new MgClassNotFoundException(L"MgServerSelectFeatures.IsFunctionOnPrimaryProperty", __LINE__, __WFILE__, NULL, L"", NULL);
+    }
+
+    FdoPtr<FdoPropertyDefinitionCollection> properties = classDef->GetProperties();
+    for (FdoInt32 i = 0; i < identifiers->GetCount(); i++)
+    {
+        FdoPtr<FdoIdentifier> identifier = identifiers->GetItem(i);
+        FdoString* name = identifier->GetName();
+        if (properties->IndexOf(name) < 0) //Not in primary class or not recognised
+        {
+#ifdef DEBUG_FDO_JOIN
+            FdoString* funcName = function->GetName();
+            ACE_DEBUG((LM_INFO, ACE_TEXT("\n\t(%t) [FDO Join Test] The aggregate function %W contains an unknown or non-primary identifier: %W"), funcName, name));
+#endif
+            return false;
+        }
+    }
+
+    return true;
+}
+
+bool MgSelectFeatures::FilterContainsSecondaryProperties(MgResourceIdentifier* featureSourceId, CREFSTRING filter, STRING secondarySchema, STRING secondaryClassName, STRING secondaryPrefix)
+{
+    if (filter.empty())
+        return false;
+
+    //TODO: There's probably a more efficient way to do this without needing to fetch the secondary
+    //class definition. But we're aiming for functionality and simplicity first.
+    Ptr<MgFeatureConnection> conn = new MgFeatureConnection(featureSourceId);
+    {
+        if (!conn->IsConnectionOpen())
+        {
+            throw new MgConnectionFailedException(L"MgServerSelectFeatures.SupportsFdoJoin", __LINE__, __WFILE__, NULL, L"", NULL);
+        }
+
+        FdoPtr<FdoIConnection> fdoConn = conn->GetConnection();
+
+        FdoPtr<FdoIDescribeSchema> descSchema = dynamic_cast<FdoIDescribeSchema*>(fdoConn->CreateCommand(FdoCommandType_DescribeSchema));
+        CHECKNULL((FdoIDescribeSchema*)descSchema, L"MgServerSelectFeatures.SelectFdoJoin");
+
+        if (!secondarySchema.empty())
+        {
+            descSchema->SetSchemaName(secondarySchema.c_str());
+        }
+        if (!secondaryClassName.empty())
+        {
+            FdoPtr<FdoStringCollection> classNames = FdoStringCollection::Create();
+            classNames->Add(secondaryClassName.c_str());
+            descSchema->SetClassNames(classNames);
+        }
+
+        FdoPtr<FdoClassDefinition> classDef;
+        FdoPtr<FdoFeatureSchemaCollection> schemas = descSchema->Execute();
+        for (FdoInt32 i = 0; i < schemas->GetCount(); i++)
+        {
+            FdoPtr<FdoFeatureSchema> schema = schemas->GetItem(i);
+            if (wcscmp(schema->GetName(), secondarySchema.c_str()) == 0) 
+            {
+                FdoPtr<FdoClassCollection> classes = schema->GetClasses();
+                for (FdoInt32 j = 0; j < classes->GetCount(); j++) 
+                {
+                    FdoPtr<FdoClassDefinition> klassDef = classes->GetItem(j);
+                    if (wcscmp(klassDef->GetName(), secondaryClassName.c_str()) == 0)
+                    {
+                        classDef = SAFE_ADDREF(klassDef.p);
+                        break;
+                    }
+                }
+            }
+        }
+
+        if (NULL == (FdoClassDefinition*)classDef)
+        {
+            //TODO: Refine message if available
+            throw new MgClassNotFoundException(L"MgServerSelectFeatures.FilterContainsSecondaryProperties", __LINE__, __WFILE__, NULL, L"", NULL);
+        }
+
+        FdoPtr<FdoPropertyDefinitionCollection> propDefs = classDef->GetProperties();
+        for (INT32 i = 0; i < propDefs->GetCount(); i++)
+        {
+            FdoPtr<FdoPropertyDefinition> propDef = propDefs->GetItem(i);
+            STRING findStr = secondaryPrefix;
+            findStr += propDef->GetName();
+
+            if (filter.find(findStr) != STRING::npos)
+                return true; //The filter string contains this extended feature class property
+        }
+    }
+    return false;
+}
+
+MgReader* MgSelectFeatures::SelectFdoJoin(MgResourceIdentifier* featureSourceId, CREFSTRING extensionName, bool isAggregate)
+{
+    // TODO: This does not handle filters on the secondary side (yet)
+    // Can GwsQueryEngine do this?
+
+    Ptr<MgReader> ret;
+
+    MG_FEATURE_SERVICE_TRY()
+
+    //This could be qualified, so parse it to be sure
+    STRING schemaName;
+    STRING extName;
+    MgUtil::ParseQualifiedClassName(extensionName, schemaName, extName);
+
+    CHECKNULL(m_featureSourceCacheItem.p, L"MgServerSelectFeatures.SelectFdoJoin");
+    MdfModel::FeatureSource* featureSource = m_featureSourceCacheItem->Get();
+    MdfModel::ExtensionCollection* extensions = featureSource->GetExtensions();
+    CHECKNULL(extensions, L"MgServerSelectFeatures.SelectFdoJoin");
+
+    MdfModel::Extension* extension = NULL;
+    for (INT32 i = 0; i < extensions->GetCount(); i++) 
+    {
+        MdfModel::Extension* ext = extensions->GetAt(i);
+        if (ext->GetName() == extName)
+        {
+            extension = ext;
+            break;
+        }
+    }
+
+    CHECKNULL(extension, L"MgServerSelectFeatures.SelectFdoJoin");
+    m_command->SetFeatureClassName(extension->GetFeatureClass().c_str());
+    MdfModel::AttributeRelateCollection* relates = extension->GetAttributeRelates();
+    CHECKNULL(relates, L"MgServerSelectFeatures.SelectFdoJoin");
+    MdfModel::AttributeRelate* relate = relates->GetAt(0);
+
+    const MdfModel::MdfString& prefix = relate->GetName();
+
+    STRING primaryAlias = PRIMARY_ALIAS;
+    STRING secondaryAlias = SECONDARY_ALIAS;
+
+    FdoPtr<FdoJoinCriteriaCollection> joinCriteria;
+    if (isAggregate)
+    {
+        MgSelectAggregateCommand* cmd = static_cast<MgSelectAggregateCommand*>(m_command.p);
+        cmd->SetAlias(primaryAlias.c_str());
+        joinCriteria = cmd->GetJoinCriteria();
+    }
+    else
+    {
+        MgSelectCommand* cmd = static_cast<MgSelectCommand*>(m_command.p);
+        cmd->SetAlias(primaryAlias.c_str());
+        joinCriteria = cmd->GetJoinCriteria();
+    }
+
+    Ptr<MgStringCollection> idPropNames = new MgStringCollection();
+    Ptr<MgFeatureConnection> conn = new MgFeatureConnection(featureSourceId);
+    {
+        if (!conn->IsConnectionOpen())
+        {
+            throw new MgConnectionFailedException(L"MgServerSelectFeatures.SelectFdoJoin", __LINE__, __WFILE__, NULL, L"", NULL);
+        }
+
+        CHECKNULL(m_command, L"MgServerSelectFeatures.SelectFdoJoin");
+        FdoPtr<FdoIConnection> fdoConn = conn->GetConnection();
+
+        bool bAppliedProperties = false;
+        if (m_options != NULL)
+        {
+            //ApplyClassProperties();
+            ApplyComputedProperties();
+            // TODO: We need to find out if there are any filters involving the secondary side
+            ApplyFilter();
+            // ApplySpatialFilter();
+            ApplyOrderingOptions();
+            // We don't apply aggregate options here because these go through the FDO Expression Engine
+            ApplyAggregateOptions(isAggregate);
+            ApplyFetchSize();
+
+            //If an explicit list is specified, we assume the caller knows about prefixed
+            //extended feature class properties.
+            Ptr<MgStringCollection> props = m_options->GetClassProperties();
+            if (props->GetCount() > 0)
+            {
+                ApplyClassProperties();
+                bAppliedProperties = true;
+            }
+        }
+
+        //We need to fetch full class definitions of primary and secondary classes
+        if (!bAppliedProperties)
+        {
+            //Add primary class properties
+            STRING primaryClass = extension->GetFeatureClass();
+            STRING primarySchemaName;
+            STRING primaryClassName;
+            MgUtil::ParseQualifiedClassName(primaryClass, primarySchemaName, primaryClassName);
+
+            ApplyClassProperties(fdoConn, primarySchemaName, primaryClassName, idPropNames, primaryAlias);
+
+            if (!isAggregate)
+            {
+                //Add secondary class properties
+                STRING joinClass = relate->GetAttributeClass();
+                STRING joinSchemaName;
+                STRING joinClassName;
+                MgUtil::ParseQualifiedClassName(joinClass, joinSchemaName, joinClassName);
+
+                ApplyClassProperties(fdoConn, joinSchemaName, joinClassName, NULL, secondaryAlias, prefix); 
+            }
+        }
+    }
+
+    //Set join type
+    FdoJoinType jtype = FdoJoinType_None;
+    switch(relate->GetRelateType())
+    {
+    case MdfModel::AttributeRelate::Inner:
+        jtype = FdoJoinType_Inner;
+        break;
+    case MdfModel::AttributeRelate::LeftOuter:
+        jtype = FdoJoinType_LeftOuter;
+        break;
+    case MdfModel::AttributeRelate::RightOuter:
+        jtype = FdoJoinType_RightOuter;
+        break;
+    }
+
+    bool bForceOneToOne = relate->GetForceOneToOne();
+    //Set filter for this join
+    STRING secondaryClass = relate->GetAttributeClass();
+    STRING filterText;
+    MdfModel::RelatePropertyCollection* relProps = relate->GetRelateProperties();
+    for (INT32 i = 0; i < relProps->GetCount(); i++)
+    {
+        MdfModel::RelateProperty* prop = relProps->GetAt(i);
+        if (!filterText.empty())
+        {
+            filterText += L" AND ";
+        }
+
+        //[primaryAlias].[PropertyName] = [secondaryAlias].[PropertyName]
+        filterText += primaryAlias;
+        filterText += L".";
+        filterText += prop->GetFeatureClassProperty();
+        filterText += L" = ";
+        filterText += secondaryAlias;
+        filterText += L".";
+        filterText += prop->GetAttributeClassProperty();
+    }
+
+    FdoPtr<FdoJoinCriteria> criteria;
+    FdoPtr<FdoIdentifier> idJoinClass = FdoIdentifier::Create(secondaryClass.c_str());
+    FdoPtr<FdoFilter> filter = FdoFilter::Parse(filterText.c_str());
+    if (prefix.empty())
+        criteria = FdoJoinCriteria::Create(idJoinClass, jtype, filter);
+    else
+        criteria = FdoJoinCriteria::Create(secondaryAlias.c_str(), idJoinClass, jtype, filter);
+
+    joinCriteria->Add(criteria);
+
+    if (isAggregate)
+        ret = ((MgSelectAggregateCommand*)m_command.p)->ExecuteJoined(idPropNames, bForceOneToOne);
+    else
+        ret = ((MgSelectCommand*)m_command.p)->ExecuteJoined(idPropNames, bForceOneToOne);
+
+    MG_FEATURE_SERVICE_CATCH_AND_THROW(L"MgServerSelectFeatures.SelectFdoJoin")
+
+    return ret.Detach();
+}
+
+void MgSelectFeatures::ApplyAggregateCommandJoinFilterAndCriteria(MgResourceIdentifier* featureSourceId, CREFSTRING extensionName)
+{
+#ifdef DEBUG_FDO_JOIN
+    ACE_DEBUG((LM_INFO, ACE_TEXT("\n\t(%t) Applying FDO join criteria and filter to aggregate command")));
+#endif
+
+     //This could be qualified, so parse it to be sure
+    STRING schemaName;
+    STRING extName;
+    MgUtil::ParseQualifiedClassName(extensionName, schemaName, extName);
+
+    CHECKNULL(m_featureSourceCacheItem.p, L"MgServerSelectFeatures.SupportsFdoJoin");
+    MdfModel::FeatureSource* featureSource = m_featureSourceCacheItem->Get();
+    MdfModel::ExtensionCollection* extensions = featureSource->GetExtensions();
+    CHECKNULL(extensions, L"MgServerSelectFeatures.SupportsFdoJoin");
+
+    MdfModel::Extension* extension = NULL;
+    for (INT32 i = 0; i < extensions->GetCount(); i++) 
+    {
+        MdfModel::Extension* ext = extensions->GetAt(i);
+        if (ext->GetName() == extName)
+        {
+            extension = ext;
+            break;
+        }
+    }
+
+    CHECKNULL(extension, L"MgServerSelectFeatures.SelectFdoJoin");
+    m_command->SetFeatureClassName(extension->GetFeatureClass().c_str());
+    MdfModel::AttributeRelateCollection* relates = extension->GetAttributeRelates();
+    CHECKNULL(relates, L"MgServerSelectFeatures.SelectFdoJoin");
+    MdfModel::AttributeRelate* relate = relates->GetAt(0);
+
+    const MdfModel::MdfString& prefix = relate->GetName();
+
+    STRING primaryAlias = PRIMARY_ALIAS;
+    STRING secondaryAlias = SECONDARY_ALIAS;
+
+    MgSelectAggregateCommand* extSelect = static_cast<MgSelectAggregateCommand*>(m_command.p);
+    extSelect->SetAlias(primaryAlias.c_str());
+
+    FdoPtr<FdoJoinCriteriaCollection> joinCriteria = extSelect->GetJoinCriteria();
+
+    //Set join type
+    FdoJoinType jtype = FdoJoinType_None;
+    switch(relate->GetRelateType())
+    {
+    case MdfModel::AttributeRelate::Inner:
+        jtype = FdoJoinType_Inner;
+        break;
+    case MdfModel::AttributeRelate::LeftOuter:
+        jtype = FdoJoinType_LeftOuter;
+        break;
+    case MdfModel::AttributeRelate::RightOuter:
+        jtype = FdoJoinType_RightOuter;
+        break;
+    }
+
+    bool bForceOneToOne = relate->GetForceOneToOne();
+    //Set filter for this join
+    STRING secondaryClass = relate->GetAttributeClass();
+    STRING filterText;
+    MdfModel::RelatePropertyCollection* relProps = relate->GetRelateProperties();
+    for (INT32 i = 0; i < relProps->GetCount(); i++)
+    {
+        MdfModel::RelateProperty* prop = relProps->GetAt(i);
+        if (!filterText.empty())
+        {
+            filterText += L" AND ";
+        }
+
+        //[primaryAlias].[PropertyName] = [secondaryAlias].[PropertyName]
+        filterText += primaryAlias;
+        filterText += L".";
+        filterText += prop->GetFeatureClassProperty();
+        filterText += L" = ";
+        filterText += secondaryAlias;
+        filterText += L".";
+        filterText += prop->GetAttributeClassProperty();
+    }
+
+    FdoPtr<FdoJoinCriteria> criteria;
+    FdoPtr<FdoIdentifier> idJoinClass = FdoIdentifier::Create(secondaryClass.c_str());
+    FdoPtr<FdoFilter> filter = FdoFilter::Parse(filterText.c_str());
+    if (prefix.empty())
+        criteria = FdoJoinCriteria::Create(idJoinClass, jtype, filter);
+    else
+        criteria = FdoJoinCriteria::Create(secondaryAlias.c_str(), idJoinClass, jtype, filter);
+
+    joinCriteria->Add(criteria);
+}
+
+void MgSelectFeatures::ApplyClassProperties(FdoIConnection* fdoConn, CREFSTRING schemaName, CREFSTRING className, MgStringCollection* idPropNames, CREFSTRING alias, CREFSTRING prefix)
+{
+    FdoPtr<FdoIDescribeSchema> descSchema = dynamic_cast<FdoIDescribeSchema*>(fdoConn->CreateCommand(FdoCommandType_DescribeSchema));
+    CHECKNULL((FdoIDescribeSchema*)descSchema, L"MgServerSelectFeatures.SelectFdoJoin");
+
+    if (!schemaName.empty())
+    {
+        descSchema->SetSchemaName(schemaName.c_str());
+    }
+    if (!className.empty())
+    {
+        FdoPtr<FdoStringCollection> classNames = FdoStringCollection::Create();
+        classNames->Add(className.c_str());
+        descSchema->SetClassNames(classNames);
+    }
+
+    FdoPtr<FdoClassDefinition> classDef;
+    FdoPtr<FdoFeatureSchemaCollection> schemas = descSchema->Execute();
+    for (FdoInt32 i = 0; i < schemas->GetCount(); i++)
+    {
+        FdoPtr<FdoFeatureSchema> schema = schemas->GetItem(i);
+        if (wcscmp(schema->GetName(), schemaName.c_str()) == 0) 
+        {
+            FdoPtr<FdoClassCollection> classes = schema->GetClasses();
+            for (FdoInt32 j = 0; j < classes->GetCount(); j++) 
+            {
+                FdoPtr<FdoClassDefinition> klassDef = classes->GetItem(j);
+                if (wcscmp(klassDef->GetName(), className.c_str()) == 0)
+                {
+                    classDef = SAFE_ADDREF(klassDef.p);
+                    break;
+                }
+            }
+        }
+    }
+
+    if (NULL == (FdoClassDefinition*)classDef)
+    {
+        //TODO: Refine message if available
+        throw new MgClassNotFoundException(L"MgServerSelectFeatures.ApplyClassProperties", __LINE__, __WFILE__, NULL, L"", NULL);
+    }
+
+    FdoPtr<FdoIdentifierCollection> propNames = m_command->GetPropertyNames();
+
+    //Add primary class properties
+    FdoPtr<FdoPropertyDefinitionCollection> propDefs = classDef->GetProperties();
+    for (FdoInt32 i = 0; i < propDefs->GetCount(); i++) 
+    {
+        FdoPtr<FdoPropertyDefinition> propDef = propDefs->GetItem(i);
+
+        //Skip ones that aren't data/geometry
+        if (propDef->GetPropertyType() != FdoPropertyType_DataProperty &&
+            propDef->GetPropertyType() != FdoPropertyType_GeometricProperty)
+            continue;
+
+        STRING exprText = alias + L".";
+        exprText += propDef->GetName();
+
+        FdoPtr<FdoExpression> expr = FdoExpression::Parse(exprText.c_str());
+        STRING idName = prefix + propDef->GetName();
+        //[alias].[propertyName] AS [prefix][propertyName]
+        FdoPtr<FdoComputedIdentifier> compId = FdoComputedIdentifier::Create(idName.c_str(), expr);
+
+        propNames->Add(compId);
+    }
+
+    if (NULL != idPropNames)
+    {
+        FdoPtr<FdoDataPropertyDefinitionCollection> idPropDefs = classDef->GetIdentityProperties();
+        for (FdoInt32 i = 0; i < idPropDefs->GetCount(); i++)
+        {
+            FdoPtr<FdoDataPropertyDefinition> dp = idPropDefs->GetItem(i);
+            STRING propName = L"";
+            propName += dp->GetName();
+            idPropNames->Add(propName);
+        }
+    }
+}

Added: branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/SelectFeatures.h
===================================================================
--- branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/SelectFeatures.h	                        (rev 0)
+++ branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/SelectFeatures.h	2012-07-15 16:59:27 UTC (rev 6903)
@@ -0,0 +1,104 @@
+//
+//  Copyright (C) 2004-2011 by Autodesk, Inc.
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of version 2.1 of the GNU Lesser
+//  General Public License as published by the Free Software Foundation.
+//
+//  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 St, Fifth Floor, Boston, MA  02110-1301  USA
+//
+
+#ifndef DESKTOP_SELECT_FEATURES_H_
+#define DESKTOP_SELECT_FEATURES_H_
+
+#include "MgDesktop.h"
+#include "System/XmlDefs.h"
+#include "System/XmlUtil.h"
+#include "Fdo.h"
+#include "Services/Feature/GwsFeatureReader.h"
+
+class MgFeatureQueryOptions;
+class MgFeatureServiceCommand;
+template class Ptr<MgFeatureSourceCacheItem>;
+
+class MgSelectFeatures
+{
+public:
+    MgSelectFeatures();
+    ~MgSelectFeatures();
+    MgReader* SelectFeatures(MgResourceIdentifier* resource,
+                             CREFSTRING className,
+                             MgFeatureQueryOptions* options,
+                             bool isSelectAggregate);
+
+private:
+    void  ApplyQueryOptions(bool isSelectAggregate);
+    void  ApplyClassProperties();
+    void  ApplyComputedProperties();
+    void  ApplyFilter();
+    // void  ApplySpatialFilter();
+    void  ApplyOrderingOptions();
+    void  ApplyFetchSize();
+
+    //bool HasCustomProperty() { return m_customPropertyFound; }
+    //FdoFunction* GetCustomFunction() { return FDO_SAFE_ADDREF(m_customFunction); }
+    //STRING GetCustomPropertyName() { return m_customPropertyName; }
+
+    bool IsFdoSupportedFunction(FdoIConnection* connection, FdoFunction* fdoFunc);
+    bool ContainsUdf(FdoExpression* expression);
+    bool IsCustomFunction(FdoFunction* fdoFunc);
+    void AddFdoComputedProperty(CREFSTRING aliasName, FdoExpression* expression);
+    void AddCustomComputedProperty(CREFSTRING aliasName, FdoExpression* expression);
+    void ValidateConstraintsOnCustomFunctions();
+    void ApplyAggregateOptions(bool isSelectAggregate);
+    void CreateCommand(MgResourceIdentifier* resource, bool isSelectAggregate);
+    void ValidateParam(MgResourceIdentifier* resource, CREFSTRING className);
+    void ApplyFdoGroupingProperties(MgStringCollection* propertyNames);
+    bool ContainsCustomFunction(MgFeatureQueryOptions* options);
+    MgReader* GetCustomReader(MgReader* reader);
+
+    // STRING                  m_providerName;
+    STRING                  className;
+    Ptr<MgStringCollection> properties;
+    Ptr<MgFeatureQueryOptions> m_options;
+    STRING                  filterText;
+    Ptr<MgFeatureServiceCommand>    m_command;
+
+    Ptr<MgFeatureSourceCacheItem> m_featureSourceCacheItem;
+
+    // Only one custom property is supported. No nesting of custom properties allowed.
+    STRING                  m_customPropertyName;
+    bool                    m_customPropertyFound;
+    FdoPtr<FdoFunction>     m_customFunction;
+
+    // Methods for Feature Join
+    bool FindFeatureJoinProperties(MgResourceIdentifier* resourceId, CREFSTRING extensionName);
+    bool FindFeatureCalculation(MgResourceIdentifier* resourceId, CREFSTRING extensionName);
+    MgdGwsFeatureReader* JoinFeatures(MgResourceIdentifier* featureSourceId, CREFSTRING extensionName, FdoFilter* filter);
+    void UpdateCommandOnCalculation(MgResourceIdentifier* featureSourceId, CREFSTRING extensionName);
+    void UpdateCommandOnJoinCalculation(MgResourceIdentifier* featureSourceId, CREFSTRING extensionName);
+    void ParseQualifiedClassNameForCalculation(MdfModel::Extension* extension, CREFSTRING qualifiedClassName, STRING& schemaName, STRING& className);
+    MgResourceIdentifier* GetSecondaryResourceIdentifier(MgResourceIdentifier* primResId, CREFSTRING extensionName, CREFSTRING relationName);
+
+    // This setting limits the batch size used by the join query algorithm
+    INT32 m_nJoinQueryBatchSize;
+
+    INT32 m_nDataCacheSize;
+
+    // FDO join optimization
+    bool IsFunctionOnPrimaryProperty(FdoFunction* function, FdoIConnection* conn, CREFSTRING schemaName, CREFSTRING className);
+    bool SupportsFdoJoin(MgResourceIdentifier* featureSourceId, CREFSTRING extension, bool isAggregate);
+    MgReader* SelectFdoJoin(MgResourceIdentifier* featureSourceId, CREFSTRING extension, bool isAggregate);
+    void ApplyAggregateCommandJoinFilterAndCriteria(MgResourceIdentifier* featureSourceId, CREFSTRING extension);
+    void ApplyClassProperties(FdoIConnection* fdoConn, CREFSTRING schemaName, CREFSTRING className, MgStringCollection* idPropNames, CREFSTRING alias, CREFSTRING prefix = L"");
+    bool FilterContainsSecondaryProperties(MgResourceIdentifier* featureSourceId, CREFSTRING filter, STRING secondarySchema, STRING secondaryClassName, STRING secondaryPrefix);
+};
+
+#endif

Added: branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/SqlCommand.cpp
===================================================================
--- branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/SqlCommand.cpp	                        (rev 0)
+++ branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/SqlCommand.cpp	2012-07-15 16:59:27 UTC (rev 6903)
@@ -0,0 +1,188 @@
+//
+//  Copyright (C) 2004-2011 by Autodesk, Inc.
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of version 2.1 of the GNU Lesser
+//  General Public License as published by the Free Software Foundation.
+//
+//  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 St, Fifth Floor, Boston, MA  02110-1301  USA
+//
+
+#include "Services/Feature/FeatureDefs.h"
+#include "Services/FeatureService.h"
+#include "SqlCommand.h"
+#include "Services/Feature/FeatureConnection.h"
+#include "Services/SqlDataReader.h"
+#include "Services/Feature/FeatureUtil.h"
+#include "Services/Transaction.h"
+
+MgServerSqlCommand::MgServerSqlCommand()
+{
+}
+
+MgServerSqlCommand::~MgServerSqlCommand()
+{
+    MG_TRY()
+
+    CloseConnection();
+
+    MG_CATCH_AND_RELEASE()
+}
+
+void MgServerSqlCommand::CloseConnection()
+{
+    // The FDO connection must be released before the parent object is released
+    m_fdoConn = NULL;
+    m_featureConnection = NULL;
+}
+
+// Executes the describe schema command and serializes the schema to XML
+MgSqlDataReader* MgServerSqlCommand::ExecuteQuery(
+    MgResourceIdentifier* resource,
+    CREFSTRING sqlStatement,
+    MgParameterCollection* params,
+    MgTransaction* transaction,
+    INT32 fetchSize)
+{
+    Ptr<MgSqlDataReader> mgSqlDataReader;
+
+    MG_FEATURE_SERVICE_TRY()
+
+    // If validation does succeeds, it will throw exception
+    Validate(resource, sqlStatement, FdoCommandType_SQLCommand, transaction);
+
+    // Create the SQL command
+    FdoPtr<FdoISQLCommand> fdoCommand = (FdoISQLCommand*)m_fdoConn->CreateCommand(FdoCommandType_SQLCommand);
+    CHECKNULL((FdoISQLCommand*)fdoCommand, L"MgServerSqlCommand.ExecuteQuery");
+
+    // Set SQL statement
+    fdoCommand->SetSQLStatement((FdoString*)sqlStatement.c_str());
+
+    // Set fetch size
+    fdoCommand->SetFetchSize(fetchSize);
+
+    // Set parameters
+    FdoPtr<FdoParameterValueCollection> fdoParams = NULL;
+    if (NULL != params && params->GetCount() > 0)
+    {
+        fdoParams = fdoCommand->GetParameterValues();
+        MgFeatureUtil::FillFdoParameterCollection(params, fdoParams);
+    }
+
+    // Execute the command
+    FdoPtr<FdoISQLDataReader> sqlReader = fdoCommand->ExecuteReader();
+    CHECKNULL((FdoISQLDataReader*)sqlReader, L"MgServerSqlCommand.ExecuteQuery");
+
+    // Update parameter whose direction is InputOutput, Output, or Return.
+    if (NULL != params && params->GetCount() > 0)
+        MgFeatureUtil::UpdateParameterCollection(fdoParams, params);
+
+    mgSqlDataReader = new MgdSqlDataReader(m_featureConnection, sqlReader); //, m_providerName);
+    CHECKNULL((MgSqlDataReader*)mgSqlDataReader, L"MgServerSqlCommand.ExecuteQuery");
+
+    MG_FEATURE_SERVICE_CHECK_CONNECTION_CATCH_AND_THROW(resource, L"MgServerSqlCommand.ExecuteQuery")
+
+    return mgSqlDataReader.Detach();
+}
+
+// Executes the describe schema command and serializes the schema to XML
+INT32 MgServerSqlCommand::ExecuteNonQuery(
+    MgResourceIdentifier* resource,
+    CREFSTRING sqlStatement,
+    MgParameterCollection* params,
+    MgTransaction* transaction)
+{
+    INT32 rowsAffected = 0;
+
+    MG_FEATURE_SERVICE_TRY()
+
+    // If validation does succeeds, it will throw exception
+    Validate(resource, sqlStatement, FdoCommandType_SQLCommand, transaction);
+
+    // Create the SQL command
+    FdoPtr<FdoISQLCommand> fdoCommand = (FdoISQLCommand*)m_fdoConn->CreateCommand(FdoCommandType_SQLCommand);
+    CHECKNULL((FdoISQLCommand*)fdoCommand, L"MgServerSqlCommand.ExecuteQuery");
+
+    // Set SQL statement
+    fdoCommand->SetSQLStatement((FdoString*)sqlStatement.c_str());
+
+    // Set parameters
+    FdoPtr<FdoParameterValueCollection> fdoParams = NULL;
+    if (NULL != params && params->GetCount() > 0)
+    {
+        fdoParams = fdoCommand->GetParameterValues();
+        MgFeatureUtil::FillFdoParameterCollection(params, fdoParams);
+    }
+
+    // Execute the command
+    rowsAffected = fdoCommand->ExecuteNonQuery();
+
+    // Update parameter whose direction is InputOutput, Output, or Return.
+    if (NULL != params && params->GetCount() > 0)
+        MgFeatureUtil::UpdateParameterCollection(fdoParams, params);
+
+    MG_FEATURE_SERVICE_CHECK_CONNECTION_CATCH_AND_THROW(resource, L"MgServerSqlCommand.ExecuteQuery")
+
+    return rowsAffected;
+}
+
+
+void MgServerSqlCommand::Validate(MgResourceIdentifier* resource, CREFSTRING sqlStatement, INT32 commandType, MgTransaction* transaction)
+{
+    // SQL statement can not be empty
+    if (resource == NULL)
+    {
+        throw new MgNullArgumentException(L"MgServerSqlCommand.Validate", __LINE__, __WFILE__, NULL, L"", NULL);
+    }
+
+    if (sqlStatement.empty())
+    {
+        MgStringCollection arguments;
+        arguments.Add(L"2");
+        arguments.Add(MgResources::BlankArgument);
+
+        throw new MgInvalidArgumentException(L"MgServerSqlCommand.Validate",
+            __LINE__, __WFILE__, &arguments, L"MgStringEmpty", NULL);
+    }
+
+    // Close any previously opened connection.
+    CloseConnection();
+
+    // Connect to provider
+    if (NULL != transaction)
+    {
+        // grab the connection used to start the transaction.
+        MgdTransaction* featureTransaction = static_cast<MgdTransaction*>(transaction);
+        m_featureConnection = featureTransaction->GetConnection();
+    }
+    else
+    {
+        // No transaction, grab the connection as usual.
+        m_featureConnection = new MgFeatureConnection(resource);
+    }
+
+    if (m_featureConnection->IsConnectionOpen() )
+    {
+        m_fdoConn = m_featureConnection->GetConnection();
+        m_providerName = m_featureConnection->GetProviderName();
+
+        // Check whether command is supported by provider
+        if (!m_featureConnection->SupportsCommand(commandType))
+        {
+            // TODO: specify which argument and message, once we have the mechanism
+            STRING message = MgFeatureUtil::GetMessage(L"MgCommandNotSupported");
+            throw new MgInvalidOperationException(L"MgServerSqlCommand.Validate", __LINE__, __WFILE__, NULL, L"", NULL);
+        }
+    }
+    else
+    {
+        throw new MgConnectionFailedException(L"MgServerSqlCommand::Validate", __LINE__, __WFILE__, NULL, L"", NULL);
+    }
+}

Added: branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/SqlCommand.h
===================================================================
--- branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/SqlCommand.h	                        (rev 0)
+++ branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/SqlCommand.h	2012-07-15 16:59:27 UTC (rev 6903)
@@ -0,0 +1,56 @@
+//
+//  Copyright (C) 2004-2011 by Autodesk, Inc.
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of version 2.1 of the GNU Lesser
+//  General Public License as published by the Free Software Foundation.
+//
+//  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 St, Fifth Floor, Boston, MA  02110-1301  USA
+//
+
+#ifndef _MG_SERVER_SQLCOMMAND_H_
+#define _MG_SERVER_SQLCOMMAND_H_
+
+#include "MgDesktop.h"
+#include "System/XmlDefs.h"
+#include "System/XmlUtil.h"
+#include "Fdo.h"
+
+class MgFeatureConnection;
+
+class MgServerSqlCommand
+{
+public:
+    MgServerSqlCommand();
+    ~MgServerSqlCommand();
+    MgSqlDataReader* ExecuteQuery(
+                        MgResourceIdentifier* resource,
+                        CREFSTRING sqlStatement,
+                        MgParameterCollection* params,
+                        MgTransaction* transaction,
+                        INT32 fetchSize = 0);
+    INT32 ExecuteNonQuery(
+                        MgResourceIdentifier* resource,
+                        CREFSTRING sqlStatement,
+                        MgParameterCollection* params,
+                        MgTransaction* transaction);
+
+private:
+    void Validate(MgResourceIdentifier* resource, CREFSTRING sqlStatement, INT32 commandType, MgTransaction* transaction);
+    void CloseConnection();
+
+private:
+    STRING                  m_providerName;
+    STRING                  m_sqlStatement;
+    FdoPtr<FdoIConnection> m_fdoConn;
+    Ptr<MgFeatureConnection> m_featureConnection;
+};
+
+#endif

Added: branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/UpdateCommand.cpp
===================================================================
--- branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/UpdateCommand.cpp	                        (rev 0)
+++ branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/UpdateCommand.cpp	2012-07-15 16:59:27 UTC (rev 6903)
@@ -0,0 +1,73 @@
+//
+//  Copyright (C) 2004-2011 by Autodesk, Inc.
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of version 2.1 of the GNU Lesser
+//  General Public License as published by the Free Software Foundation.
+//
+//  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 St, Fifth Floor, Boston, MA  02110-1301  USA
+//
+
+#include "Services/Feature/FeatureDefs.h"
+#include "MgDesktop.h"
+#include "Services/FeatureService.h"
+#include "Services/Feature/FeatureConnection.h"
+#include "FeatureManipulationCommand.h"
+#include "UpdateCommand.h"
+#include "Services/Feature/FeatureUtil.h"
+#include "Services/FeatureReader.h"
+
+MgServerUpdateCommand::MgServerUpdateCommand()
+{
+    m_srvrFeatConn = NULL;
+    m_featCommand = NULL;
+}
+
+MgServerUpdateCommand::MgServerUpdateCommand(MgFeatureCommand* command, MgFeatureConnection* connection, INT32 cmdId)
+{
+    CHECKNULL(command, L"MgServerUpdateCommand.MgServerUpdateCommand");
+    CHECKNULL(connection, L"MgServerUpdateCommand.MgServerUpdateCommand");
+
+    m_srvrFeatConn = SAFE_ADDREF((MgFeatureConnection*)connection);
+    m_featCommand = SAFE_ADDREF((MgUpdateFeatures*)command);
+    m_cmdId = cmdId;
+}
+
+MgServerUpdateCommand::~MgServerUpdateCommand()
+{
+    m_srvrFeatConn = NULL;
+}
+
+MgProperty* MgServerUpdateCommand::Execute()
+{
+    STRING clsName = m_featCommand->GetFeatureClassName();
+    STRING filterText = m_featCommand->GetFilterText();
+    Ptr<MgPropertyCollection> propCol = m_featCommand->GetPropertyValues();
+
+    FdoPtr<FdoIConnection> fdoConn = m_srvrFeatConn->GetConnection();
+
+    // Create the SQL command
+    FdoPtr<FdoIUpdate> fdoCommand = (FdoIUpdate*)fdoConn->CreateCommand(FdoCommandType_Update);
+    CHECKNULL((FdoIUpdate*)fdoCommand, L"MgServerUpdateCommand.Execute");
+
+    fdoCommand->SetFeatureClassName(clsName.c_str());
+    fdoCommand->SetFilter(filterText.c_str());
+
+    FdoPtr<FdoPropertyValueCollection> paramValCol = fdoCommand->GetPropertyValues();
+    MgFeatureUtil::FillFdoPropertyCollection(propCol, paramValCol);
+
+    INT32 recordsUpdated = fdoCommand->Execute();
+
+    char buff[32];
+    sprintf(buff, "%d", m_cmdId);
+    STRING str = MgUtil::MultiByteToWideChar(string(buff));
+
+    return new MgInt32Property(str, recordsUpdated);
+}

Added: branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/UpdateCommand.h
===================================================================
--- branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/UpdateCommand.h	                        (rev 0)
+++ branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/UpdateCommand.h	2012-07-15 16:59:27 UTC (rev 6903)
@@ -0,0 +1,39 @@
+//
+//  Copyright (C) 2004-2011 by Autodesk, Inc.
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of version 2.1 of the GNU Lesser
+//  General Public License as published by the Free Software Foundation.
+//
+//  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 St, Fifth Floor, Boston, MA  02110-1301  USA
+//
+
+#ifndef _MG_SERVER_UPDATE_COMMAND_H_
+#define _MG_SERVER_UPDATE_COMMAND_H_
+
+class MgFeatureConnection;
+
+class MgServerUpdateCommand : public MgFeatureManipulationCommand
+{
+    DECLARE_CLASSNAME(MgServerUpdateCommand)
+
+public:
+    MgServerUpdateCommand(MgFeatureCommand* command, MgFeatureConnection* connection, INT32 cmdId);
+    virtual MgProperty* Execute();
+protected:
+    MgServerUpdateCommand();
+    ~MgServerUpdateCommand();
+private:
+    Ptr<MgUpdateFeatures> m_featCommand;
+    Ptr<MgFeatureConnection> m_srvrFeatConn;
+    INT32 m_cmdId;
+};
+
+#endif

Added: branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/UpdateFeatures.cpp
===================================================================
--- branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/UpdateFeatures.cpp	                        (rev 0)
+++ branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/UpdateFeatures.cpp	2012-07-15 16:59:27 UTC (rev 6903)
@@ -0,0 +1,221 @@
+//
+//  Copyright (C) 2004-2011 by Autodesk, Inc.
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of version 2.1 of the GNU Lesser
+//  General Public License as published by the Free Software Foundation.
+//
+//  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 St, Fifth Floor, Boston, MA  02110-1301  USA
+//
+
+#include "Services/Feature/FeatureDefs.h"
+#include "Services/FeatureService.h"
+#include "Services/Feature/FeatureConnection.h"
+#include "UpdateFeatures.h"
+#include "Services/Feature/FeatureUtil.h"
+#include "FeatureManipulationCommand.h"
+#include "Services/Feature/FeatureServiceCache.h"
+#include "Services/Transaction.h"
+
+MgServerUpdateFeatures::MgServerUpdateFeatures()
+{
+    m_SrvrFeatConn = NULL;
+}
+
+MgServerUpdateFeatures::~MgServerUpdateFeatures()
+{
+}
+
+void MgServerUpdateFeatures::Connect(MgResourceIdentifier* resource, MgTransaction* transaction)
+{
+    if (NULL == transaction)
+    {
+        m_SrvrFeatConn = new MgFeatureConnection(resource);
+    }
+    else
+    {
+        MgdTransaction* featTransaction = static_cast<MgdTransaction*>(transaction);
+        m_SrvrFeatConn = featTransaction->GetConnection();
+    }
+
+    if ((NULL != m_SrvrFeatConn.p) && ( !m_SrvrFeatConn->IsConnectionOpen() ))
+    {
+
+        throw new MgConnectionFailedException(L"MgServerUpdateFeatures::MgServerUpdateFeatures()",
+            __LINE__, __WFILE__, NULL, L"", NULL);
+    }
+}
+
+// Executes the commands
+MgPropertyCollection* MgServerUpdateFeatures::Execute(MgResourceIdentifier* resource,
+                                                      MgFeatureCommandCollection* commands,
+                                                      bool useTransaction)
+{
+    Ptr<MgPropertyCollection> propCol;
+    FdoITransaction* transaction = NULL;
+    bool commited = false;
+
+    MG_FEATURE_SERVICE_TRY()
+
+    if (resource == NULL || commands == NULL)
+    {
+        throw new MgNullArgumentException(L"MgServerUpdateFeatures.UpdateFeatures", __LINE__, __WFILE__, NULL, L"", NULL);
+    }
+
+    INT32 cnt = commands->GetCount();
+    if (cnt == 0)
+    {
+        MgStringCollection arguments;
+        arguments.Add(L"2");
+        arguments.Add(L"0");
+
+        throw new MgInvalidArgumentException(L"MgServerUpdateFeatures.UpdateFeatures",
+            __LINE__, __WFILE__, &arguments, L"MgCollectionEmpty", NULL);
+    }
+
+    // Connect to provider
+    Connect(resource, NULL);
+
+    propCol = new MgPropertyCollection();
+
+    FdoPtr<FdoIConnection> fdoConn = m_SrvrFeatConn->GetConnection();
+    if (useTransaction)
+    {
+        transaction = fdoConn->BeginTransaction();
+    }
+
+    for (INT32 i = 0; i < cnt; i++)
+    {
+        Ptr<MgProperty> result;
+        Ptr<MgFeatureCommand> command = commands->GetItem(i);
+        Ptr<MgFeatureManipulationCommand> fmServerCommand = MgFeatureManipulationCommand::CreateCommand(command, m_SrvrFeatConn, i);
+
+        MG_FEATURE_SERVICE_TRY()
+        // Execute the manipulation command
+        result = fmServerCommand->Execute();
+
+        MG_FEATURE_SERVICE_CATCH(L"MgServerUpdateFeatures.UpdateFeatures")
+
+        if (transaction != NULL)
+        {
+            MG_FEATURE_SERVICE_THROW() // rethrow if updates are done in transaction
+        }
+        else
+        {
+            if (mgException != NULL)
+            {
+                // When an exception is thrown, we need to communicate this back to user in non-transactional case.
+                // We can do this either by setting warnings or a string property. Making it as StringProperty would
+                // let users know exactly which ones failed and why.
+                STRING str;
+                MgUtil::Int32ToString(i, str);
+                STRING errMsg = mgException->GetDetails();
+
+                result = new MgStringProperty(str, errMsg);  // If there is an exception which means result would null from execute
+                mgException = NULL; // Release the pointer
+            }
+        }
+        // NULL property should not be added.
+        if (result != NULL)
+        {
+            propCol->Add(result);
+        }
+    }
+
+    if (transaction != NULL)
+    {
+        transaction->Commit();
+        commited = true;
+    }
+
+    MG_FEATURE_SERVICE_CHECK_CONNECTION_CATCH_AND_THROW(resource, L"MgServerUpdateFeatures.UpdateFeatures")
+
+    if (transaction != NULL && !commited)
+    {
+        transaction->Rollback();
+    }
+
+    MG_FEATURE_SERVICE_THROW()
+
+    return propCol.Detach();
+}
+
+// Executes the commands
+MgPropertyCollection* MgServerUpdateFeatures::Execute(MgResourceIdentifier* resource,
+                                                      MgFeatureCommandCollection* commands,
+                                                      MgTransaction* transaction)
+{
+    Ptr<MgPropertyCollection> propCol;
+
+    MG_FEATURE_SERVICE_TRY()
+
+    if (resource == NULL || commands == NULL)
+    {
+        throw new MgNullArgumentException(L"MgServerUpdateFeatures.UpdateFeatures", __LINE__, __WFILE__, NULL, L"", NULL);
+    }
+
+    INT32 cnt = commands->GetCount();
+    if (cnt == 0)
+    {
+        MgStringCollection arguments;
+        arguments.Add(L"2");
+        arguments.Add(L"0");
+
+        throw new MgInvalidArgumentException(L"MgServerUpdateFeatures.UpdateFeatures",
+            __LINE__, __WFILE__, &arguments, L"MgCollectionEmpty", NULL);
+    }
+
+    // Connect to provider
+    Connect(resource, transaction);
+
+    propCol = new MgPropertyCollection();
+
+    for (INT32 i = 0; i < cnt; i++)
+    {
+        Ptr<MgProperty> result;
+        Ptr<MgFeatureCommand> command = commands->GetItem(i);
+        Ptr<MgFeatureManipulationCommand> fmServerCommand = MgFeatureManipulationCommand::CreateCommand(command, m_SrvrFeatConn, i);
+
+        MG_FEATURE_SERVICE_TRY()
+        // Execute the manipulation command
+        result = fmServerCommand->Execute();
+
+        MG_FEATURE_SERVICE_CATCH(L"MgServerUpdateFeatures.UpdateFeatures")
+
+        if (transaction != NULL)
+        {
+            MG_FEATURE_SERVICE_THROW() // rethrow if updates are done in transaction
+        }
+        else
+        {
+            if (mgException != NULL)
+            {
+                // When an exception is thrown, we need to communicate this back to user in non-transactional case.
+                // We can do this either by setting warnings or a string property. Making it as StringProperty would
+                // let users know exactly which ones failed and why.
+                STRING str;
+                MgUtil::Int32ToString(i, str);
+                STRING errMsg = mgException->GetDetails();
+
+                result = new MgStringProperty(str, errMsg);  // If there is an exception which means result would null from execute
+                mgException = NULL; // Release the pointer
+            }
+        }
+        // NULL property should not be added.
+        if (result != NULL)
+        {
+            propCol->Add(result);
+        }
+    }
+
+    MG_FEATURE_SERVICE_CHECK_CONNECTION_CATCH_AND_THROW(resource, L"MgServerUpdateFeatures.UpdateFeatures")
+
+    return propCol.Detach();
+}

Added: branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/UpdateFeatures.h
===================================================================
--- branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/UpdateFeatures.h	                        (rev 0)
+++ branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/Commands/UpdateFeatures.h	2012-07-15 16:59:27 UTC (rev 6903)
@@ -0,0 +1,52 @@
+//
+//  Copyright (C) 2004-2011 by Autodesk, Inc.
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of version 2.1 of the GNU Lesser
+//  General Public License as published by the Free Software Foundation.
+//
+//  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 St, Fifth Floor, Boston, MA  02110-1301  USA
+//
+
+#ifndef _MG_SERVER_UPDATE_FEATURES_H_
+#define _MG_SERVER_UPDATE_FEATURES_H_
+
+#include "MgDesktop.h"
+#include "System/XmlDefs.h"
+#include "System/XmlUtil.h"
+#include "Fdo.h"
+
+class MgFeatureConnection;
+class MgFeatureCommandCollection;
+class MgIntCollection;
+
+class MgServerUpdateFeatures
+{
+public:
+    MgServerUpdateFeatures();
+    ~MgServerUpdateFeatures();
+    MgPropertyCollection* Execute(MgResourceIdentifier* resource,
+                                  MgFeatureCommandCollection* commands,
+                                  bool useTransaction);
+
+    MgPropertyCollection* Execute(MgResourceIdentifier* resource,
+                                  MgFeatureCommandCollection* commands,
+                                  MgTransaction* transaction);
+
+private:
+    void Connect(MgResourceIdentifier* resource, MgTransaction* transaction);
+
+private:
+
+    Ptr<MgFeatureConnection> m_SrvrFeatConn;
+    STRING m_providerName;
+};
+
+#endif

Added: branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/FdoFeatureReader.cpp
===================================================================
--- branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/FdoFeatureReader.cpp	                        (rev 0)
+++ branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/FdoFeatureReader.cpp	2012-07-15 16:59:27 UTC (rev 6903)
@@ -0,0 +1,470 @@
+//
+//  Copyright (C) 2004-2011 by Autodesk, Inc.
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of version 2.1 of the GNU Lesser
+//  General Public License as published by the Free Software Foundation.
+//
+//  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 St, Fifth Floor, Boston, MA  02110-1301  USA
+//
+
+#include "stdafx.h"
+#include <assert.h>
+#include "Fdo.h"
+#include "FdoCommon.h"
+#include "FdoFeatureReader.h"
+
+#include <limits>       // For quiet_NaN()
+using namespace std;
+
+
+// Class MgFdoFeatureReader
+MgFdoFeatureReader::MgFdoFeatureReader() : m_currentReaderId(-1)
+{
+    m_readerDepleted = false;
+    m_readerCollection = MgFdoReaderCollection::Create();
+}
+
+MgFdoFeatureReader::MgFdoFeatureReader(MgFdoReaderCollection *readerCollection) : m_currentReaderId(-1)
+{
+    m_readerDepleted = false;
+    m_readerCollection = FDO_SAFE_ADDREF(readerCollection);
+}
+
+MgFdoFeatureReader::~MgFdoFeatureReader()
+{
+    MG_TRY()
+
+    Close();
+
+    MG_CATCH_AND_RELEASE()
+}
+
+void MgFdoFeatureReader::Dispose()
+{
+    delete this;
+}
+
+FdoClassDefinition *MgFdoFeatureReader::GetClassDefinition()
+{
+    if (m_currentReader == NULL)
+    {
+        Initialize();
+    }
+
+    return m_currentReader->GetClassDefinition();
+}
+
+
+int MgFdoFeatureReader::GetDepth()
+{
+    if (m_currentReader == NULL)
+    {
+        Initialize();
+    }
+
+    return m_currentReader->GetDepth();
+}
+
+FdoString* MgFdoFeatureReader::GetPropertyName(FdoInt32 index)
+{
+    if (m_currentReader == NULL)
+    {
+        Initialize();
+    }
+
+    return m_currentReader->GetPropertyName(index);
+}
+
+FdoInt32 MgFdoFeatureReader::GetPropertyIndex(FdoString* propertyName)
+{
+    if (m_currentReader == NULL)
+    {
+        Initialize();
+    }
+
+    return m_currentReader->GetPropertyIndex(propertyName);
+}
+
+FdoIFeatureReader* MgFdoFeatureReader::GetFeatureObject( const wchar_t* propertyName )
+{
+    if (m_currentReader == NULL)
+    {
+        Initialize();
+    }
+
+    return m_currentReader->GetFeatureObject(propertyName);
+}
+
+FdoIFeatureReader* MgFdoFeatureReader::GetFeatureObject( FdoInt32 index )
+{
+    if (m_currentReader == NULL)
+    {
+        Initialize();
+    }
+
+    return m_currentReader->GetFeatureObject(index);
+}
+
+bool MgFdoFeatureReader::GetBoolean( const wchar_t *propertyName )
+{
+    if (m_currentReader == NULL)
+    {
+        Initialize();
+    }
+
+    return m_currentReader->GetBoolean(propertyName);
+}
+
+bool MgFdoFeatureReader::GetBoolean( FdoInt32 index )
+{
+    if (m_currentReader == NULL)
+    {
+        Initialize();
+    }
+
+    return m_currentReader->GetBoolean(index);
+}
+
+FdoByte MgFdoFeatureReader::GetByte( const wchar_t *propertyName )
+{
+    if (m_currentReader == NULL)
+    {
+        Initialize();
+    }
+
+    return m_currentReader->GetByte(propertyName);
+}
+
+FdoByte MgFdoFeatureReader::GetByte( FdoInt32 index )
+{
+    if (m_currentReader == NULL)
+    {
+        Initialize();
+    }
+
+    return m_currentReader->GetByte(index);
+}
+
+FdoDateTime MgFdoFeatureReader::GetDateTime( const wchar_t *propertyName )
+{
+    if (m_currentReader == NULL)
+    {
+        Initialize();
+    }
+
+    return m_currentReader->GetDateTime(propertyName);
+}
+
+FdoDateTime MgFdoFeatureReader::GetDateTime( FdoInt32 index )
+{
+    if (m_currentReader == NULL)
+    {
+        Initialize();
+    }
+
+    return m_currentReader->GetDateTime(index);
+}
+
+double MgFdoFeatureReader::GetDouble( const wchar_t *propertyName )
+{
+    if (m_currentReader == NULL)
+    {
+        Initialize();
+    }
+
+    return m_currentReader->GetDouble(propertyName);
+}
+
+double MgFdoFeatureReader::GetDouble( FdoInt32 index )
+{
+    if (m_currentReader == NULL)
+    {
+        Initialize();
+    }
+
+    return m_currentReader->GetDouble(index);
+}
+
+const wchar_t* MgFdoFeatureReader::GetString( const wchar_t *propertyName )
+{
+    if (m_currentReader == NULL)
+    {
+        Initialize();
+    }
+
+    return m_currentReader->GetString(propertyName);
+
+}
+
+const wchar_t* MgFdoFeatureReader::GetString( FdoInt32 index )
+{
+    if (m_currentReader == NULL)
+    {
+        Initialize();
+    }
+
+    return m_currentReader->GetString(index);
+
+}
+
+short MgFdoFeatureReader::GetInt16( const wchar_t *propertyName )
+{
+    if (m_currentReader == NULL)
+    {
+        Initialize();
+    }
+
+    return m_currentReader->GetInt16(propertyName);
+}
+
+short MgFdoFeatureReader::GetInt16( FdoInt32 index )
+{
+    if (m_currentReader == NULL)
+    {
+        Initialize();
+    }
+
+    return m_currentReader->GetInt16(index);
+}
+
+int MgFdoFeatureReader::GetInt32( const wchar_t *propertyName )
+{
+    if (m_currentReader == NULL)
+    {
+        Initialize();
+    }
+
+    return m_currentReader->GetInt32(propertyName);
+}
+
+int MgFdoFeatureReader::GetInt32( FdoInt32 index )
+{
+    if (m_currentReader == NULL)
+    {
+        Initialize();
+    }
+
+    return m_currentReader->GetInt32(index);
+}
+
+FdoInt64 MgFdoFeatureReader::GetInt64( const wchar_t *propertyName )
+{
+    if (m_currentReader == NULL)
+    {
+        Initialize();
+    }
+
+    return m_currentReader->GetInt64(propertyName);
+}
+
+FdoInt64 MgFdoFeatureReader::GetInt64( FdoInt32 index )
+{
+    if (m_currentReader == NULL)
+    {
+        Initialize();
+    }
+
+    return m_currentReader->GetInt64(index);
+}
+
+float MgFdoFeatureReader::GetSingle( const wchar_t *propertyName )
+{
+    if (m_currentReader == NULL)
+    {
+        Initialize();
+    }
+
+    return m_currentReader->GetSingle(propertyName);
+}
+
+float MgFdoFeatureReader::GetSingle( FdoInt32 index )
+{
+    if (m_currentReader == NULL)
+    {
+        Initialize();
+    }
+
+    return m_currentReader->GetSingle(index);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+FdoIStreamReader* MgFdoFeatureReader::GetLOBStreamReader(const wchar_t* propertyName)
+{
+    if (m_currentReader == NULL)
+    {
+        Initialize();
+    }
+
+    return m_currentReader->GetLOBStreamReader(propertyName);
+}
+
+FdoIStreamReader* MgFdoFeatureReader::GetLOBStreamReader(FdoInt32 index)
+{
+    if (m_currentReader == NULL)
+    {
+        Initialize();
+    }
+
+    return m_currentReader->GetLOBStreamReader(index);
+}
+///////////////////////////////////////////////////////////////////////////////
+FdoLOBValue* MgFdoFeatureReader::GetLOB(const wchar_t* propertyName)
+{
+    if (m_currentReader == NULL)
+    {
+        Initialize();
+    }
+
+    return m_currentReader->GetLOB(propertyName);
+}
+
+FdoLOBValue* MgFdoFeatureReader::GetLOB(FdoInt32 index)
+{
+    if (m_currentReader == NULL)
+    {
+        Initialize();
+    }
+
+    return m_currentReader->GetLOB(index);
+}
+
+bool MgFdoFeatureReader::IsNull( const wchar_t *propertyName )
+{
+    if (m_currentReader == NULL)
+    {
+        Initialize();
+    }
+
+    return m_currentReader->IsNull(propertyName);
+}
+
+bool MgFdoFeatureReader::IsNull( FdoInt32 index )
+{
+    if (m_currentReader == NULL)
+    {
+        Initialize();
+    }
+
+    return m_currentReader->IsNull(index);
+}
+
+FdoByteArray* MgFdoFeatureReader::GetGeometry(const wchar_t* propertyName)
+{
+    if (m_currentReader == NULL)
+    {
+        Initialize();
+    }
+
+    return m_currentReader->GetGeometry(propertyName);
+}
+
+FdoByteArray* MgFdoFeatureReader::GetGeometry(FdoInt32 index)
+{
+    if (m_currentReader == NULL)
+    {
+        Initialize();
+    }
+
+    return m_currentReader->GetGeometry(index);
+}
+
+const FdoByte * MgFdoFeatureReader::GetGeometry(const wchar_t* propertyName, FdoInt32 * count)
+{
+    if (m_currentReader == NULL)
+    {
+        Initialize();
+    }
+
+    return m_currentReader->GetGeometry(propertyName, count);
+}
+
+const FdoByte * MgFdoFeatureReader::GetGeometry(FdoInt32 index, FdoInt32 * count)
+{
+    if (m_currentReader == NULL)
+    {
+        Initialize();
+    }
+
+    return m_currentReader->GetGeometry(index, count);
+}
+
+/// <summary>Gets the raster object of the specified property.
+/// Because no conversion is performed, the property must be
+/// of Raster type; otherwise, an exception is thrown.</summary>
+/// <param name="propertyName">Input the property name.</param>
+/// <returns>Returns the raster object.</returns>
+FdoIRaster* MgFdoFeatureReader::GetRaster(FdoString* propertyName)
+{
+    if (m_currentReader == NULL)
+    {
+        Initialize();
+    }
+
+    return m_currentReader->GetRaster(propertyName);
+}
+
+FdoIRaster* MgFdoFeatureReader::GetRaster(FdoInt32 index)
+{
+    if (m_currentReader == NULL)
+    {
+        Initialize();
+    }
+
+    return m_currentReader->GetRaster(index);
+}
+
+bool MgFdoFeatureReader::ReadNext( )
+{
+    if (m_readerDepleted)
+        return false;
+
+   if (m_currentReader == NULL)
+       Initialize();
+
+   if (m_currentReader->ReadNext())
+       return true;
+
+   m_currentReader = NULL;
+   m_currentReaderId++;
+   if ((m_readerCollection->GetCount() > m_currentReaderId))
+       m_currentReader = static_cast<FdoIFeatureReader*>(m_readerCollection->GetItem(m_currentReaderId));
+
+   if (m_currentReader != NULL)
+       return this->ReadNext();
+
+   m_readerDepleted = true;
+   return false;
+}
+
+void MgFdoFeatureReader::Close( )
+{
+    if (m_currentReader)
+    {
+        m_currentReader->Close();
+    }
+}
+
+void MgFdoFeatureReader::Add(FdoIFeatureReader *reader)
+{
+    m_readerCollection->Add(reader);
+}
+
+void MgFdoFeatureReader::Initialize()
+{
+    if (m_currentReader == NULL)
+    {
+        if (m_readerCollection->GetCount())
+        {
+            m_currentReader = (FdoIFeatureReader*)m_readerCollection->GetItem(0);
+            m_currentReaderId = 0;
+        }
+    }
+}

Added: branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/FdoFeatureReader.h
===================================================================
--- branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/FdoFeatureReader.h	                        (rev 0)
+++ branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/FdoFeatureReader.h	2012-07-15 16:59:27 UTC (rev 6903)
@@ -0,0 +1,100 @@
+//
+//  Copyright (C) 2004-2011 by Autodesk, Inc.
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of version 2.1 of the GNU Lesser
+//  General Public License as published by the Free Software Foundation.
+//
+//  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 St, Fifth Floor, Boston, MA  02110-1301  USA
+//
+
+#ifndef _MGFDOFEATUREREADER_H
+#define _MGFDOFEATUREREADER_H
+
+#include "FdoReaderCollection.h"
+
+class FdoIFeatureReader;
+
+class MgFdoFeatureReader: public FdoIFeatureReader
+{
+public:
+    // constructs a MgFdoFeatureReader
+    MgFdoFeatureReader();
+    MgFdoFeatureReader(MgFdoReaderCollection* readerCollection);
+    // default destructor
+    virtual ~MgFdoFeatureReader();
+
+protected:
+
+    virtual void Dispose();
+
+public:
+
+        virtual FdoClassDefinition* GetClassDefinition();
+        virtual int GetDepth();
+        virtual bool     GetBoolean( const wchar_t *propertyName );
+        virtual FdoByte  GetByte( const wchar_t *propertyName );
+        virtual double   GetDouble(const wchar_t* propertyName);
+        virtual short    GetInt16( const wchar_t *propertyName );
+        virtual int      GetInt32( const wchar_t *propertyName );
+        virtual FdoInt64 GetInt64( const wchar_t *propertyName );
+        virtual float    GetSingle( const wchar_t *propertyName );
+        virtual const wchar_t* GetString( const wchar_t *propertyName );
+
+        virtual FdoLOBValue* GetLOB(const wchar_t* propertyName );
+        virtual FdoIStreamReader* GetLOBStreamReader(const wchar_t* propertyName );
+
+        virtual bool     IsNull( const wchar_t *propertyName );
+        virtual FdoIFeatureReader* GetFeatureObject(const wchar_t* propertyName);
+        virtual FdoByteArray* GetGeometry(const wchar_t* propertyName);
+        virtual const FdoByte * GetGeometry(const wchar_t* propertyName, FdoInt32 * count);
+        virtual FdoIRaster* GetRaster(const wchar_t* propertyName);
+
+        virtual bool                IsNull (FdoInt32 index);
+        virtual const wchar_t*      GetString   (FdoInt32 index);
+        virtual bool                GetBoolean  (FdoInt32 index);
+        virtual FdoByte             GetByte     (FdoInt32 index);
+        virtual FdoDateTime         GetDateTime (FdoInt32 index);
+        virtual double              GetDouble   (FdoInt32 index);
+        virtual short               GetInt16    (FdoInt32 index);
+        virtual int                 GetInt32    (FdoInt32 index);
+        virtual FdoInt64            GetInt64    (FdoInt32 index);
+        virtual float               GetSingle   (FdoInt32 index);
+        virtual FdoLOBValue*        GetLOB      (FdoInt32 index);
+        virtual FdoIStreamReader*   GetLOBStreamReader (FdoInt32 index);
+        virtual FdoIRaster*         GetRaster   (FdoInt32 index);
+        virtual const FdoByte *     GetGeometry (FdoInt32 index, FdoInt32 * count);
+        virtual FdoByteArray*       GetGeometry (FdoInt32 index);
+        virtual FdoIFeatureReader*  GetFeatureObject (FdoInt32 index);
+
+        virtual FdoString*          GetPropertyName(FdoInt32 index);
+        virtual FdoInt32            GetPropertyIndex(FdoString* propertyName);
+
+        virtual bool     ReadNext( );
+        virtual void     Close();
+
+
+        virtual FdoDateTime GetDateTime(const wchar_t *propertyName );
+
+        // Add an FdoIFeatureReader to the reader collection
+        void Add(FdoIFeatureReader* reader);
+
+protected:
+
+private:
+    FdoPtr<MgFdoReaderCollection> m_readerCollection;
+    FdoPtr<FdoIFeatureReader> m_currentReader;
+    FdoInt32 m_currentReaderId;
+    FdoBoolean m_readerDepleted;
+    void Initialize();
+
+};
+
+#endif // _MGFDOFEATUREREADER_H

Added: branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/FdoFilterCollection.cpp
===================================================================
--- branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/FdoFilterCollection.cpp	                        (rev 0)
+++ branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/FdoFilterCollection.cpp	2012-07-15 16:59:27 UTC (rev 6903)
@@ -0,0 +1,24 @@
+//
+//  Copyright (C) 2004-2011 by Autodesk, Inc.
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of version 2.1 of the GNU Lesser
+//  General Public License as published by the Free Software Foundation.
+//
+//  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 St, Fifth Floor, Boston, MA  02110-1301  USA
+//
+
+#include "stdafx.h"
+#include "FdoFilterCollection.h"
+
+/*FDO_API*/ MgFdoFilterCollection* MgFdoFilterCollection::Create()
+{
+    return new MgFdoFilterCollection();
+}

Added: branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/FdoFilterCollection.h
===================================================================
--- branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/FdoFilterCollection.h	                        (rev 0)
+++ branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/FdoFilterCollection.h	2012-07-15 16:59:27 UTC (rev 6903)
@@ -0,0 +1,54 @@
+//
+//  Copyright (C) 2004-2011 by Autodesk, Inc.
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of version 2.1 of the GNU Lesser
+//  General Public License as published by the Free Software Foundation.
+//
+//  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 St, Fifth Floor, Boston, MA  02110-1301  USA
+//
+
+#ifndef _MGFDOFILTERCOLLECTION_H_
+#define _MGFDOFILTERCOLLECTION_H_
+
+#include <FdoStd.h>
+
+class FdoFilter;
+
+/// \brief
+/// The MgFdoFilterCollection class represents a collection of FdoFilter objects.
+class MgFdoFilterCollection : public FdoCollection<FdoFilter, FdoException>
+{
+protected:
+/// \cond DOXYGEN-IGNORE
+    MgFdoFilterCollection() : FdoCollection<FdoFilter, FdoException>()
+    {
+    }
+
+    virtual ~MgFdoFilterCollection()
+    {
+    }
+
+    virtual void Dispose()
+    {
+        delete this;
+    }
+/// \endcond
+
+public:
+    /// \brief
+    /// Constructs a default instance of an MgFdoFilterCollection.
+    ///
+    /// \return
+    /// Returns MgFdoFilterCollection
+    ///
+    /*FDO_API*/ static MgFdoFilterCollection* Create();
+};
+#endif

Added: branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/FdoReaderCollection.cpp
===================================================================
--- branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/FdoReaderCollection.cpp	                        (rev 0)
+++ branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/FdoReaderCollection.cpp	2012-07-15 16:59:27 UTC (rev 6903)
@@ -0,0 +1,24 @@
+//
+//  Copyright (C) 2004-2011 by Autodesk, Inc.
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of version 2.1 of the GNU Lesser
+//  General Public License as published by the Free Software Foundation.
+//
+//  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 St, Fifth Floor, Boston, MA  02110-1301  USA
+//
+
+#include "stdafx.h"
+#include "FdoReaderCollection.h"
+
+/*FDO_API*/ MgFdoReaderCollection* MgFdoReaderCollection::Create()
+{
+    return new MgFdoReaderCollection();
+}

Added: branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/FdoReaderCollection.h
===================================================================
--- branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/FdoReaderCollection.h	                        (rev 0)
+++ branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/FdoReaderCollection.h	2012-07-15 16:59:27 UTC (rev 6903)
@@ -0,0 +1,54 @@
+//
+//  Copyright (C) 2004-2011 by Autodesk, Inc.
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of version 2.1 of the GNU Lesser
+//  General Public License as published by the Free Software Foundation.
+//
+//  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 St, Fifth Floor, Boston, MA  02110-1301  USA
+//
+
+#ifndef _MGFDOREADERCOLLECTION_H_
+#define _MGFDOREADERCOLLECTION_H_
+
+#include <FdoStd.h>
+
+class FdoIFeatureReader;
+
+/// \brief
+/// The MgFdoReaderCollection class represents a collection of FdoIFeatureReader objects.
+class MgFdoReaderCollection : public FdoCollection<FdoIFeatureReader, FdoException>
+{
+protected:
+/// \cond DOXYGEN-IGNORE
+    MgFdoReaderCollection() : FdoCollection<FdoIFeatureReader, FdoException>()
+    {
+    }
+
+    virtual ~MgFdoReaderCollection()
+    {
+    }
+
+    virtual void Dispose()
+    {
+        delete this;
+    }
+/// \endcond
+
+public:
+    /// \brief
+    /// Constructs a default instance of an MgFdoReaderCollection.
+    ///
+    /// \return
+    /// Returns MgFdoReaderCollection
+    ///
+    /*FDO_API*/ static MgFdoReaderCollection* Create();
+};
+#endif

Modified: branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/FeatureDefs.h
===================================================================
--- branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/FeatureDefs.h	2012-07-15 15:04:11 UTC (rev 6902)
+++ branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/FeatureDefs.h	2012-07-15 16:59:27 UTC (rev 6903)
@@ -155,4 +155,7 @@
     MG_FEATURE_SERVICE_THROW()                                                \
 
 
-#endif
\ No newline at end of file
+#endif
+
+#define PRIMARY_ALIAS L"a"
+#define SECONDARY_ALIAS L"b"
\ No newline at end of file

Added: branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/FeatureSetReader.cpp
===================================================================
--- branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/FeatureSetReader.cpp	                        (rev 0)
+++ branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/FeatureSetReader.cpp	2012-07-15 16:59:27 UTC (rev 6903)
@@ -0,0 +1,841 @@
+#include "MgDesktop.h"
+#include "FeatureSetReader.h"
+
+#define CHECK_FEATURESET_COUNT(pointer, methodname)        \
+if (0 == pointer->GetCount())                           \
+{                                                       \
+    throw new MgEmptyFeatureSetException(methodname,    \
+                                       __LINE__, __WFILE__, NULL, L"", NULL); \
+}
+
+#define CHECK_PROPERTY_TYPE(property, type, methodname) \
+if (property != type)                                   \
+{                                                       \
+    throw new MgInvalidPropertyTypeException(methodname, \
+                                       __LINE__, __WFILE__, NULL, L"", NULL); \
+}
+
+//////////////////////////////////////////////////////////////////
+///<summary>
+/// Construct a MgdFeatureSetReader object from a byte source
+///</summary>
+///<param name="byteSource">Byte  source object</param>
+///
+MgdFeatureSetReader::MgdFeatureSetReader(MgFeatureSet* featureSet)
+{
+    m_currRecord = 0;
+    m_set = SAFE_ADDREF(featureSet);
+}
+
+//////////////////////////////////////////////////////////////////
+///<summary>
+/// Destruct a MgdFeatureSetReader object
+///</summary>
+///
+MgdFeatureSetReader::~MgdFeatureSetReader()
+{
+    Close();
+}
+
+//////////////////////////////////////////////////////////////////
+///<summary>
+/// Set the byte source for an empty reader
+///</summary>
+///<param name="byteSource">Byte source object</param>
+///
+void MgdFeatureSetReader::AssignFeatureSet(MgFeatureSet* featureSet)
+{
+    m_currRecord = 0;
+    m_set = SAFE_ADDREF(featureSet);
+}
+
+//////////////////////////////////////////////////////////////////
+/// <summary>
+/// Advances the reader to the next item and returns true if there is
+/// another object to read or false if reading is complete. The default
+/// position of the reader is prior to the first item. Thus you must
+/// call ReadNext to begin accessing any data.
+/// </summary>
+/// <returns>
+/// Returns true if there is a next item.
+/// </returns>
+bool MgdFeatureSetReader::ReadNext()
+{
+    CHECKNULL(m_set, L"MgdFeatureSetReader.ReadNext");
+
+    bool foundNextFeature = false;
+
+    INT32 cnt = m_set->GetCount();
+
+    if ( m_currRecord < cnt )
+    {
+        m_currRecord++;
+        foundNextFeature = true;
+    }
+
+    return foundNextFeature;
+}
+
+//////////////////////////////////////////////////////////////////
+/// <summary>
+/// Gets the definition of the object currently being read. If the user
+/// has requested only a subset of the class properties, the class
+/// definition reflects what the user has asked, rather than the full class
+/// definition.
+/// </summary>
+/// <returns>A MgClassDefinition representing the current object
+///</returns>
+MgClassDefinition* MgdFeatureSetReader::GetClassDefinition()
+{
+    CHECKNULL(m_set, L"MgdFeatureSetReader.GetClassDefinition");
+
+    return m_set->GetClassDefinition();
+}
+
+MgClassDefinition* MgdFeatureSetReader::GetClassDefinitionNoXml()
+{
+    //fall back to regular public call in this case
+    return GetClassDefinition();
+}
+
+//////////////////////////////////////////////////////////////////
+/// <summary>
+///  Returns true if the value of the specified property is null.
+/// </summary>
+/// <param name="propertyName">Property name.</param>
+/// <returns>Returns true if the value is null.</returns>
+bool MgdFeatureSetReader::IsNull(CREFSTRING propertyName)
+{
+    bool isNull = false;
+
+    Ptr<MgNullableProperty> ptrProp = (MgNullableProperty*)GetProperty(propertyName);
+
+    if (ptrProp != NULL)
+    {
+        isNull = ptrProp->IsNull();
+    }
+
+    return isNull;
+}
+
+//////////////////////////////////////////////////////////////////
+/// <summary>
+///  Returns true if the value of the specified property is null.
+/// </summary>
+/// <param name="index">Property index.</param>
+/// <returns>Returns true if the value is null.</returns>
+bool MgdFeatureSetReader::IsNull(INT32 index)
+{
+    bool isNull = false;
+
+    Ptr<MgNullableProperty> ptrProp = (MgNullableProperty*)GetProperty(index);
+
+    if (ptrProp != NULL)
+    {
+        isNull = ptrProp->IsNull();
+    }
+
+    return isNull;
+}
+
+//////////////////////////////////////////////////////////////////
+/// <summary>
+/// Gets the Boolean value of the specified property. No conversion is
+/// performed, thus the property must be a of boolean type the result
+/// is undertermined</summary>
+/// <param name="propertyName">Property name.</param>
+/// <returns>Returns the Boolean value.</returns>
+/// EXCEPTIONS:
+/// InvalidPropertyType
+bool MgdFeatureSetReader::GetBoolean(CREFSTRING propertyName)
+{
+    bool retVal = false;
+
+    Ptr<MgBooleanProperty> ptrProp = (MgBooleanProperty*)GetProperty(propertyName, MgPropertyType::Boolean);
+    retVal = ptrProp->GetValue();
+
+    return retVal;
+}
+
+//////////////////////////////////////////////////////////////////
+/// <summary>
+/// Gets the Boolean value of the specified property. No conversion is
+/// performed, thus the property must be a of boolean type the result
+/// is undertermined</summary>
+/// <param name="index">Property index.</param>
+/// <returns>Returns the Boolean value.</returns>
+/// EXCEPTIONS:
+/// InvalidPropertyType
+bool MgdFeatureSetReader::GetBoolean(INT32 index)
+{
+    bool retVal = false;
+
+    Ptr<MgBooleanProperty> ptrProp = (MgBooleanProperty*)GetProperty(index, MgPropertyType::Boolean);
+    retVal = ptrProp->GetValue();
+
+    return retVal;
+}
+
+//////////////////////////////////////////////////////////////////
+/// <summary>
+/// Gets the Byte value of the specified property. No conversion is
+/// performed, thus the property must be a of byte type or the result
+/// is undertermined</summary>
+/// <param name="propertyName">Property name.</param>
+/// <returns>Returns the Byte value.</returns>
+/// EXCEPTIONS:
+/// InvalidPropertyType
+BYTE MgdFeatureSetReader::GetByte(CREFSTRING propertyName)
+{
+    BYTE retVal = 0;
+
+    Ptr<MgByteProperty> ptrProp = (MgByteProperty*)GetProperty(propertyName, MgPropertyType::Byte);
+    retVal = ptrProp->GetValue();
+
+    return retVal;
+}
+
+//////////////////////////////////////////////////////////////////
+/// <summary>
+/// Gets the Byte value of the specified property. No conversion is
+/// performed, thus the property must be a of byte type or the result
+/// is undertermined</summary>
+/// <param name="index">Property index.</param>
+/// <returns>Returns the Byte value.</returns>
+/// EXCEPTIONS:
+/// InvalidPropertyType
+BYTE MgdFeatureSetReader::GetByte(INT32 index)
+{
+    BYTE retVal = 0;
+
+    Ptr<MgByteProperty> ptrProp = (MgByteProperty*)GetProperty(index, MgPropertyType::Byte);
+    retVal = ptrProp->GetValue();
+
+    return retVal;
+}
+
+//////////////////////////////////////////////////////////////////
+/// <summary>
+/// Gets the DTime value of the specified property. No conversion is
+/// performed, thus the property must be a of date type or the result
+/// is NULL</summary>
+/// <param name="propertyName">Property name.</param>
+/// <returns>Returns the DTime value.</returns>
+/// EXCEPTIONS:
+/// InvalidPropertyType
+MgDateTime* MgdFeatureSetReader::GetDateTime(CREFSTRING propertyName)
+{
+    Ptr<MgDateTimeProperty> ptrProp = (MgDateTimeProperty*)GetProperty(propertyName, MgPropertyType::DateTime);
+    Ptr<MgDateTime> retVal = ptrProp->GetValue();
+
+    return SAFE_ADDREF((MgDateTime*)retVal);
+}
+
+//////////////////////////////////////////////////////////////////
+/// <summary>
+/// Gets the DTime value of the specified property. No conversion is
+/// performed, thus the property must be a of date type or the result
+/// is NULL</summary>
+/// <param name="index">Property index.</param>
+/// <returns>Returns the DTime value.</returns>
+/// EXCEPTIONS:
+/// InvalidPropertyType
+MgDateTime* MgdFeatureSetReader::GetDateTime(INT32 index)
+{
+    Ptr<MgDateTimeProperty> ptrProp = (MgDateTimeProperty*)GetProperty(index, MgPropertyType::DateTime);
+    Ptr<MgDateTime> retVal = ptrProp->GetValue();
+
+    return SAFE_ADDREF((MgDateTime*)retVal);
+}
+
+
+//////////////////////////////////////////////////////////////////
+/// <summary>
+/// Gets the Single value of the specified property. No conversion is
+/// performed, thus the property must be a of type single or the result
+/// is undetermined</summary>
+/// <param name="propertyName">Property name.</param>
+/// <returns>Returns the single value.</returns>
+/// EXCEPTIONS:
+/// InvalidPropertyType
+float MgdFeatureSetReader::GetSingle(CREFSTRING propertyName)
+{
+    float retVal = 0;
+
+    Ptr<MgSingleProperty> ptrProp = (MgSingleProperty*)GetProperty(propertyName, MgPropertyType::Single);
+    retVal = ptrProp->GetValue();
+
+    return retVal;
+}
+
+//////////////////////////////////////////////////////////////////
+/// <summary>
+/// Gets the Single value of the specified property. No conversion is
+/// performed, thus the property must be a of type single or the result
+/// is undetermined</summary>
+/// <param name="index">Property index.</param>
+/// <returns>Returns the single value.</returns>
+/// EXCEPTIONS:
+/// InvalidPropertyType
+float MgdFeatureSetReader::GetSingle(INT32 index)
+{
+    float retVal = 0;
+
+    Ptr<MgSingleProperty> ptrProp = (MgSingleProperty*)GetProperty(index, MgPropertyType::Single);
+    retVal = ptrProp->GetValue();
+
+    return retVal;
+}
+
+//////////////////////////////////////////////////////////////////
+/// <summary>
+/// Gets the Double value of the specified property. No conversion is
+/// performed, thus the property must be a of type double or the result
+/// is undetermined</summary>
+/// <param name="propertyName">Property name.</param>
+/// <returns>Returns the double value.</returns>
+/// EXCEPTIONS:
+/// InvalidPropertyType
+double MgdFeatureSetReader::GetDouble(CREFSTRING propertyName)
+{
+    double retVal = 0;
+
+    Ptr<MgDoubleProperty> ptrProp = (MgDoubleProperty*)GetProperty(propertyName, MgPropertyType::Double);
+    retVal = ptrProp->GetValue();
+
+    return retVal;
+}
+
+//////////////////////////////////////////////////////////////////
+/// <summary>
+/// Gets the Double value of the specified property. No conversion is
+/// performed, thus the property must be a of type double or the result
+/// is undetermined</summary>
+/// <param name="index">Property index.</param>
+/// <returns>Returns the double value.</returns>
+/// EXCEPTIONS:
+/// InvalidPropertyType
+double MgdFeatureSetReader::GetDouble(INT32 index)
+{
+    double retVal = 0;
+
+    Ptr<MgDoubleProperty> ptrProp = (MgDoubleProperty*)GetProperty(index, MgPropertyType::Double);
+    retVal = ptrProp->GetValue();
+
+    return retVal;
+}
+
+//////////////////////////////////////////////////////////////////
+/// <summary>
+/// Gets the integer 16 bits value of the specified property. No conversion is
+/// performed, thus the property must be a of type integer 16 bits or the result
+/// is undetermined</summary>
+/// <param name="propertyName">Property name.</param>
+/// <returns>Returns the integer 16 bits value.</returns>
+/// EXCEPTIONS:
+/// InvalidPropertyType
+INT16 MgdFeatureSetReader::GetInt16(CREFSTRING propertyName)
+{
+    INT16 retVal = 0;
+
+    Ptr<MgInt16Property> ptrProp = (MgInt16Property*)GetProperty(propertyName, MgPropertyType::Int16);
+    retVal = ptrProp->GetValue();
+
+    return retVal;
+}
+
+//////////////////////////////////////////////////////////////////
+/// <summary>
+/// Gets the integer 16 bits value of the specified property. No conversion is
+/// performed, thus the property must be a of type integer 16 bits or the result
+/// is undetermined</summary>
+/// <param name="index">Property index.</param>
+/// <returns>Returns the integer 16 bits value.</returns>
+/// EXCEPTIONS:
+/// InvalidPropertyType
+INT16 MgdFeatureSetReader::GetInt16(INT32 index)
+{
+    INT16 retVal = 0;
+
+    Ptr<MgInt16Property> ptrProp = (MgInt16Property*)GetProperty(index, MgPropertyType::Int16);
+    retVal = ptrProp->GetValue();
+
+    return retVal;
+}
+
+//////////////////////////////////////////////////////////////////
+/// <summary>
+/// Gets the integer 32 bits value of the specified property. No conversion is
+/// performed, thus the property must be a of type integer 32 bits or the result
+/// is undetermined</summary>
+/// <param name="propertyName">Property name.</param>
+/// <returns>Returns the integer 32 bits value.</returns>
+/// EXCEPTIONS:
+/// InvalidPropertyType
+INT32 MgdFeatureSetReader::GetInt32(CREFSTRING propertyName)
+{
+    INT32 retVal = 0;
+
+    Ptr<MgInt32Property> ptrProp = (MgInt32Property*)GetProperty(propertyName, MgPropertyType::Int32);
+    retVal = ptrProp->GetValue();
+
+    return retVal;
+}
+
+//////////////////////////////////////////////////////////////////
+/// <summary>
+/// Gets the integer 32 bits value of the specified property. No conversion is
+/// performed, thus the property must be a of type integer 32 bits or the result
+/// is undetermined</summary>
+/// <param name="index">Property index.</param>
+/// <returns>Returns the integer 32 bits value.</returns>
+/// EXCEPTIONS:
+/// InvalidPropertyType
+INT32 MgdFeatureSetReader::GetInt32(INT32 index)
+{
+    INT32 retVal = 0;
+
+    Ptr<MgInt32Property> ptrProp = (MgInt32Property*)GetProperty(index, MgPropertyType::Int32);
+    retVal = ptrProp->GetValue();
+
+    return retVal;
+}
+
+//////////////////////////////////////////////////////////////////
+/// <summary>
+/// Gets the integer 64 bits value of the specified property. No conversion is
+/// performed, thus the property must be a of type integer 64 bits or the result
+/// is NULL</summary>
+/// <param name="propertyName">Property name.</param>
+/// <returns>Returns the integer 64 bits value.
+/// Note: INT64 is actually a pointer to an Integer64 object
+///</returns>
+/// EXCEPTIONS:
+/// InvalidPropertyType
+INT64 MgdFeatureSetReader::GetInt64(CREFSTRING propertyName)
+{
+    INT64 retVal = 0;
+
+    Ptr<MgInt64Property> ptrProp = (MgInt64Property*)GetProperty(propertyName, MgPropertyType::Int64);
+    retVal = ptrProp->GetValue();
+
+    return retVal;
+}
+
+//////////////////////////////////////////////////////////////////
+/// <summary>
+/// Gets the integer 64 bits value of the specified property. No conversion is
+/// performed, thus the property must be a of type integer 64 bits or the result
+/// is NULL</summary>
+/// <param name="index">Property index.</param>
+/// <returns>Returns the integer 64 bits value.
+/// Note: INT64 is actually a pointer to an Integer64 object
+///</returns>
+/// EXCEPTIONS:
+/// InvalidPropertyType
+INT64 MgdFeatureSetReader::GetInt64(INT32 index)
+{
+    INT64 retVal = 0;
+
+    Ptr<MgInt64Property> ptrProp = (MgInt64Property*)GetProperty(index, MgPropertyType::Int64);
+    retVal = ptrProp->GetValue();
+
+    return retVal;
+}
+
+//////////////////////////////////////////////////////////////////
+/// <summary>
+/// Gets the string value of the specified property. No conversion is
+/// performed, thus the property must be a of type string or the result
+/// is NULL</summary>
+/// <param name="propertyName">Property name.</param>
+/// <returns>Returns the string value.</returns>
+/// EXCEPTIONS:
+/// InvalidPropertyType
+STRING MgdFeatureSetReader::GetString(CREFSTRING propertyName)
+{
+    STRING retVal = L"";
+
+    Ptr<MgStringProperty> ptrProp = (MgStringProperty*)GetProperty(propertyName, MgPropertyType::String);
+    retVal = ptrProp->GetValue();
+
+    return retVal;
+}
+
+//////////////////////////////////////////////////////////////////
+/// <summary>
+/// Gets the string value of the specified property. No conversion is
+/// performed, thus the property must be a of type string or the result
+/// is NULL</summary>
+/// <param name="index">Property index.</param>
+/// <returns>Returns the string value.</returns>
+/// EXCEPTIONS:
+/// InvalidPropertyType
+STRING MgdFeatureSetReader::GetString(INT32 index)
+{
+    STRING retVal = L"";
+
+    Ptr<MgStringProperty> ptrProp = (MgStringProperty*)GetProperty(index, MgPropertyType::String);
+    retVal = ptrProp->GetValue();
+
+    return retVal;
+}
+
+//////////////////////////////////////////////////////////////////
+/// <summary>
+/// Gets the BLOB value of the specified property. No conversion is
+/// performed, thus the property must be a of type BLOBs or the result
+/// is NULL</summary>
+/// <param name="propertyName">Property name.</param>
+/// <returns>Returns the BLOB value.</returns>
+/// EXCEPTIONS:
+/// InvalidPropertyType
+MgByteReader* MgdFeatureSetReader::GetBLOB(CREFSTRING propertyName)
+{
+    Ptr<MgBlobProperty> ptrProp = (MgBlobProperty*)GetProperty(propertyName, MgPropertyType::Blob);
+    return ptrProp->GetValue();
+}
+
+//////////////////////////////////////////////////////////////////
+/// <summary>
+/// Gets the BLOB value of the specified property. No conversion is
+/// performed, thus the property must be a of type BLOBs or the result
+/// is NULL</summary>
+/// <param name="index">Property index.</param>
+/// <returns>Returns the BLOB value.</returns>
+/// EXCEPTIONS:
+/// InvalidPropertyType
+MgByteReader* MgdFeatureSetReader::GetBLOB(INT32 index)
+{
+    Ptr<MgBlobProperty> ptrProp = (MgBlobProperty*)GetProperty(index, MgPropertyType::Blob);
+    return ptrProp->GetValue();
+}
+
+//////////////////////////////////////////////////////////////////
+/// <summary>
+/// Gets the CLOB value of the specified property. No conversion is
+/// performed, thus the property must be a of type CLOB or the result
+/// is NULL</summary>
+/// <param name="propertyName">Property name.</param>
+/// <returns>Returns the CLOB value.</returns>
+/// EXCEPTIONS:
+/// InvalidPropertyType
+MgByteReader* MgdFeatureSetReader::GetCLOB(CREFSTRING propertyName)
+{
+    Ptr<MgClobProperty> ptrProp = (MgClobProperty*)GetProperty(propertyName, MgPropertyType::Clob);
+    return ptrProp->GetValue();
+}
+
+//////////////////////////////////////////////////////////////////
+/// <summary>
+/// Gets the CLOB value of the specified property. No conversion is
+/// performed, thus the property must be a of type CLOB or the result
+/// is NULL</summary>
+/// <param name="index">Property index.</param>
+/// <returns>Returns the CLOB value.</returns>
+/// EXCEPTIONS:
+/// InvalidPropertyType
+MgByteReader* MgdFeatureSetReader::GetCLOB(INT32 index)
+{
+    Ptr<MgClobProperty> ptrProp = (MgClobProperty*)GetProperty(index, MgPropertyType::Clob);
+    return ptrProp->GetValue();
+}
+
+
+//////////////////////////////////////////////////////////////////
+/// <summary>
+/// Gets the FeatureReader to access this object value.
+/// The property must be of an object type{} otherwise, the result is NULL.
+/// </summary>
+/// <param name="propertyName">Input the property name.</param>
+/// <returns>Returns the feature reader to access this object.</returns>
+/// EXCEPTIONS:
+/// InvalidPropertyType
+MgFeatureReader* MgdFeatureSetReader::GetFeatureObject(CREFSTRING propertyName)
+{
+    Ptr<MgFeatureProperty> ptrProp = (MgFeatureProperty*)GetProperty(propertyName, MgPropertyType::Feature);
+    return ptrProp->GetValue();
+}
+
+//////////////////////////////////////////////////////////////////
+/// <summary>
+/// Gets the FeatureReader to access this object value.
+/// The property must be of an object type{} otherwise, the result is NULL.
+/// </summary>
+/// <param name="index">Property index.</param>
+/// <returns>Returns the feature reader to access this object.</returns>
+/// EXCEPTIONS:
+/// InvalidPropertyType
+MgFeatureReader* MgdFeatureSetReader::GetFeatureObject(INT32 index)
+{
+    Ptr<MgFeatureProperty> ptrProp = (MgFeatureProperty*)GetProperty(index, MgPropertyType::Feature);
+    return ptrProp->GetValue();
+}
+
+//////////////////////////////////////////////////////////////////
+/// <summary>
+/// Gets the geometry value of the specified property as a GeometryReader.
+/// Because no conversion is performed, the property must be
+/// of Geometric type{} otherwise, the result is NULL.</summary>
+/// <param name="propertyName">Input the property name.</param>
+/// <returns>Returns the Geometry object.</returns>
+/// EXCEPTIONS:
+/// InvalidPropertyType
+MgByteReader* MgdFeatureSetReader::GetGeometry(CREFSTRING propertyName)
+{
+    Ptr<MgGeometryProperty> ptrProp = (MgGeometryProperty*)GetProperty(propertyName, MgPropertyType::Geometry);
+    return ptrProp->GetValue();
+}
+
+//////////////////////////////////////////////////////////////////
+/// <summary>
+/// Gets the geometry value of the specified property as a GeometryReader.
+/// Because no conversion is performed, the property must be
+/// of Geometric type{} otherwise, the result is NULL.</summary>
+/// <param name="index">Property index.</param>
+/// <returns>Returns the Geometry object.</returns>
+/// EXCEPTIONS:
+/// InvalidPropertyType
+MgByteReader* MgdFeatureSetReader::GetGeometry(INT32 index)
+{
+    Ptr<MgGeometryProperty> ptrProp = (MgGeometryProperty*)GetProperty(index, MgPropertyType::Geometry);
+    return ptrProp->GetValue();
+}
+
+// Get the property for the specified name
+MgProperty* MgdFeatureSetReader::GetProperty(CREFSTRING propertyName, INT16 expectedType)
+{
+    Ptr<MgNullableProperty> ptrProp = (MgNullableProperty*)this->GetProperty(propertyName);
+    CHECKNULL(ptrProp, L"MgdFeatureSetReader.GetProperty");
+
+    if (ptrProp->IsNull())
+    {
+        MgStringCollection arguments;
+        arguments.Add(propertyName);
+
+        throw new MgNullPropertyValueException(L"MgdFeatureSetReader.GetProperty",
+            __LINE__, __WFILE__, &arguments, L"", NULL);
+    }
+
+    INT16 propType = ptrProp->GetPropertyType();
+    CHECK_PROPERTY_TYPE(propType, expectedType, L"MgdFeatureSetReader.GetProperty");
+
+    return SAFE_ADDREF(ptrProp.p);
+}
+
+// Get the property for the specified index
+MgProperty* MgdFeatureSetReader::GetProperty(INT32 index, INT16 expectedType)
+{
+    Ptr<MgNullableProperty> ptrProp = (MgNullableProperty*)this->GetProperty(index);
+    CHECKNULL(ptrProp, L"MgdFeatureSetReader.GetProperty");
+
+    if (ptrProp->IsNull())
+    {
+        STRING buffer;
+        MgUtil::Int32ToString(index, buffer);
+        MgStringCollection arguments;
+        arguments.Add(buffer);
+
+        throw new MgNullPropertyValueException(L"MgdFeatureSetReader.GetProperty",
+            __LINE__, __WFILE__, &arguments, L"", NULL);
+    }
+
+    INT16 propType = ptrProp->GetPropertyType();
+    CHECK_PROPERTY_TYPE(propType, expectedType, L"MgdFeatureSetReader.GetProperty");
+
+    return SAFE_ADDREF(ptrProp.p);
+}
+
+// Get the property for the specified name
+MgProperty* MgdFeatureSetReader::GetProperty(CREFSTRING propertyName)
+{
+    CHECKNULL(m_set, L"MgdFeatureSetReader.GetProperty");
+    CHECK_FEATURESET_COUNT(m_set, L"MgdFeatureSetReader.GetProperty");
+
+    Ptr<MgPropertyCollection> ptrCol = m_set->GetFeatureAt(m_currRecord-1);
+    CHECKNULL(ptrCol, L"MgdFeatureSetReader.GetProperty");
+
+    Ptr<MgProperty> ptrProp = ptrCol->GetItem(propertyName);
+    CHECKNULL(ptrProp, L"MgdFeatureSetReader.GetProperty");
+
+    return SAFE_ADDREF(ptrProp.p);
+}
+
+// Get the property for the specified index
+MgProperty* MgdFeatureSetReader::GetProperty(INT32 index)
+{
+    CHECKNULL(m_set, L"MgdFeatureSetReader.GetProperty");
+    CHECK_FEATURESET_COUNT(m_set, L"MgdFeatureSetReader.GetProperty");
+
+    Ptr<MgPropertyCollection> ptrCol = m_set->GetFeatureAt(m_currRecord-1);
+    CHECKNULL(ptrCol, L"MgdFeatureSetReader.GetProperty");
+
+    Ptr<MgProperty> ptrProp = ptrCol->GetItem(index);
+    CHECKNULL(ptrProp, L"MgdFeatureSetReader.GetProperty");
+
+    return SAFE_ADDREF(ptrProp.p);
+}
+
+//////////////////////////////////////////////////////////////////
+///<summary>
+/// Serialize data to TCP/IP stream
+///</summary>
+///<param name="stream">
+/// Stream
+///</param>
+
+void MgdFeatureSetReader::Serialize(MgStream* stream)
+{
+    NOT_IMPLEMENTED(L"MgdFeatureSetReader::Serialize");
+}
+
+//////////////////////////////////////////////////////////////////
+///<summary>
+/// Deserialize data from TCP/IP stream
+///</summary>
+///<param name="stream">
+/// Stream
+///</param>
+
+void MgdFeatureSetReader::Deserialize(MgStream* stream)
+{
+    NOT_IMPLEMENTED(L"MgdFeatureSetReader::Deserialize");
+}
+
+//////////////////////////////////////////////////////////////////
+/// <summary>
+/// Serializes all features into an XML.
+/// XML is serialized from the current position of feature reader in the order
+/// data are retrieved.
+/// <returns>MgByteReader holding XML.</returns>
+MgByteReader* MgdFeatureSetReader::ToXml()
+{
+    string xmlStr;
+    this->ToXml(xmlStr);
+
+    Ptr<MgByteSource> byteSource = new MgByteSource((BYTE_ARRAY_IN)xmlStr.c_str(), (INT32)xmlStr.length());
+    byteSource->SetMimeType(MgMimeType::Xml);
+
+    return byteSource->GetReader();
+}
+
+void MgdFeatureSetReader::ToXml(string &str)
+{
+    CHECKNULL(m_set, L"MgdFeatureSetReader.ToXml");
+
+    Ptr<MgClassDefinition> classDef = this->GetClassDefinition();
+
+    if (classDef != NULL)
+    {
+        // TODO: define a schema for this XML
+        // TODO: rename FeatureSet element to avoid conflict with FeatureSet-1.0.0.xsd?
+        str += "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
+        str += "<FeatureSet>";
+        classDef->ToXml(str);
+        str += "<Features>";
+        while ( this->ReadNext() )
+        {
+            Ptr<MgPropertyCollection> propCol = m_set->GetFeatureAt(m_currRecord-1);
+            INT32 cnt = propCol->GetCount();
+            if (propCol != NULL && cnt > 0)
+            {
+                propCol->ToFeature(str);
+            }
+        }
+        str += "</Features>";
+        str += "</FeatureSet>";
+    }
+}
+
+//////////////////////////////////////////////////////////////////
+/// <summary>
+/// Releases all the resources of feature reader.
+/// This must be called when user is done with Feature Reader
+/// <returns>Nothing</returns>
+void MgdFeatureSetReader::Close()
+{
+}
+
+/// <summary>Gets the raster object of the specified property.
+/// the property must be of Raster type; otherwise, an exception is thrown.
+/// </summary>
+/// <param name="propertyName">Input the property name.</param>
+/// <returns>Returns the raster object.</returns>
+MgRaster* MgdFeatureSetReader::GetRaster(CREFSTRING propertyName)
+{
+    NOT_IMPLEMENTED(L"MgdFeatureSetReader::GetRaster");
+}
+
+/// <summary>Gets the raster object of the specified property.
+/// the property must be of Raster type; otherwise, an exception is thrown.
+/// </summary>
+/// <param name="index">Input the property index.</param>
+/// <returns>Returns the raster object.</returns>
+MgRaster* MgdFeatureSetReader::GetRaster(INT32 index)
+{
+    NOT_IMPLEMENTED(L"MgdFeatureSetReader::GetRaster");
+}
+
+//////////////////////////////////////////////////////////////////
+/// <summary>
+/// Gets the Geometry for the specified property. No conversion is
+/// performed, thus the property must be a of type Geometry or the result
+/// is NULL</summary>
+/// <param name="propertyName">Property name.</param>
+/// <returns>Returns a ByteReader object</returns>
+BYTE_ARRAY_OUT MgdFeatureSetReader::GetGeometry(CREFSTRING propertyName, INT32& length)
+{
+    throw new MgNotImplementedException(L"MgdFeatureSetReader.GetGeometry",
+        __LINE__, __WFILE__, NULL, L"", NULL);
+}
+
+//////////////////////////////////////////////////////////////////
+/// <summary>
+/// Gets the Geometry for the specified property. No conversion is
+/// performed, thus the property must be a of type Geometry or the result
+/// is NULL</summary>
+/// <param name="index">Property index.</param>
+/// <returns>Returns a ByteReader object</returns>
+BYTE_ARRAY_OUT MgdFeatureSetReader::GetGeometry(INT32 index, INT32& length)
+{
+    throw new MgNotImplementedException(L"MgdFeatureSetReader.GetGeometry",
+        __LINE__, __WFILE__, NULL, L"", NULL);
+}
+
+//////////////////////////////////////////////////////////////////
+/// <summary>
+/// Gets the string value of the specified property. No conversion is
+/// performed, thus the property must be a of type string or the result
+/// is NULL</summary>
+/// <param name="propertyName">Property name.</param>
+/// <returns>Returns the string value.</returns>
+const wchar_t* MgdFeatureSetReader::GetString(CREFSTRING propertyName, INT32& length)
+{
+    STRING str = this->GetString(propertyName);
+    length = (INT32)str.size();
+
+    return str.c_str();
+}
+
+//////////////////////////////////////////////////////////////////
+/// <summary>
+/// Gets the string value of the specified property. No conversion is
+/// performed, thus the property must be a of type string or the result
+/// is NULL</summary>
+/// <param name="index">Property index.</param>
+/// <returns>Returns the string value.</returns>
+const wchar_t* MgdFeatureSetReader::GetString(INT32 index, INT32& length)
+{
+    STRING str = this->GetString(index);
+    length = (INT32)str.size();
+
+    return str.c_str();
+}
+
+MgFeatureSet* MgdFeatureSetReader::GetFeatures(INT32 count)
+{
+    throw new MgNotImplementedException(L"MgdFeatureSetReader.GetFeatures",
+        __LINE__, __WFILE__, NULL, L"", NULL);
+}
+
+INT32 MgdFeatureSetReader::GetReaderType() { return MgReaderType::FeatureReader; }
\ No newline at end of file

Added: branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/FeatureSetReader.h
===================================================================
--- branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/FeatureSetReader.h	                        (rev 0)
+++ branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/FeatureSetReader.h	2012-07-15 16:59:27 UTC (rev 6903)
@@ -0,0 +1,134 @@
+#ifndef DESKTOP_FEATURE_SET_READER_H
+#define DESKTOP_FEATURE_SET_READER_H
+
+class MgdFeatureSetReader : public MgFeatureReader
+{
+    DECLARE_CLASSNAME(MgdFeatureSetReader);
+
+INTERNAL_API:
+	MgdFeatureSetReader(MgFeatureSet* featureSet);
+
+EXTERNAL_API:
+	virtual ~MgdFeatureSetReader();
+
+	//MgReader
+PUBLISHED_API:
+    virtual bool ReadNext();
+
+    virtual bool IsNull(CREFSTRING propertyName);
+
+    virtual bool GetBoolean(CREFSTRING propertyName);
+
+    virtual BYTE GetByte(CREFSTRING propertyName);
+
+    virtual MgDateTime* GetDateTime(CREFSTRING propertyName);
+
+    virtual float GetSingle(CREFSTRING propertyName);
+
+    virtual double GetDouble(CREFSTRING propertyName);
+
+    virtual INT16 GetInt16(CREFSTRING propertyName);
+
+    virtual INT32 GetInt32(CREFSTRING propertyName);
+
+    virtual INT64 GetInt64(CREFSTRING propertyName);
+
+    virtual STRING GetString(CREFSTRING propertyName);
+
+    virtual MgByteReader* GetBLOB(CREFSTRING propertyName);
+
+    virtual MgByteReader* GetCLOB(CREFSTRING propertyName);
+
+    virtual MgByteReader* GetGeometry(CREFSTRING propertyName);
+
+    virtual MgRaster* GetRaster(CREFSTRING propertyName);
+
+    virtual bool IsNull(INT32 index);
+
+    virtual bool GetBoolean(INT32 index);
+
+    virtual BYTE GetByte(INT32 index);
+
+    virtual MgDateTime* GetDateTime(INT32 index);
+
+    virtual float GetSingle(INT32 index);
+
+    virtual double GetDouble(INT32 index);
+
+    virtual INT16 GetInt16(INT32 index);
+
+    virtual INT32 GetInt32(INT32 index);
+
+    virtual INT64 GetInt64(INT32 index);
+
+    virtual STRING GetString(INT32 index);
+
+    virtual MgByteReader* GetBLOB(INT32 index);
+
+    virtual MgByteReader* GetCLOB(INT32 index);
+
+    virtual MgByteReader* GetGeometry(INT32 index);
+
+    virtual MgRaster* GetRaster(INT32 index);
+
+    virtual void Close();
+
+    virtual INT32 GetReaderType();
+
+EXTERNAL_API:
+
+    virtual MgByteReader* ToXml();
+
+INTERNAL_API:
+
+    virtual const wchar_t* GetString(CREFSTRING propertyName, INT32& length);
+
+    virtual const wchar_t* GetString(INT32 index, INT32& length);
+
+    virtual void Serialize(MgStream* stream);
+
+    virtual void Deserialize(MgStream* stream);
+
+    void ToXml(string &str);
+
+    void AssignFeatureSet(MgFeatureSet* featureSet);
+
+	//MgFeatureReader
+PUBLISHED_API:
+    virtual MgClassDefinition* GetClassDefinition();
+
+    virtual MgFeatureReader* GetFeatureObject(CREFSTRING propertyName);
+
+    virtual MgFeatureReader* GetFeatureObject(INT32 index);
+
+INTERNAL_API:
+
+    virtual BYTE_ARRAY_OUT GetGeometry(CREFSTRING propertyName, INT32& length);
+
+    virtual BYTE_ARRAY_OUT GetGeometry(INT32 index, INT32& length);
+
+INTERNAL_API:
+
+    virtual MgClassDefinition* GetClassDefinitionNoXml();
+
+    virtual MgFeatureSet* GetFeatures(INT32 count);
+
+    MgByteReader* GetRaster(STRING rasterPropName, INT32 xSize, INT32 ySize);
+
+protected:
+	virtual void Dispose() { delete this; }
+
+private:
+    MgProperty* GetProperty(CREFSTRING propertyName, INT16 expectedType);
+    /// Get the property for the specified name
+    MgProperty* GetProperty(CREFSTRING propertyName);
+
+    MgProperty* GetProperty(INT32 index, INT16 expectedType);
+    /// Get the property at the specified index
+    MgProperty* GetProperty(INT32 index);
+
+    Ptr<MgFeatureSet> m_set;
+    INT32 m_currRecord;
+};
+
+#endif
\ No newline at end of file

Modified: branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/FeatureUtil.cpp
===================================================================
--- branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/FeatureUtil.cpp	2012-07-15 15:04:11 UTC (rev 6902)
+++ branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/FeatureUtil.cpp	2012-07-15 16:59:27 UTC (rev 6903)
@@ -3430,4 +3430,73 @@
         }
         break;
     }
-}
\ No newline at end of file
+}
+
+FdoIdentifierCollection* MgFeatureUtil::ExtractIdentifiers(FdoExpression* expr)
+{
+    CHECKNULL(expr, L"MgFeatureUtil.ExtractIdentifiers");
+
+    FdoPtr<FdoIdentifierCollection> ret;
+    MG_FEATURE_SERVICE_TRY()
+
+    ret = FdoIdentifierCollection::Create();
+
+    switch(expr->GetExpressionType())
+    {
+    case FdoExpressionItemType_ComputedIdentifier:
+        {
+            FdoComputedIdentifier* comp = static_cast<FdoComputedIdentifier*>(expr);
+            FdoPtr<FdoExpression> inner = comp->GetExpression();
+
+            FdoPtr<FdoIdentifierCollection> result = ExtractIdentifiers(inner);
+            for (FdoInt32 i = 0; i < result->GetCount(); i++)
+            {
+                FdoPtr<FdoIdentifier> resultItem = result->GetItem(i);
+                ret->Add(resultItem);
+            }
+        }
+        break;
+    case FdoExpressionItemType_Function:
+        {
+            FdoFunction* func = static_cast<FdoFunction*>(expr);
+            FdoExpressionCollection* funcArgs = func->GetArguments();
+            for (FdoInt32 i = 0; i < funcArgs->GetCount(); i++)
+            {
+                FdoPtr<FdoExpression> arg = funcArgs->GetItem(i);
+                FdoPtr<FdoIdentifierCollection> result = ExtractIdentifiers(arg);
+                for (FdoInt32 j = 0; j < result->GetCount(); j++)
+                {
+                    FdoPtr<FdoIdentifier> resultItem = result->GetItem(j);
+                    ret->Add(resultItem);
+                }
+            }
+        }
+        break;
+    case FdoExpressionItemType_Identifier:
+        ret->Add(static_cast<FdoIdentifier*>(expr));
+        break;
+    case FdoExpressionItemType_UnaryExpression:
+        {
+            FdoUnaryExpression* unexpr = static_cast<FdoUnaryExpression*>(expr);
+            FdoExpression* inner = unexpr->GetExpression();
+
+            FdoPtr<FdoIdentifierCollection> result = ExtractIdentifiers(inner);
+            for (FdoInt32 i = 0; i < result->GetCount(); i++)
+            {
+                FdoPtr<FdoIdentifier> resultItem = result->GetItem(i);
+                ret->Add(resultItem);
+            }
+        }
+        break;
+    case FdoExpressionItemType_SubSelectExpression:
+        {
+            FdoSubSelectExpression* subSelect = static_cast<FdoSubSelectExpression*>(expr);
+            FdoPtr<FdoIdentifier> propName = subSelect->GetPropertyName();
+            ret->Add(propName);
+        }
+        break;
+    }
+
+    MG_FEATURE_SERVICE_CATCH_AND_THROW(L"MgServerFeatureUtil.ExtractIdentifiers")
+    return ret.Detach();
+}

Modified: branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/FeatureUtil.h
===================================================================
--- branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/FeatureUtil.h	2012-07-15 15:04:11 UTC (rev 6902)
+++ branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/FeatureUtil.h	2012-07-15 16:59:27 UTC (rev 6903)
@@ -115,6 +115,7 @@
     static MgClassDefinition* CloneMgClassDefinition(MgClassDefinition* classDef);
     static MgFeatureSchema* CloneMgSchema(MgFeatureSchema* schema);
     static void UpdateFdoPropertyValue(FdoPropertyValue* fp, MgProperty* prop);
+    static FdoIdentifierCollection* ExtractIdentifiers(FdoExpression* expr);
 private:
     static bool Initialize();
 

Deleted: branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/FeautreNumericFunctions.h
===================================================================
--- branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/FeautreNumericFunctions.h	2012-07-15 15:04:11 UTC (rev 6902)
+++ branches/2.4/MgDev/Desktop/MgDesktop/Services/Feature/FeautreNumericFunctions.h	2012-07-15 16:59:27 UTC (rev 6903)
@@ -1,92 +0,0 @@
-//
-//  Copyright (C) 2004-2011 by Autodesk, Inc.
-//
-//  This library is free software; you can redistribute it and/or
-//  modify it under the terms of version 2.1 of the GNU Lesser
-//  General Public License as published by the Free Software Foundation.
-//
-//  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 St, Fifth Floor, Boston, MA  02110-1301  USA
-//
-
-#ifndef MG_FEATURE_NUMERIC_FUNCTIONS_H_
-#define MG_FEATURE_NUMERIC_FUNCTIONS_H_
-
-class MgDisposable;
-class FdoFunction;
-class MgReader;
-class MgFeatureDistribution;
-
-class MgFeatureNumericFunctions : public MgFeatureDistribution
-{
-    DECLARE_CLASSNAME(MgFeatureNumericFunctions)
-
-public:
-
-    MgFeatureNumericFunctions(MgReader* reader, FdoFunction* customFunction, CREFSTRING propertyAlias);
-    virtual ~MgFeatureNumericFunctions();
-    virtual MgReader* Execute();
-    virtual void Dispose()
-    {
-        delete this;
-    }
-
-protected:
-
-    MgFeatureNumericFunctions();
-
-private:
-
-    void Initialize(MgReader* reader, FdoFunction* customFunction, CREFSTRING propertyAlias);
-
-    void CalculateDistribution(VECTOR& values, VECTOR& distValues);
-    // do not call this method for other functions than MINIMUM, MAXIMUM, UNIQUE
-    void CalculateDistribution(VECTOR_INT64& values, VECTOR_INT64& distValues);
-    MgReader* GetReader(VECTOR& distValues);
-
-
-    // Distribution methods
-    void GetEqualCategories(VECTOR &values, int numCats, double dataMin, double dataMax, VECTOR &distValues);
-    void GetStandardDeviationCategories(VECTOR &values, int numCats, double dataMin, double dataMax, VECTOR &distValues);
-    void GetQuantileCategories(VECTOR &values, int numCats, double dataMin, double dataMax, VECTOR &distValues );
-
-    // Jenk methods
-    void GetJenksCategories(VECTOR &inputData, int numPartsRequested, double dataMin, double dataMax, VECTOR &distValues);
-    bool FixGroups(const std::vector<double>& data, std::vector<int>& indices);
-    bool FixDuplicateIndices(std::vector<int>& indices);
-    bool FixIndicesByValue(const std::vector<double>& data, std::vector<int>& indices);
-    bool doubles_equal(double d1, double d2);
-
-    // Single row methods
-    void GetMeanValue(VECTOR &values, VECTOR &distValues);
-    void GetStandardDeviation(VECTOR &values, VECTOR &distValues);
-    void GetUniqueValue(VECTOR &values, VECTOR &distValues);
-    void GetUniqueValue(VECTOR_INT64 &values, VECTOR_INT64 &distValues);
-    void GetMinimum(VECTOR &values, VECTOR &distValues);
-    void GetMinimum(VECTOR_INT64 &values, VECTOR_INT64 &distValues);
-    void GetMaximum(VECTOR &values, VECTOR &distValues);
-    void GetMaximum(VECTOR_INT64 &values, VECTOR_INT64 &distValues);
-
-    // Utility methods
-    bool IsInf(double x);
-    bool IsNan(double x);
-
-    void CheckSupportedPropertyType();
-    double GetValue();
-
-private:
-
-    STRING m_propertyName;
-    INT16 m_type;
-    Ptr<MgReader> m_reader;
-    FdoPtr<FdoFunction> m_customFunction;
-    STRING m_propertyAlias;
-};
-
-#endif



More information about the mapguide-commits mailing list