[mapguide-commits] r7762 - sandbox/jng/streaming_v2/Web/src/HttpHandler

svn_mapguide at osgeo.org svn_mapguide at osgeo.org
Mon Aug 12 07:49:57 PDT 2013


Author: jng
Date: 2013-08-12 07:49:57 -0700 (Mon, 12 Aug 2013)
New Revision: 7762

Removed:
   sandbox/jng/streaming_v2/Web/src/HttpHandler/WfsFeatures.cpp
   sandbox/jng/streaming_v2/Web/src/HttpHandler/WfsFeatures.h
Modified:
   sandbox/jng/streaming_v2/Web/src/HttpHandler/HttpHandler.vcxproj
   sandbox/jng/streaming_v2/Web/src/HttpHandler/HttpHandler.vcxproj.filters
   sandbox/jng/streaming_v2/Web/src/HttpHandler/HttpHandlerBuild.cpp
   sandbox/jng/streaming_v2/Web/src/HttpHandler/HttpWfsGetFeature.cpp
   sandbox/jng/streaming_v2/Web/src/HttpHandler/Makefile.am
   sandbox/jng/streaming_v2/Web/src/HttpHandler/OgcServer.h
   sandbox/jng/streaming_v2/Web/src/HttpHandler/OgcWfsServer.cpp
   sandbox/jng/streaming_v2/Web/src/HttpHandler/OgcWfsServer.h
   sandbox/jng/streaming_v2/Web/src/HttpHandler/ResponseStream.h
Log:
Here's the big one. WFS GetFeature responses are now streamed on the mapagent side! 

This will fix #1070 as we are no longer buffering to a size-limited MgByte before writing out the response. 

We are able to do this by simply ... bypassing the XML templating code! 

MgFeatureService.GetWfsFeature() is already returning GetFeature response content. I do not know why this response then had to go through the OGC XML templating code, where the full XML content had to be read into memory (the cause of the memory spikes on large GetFeature responses). The only difference between the GetFeature response (that goes through the XML templating code) and the GetFeature response (that bypasses the XML templating code) is that the GetFeature response that goes through the XML templating code contains comment markers denoting each individual feature in the response. Besides that, the responses are identical!

For large responses there will be a small pause because the server-side is still buffered first before being streamed down to the web tier. The problem here is that MgServerFeatureService.GetWfsFeature() is dumping the GML result into a temporary file before returning a MgByteReader from this temp file. Ideally for the server-side to stream this as well, we should have a custom FdoIoStream class that writes direct to the TCP/IP MgStream with some type gymnastics so that we can still return a MgByteReader to respect the original API.

This submission renders the MgWfsFeatures class and some methods of MgOgcWfsServer useless. This submission also removes these items in question.

Modified: sandbox/jng/streaming_v2/Web/src/HttpHandler/HttpHandler.vcxproj
===================================================================
--- sandbox/jng/streaming_v2/Web/src/HttpHandler/HttpHandler.vcxproj	2013-08-12 14:46:48 UTC (rev 7761)
+++ sandbox/jng/streaming_v2/Web/src/HttpHandler/HttpHandler.vcxproj	2013-08-12 14:49:57 UTC (rev 7762)
@@ -724,12 +724,6 @@
       <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
       <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
     </ClCompile>
-    <ClCompile Include="WfsFeatures.cpp">
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
-    </ClCompile>
     <ClCompile Include="WfsGetFeatureParams.cpp">
       <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
       <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
@@ -1042,7 +1036,6 @@
     <ClInclude Include="Stream.h" />
     <ClInclude Include="StringStream.h" />
     <ClInclude Include="WfsFeatureDefinitions.h" />
-    <ClInclude Include="WfsFeatures.h" />
     <ClInclude Include="WfsGetFeatureParams.h" />
     <ClInclude Include="WmsFeatureInfo.h" />
     <ClInclude Include="WmsFeatureProperties.h" />

Modified: sandbox/jng/streaming_v2/Web/src/HttpHandler/HttpHandler.vcxproj.filters
===================================================================
--- sandbox/jng/streaming_v2/Web/src/HttpHandler/HttpHandler.vcxproj.filters	2013-08-12 14:46:48 UTC (rev 7761)
+++ sandbox/jng/streaming_v2/Web/src/HttpHandler/HttpHandler.vcxproj.filters	2013-08-12 14:49:57 UTC (rev 7762)
@@ -294,9 +294,6 @@
     <ClCompile Include="WfsFeatureDefinitions.cpp">
       <Filter>Ogc</Filter>
     </ClCompile>
-    <ClCompile Include="WfsFeatures.cpp">
-      <Filter>Ogc</Filter>
-    </ClCompile>
     <ClCompile Include="WfsGetFeatureParams.cpp">
       <Filter>Ogc</Filter>
     </ClCompile>
@@ -661,9 +658,6 @@
     <ClInclude Include="WfsFeatureDefinitions.h">
       <Filter>Ogc</Filter>
     </ClInclude>
-    <ClInclude Include="WfsFeatures.h">
-      <Filter>Ogc</Filter>
-    </ClInclude>
     <ClInclude Include="WfsGetFeatureParams.h">
       <Filter>Ogc</Filter>
     </ClInclude>

Modified: sandbox/jng/streaming_v2/Web/src/HttpHandler/HttpHandlerBuild.cpp
===================================================================
--- sandbox/jng/streaming_v2/Web/src/HttpHandler/HttpHandlerBuild.cpp	2013-08-12 14:46:48 UTC (rev 7761)
+++ sandbox/jng/streaming_v2/Web/src/HttpHandler/HttpHandlerBuild.cpp	2013-08-12 14:49:57 UTC (rev 7762)
@@ -143,7 +143,6 @@
 #include "WmsFeatureInfo.cpp"
 #include "WmsFeatureProperties.cpp"
 #include "WfsFeatureDefinitions.cpp"
-#include "WfsFeatures.cpp"
 #include "XmlParser.cpp"
 #include "Dictionary.cpp"
 #include "NameStringValueCollection.cpp"

Modified: sandbox/jng/streaming_v2/Web/src/HttpHandler/HttpWfsGetFeature.cpp
===================================================================
--- sandbox/jng/streaming_v2/Web/src/HttpHandler/HttpWfsGetFeature.cpp	2013-08-12 14:46:48 UTC (rev 7761)
+++ sandbox/jng/streaming_v2/Web/src/HttpHandler/HttpWfsGetFeature.cpp	2013-08-12 14:49:57 UTC (rev 7762)
@@ -34,7 +34,7 @@
             ogc_server.ServiceExceptionReportResponse(                                        \
                 MgOgcWfsException(MgOgcWfsException::ogc_exception_code,                      \
                                   sReport.c_str() ));                                         \
-            Ptr<MgByteReader> capabilities = responseStream.Stream().GetReader();             \
+            Ptr<MgByteReader> capabilities = responseStream.GetReader();                      \
             hResult->SetResultObject(capabilities, capabilities->GetMimeType());              \
             e->Release();                                                                     \
         }                                                                                     \
@@ -49,7 +49,7 @@
             ogc_server.ServiceExceptionReportResponse(                                        \
                 MgOgcWfsException(MgOgcWfsException::kpszInternalError,                       \
                                   _("Unexpected exception was thrown.  No additional details available.")));\
-            Ptr<MgByteReader> capabilities = responseStream.Stream().GetReader();             \
+            Ptr<MgByteReader> capabilities = responseStream.GetReader();                      \
             hResult->SetResultObject(capabilities, capabilities->GetMimeType());              \
         }                                                                                     \
 ///////////////////////////////////////////////////////////////////////////////////////////////
@@ -119,7 +119,7 @@
     }
     MgHttpRequestParameters requestParams(origReqParams);
 
-    MgHttpResponseStream responseStream;
+    MgGetWfsFeaturesResponseStream responseStream;
     MgOgcServer::SetLoader(GetDocument);
 
     MgUserInformation::SetCurrentUserInfo(m_userInfo);
@@ -132,8 +132,12 @@
         wfsServer.ProcessRequest(this);
 
         // Obtain the response byte reader
-        Ptr<MgByteReader> responseReader = responseStream.Stream().GetReader();
+        Ptr<MgByteReader> responseReader = responseStream.GetReader();
 
+        Ptr<MgHttpHeader> respHeader = hResponse.GetHeader();
+        //This is the "hint" to chunk the MgByteReader content
+        respHeader->AddHeader(MgHttpResourceStrings::hrhnTransfer_Encoding, MgHttpResourceStrings::hrhnChunked);
+
         // Set the result
         hResult->SetResultObject(responseReader, responseReader->GetMimeType());
     }
@@ -165,6 +169,7 @@
 // Acquire data required to generate the response
 void MgHttpWfsGetFeature::AcquireResponseData(MgOgcServer* ogcServer)
 {
+    Ptr<MgByteReader> resultReader;
     MgOgcWfsServer* wfsServer = (MgOgcWfsServer*)ogcServer;
     if(wfsServer != NULL)
     {
@@ -274,33 +279,26 @@
 
                             // Call the C++ API
                             // NOTE: I updated the maxFeatures value from numFeaturesToRetrieve to numFeaturesToRetrieve-1
-                            // Because the MgServerFdoFeatureReader in MapGudie server uses -1 to mark empty, while MgWfsFeatures
+                            // Because the MgServerFdoFeatureReader in MapGuide server uses -1 to mark empty, while MgWfsFeatures
                             // in MapGuide web tier uses 0
-                            Ptr<MgByteReader> resultReader = featureService->GetWfsFeature(featureSourceId, ((sSchemaHash.size()==0) ? sClass : sSchemaHash + _(":") + sClass),
+                            resultReader = featureService->GetWfsFeature(featureSourceId, ((sSchemaHash.size()==0) ? sClass : sSchemaHash + _(":") + sClass),
                                 requiredProperties, m_getFeatureParams->GetSrs(), filter, numFeaturesToRetrieve-1, sVersion, sOutputFormat, sSortCriteria, sPrefix, oFeatureTypes.GetNamespaceUrl());
 
-                            // TODO How to determine number of features retrieved...?
-                            // Note: for now, maxFeatures is managed by the MgWfsFeatures object. - TMT 2006-3-20
-                            // numFeaturesRetrieved += ?
-
-                            // Write the byte reader's data into our response data object
-                            string thisResponseString;
-                            resultReader->ToStringUtf8(thisResponseString);
-
-                            // just append the entire thing; there's important stuff, like namespace declarations
-                            // that we would lose if we just extracted the <featureMember> elements.
-                            // The MgWfsFeatures object will parse the pseudo-XML that results.
-                            responseString += thisResponseString;
+                            // 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!
                         }
                     }
                 }
             }
         }
-        if(responseString.length() > 0)
+        if (NULL != resultReader.p)
         {
-            STRING wResponseString = MgUtil::MultiByteToWideChar(responseString);
-            Ptr<MgWfsFeatures> features = new MgWfsFeatures(wResponseString.c_str(),m_getFeatureParams->GetMaxFeatures());
-            wfsServer->SetFeatures(features);
+            wfsServer->SetFeatures(resultReader);
         }
     }
 }

Modified: sandbox/jng/streaming_v2/Web/src/HttpHandler/Makefile.am
===================================================================
--- sandbox/jng/streaming_v2/Web/src/HttpHandler/Makefile.am	2013-08-12 14:46:48 UTC (rev 7761)
+++ sandbox/jng/streaming_v2/Web/src/HttpHandler/Makefile.am	2013-08-12 14:49:57 UTC (rev 7762)
@@ -133,7 +133,6 @@
   OgcWmsServer.cpp \
   ReaderByteSourceImpl.cpp \
   WfsFeatureDefinitions.cpp \
-  WfsFeatures.cpp \
   WfsGetFeatureParams.cpp \
   WmsFeatureInfo.cpp \
   WmsFeatureProperties.cpp \

Modified: sandbox/jng/streaming_v2/Web/src/HttpHandler/OgcServer.h
===================================================================
--- sandbox/jng/streaming_v2/Web/src/HttpHandler/OgcServer.h	2013-08-12 14:46:48 UTC (rev 7761)
+++ sandbox/jng/streaming_v2/Web/src/HttpHandler/OgcServer.h	2013-08-12 14:49:57 UTC (rev 7762)
@@ -512,9 +512,7 @@
     // These are the links to the outside world.  The input (request) and
     // the output (response) objects.
     MgHttpRequestParameters& m_Request;
-    CStream*                m_pResponse;
-
-
+    
     // This determines whether writing is enabled.
     bool m_bWriteEnabled;
     EscapeState m_eEscapeState;
@@ -528,8 +526,11 @@
     int  m_iExpansionRecursionDepth;
 
 
+protected:
+    CStream*                m_pResponse;
+
     // Statics...
-protected:
+
     // Given a parser and a dictionary, shove definitions found in the former
     // into the latter.
     static void ProcessDefinitions(MgXmlParser& Template,MgUtilDictionary& Dictionary);

Modified: sandbox/jng/streaming_v2/Web/src/HttpHandler/OgcWfsServer.cpp
===================================================================
--- sandbox/jng/streaming_v2/Web/src/HttpHandler/OgcWfsServer.cpp	2013-08-12 14:46:48 UTC (rev 7761)
+++ sandbox/jng/streaming_v2/Web/src/HttpHandler/OgcWfsServer.cpp	2013-08-12 14:49:57 UTC (rev 7762)
@@ -367,22 +367,10 @@
 {
     try
     {
-        // See what format they requested the GetFeature response in...
-        CPSZ pszFormat = RequestParameter(kpszQueryStringOutputFormat);
-        STRING sOutputFormat;
-
-        if(pszFormat == NULL)
-        {
-            CPSZ pszVersion = RequestParameter(MgHttpResourceStrings::reqWfsVersion.c_str());
-            sOutputFormat = this->GetDefaultGetFeatureOutputFormat(pszVersion);
-            pszFormat = sOutputFormat.c_str();
-        }
-        // Generate a response to the GetFeature request
-        if(GenerateResponse(kpszQueryValueGetFeature,pszFormat))
-        {
-            // The response was generated successfully, so we return
-            return;
-        }
+        //MgHttpWfsGetFeature will pass a MgGetWfsFeaturesResponseStream to this instance when executing
+        MgGetWfsFeaturesResponseStream* wfsResponse = static_cast<MgGetWfsFeaturesResponseStream*>(m_pResponse);
+        wfsResponse->SetReader(m_pFeatureSet);
+        return;
     }
     catch(MgException* pEx)
     {
@@ -453,14 +441,6 @@
     {
         ProcedureEnumFeatureTypes(PI);
     }
-    else if(sProc == kpszPiEnumFeatures)
-    {
-        ProcedureEnumFeatures(PI);
-    }
-    else if(sProc == kpszPiGetFeatureCollection)
-    {
-        ProcedureGetFeatureCollection(PI);
-    }
     else
     {
         return false; // Unknown
@@ -511,41 +491,6 @@
     }
 }
 
-
-void MgOgcWfsServer::ProcedureEnumFeatures(MgXmlProcessingInstruction& PIEnum)
-{
-    STRING sFormat;
-    if(!PIEnum.GetAttribute(kpszPiAttributeUsing,sFormat))
-        sFormat = kpszPiGetFeatureCollectionDefaultFormat;
-
-    STRING sSubset;
-    if(!PIEnum.GetAttribute(kpszPiAttributeSubset,sSubset))
-        sSubset = kpszEmpty;
-    ProcessExpandableTextIntoString(sSubset,sSubset);
-
-    int iNum = 0;
-
-    if(m_pFeatureSet != NULL) {
-        while(m_pFeatureSet->Next())
-        {
-            // We ensure that each feature gets its own stack frame
-            // so definitions don't get carried over to the next feature.
-            CDictionaryStackFrame ForEachFeature(this);
-
-            m_pFeatureSet->GenerateDefinitions(*m_pTopOfDefinitions);
-
-            if(IsIterationInSubset(++iNum,sSubset,kpszPiDefinitionFeatureIteration) && (*m_pTopOfDefinitions)[L"Feature.OuterXml"] )
-            {
-                ProcessExpandableText(sFormat);
-            }
-        }
-    }
-}
-
-
-
-
-
 void MgOgcWfsServer::GenerateTypeNameException(CREFSTRING sTypeName)
 {
     sTypeName; // RESERVED FOR FUTURE USE; unused for now... to provide this info in exception body.
@@ -554,30 +499,8 @@
                                                      MgHttpResourceStrings::reqWfsTypeName.c_str()));
 }
 
-void MgOgcWfsServer::ProcedureGetFeatureCollection(MgXmlProcessingInstruction& PI)
+void MgOgcWfsServer::SetFeatures(MgByteReader* pFeatures)
 {
-    STRING sFormat;
-    if(!PI.GetAttribute(kpszPiAttributeUsing,sFormat))
-        sFormat = kpszPiGetFeatureCollectionDefaultFormat;
-
-    STRING sSubset;
-    if(!PI.GetAttribute(kpszPiAttributeSubset,sSubset))
-        sSubset = kpszEmpty;
-    ProcessExpandableTextIntoString(sSubset,sSubset);
-
-    bool bHasNamespace = false;
-
-    if(m_pFeatureSet != NULL) {
-        while(!bHasNamespace && m_pFeatureSet->Next()) {
-            bHasNamespace = m_pFeatureSet->GenerateNamespacesDefinition(*m_pTopOfDefinitions);
-        }
-    }
-
-    ProcessExpandableText(sFormat);
-}
-
-void MgOgcWfsServer::SetFeatures(MgWfsFeatures* pFeatures)
-{
     m_pFeatureSet = SAFE_ADDREF(pFeatures);
 }
 

Modified: sandbox/jng/streaming_v2/Web/src/HttpHandler/OgcWfsServer.h
===================================================================
--- sandbox/jng/streaming_v2/Web/src/HttpHandler/OgcWfsServer.h	2013-08-12 14:46:48 UTC (rev 7761)
+++ sandbox/jng/streaming_v2/Web/src/HttpHandler/OgcWfsServer.h	2013-08-12 14:49:57 UTC (rev 7762)
@@ -21,7 +21,6 @@
 #include "OgcServer.h"
 #include "OgcWfsException.h"
 #include "WfsFeatureDefinitions.h"
-#include "WfsFeatures.h"
 
 class MgOgcWfsServer: public MgOgcServer
 {
@@ -30,7 +29,8 @@
     MgOgcWfsServer(MgHttpRequestParameters& Request, CStream& Response);
 
     void GenerateTypeNameException(CREFSTRING sTypeName);
-    void SetFeatures(MgWfsFeatures* pFeatures);
+    
+    void SetFeatures(MgByteReader* pFeatures);
     void SetGetFeatureRequestParams(WfsGetFeatureParams* pGetFeatureParams);
     void SetFeatureDefinitions(MgWfsFeatureDefinitions* pFeatureDefs);
 
@@ -93,16 +93,10 @@
     // ?>
     void ProcedureEnumFeatureTypes(MgXmlProcessingInstruction& PIEnum);
 
-    void ProcedureGetFeatureCollection(MgXmlProcessingInstruction& PIEnum);
-
-    // <?EnumFeatures
-    //
-    void ProcedureEnumFeatures(MgXmlProcessingInstruction& PIEnum);
-
     CPSZ ServiceExceptionReportElement();
 
     MgWfsFeatureDefinitions* m_pFeatures;
-    Ptr<MgWfsFeatures> m_pFeatureSet;
+    Ptr<MgByteReader> m_pFeatureSet;
     Ptr<WfsGetFeatureParams> m_pGetFeatureParams;
 
     // The backing store for the default exception.

Modified: sandbox/jng/streaming_v2/Web/src/HttpHandler/ResponseStream.h
===================================================================
--- sandbox/jng/streaming_v2/Web/src/HttpHandler/ResponseStream.h	2013-08-12 14:46:48 UTC (rev 7761)
+++ sandbox/jng/streaming_v2/Web/src/HttpHandler/ResponseStream.h	2013-08-12 14:49:57 UTC (rev 7762)
@@ -52,6 +52,31 @@
 };
 */
 
+// This is not a true stream. It's just a temporary MgByteReader
+// placeholder that passes the CStream type test allowing us to 
+// pass this into a MgOgcWfsServer instance.
+class MgGetWfsFeaturesResponseStream : public CStream
+{
+public:
+    MgGetWfsFeaturesResponseStream() 
+    {
+        m_reader = NULL;
+    }
+    ~MgGetWfsFeaturesResponseStream() 
+    { 
+        m_reader = NULL;
+    }
+
+    virtual void SetContentType(CPSZ pszContentTypeMime) { }
+    virtual long Write(CPSZ pszBuffer,size_t uBytesToWrite,size_t* puBytesWritten) { return -1; }
+
+    void SetReader(MgByteReader* reader) { m_reader = SAFE_ADDREF(reader); }
+    MgByteReader* GetReader() { return SAFE_ADDREF(m_reader); }
+
+private:
+    MgByteReader* m_reader;
+};
+
 class MgHttpResponseStream: public CStream
 {
 public:

Deleted: sandbox/jng/streaming_v2/Web/src/HttpHandler/WfsFeatures.cpp
===================================================================
--- sandbox/jng/streaming_v2/Web/src/HttpHandler/WfsFeatures.cpp	2013-08-12 14:46:48 UTC (rev 7761)
+++ sandbox/jng/streaming_v2/Web/src/HttpHandler/WfsFeatures.cpp	2013-08-12 14:49:57 UTC (rev 7762)
@@ -1,142 +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
-//
-
-#include "OgcFramework.h"
-#include "WfsFeatures.h"
-
-
-CPSZ gszElementNameFeatureMember = _("http://www.opengis.net/gml:featureMember");
-CPSZ gszElementNameFeatureCollection = _("http://www.opengis.net/wfs:FeatureCollection");
-
-MgWfsFeatures::MgWfsFeatures(CPSZ szInputXml,int iMaxFeatures)
-:   m_sFeatureCollection(szInputXml)
-,   m_XmlInput(m_sFeatureCollection.c_str())
-,   m_iMaxFeatures(iMaxFeatures)
-,   m_bOk(true)
-,   m_bDone(false)
-{
-    if(m_iMaxFeatures < 1)
-        m_iMaxFeatures = 1000000; // a million features max should be enough.
-    m_XmlInput.Next();
-}
-
-MgWfsFeatures::~MgWfsFeatures()
-{
-}
-
-bool MgWfsFeatures::Next()
-{
-    // Blitz anything that's there.
-    m_sCurrentFeature = _("");
-
-    if(m_bOk && m_iMaxFeatures--) {
-        while(true) {
-            // End of stream?
-            if(m_XmlInput.AtEnd()) {
-                m_bOk = false;
-                break; // while
-            }
-
-           // Okay; a good sign... let's start poking around.
-            switch(m_XmlInput.Current().Type()) {
-            case keBeginElement:
-                {
-                    MgXmlBeginElement& Begin = (MgXmlBeginElement&)m_XmlInput.Current();
-                    m_Namespaces.TrackBeginElement(Begin);
-
-                    // If it's a <featureMember> element...
-                    if(m_Namespaces.QualifiedName(Begin) == gszElementNameFeatureMember) {
-                        m_sCurrentFeature = Begin.Contents();
-                        m_iCurrentInnerContent = m_sCurrentFeature.length();
-
-                        MgXmlSynchronizeOnNamespaceElement SlurpThis(m_XmlInput,
-                                                                     gszElementNameFeatureMember,
-                                                                     m_Namespaces);
-                        // Declare our intent to go into the element.
-                        SlurpThis.AtBegin();
-                        // Now slurp out the contents.
-                        while(!SlurpThis.AtEnd()) {
-                            m_sCurrentFeature += m_XmlInput.Current().Contents();
-                            m_XmlInput.Next();
-                        }
-                        // Make a note of how much has been added.
-                        m_iCurrentInnerLength = m_sCurrentFeature.length() - m_iCurrentInnerContent;
-                        // We're currently parked over the </featureMember> element; tack that on.
-                        m_sCurrentFeature += m_XmlInput.Current().Contents();
-                        // Track the end element's going.
-                        m_Namespaces.TrackEndElement((MgXmlEndElement&)m_XmlInput.Current());
-                        // And tell the caller we've got a hit.
-                        return m_bOk;
-                    }
-                    else if(m_Namespaces.QualifiedName(Begin) == gszElementNameFeatureCollection){
-                        MgXmlAttribute& attributes = Begin.Attributes();
-                        m_sFeatureCollectionNamespaces = attributes.Contents();
-
-                        m_iMaxFeatures++; // Read schema namespaces should not count the feature
-
-                        m_XmlInput.Next();
-                        return m_bOk;
-                    }
-                    else {
-                        m_XmlInput.Next();
-                    }
-                }
-                break;
-
-            case keEndElement:
-                {
-                    // The </featureMember> element is swallowed above,
-                    // This processes only non-featureMember elements, as is
-                    // the case when querying for two or more feature classes.
-                    MgXmlEndElement& End = (MgXmlEndElement&)m_XmlInput.Current();
-                    m_Namespaces.TrackEndElement(End);
-                    m_XmlInput.Next();
-                }
-                break;
-
-            default:
-                // Unexpected and uninteresting (<?xml?>, white space, comments, etc.); skip it.
-                m_XmlInput.Next();
-            }
-        }
-    }
-    else
-        m_bOk = false;
-
-    return m_bOk;
-}
-
-void MgWfsFeatures::GenerateDefinitions(MgUtilDictionary& Dictionary)
-{
-    if(m_bOk && !m_sCurrentFeature.empty()) {
-        Dictionary.AddDefinition(L"Feature.OuterXml",    m_sCurrentFeature);
-        Dictionary.AddDefinition(L"Feature.InnerXml",    m_sCurrentFeature.substr(m_iCurrentInnerContent,m_iCurrentInnerLength));
-        Dictionary.AddDefinition(L"Feature.EndElement",  m_sCurrentFeature.substr(m_iCurrentInnerContent+m_iCurrentInnerLength));
-        Dictionary.AddDefinition(L"Feature.BeginElement",m_sCurrentFeature.substr(0,m_iCurrentInnerContent));
-    }
-}
-
-bool MgWfsFeatures::GenerateNamespacesDefinition(MgUtilDictionary& Dictionary)
-{
-    if(m_bOk && !m_sFeatureCollectionNamespaces.empty()) {
-        Dictionary.AddDefinition(L"FeatureCollection.Namespaces", m_sFeatureCollectionNamespaces);
-        return true;
-    }
-
-    return false;
-}
-

Deleted: sandbox/jng/streaming_v2/Web/src/HttpHandler/WfsFeatures.h
===================================================================
--- sandbox/jng/streaming_v2/Web/src/HttpHandler/WfsFeatures.h	2013-08-12 14:46:48 UTC (rev 7761)
+++ sandbox/jng/streaming_v2/Web/src/HttpHandler/WfsFeatures.h	2013-08-12 14:49:57 UTC (rev 7762)
@@ -1,54 +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 _MgWfsFeatures_h
-#define _MgWfsFeatures_h
-
-#include "XmlParser.h"
-#include "Dictionary.h"
-
-class MgWfsFeatures: public IOgcResourceEnumerator, public MgDisposable
-{
-public:
-    MgWfsFeatures(CPSZ inputXml,int iMaxFeatures);
-    //Default constructor to keep Ptr<> happy
-    MgWfsFeatures();
-    virtual ~MgWfsFeatures();
-
-    bool Next();
-    void GenerateDefinitions(MgUtilDictionary& Dictionary);
-    bool GenerateNamespacesDefinition(MgUtilDictionary& Dictionary);
-    virtual void Dispose()
-    {
-        delete this;
-    }
-
-private:
-    STRING m_sFeatureCollection;  // the entire blob of features
-    MgXmlNamespaceManager m_Namespaces;
-    MgXmlParser m_XmlInput;
-    STRING m_sCurrentFeature;                 // just the current feature.
-    STRING m_sFeatureCollectionNamespaces;    // the namespaces in <wfs:FeatureCollection>
-    STRING::size_type m_iCurrentInnerContent; // index to start of content after <gml:featureMember>
-    STRING::size_type m_iCurrentInnerLength;  // length of content between <gml:featureMember> and </gml:featureMember>
-    bool m_bOk;
-    bool m_bDone;
-    int m_iMaxFeatures;
-};
-
-#endif//_MgWfsFeatures_h
-



More information about the mapguide-commits mailing list