[mapguide-commits] r9576 - in trunk/MgDev: . Common/MapGuideCommon/Services Common/PlatformBase/Services Oem/LinuxApt Server/src/Services/Feature Web/src/ApacheAgent Web/src/CgiAgent Web/src/HttpHandler Web/src/IsapiAgent Web/src/MapAgentCommon
svn_mapguide at osgeo.org
svn_mapguide at osgeo.org
Wed Jul 17 02:32:14 PDT 2019
Author: jng
Date: 2019-07-17 02:32:14 -0700 (Wed, 17 Jul 2019)
New Revision: 9576
Modified:
trunk/MgDev/
trunk/MgDev/Common/MapGuideCommon/Services/ProxyFeatureService.cpp
trunk/MgDev/Common/MapGuideCommon/Services/ProxyFeatureService.h
trunk/MgDev/Common/PlatformBase/Services/FeatureDefs.h
trunk/MgDev/Common/PlatformBase/Services/FeatureService.h
trunk/MgDev/Oem/LinuxApt/
trunk/MgDev/Server/src/Services/Feature/FeatureOperationFactory.cpp
trunk/MgDev/Server/src/Services/Feature/ServerFeatureService.cpp
trunk/MgDev/Server/src/Services/Feature/ServerFeatureService.h
trunk/MgDev/Server/src/Services/Feature/ServerFeatureService.vcxproj
trunk/MgDev/Server/src/Services/Feature/ServerFeatureService.vcxproj.filters
trunk/MgDev/Server/src/Services/Feature/ServerFeatureServiceBuild.cpp
trunk/MgDev/Server/src/Services/Feature/WfsQueryAdapter.cpp
trunk/MgDev/Server/src/Services/Feature/WfsQueryAdapter.h
trunk/MgDev/Web/src/ApacheAgent/ApachePostParser.cpp
trunk/MgDev/Web/src/CgiAgent/CgiPostParser.cpp
trunk/MgDev/Web/src/HttpHandler/HttpResourceStrings.cpp
trunk/MgDev/Web/src/HttpHandler/HttpResourceStrings.h
trunk/MgDev/Web/src/HttpHandler/HttpWfsGetFeature.cpp
trunk/MgDev/Web/src/HttpHandler/ReaderByteSourceImpl.cpp
trunk/MgDev/Web/src/HttpHandler/WfsGetFeatureParams.cpp
trunk/MgDev/Web/src/HttpHandler/WfsGetFeatureParams.h
trunk/MgDev/Web/src/HttpHandler/WmsMapUtil.cpp
trunk/MgDev/Web/src/IsapiAgent/IsapiPostParser.cpp
trunk/MgDev/Web/src/MapAgentCommon/MapAgentStrings.cpp
trunk/MgDev/Web/src/MapAgentCommon/MapAgentStrings.h
Log:
MapGuide RFC 175: Merge wfs_hits sandbox.
Index: trunk/MgDev
===================================================================
--- trunk/MgDev 2019-07-14 13:50:50 UTC (rev 9575)
+++ trunk/MgDev 2019-07-17 09:32:14 UTC (rev 9576)
Property changes on: trunk/MgDev
___________________________________________________________________
Modified: svn:mergeinfo
## -30,5 +30,6 ##
/sandbox/jng/utfgrid:9179-9212
/sandbox/jng/v30:8212-8227
/sandbox/jng/v4:9511-9519
+/sandbox/jng/wfs_hits:9569-9575
/sandbox/rfc94:5099-5163
/trunk/MgDev:9397-9399
\ No newline at end of property
Modified: trunk/MgDev/Common/MapGuideCommon/Services/ProxyFeatureService.cpp
===================================================================
--- trunk/MgDev/Common/MapGuideCommon/Services/ProxyFeatureService.cpp 2019-07-14 13:50:50 UTC (rev 9575)
+++ trunk/MgDev/Common/MapGuideCommon/Services/ProxyFeatureService.cpp 2019-07-17 09:32:14 UTC (rev 9576)
@@ -1505,6 +1505,28 @@
return SAFE_ADDREF((MgProxyFeatureReader*)featReader);
}
+INT32 MgProxyFeatureService::GetWfsFeatureTotal(MgResourceIdentifier* featureSourceId,
+ CREFSTRING featureClass,
+ CREFSTRING filter,
+ INT32 maxFeatures)
+{
+ MgCommand cmd;
+ cmd.ExecuteCommand(m_connProp, // Connection
+ MgCommand::knInt32, // Return type expected
+ MgFeatureServiceOpId::GetWfsFeatureTotal_Id, // Command Code
+ 4, // No of arguments
+ Feature_Service, // Service Id
+ BUILD_VERSION(4, 0, 0), // Operation version
+ MgCommand::knObject, featureSourceId, // Argument#1
+ MgCommand::knString, &featureClass, // Argument#2
+ MgCommand::knString, &filter, // Argument#3
+ MgCommand::knInt32, maxFeatures, // Argument#4
+ MgCommand::knNone); // End of argument
+
+ SetWarning(cmd.GetWarningObject());
+ return cmd.GetReturnValue().val.m_i32;
+}
+
//////////////////////////////////////////////////////////////////
MgBatchPropertyCollection* MgProxyFeatureService::GetFeatures(CREFSTRING featureReader)
{
Modified: trunk/MgDev/Common/MapGuideCommon/Services/ProxyFeatureService.h
===================================================================
--- trunk/MgDev/Common/MapGuideCommon/Services/ProxyFeatureService.h 2019-07-14 13:50:50 UTC (rev 9575)
+++ trunk/MgDev/Common/MapGuideCommon/Services/ProxyFeatureService.h 2019-07-17 09:32:14 UTC (rev 9576)
@@ -1563,6 +1563,49 @@
CREFSTRING filter,
CREFSTRING sortCriteria);
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////
+ /// \brief
+ /// Retrieves the total feature count for the given WFS query
+ ///
+ /// \note1
+ ///
+ /// <!-- Syntax in .Net, Java, and PHP -->
+ /// \htmlinclude DotNetSyntaxTop.html
+ /// virtual int GetWfsFeatureTotal(MgResourceIdentifier featureSourceId, string featureClass, string filter, int maxFeatures);
+ /// \htmlinclude SyntaxBottom.html
+ /// \htmlinclude JavaSyntaxTop.html
+ /// virtual int GetWfsFeatureTotal(MgResourceIdentifier featureSourceId, string featureClass, string filter, int maxFeatures);
+ /// \htmlinclude SyntaxBottom.html
+ /// \htmlinclude PHPSyntaxTop.html
+ /// virtual int GetWfsFeatureTotal(MgResourceIdentifier featureSourceId, string featureClass, string filter, int maxFeatures);
+ /// \htmlinclude SyntaxBottom.html
+ ///
+ /// \param featureSourceId (MgResourceIdentifier)
+ /// The resource identifier defining the
+ /// location of the feature source in
+ /// the repository.
+ /// \param featureClass (String/string)
+ /// The feature class containing the features to retrieve.
+ /// \param filter (String/string)
+ /// An XML string containing the definition for an OGC filter
+ /// \param maxFeatures (int)
+ /// If greater than 0 and less than the real computed total, this will be the value returned
+ ///
+ /// \remarks
+ /// This method is primarily used to service the WFS GetFeatures operation in resultType=hits mode
+ /// where a total is desired over requesting the whole set of feature data
+ ///
+ /// \return
+ /// Returns an MgByteReader containing the requested feature information.
+ ///
+ /// \exception MgInvalidArgumentException
+ ///
+ /// \since 4.0
+ INT32 GetWfsFeatureTotal(MgResourceIdentifier* featureSourceId,
+ CREFSTRING featureClass,
+ CREFSTRING filter,
+ INT32 maxFeatures);
+
////////////////////////////////////////////////////////////////////////////////
/// \brief
/// This method enumerates all the providers and if they are FDO enabled for
Modified: trunk/MgDev/Common/PlatformBase/Services/FeatureDefs.h
===================================================================
--- trunk/MgDev/Common/PlatformBase/Services/FeatureDefs.h 2019-07-14 13:50:50 UTC (rev 9575)
+++ trunk/MgDev/Common/PlatformBase/Services/FeatureDefs.h 2019-07-17 09:32:14 UTC (rev 9576)
@@ -85,6 +85,7 @@
static const int SelectFeaturesWithTransform = 0x1111ED35;
static const int GetWfsReader_Id = 0x1111ED36;
+ static const int GetWfsFeatureTotal_Id = 0x1111ED37;
};
/// \endcond
Modified: trunk/MgDev/Common/PlatformBase/Services/FeatureService.h
===================================================================
--- trunk/MgDev/Common/PlatformBase/Services/FeatureService.h 2019-07-14 13:50:50 UTC (rev 9575)
+++ trunk/MgDev/Common/PlatformBase/Services/FeatureService.h 2019-07-17 09:32:14 UTC (rev 9576)
@@ -2046,13 +2046,13 @@
///
/// <!-- Syntax in .Net, Java, and PHP -->
/// \htmlinclude DotNetSyntaxTop.html
- /// virtual MgFeatureReader GetWfsReader(MgResourceIdentifier featureSourceId, string featureClass, MgStringCollection requiredProperties, string srs, string filter, int maxFeatures, string outputFormat, string sortCriteria);
+ /// virtual MgFeatureReader GetWfsReader(MgResourceIdentifier featureSourceId, string featureClass, MgStringCollection requiredProperties, string srs, string filter, string sortCriteria);
/// \htmlinclude SyntaxBottom.html
/// \htmlinclude JavaSyntaxTop.html
- /// virtual MgFeatureReader GetWfsReader(MgResourceIdentifier featureSourceId, string featureClass, MgStringCollection requiredProperties, string srs, string filter, int maxFeatures, string outputFormat, string sortCriteria);
+ /// virtual MgFeatureReader GetWfsReader(MgResourceIdentifier featureSourceId, string featureClass, MgStringCollection requiredProperties, string srs, string filter, string sortCriteria);
/// \htmlinclude SyntaxBottom.html
/// \htmlinclude PHPSyntaxTop.html
- /// virtual MgFeatureReader GetWfsReader(MgResourceIdentifier featureSourceId, string featureClass, MgStringCollection requiredProperties, string srs, string filter, int maxFeatures, string outputFormat, string sortCriteria);
+ /// virtual MgFeatureReader GetWfsReader(MgResourceIdentifier featureSourceId, string featureClass, MgStringCollection requiredProperties, string srs, string filter, string sortCriteria);
/// \htmlinclude SyntaxBottom.html
///
/// \param featureSourceId (MgResourceIdentifier)
@@ -2122,6 +2122,49 @@
INTERNAL_API:
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////
+ /// \brief
+ /// Retrieves the total feature count for the given WFS query
+ ///
+ /// \note1
+ ///
+ /// <!-- Syntax in .Net, Java, and PHP -->
+ /// \htmlinclude DotNetSyntaxTop.html
+ /// virtual int GetWfsFeatureTotal(MgResourceIdentifier featureSourceId, string featureClass, string filter, int maxFeatures);
+ /// \htmlinclude SyntaxBottom.html
+ /// \htmlinclude JavaSyntaxTop.html
+ /// virtual int GetWfsFeatureTotal(MgResourceIdentifier featureSourceId, string featureClass, string filter, int maxFeatures);
+ /// \htmlinclude SyntaxBottom.html
+ /// \htmlinclude PHPSyntaxTop.html
+ /// virtual int GetWfsFeatureTotal(MgResourceIdentifier featureSourceId, string featureClass, string filter, int maxFeatures);
+ /// \htmlinclude SyntaxBottom.html
+ ///
+ /// \param featureSourceId (MgResourceIdentifier)
+ /// The resource identifier defining the
+ /// location of the feature source in
+ /// the repository.
+ /// \param featureClass (String/string)
+ /// The feature class containing the features to retrieve.
+ /// \param filter (String/string)
+ /// An XML string containing the definition for an OGC filter
+ /// \param maxFeatures (int)
+ /// If greater than 0 and less than the real computed total, this will be the value returned
+ ///
+ /// \remarks
+ /// This method is primarily used to service the WFS GetFeatures operation in resultType=hits mode
+ /// where a total is desired over requesting the whole set of feature data
+ ///
+ /// \return
+ /// Returns an MgByteReader containing the requested feature information.
+ ///
+ /// \exception MgInvalidArgumentException
+ ///
+ /// \since 4.0
+ virtual INT32 GetWfsFeatureTotal(MgResourceIdentifier* featureSourceId,
+ CREFSTRING featureClass,
+ CREFSTRING filter,
+ INT32 maxFeatures) = 0;
+
//////////////////////////////////////////////////////////////////
/// \brief
/// Construct an MgFeatureService object.
Index: trunk/MgDev/Oem/LinuxApt
===================================================================
--- trunk/MgDev/Oem/LinuxApt 2019-07-14 13:50:50 UTC (rev 9575)
+++ trunk/MgDev/Oem/LinuxApt 2019-07-17 09:32:14 UTC (rev 9576)
Property changes on: trunk/MgDev/Oem/LinuxApt
___________________________________________________________________
Modified: svn:ignore
## -1,3 +1,3 ##
*.tar
-httpd-2.4.29
-php-5.6.33
+httpd-2.4.37
+php-5.6.40
Modified: trunk/MgDev/Server/src/Services/Feature/FeatureOperationFactory.cpp
===================================================================
--- trunk/MgDev/Server/src/Services/Feature/FeatureOperationFactory.cpp 2019-07-14 13:50:50 UTC (rev 9575)
+++ trunk/MgDev/Server/src/Services/Feature/FeatureOperationFactory.cpp 2019-07-17 09:32:14 UTC (rev 9576)
@@ -59,6 +59,7 @@
#include "OpDescribeWfsFeatureType.h"
#include "OpGetWfsFeature.h"
#include "OpGetWfsReader.h"
+#include "OpGetWfsFeatureTotal.h"
#include "OpEnumerateDataStores.h"
#include "OpGetSchemaMapping.h"
#include "OpGetFdoCacheInfo.h"
@@ -592,6 +593,18 @@
}
break;
+ case MgFeatureServiceOpId::GetWfsFeatureTotal_Id:
+ switch (VERSION_NO_PHASE(operationVersion))
+ {
+ case VERSION_SUPPORTED(4, 0):
+ handler.reset(new MgOpGetWfsFeatureTotal());
+ break;
+ default:
+ throw new MgInvalidOperationVersionException(
+ L"MgFeatureOperationFactory.GetOperation", __LINE__, __WFILE__, NULL, L"", NULL);
+ }
+ break;
+
case MgFeatureServiceOpId::EnumerateDataStores_Id:
switch (VERSION_NO_PHASE(operationVersion))
{
Modified: trunk/MgDev/Server/src/Services/Feature/ServerFeatureService.cpp
===================================================================
--- trunk/MgDev/Server/src/Services/Feature/ServerFeatureService.cpp 2019-07-14 13:50:50 UTC (rev 9575)
+++ trunk/MgDev/Server/src/Services/Feature/ServerFeatureService.cpp 2019-07-17 09:32:14 UTC (rev 9576)
@@ -2067,6 +2067,28 @@
}
+INT32 MgServerFeatureService::GetWfsFeatureTotal(MgResourceIdentifier* fs,
+ CREFSTRING featureClass,
+ CREFSTRING wfsFilter,
+ INT32 maxFeatures)
+{
+ INT32 total = -1;
+
+ MG_LOG_TRACE_ENTRY(L"MgServerFeatureService::GetWfsFeatureTotal()");
+
+ Ptr<MgFeatureReader> mgfReader;
+
+ MG_FEATURE_SERVICE_TRY()
+
+ MgWfsQueryAdapter wfsQuery(this);
+ wfsQuery.SetOptions(fs, featureClass, NULL, L"", wfsFilter, L"");
+ total = wfsQuery.GetTotal(maxFeatures);
+
+ MG_FEATURE_SERVICE_CHECK_CONNECTION_CATCH_AND_THROW(fs, L"MgServerFeatureService.GetWfsFeatureTotal")
+
+ return total;
+}
+
////////////////////////////////////////////////////////////////////////////////////////////////////////
/// \brief
/// Retrieves feature information based on the supplied criteria with specified format.
Modified: trunk/MgDev/Server/src/Services/Feature/ServerFeatureService.h
===================================================================
--- trunk/MgDev/Server/src/Services/Feature/ServerFeatureService.h 2019-07-14 13:50:50 UTC (rev 9575)
+++ trunk/MgDev/Server/src/Services/Feature/ServerFeatureService.h 2019-07-17 09:32:14 UTC (rev 9576)
@@ -952,6 +952,11 @@
CREFSTRING filter,
CREFSTRING sortCriteria);
+ INT32 GetWfsFeatureTotal(MgResourceIdentifier* featureSourceId,
+ CREFSTRING featureClass,
+ CREFSTRING filter,
+ INT32 maxFeatures);
+
////////////////////////////////////////////////////////////////////////////////
/// <summary>
/// This method enumerates all the providers and if they are FDO enabled for
Modified: trunk/MgDev/Server/src/Services/Feature/ServerFeatureService.vcxproj
===================================================================
--- trunk/MgDev/Server/src/Services/Feature/ServerFeatureService.vcxproj 2019-07-14 13:50:50 UTC (rev 9575)
+++ trunk/MgDev/Server/src/Services/Feature/ServerFeatureService.vcxproj 2019-07-17 09:32:14 UTC (rev 9576)
@@ -513,6 +513,12 @@
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</ClCompile>
+ <ClCompile Include="OpGetWfsFeatureTotal.cpp">
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
+ </ClCompile>
<ClCompile Include="OpXmlToSchema.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
@@ -864,6 +870,7 @@
<ClInclude Include="OpGetSpatialContexts.h" />
<ClInclude Include="OpGetSqlRows.h" />
<ClInclude Include="OpGetWfsFeature.h" />
+ <ClInclude Include="OpGetWfsFeatureTotal.h" />
<ClInclude Include="OpGetWfsReader.h" />
<ClInclude Include="OpInsertFeatures.h" />
<ClInclude Include="OpInsertFeaturesBatched.h" />
Modified: trunk/MgDev/Server/src/Services/Feature/ServerFeatureService.vcxproj.filters
===================================================================
--- trunk/MgDev/Server/src/Services/Feature/ServerFeatureService.vcxproj.filters 2019-07-14 13:50:50 UTC (rev 9575)
+++ trunk/MgDev/Server/src/Services/Feature/ServerFeatureService.vcxproj.filters 2019-07-17 09:32:14 UTC (rev 9576)
@@ -205,6 +205,9 @@
<Filter>Ops</Filter>
</ClCompile>
<ClCompile Include="WfsQueryAdapter.cpp" />
+ <ClCompile Include="OpGetWfsFeatureTotal.cpp">
+ <Filter>Ops</Filter>
+ </ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="FeatureOperation.h">
@@ -419,6 +422,9 @@
<Filter>Ops</Filter>
</ClInclude>
<ClInclude Include="WfsQueryAdapter.h" />
+ <ClInclude Include="OpGetWfsFeatureTotal.h">
+ <Filter>Ops</Filter>
+ </ClInclude>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="ServerFeatureService.rc" />
Modified: trunk/MgDev/Server/src/Services/Feature/ServerFeatureServiceBuild.cpp
===================================================================
--- trunk/MgDev/Server/src/Services/Feature/ServerFeatureServiceBuild.cpp 2019-07-14 13:50:50 UTC (rev 9575)
+++ trunk/MgDev/Server/src/Services/Feature/ServerFeatureServiceBuild.cpp 2019-07-17 09:32:14 UTC (rev 9576)
@@ -86,6 +86,7 @@
#include "OpGetIdentityProperties.cpp"
#include "OpDescribeWfsFeatureType.cpp"
#include "OpGetWfsFeature.cpp"
+#include "OpGetWfsFeatureTotal.cpp"
#include "OpGetWfsReader.cpp"
#include "FilterUtil.cpp"
#include "WfsQueryAdapter.cpp"
Modified: trunk/MgDev/Server/src/Services/Feature/WfsQueryAdapter.cpp
===================================================================
--- trunk/MgDev/Server/src/Services/Feature/WfsQueryAdapter.cpp 2019-07-14 13:50:50 UTC (rev 9575)
+++ trunk/MgDev/Server/src/Services/Feature/WfsQueryAdapter.cpp 2019-07-17 09:32:14 UTC (rev 9576)
@@ -213,4 +213,29 @@
fr = m_featSvc->SelectFeatures(m_fs, m_className, m_options);
MG_FEATURE_SERVICE_CHECK_CONNECTION_CATCH_AND_THROW(m_fs, L"MgWfsQueryAdapter.GetWfsReader")
return fr.Detach();
+}
+
+INT32 MgWfsQueryAdapter::GetTotal(INT32 maxFeatures)
+{
+ INT32 total = 0;
+
+ MG_FEATURE_SERVICE_TRY()
+ // TODO: can FeatureName be an extension name rather than a FeatureClass?
+ Ptr<MgFeatureReader> fr = m_featSvc->SelectFeatures(m_fs, m_className, m_options);
+
+ // You may think: Why are we raw spinning this reader? We have select aggregates (with COUNT())
+ // and other performant shortcuts available, but the real stickler is the maxFeatures parameter
+ // passed in. WFS queries allow for this to be passed in and if we get one, we must respect
+ // the value. None of our performant shortcuts allow us to apply an upper limit on it. So given
+ // these constraints, raw spinning the feature reader is the only viable option.
+ while (fr->ReadNext())
+ {
+ total++;
+ //Break loop if we hit max features
+ if (maxFeatures > 0 && total >= maxFeatures)
+ break;
+ }
+
+ MG_FEATURE_SERVICE_CHECK_CONNECTION_CATCH_AND_THROW(m_fs, L"MgWfsQueryAdapter.GetWfsReader")
+ return total;
}
\ No newline at end of file
Modified: trunk/MgDev/Server/src/Services/Feature/WfsQueryAdapter.h
===================================================================
--- trunk/MgDev/Server/src/Services/Feature/WfsQueryAdapter.h 2019-07-14 13:50:50 UTC (rev 9575)
+++ trunk/MgDev/Server/src/Services/Feature/WfsQueryAdapter.h 2019-07-17 09:32:14 UTC (rev 9576)
@@ -37,6 +37,7 @@
MgCoordinateSystem* GetMapCs();
MgCoordinateSystemTransform* GetTransform();
MgClassDefinition* GetClassDefinition();
+ INT32 GetTotal(INT32 maxFeatures);
private:
Ptr<MgClassDefinition> m_classDef;
Modified: trunk/MgDev/Web/src/ApacheAgent/ApachePostParser.cpp
===================================================================
--- trunk/MgDev/Web/src/ApacheAgent/ApachePostParser.cpp 2019-07-14 13:50:50 UTC (rev 9575)
+++ trunk/MgDev/Web/src/ApacheAgent/ApachePostParser.cpp 2019-07-17 09:32:14 UTC (rev 9576)
@@ -158,7 +158,7 @@
// The check for text/xml is not always sufficient. CarbonTools, for example,
// fails to set Content-Type: text/xml and just sends Content-Type: utf-8.
// A better check might be looking into the buffer to find "<?xml" at the beginning.
- else if (content.find(MapAgentStrings::TextXml) != content.npos || MapAgentCommon::IsXmlPi((char *)m_pBuffer))
+ else if (MapAgentStrings::IsXmlMimeType(content) || MapAgentCommon::IsXmlPi((char *)m_pBuffer))
{
m_pBuffer[totalBytes] = '\0';
params->SetXmlPostData((char *)m_pBuffer);
Modified: trunk/MgDev/Web/src/CgiAgent/CgiPostParser.cpp
===================================================================
--- trunk/MgDev/Web/src/CgiAgent/CgiPostParser.cpp 2019-07-14 13:50:50 UTC (rev 9575)
+++ trunk/MgDev/Web/src/CgiAgent/CgiPostParser.cpp 2019-07-17 09:32:14 UTC (rev 9576)
@@ -145,9 +145,9 @@
// url-encoded, since the question mark in <?xml...?>
// should itself be url-encoded: <%3Fxml... )
if(IsXmlPi(m_buf))
- params->SetXmlPostData(m_buf);
+ params->SetXmlPostData(m_buf);
else
- MapAgentGetParser::Parse(m_buf, params);
+ MapAgentGetParser::Parse(m_buf, params);
}
}
else if (content.find(MapAgentStrings::MultiPartForm) != content.npos)
@@ -281,7 +281,7 @@
// The check for text/xml is not always sufficient. CarbonTools, for example,
// fails to set Content-Type: text/xml and just sends Content-Type: utf-8.
// A better check might be looking into the buffer to find "<?xml" at the beginning.
- else if (content.find(MapAgentStrings::TextXml) != content.npos || IsXmlPi(m_buf))
+ else if (MapAgentStrings::IsXmlMimeType(content) || IsXmlPi(m_buf))
{
m_buf[nBytes] = '\0';
params->SetXmlPostData(m_buf);
Modified: trunk/MgDev/Web/src/HttpHandler/HttpResourceStrings.cpp
===================================================================
--- trunk/MgDev/Web/src/HttpHandler/HttpResourceStrings.cpp 2019-07-14 13:50:50 UTC (rev 9575)
+++ trunk/MgDev/Web/src/HttpHandler/HttpResourceStrings.cpp 2019-07-17 09:32:14 UTC (rev 9576)
@@ -326,6 +326,7 @@
const STRING MgHttpResourceStrings::reqWfsBbox = L"BBOX";
const STRING MgHttpResourceStrings::reqWfsOutputFormat = L"OUTPUTFORMAT";
const STRING MgHttpResourceStrings::reqWfsSortBy = L"SORTBY";
+const STRING MgHttpResourceStrings::reqWfsResultType = L"RESULTTYPE";
// Web Application Parameters
const STRING MgHttpResourceStrings::reqFormat = L"FORMAT";
Modified: trunk/MgDev/Web/src/HttpHandler/HttpResourceStrings.h
===================================================================
--- trunk/MgDev/Web/src/HttpHandler/HttpResourceStrings.h 2019-07-14 13:50:50 UTC (rev 9575)
+++ trunk/MgDev/Web/src/HttpHandler/HttpResourceStrings.h 2019-07-17 09:32:14 UTC (rev 9576)
@@ -237,6 +237,7 @@
static const STRING reqWfsBbox;
static const STRING reqWfsOutputFormat;
static const STRING reqWfsSortBy;
+ static const STRING reqWfsResultType;
// PREDEFINED WEB APPLICATION REQUEST PARAMETERS
static const STRING reqFormat;
Modified: trunk/MgDev/Web/src/HttpHandler/HttpWfsGetFeature.cpp
===================================================================
--- trunk/MgDev/Web/src/HttpHandler/HttpWfsGetFeature.cpp 2019-07-14 13:50:50 UTC (rev 9575)
+++ trunk/MgDev/Web/src/HttpHandler/HttpWfsGetFeature.cpp 2019-07-17 09:32:14 UTC (rev 9576)
@@ -300,41 +300,79 @@
numFeaturesToRetrieve = limit;
}
- // Call the C++ API
- // NOTE: I updated the maxFeatures value from numFeaturesToRetrieve to numFeaturesToRetrieve-1
- // Because the MgServerFdoFeatureReader in MapGuide server uses -1 to mark empty, while MgWfsFeatures
- // in MapGuide web tier uses 0
+ // Is this hit mode? If so, just request the raw total
+ if (m_getFeatureParams->IsHitMode())
+ {
+ INT32 total = featureService->GetWfsFeatureTotal(featureSourceId, ((sSchemaHash.size() == 0) ? sClass : sSchemaHash + _(":") + sClass), sSortCriteria, numFeaturesToRetrieve);
+ std::string sTotal;
+ MgUtil::Int32ToString(total, sTotal);
+ if (sOutputFormat == MgMimeType::Json)
+ {
+ std::string json = "{";
+ json += "\"numberOfFeatures\": ";
+ json += sTotal;
+ json += "}";
+ Ptr<MgByteSource> bs = new MgByteSource((BYTE_ARRAY_IN)json.data(), (INT32)json.length());
+ bs->SetMimeType(MgMimeType::Json);
+ resultReader = bs->GetReader();
+ }
+ else
+ {
+ std::string mbPrefix;
+ MgUtil::WideCharToMultiByte(sPrefix, mbPrefix);
- //For GeoJSON, use the new GetWfsReader API
- if (sOutputFormat == MgMimeType::Json)
- {
- // NOTE: This API doesn't accept WFS version, format and XML namepaces because these are GML-isms baked into the GetWfsFeature API itself, making
- // it unsuitable for non-GML output, hence the need for this new GetWfsReader API
- Ptr<MgFeatureReader> fr = featureService->GetWfsReader(featureSourceId, ((sSchemaHash.size() == 0) ? sClass : sSchemaHash + _(":") + sClass),
- requiredProperties, m_getFeatureParams->GetSrs(), filter, sSortCriteria);
-
- //MgByteSource owns this and will clean it up when done
- MgReaderByteSourceImpl* bsImpl = new MgReaderByteSourceImpl(fr, MgMimeType::Json, true, false, -1, NULL);
- bsImpl->SetMaxFeatures(numFeaturesToRetrieve - 1);
- Ptr<MgByteSource> bs = new MgByteSource(bsImpl);
- resultReader = bs->GetReader();
+ std::string xml = "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n";
+ xml += "<wfs:FeatureCollection xmlns:gml=\"http://www.opengis.net/gml\" xmlns:wfs=\"http://www.opengis.net/wfs\" xmlns:";
+ xml += mbPrefix;
+ xml += "=\"http://fdo.osgeo.org/schemas/feature/";
+ xml += mbPrefix;
+ xml += "\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://www.opengis.net/gml http://schemas.opengis.net/gml/3.1.1/base/feature.xsd http://www.opengis.net/wfs http://schemas.opengis.net/wfs/1.1.0/wfs.xsd\"";
+ xml += " numberOfFeatures=\"";
+ xml += sTotal;
+ xml += "\" />";
+ Ptr<MgByteSource> bs = new MgByteSource((BYTE_ARRAY_IN)xml.data(), (INT32)xml.length());
+ bs->SetMimeType(MgMimeType::Xml);
+ resultReader = bs->GetReader();
+ }
}
- else
+ else
{
// Call the C++ API
// NOTE: I updated the maxFeatures value from numFeaturesToRetrieve to numFeaturesToRetrieve-1
// Because the MgServerFdoFeatureReader in MapGuide server uses -1 to mark empty, while MgWfsFeatures
// in MapGuide web tier uses 0
- resultReader = featureService->GetWfsFeature(featureSourceId, ((sSchemaHash.size() == 0) ? sClass : sSchemaHash + _(":") + sClass),
- requiredProperties, m_getFeatureParams->GetSrs(), filter, numFeaturesToRetrieve - 1, sVersion, sOutputFormat, sSortCriteria, sPrefix, oFeatureTypes.GetNamespaceUrl());
- // Store the MgByteReader directly for retrieval
- //
- // DO NOT PASS THROUGH OGC XML TEMPLATE PROCESSING CODE!
- // DO NOT PASS GO!
- // DO NOT COLLECT MEMORY SPIKES NEEDLESSLY BUFFERING XML TEMPLATE CONTENT AS A RESULT!
- //
- // This *is* already the WFS GetFeature response. There is nothing to post-process through the XML templates!
+ //For GeoJSON, use the new GetWfsReader API
+ if (sOutputFormat == MgMimeType::Json)
+ {
+ // NOTE: This API doesn't accept WFS version, format and XML namepaces because these are GML-isms baked into the GetWfsFeature API itself, making
+ // it unsuitable for non-GML output, hence the need for this new GetWfsReader API
+ Ptr<MgFeatureReader> fr = featureService->GetWfsReader(featureSourceId, ((sSchemaHash.size() == 0) ? sClass : sSchemaHash + _(":") + sClass),
+ requiredProperties, m_getFeatureParams->GetSrs(), filter, sSortCriteria);
+
+ //MgByteSource owns this and will clean it up when done
+ MgReaderByteSourceImpl* bsImpl = new MgReaderByteSourceImpl(fr, MgMimeType::Json, true, false, -1, NULL);
+ bsImpl->SetMaxFeatures(numFeaturesToRetrieve - 1);
+ Ptr<MgByteSource> bs = new MgByteSource(bsImpl);
+ resultReader = bs->GetReader();
+ }
+ else
+ {
+ // Call the C++ API
+ // NOTE: I updated the maxFeatures value from numFeaturesToRetrieve to numFeaturesToRetrieve-1
+ // Because the MgServerFdoFeatureReader in MapGuide server uses -1 to mark empty, while MgWfsFeatures
+ // in MapGuide web tier uses 0
+ resultReader = featureService->GetWfsFeature(featureSourceId, ((sSchemaHash.size() == 0) ? sClass : sSchemaHash + _(":") + sClass),
+ requiredProperties, m_getFeatureParams->GetSrs(), filter, numFeaturesToRetrieve - 1, sVersion, sOutputFormat, sSortCriteria, sPrefix, oFeatureTypes.GetNamespaceUrl());
+
+ // Store the MgByteReader directly for retrieval
+ //
+ // DO NOT PASS THROUGH OGC XML TEMPLATE PROCESSING CODE!
+ // DO NOT PASS GO!
+ // DO NOT COLLECT MEMORY SPIKES NEEDLESSLY BUFFERING XML TEMPLATE CONTENT AS A RESULT!
+ //
+ // This *is* already the WFS GetFeature response. There is nothing to post-process through the XML templates!
+ }
}
}
else //Cannot resolve feature source from feature type name
Modified: trunk/MgDev/Web/src/HttpHandler/ReaderByteSourceImpl.cpp
===================================================================
--- trunk/MgDev/Web/src/HttpHandler/ReaderByteSourceImpl.cpp 2019-07-14 13:50:50 UTC (rev 9575)
+++ trunk/MgDev/Web/src/HttpHandler/ReaderByteSourceImpl.cpp 2019-07-17 09:32:14 UTC (rev 9576)
@@ -166,7 +166,7 @@
}
}
- INT32 maxIndex = m_buf.length() - 1;
+ auto maxIndex = m_buf.length() - 1;
//We have an internal buffer. Clear this out first
if (m_bufOffset < maxIndex)
{
@@ -311,7 +311,7 @@
while (ret < length)
{
m_bufOffset++;
- INT32 maxIndex = m_buf.length() - 1;
+ auto maxIndex = m_buf.length() - 1;
if (m_bufOffset <= maxIndex)
{
buffer[fromIndex + ret] = m_buf[m_bufOffset];
Modified: trunk/MgDev/Web/src/HttpHandler/WfsGetFeatureParams.cpp
===================================================================
--- trunk/MgDev/Web/src/HttpHandler/WfsGetFeatureParams.cpp 2019-07-14 13:50:50 UTC (rev 9575)
+++ trunk/MgDev/Web/src/HttpHandler/WfsGetFeatureParams.cpp 2019-07-17 09:32:14 UTC (rev 9576)
@@ -37,6 +37,7 @@
, m_filterStrings(new MgStringCollection())
, m_featureTypeList(new MgStringCollection())
, m_pNamespaces(new MgXmlNamespaceManager())
+, m_hitMode(false)
{
// Get the required properties
@@ -105,6 +106,12 @@
// Get the sortby property name
m_sortCriteria = GetRequestParameter(oServer,MgHttpResourceStrings::reqWfsSortBy);
+ // Try to set hit mode flag (only if WFS version != 1.0.0 as it was only introduced from 1.1.0 onwards)
+ if (m_version != L"1.0.0")
+ {
+ STRING resultType = GetRequestParameter(oServer, MgHttpResourceStrings::reqWfsResultType);
+ m_hitMode = (resultType == L"hits");
+ }
}
WfsGetFeatureParams::~WfsGetFeatureParams()
@@ -134,6 +141,7 @@
, m_filterStrings(new MgStringCollection())
, m_featureTypeList(new MgStringCollection())
, m_pNamespaces(new MgXmlNamespaceManager())
+, m_hitMode(false)
{
MgXmlParser parser(xmlRequestString.c_str());
MgXmlNamespaceManager oNamespaces;
@@ -179,6 +187,15 @@
if(pBegin->GetAttribute(_("outputFormat"), sOutputFormat) && sOutputFormat.length() > 0)
m_outputFormat = oServer.ProcessArgumentAs(_("OutputFormat"),sOutputFormat.c_str());
+ // Try to set hit mode flag (only if WFS version != 1.0.0 as it was only introduced from 1.1.0 onwards)
+ if (m_version != L"1.0.0")
+ {
+ STRING sResultType;
+ if (pBegin->GetAttribute(_("resultType"), sResultType) && sResultType.length() > 0)
+ {
+ m_hitMode = (sResultType == L"hits");
+ }
+ }
// We want to hang onto the namespaces that are
// defined in the GetFeature request, since that will
@@ -609,3 +626,8 @@
}
// --------------------------------------------------------
}
+
+bool WfsGetFeatureParams::IsHitMode()
+{
+ return m_hitMode;
+}
\ No newline at end of file
Modified: trunk/MgDev/Web/src/HttpHandler/WfsGetFeatureParams.h
===================================================================
--- trunk/MgDev/Web/src/HttpHandler/WfsGetFeatureParams.h 2019-07-14 13:50:50 UTC (rev 9575)
+++ trunk/MgDev/Web/src/HttpHandler/WfsGetFeatureParams.h 2019-07-17 09:32:14 UTC (rev 9576)
@@ -68,6 +68,14 @@
~WfsGetFeatureParams();
/// <summary>
+ /// Gets whether the query is only asking for hits (ie. A total feature count)
+ /// </summary>
+ /// <returns>
+ /// True if the query is asking for hits. False otherwise
+ /// </returns>
+ bool IsHitMode();
+
+ /// <summary>
/// Retrieves the filter strings for the request
/// </summary>
/// <returns>
@@ -183,6 +191,7 @@
STRING m_outputFormat;
STRING m_version;
STRING m_sortCriteria;
+ bool m_hitMode;
};
#endif // _FS_WFS_GET_FEATURE_PARAMS_H
Modified: trunk/MgDev/Web/src/HttpHandler/WmsMapUtil.cpp
===================================================================
--- trunk/MgDev/Web/src/HttpHandler/WmsMapUtil.cpp 2019-07-14 13:50:50 UTC (rev 9575)
+++ trunk/MgDev/Web/src/HttpHandler/WmsMapUtil.cpp 2019-07-17 09:32:14 UTC (rev 9576)
@@ -219,7 +219,7 @@
STRING qualifiedName = mgLayer->GetFeatureClassName();
- int pos = qualifiedName.find(L":");
+ auto pos = qualifiedName.find(L":");
STRING schemaName = qualifiedName.substr(0,pos);
STRING className = qualifiedName.substr(pos+1,qualifiedName.length()-pos-1);
@@ -527,11 +527,11 @@
// Looking for all <Bounds> elements from layerBounds
// Example: <Bounds SRS="EPSG:4326" west="-87.74" south="43.68" east="-87.69" north="43.815"/>
Ptr<MgStringCollection> bounds = new MgStringCollection();
- int pos = 0;
+ size_t pos = 0;
while((pos = layerBounds.find(L"<Bounds",pos)) != STRING::npos)
{
pos += 7; // pos+7 to the first character after <Bounds
- int endPos = layerBounds.find(L"/>",pos);
+ auto endPos = layerBounds.find(L"/>",pos);
bounds->Add(layerBounds.substr(pos,endPos-pos));
}
@@ -541,8 +541,8 @@
STRING bound = bounds->GetItem(i);
//Find SRS value from Bounds element
- int startPos = bound.find(L"SRS=\"");
- int endPos = bound.find(L"\"",startPos+5); // pos+5 to the first character after SRS="
+ auto startPos = bound.find(L"SRS=\"");
+ auto endPos = bound.find(L"\"",startPos+5); // pos+5 to the first character after SRS="
STRING srs = bound.substr(startPos+5,endPos-startPos-5);
if(MgUtil::ToUpper(srs) == MgUtil::ToUpper(sSrs))
Modified: trunk/MgDev/Web/src/IsapiAgent/IsapiPostParser.cpp
===================================================================
--- trunk/MgDev/Web/src/IsapiAgent/IsapiPostParser.cpp 2019-07-14 13:50:50 UTC (rev 9575)
+++ trunk/MgDev/Web/src/IsapiAgent/IsapiPostParser.cpp 2019-07-17 09:32:14 UTC (rev 9576)
@@ -140,9 +140,9 @@
// url-encoded, since the question mark in <?xml...?>
// should itself be url-encoded: <%3Fxml... )
if (MapAgentCommon::IsXmlPi((char *)m_pBuffer))
- params->SetXmlPostData((char *)m_pBuffer);
+ params->SetXmlPostData((char *)m_pBuffer);
else
- MapAgentGetParser::Parse((char *)m_pBuffer, params);
+ MapAgentGetParser::Parse((char *)m_pBuffer, params);
}
}
else if (content.find(MapAgentStrings::MultiPartForm) != content.npos)
@@ -185,7 +185,7 @@
// The check for text/xml is not always sufficient. CarbonTools, for example,
// fails to set Content-Type: text/xml and just sends Content-Type: utf-8.
// A better check might be looking into the buffer to find "<?xml" at the beginning.
- else if (content.find(MapAgentStrings::TextXml) != content.npos || MapAgentCommon::IsXmlPi((char *)m_pBuffer))
+ else if (MapAgentStrings::IsXmlMimeType(content) || MapAgentCommon::IsXmlPi((char *)m_pBuffer))
{
m_pBuffer[dwTotalBytes] = '\0';
params->SetXmlPostData((char *)m_pBuffer);
Modified: trunk/MgDev/Web/src/MapAgentCommon/MapAgentStrings.cpp
===================================================================
--- trunk/MgDev/Web/src/MapAgentCommon/MapAgentStrings.cpp 2019-07-14 13:50:50 UTC (rev 9575)
+++ trunk/MgDev/Web/src/MapAgentCommon/MapAgentStrings.cpp 2019-07-17 09:32:14 UTC (rev 9576)
@@ -51,6 +51,7 @@
const char* MapAgentStrings::TextPlain = "text/plain";
const char* MapAgentStrings::TextHtml = "text/html";
const char* MapAgentStrings::TextXml = "text/xml";
+const char* MapAgentStrings::ApplicationXml = "application/xml";
const char* MapAgentStrings::PostBoundary = "boundary=";
const char* MapAgentStrings::PostName = "name=\"";
const char* MapAgentStrings::PostContent = "Content-Type: ";
@@ -71,3 +72,9 @@
// used to indicate the creation of temporary files as part of a request
const wchar_t* MapAgentStrings::TempfileKey = L"tempfile";
+
+bool MapAgentStrings::IsXmlMimeType(const std::string& content)
+{
+ return content.find(MapAgentStrings::TextXml) != content.npos
+ || content.find(MapAgentStrings::ApplicationXml) != content.npos;
+}
\ No newline at end of file
Modified: trunk/MgDev/Web/src/MapAgentCommon/MapAgentStrings.h
===================================================================
--- trunk/MgDev/Web/src/MapAgentCommon/MapAgentStrings.h 2019-07-14 13:50:50 UTC (rev 9575)
+++ trunk/MgDev/Web/src/MapAgentCommon/MapAgentStrings.h 2019-07-17 09:32:14 UTC (rev 9576)
@@ -18,6 +18,8 @@
#ifndef MAPAGENT_STRINGS_H
#define MAPAGENT_STRINGS_H
+#include <string>
+
class MapAgentStrings
{
public:
@@ -54,6 +56,7 @@
const static char* TextPlain;
const static char* TextHtml;
const static char* TextXml;
+ const static char* ApplicationXml;
const static char* PostBoundary;
const static char* PostName;
const static char* PostContent;
@@ -71,5 +74,7 @@
const static wchar_t* FailedAuth2;
const static wchar_t* ProductName;
const static wchar_t* TempfileKey;
+
+ static bool IsXmlMimeType(const std::string& mimeType);
};
#endif
More information about the mapguide-commits
mailing list