[mapguide-commits] r7489 - sandbox/jng/createruntimemap/Web/src/HttpHandler

svn_mapguide at osgeo.org svn_mapguide at osgeo.org
Fri May 10 06:50:13 PDT 2013


Author: jng
Date: 2013-05-10 06:50:13 -0700 (Fri, 10 May 2013)
New Revision: 7489

Modified:
   sandbox/jng/createruntimemap/Web/src/HttpHandler/HttpCreateRuntimeMap.cpp
   sandbox/jng/createruntimemap/Web/src/HttpHandler/HttpCreateRuntimeMap.h
   sandbox/jng/createruntimemap/Web/src/HttpHandler/HttpResourceStrings.cpp
   sandbox/jng/createruntimemap/Web/src/HttpHandler/HttpResourceStrings.h
Log:
This submission contains the following changes:
 - Use 2.6.0 for operation version
 - Support a REQUESTEDFEATURES bitmask. The idea being depending on the bits set, the user may get back extra information about the map (and its layers/groups) in the response. If this mask is not set, the response is minimal enough to create a basic OpenLayers map from. This bitmask allows for scalability in our response, with the idea of replicating (and hopefully replacing) the functionality of LoadMap.php/LoadScaleRanges.php in Fusion if all the bits are set. The bits available are:
    - 1: Includes the layer/group structure
    - 2: Includes vector layer icons as inline base64 images (still work to do here. Only the scale ranges are outputted at the moment). Does nothing if the layer/group structure bit value is not set.
    - 4: Includes feature source information for each layer. Does nothing if the layer/group structure bit value is not set.

Modified: sandbox/jng/createruntimemap/Web/src/HttpHandler/HttpCreateRuntimeMap.cpp
===================================================================
--- sandbox/jng/createruntimemap/Web/src/HttpHandler/HttpCreateRuntimeMap.cpp	2013-05-09 13:41:59 UTC (rev 7488)
+++ sandbox/jng/createruntimemap/Web/src/HttpHandler/HttpCreateRuntimeMap.cpp	2013-05-10 13:50:13 UTC (rev 7489)
@@ -17,7 +17,12 @@
 
 #include "HttpHandler.h"
 #include "HttpCreateRuntimeMap.h"
+#include "VectorLayerDefinition.h"
 
+#define REQUEST_LAYER_STRUCTURE         1 /* Request layer and group structure */
+#define REQUEST_LAYER_ICONS             2 /* Request layer scale and icon information */
+#define REQUEST_LAYER_FEATURE_SOURCE    4 /* Request information about a layer's feature source */
+
 HTTP_IMPLEMENT_CREATE_OBJECT(MgHttpCreateRuntimeMap)
 
 /// <summary>
@@ -36,6 +41,12 @@
 
     Ptr<MgHttpRequestParam> params = hRequest->GetRequestParam();
     m_mapDefinition = params->GetParameterValue(MgHttpResourceStrings::reqMappingMapDefinition);
+    STRING mask = params->GetParameterValue(MgHttpResourceStrings::reqMappingRequestedFeatures);
+    if (mask.empty())
+        m_requestDataMask = 0;
+    else
+        m_requestDataMask = MgUtil::StringToInt32(mask);
+    m_iconLimitPerScaleRange = 25;
 }
 
 /// <summary>
@@ -101,6 +112,8 @@
     sel->Save(resourceService, mapName);
     map->Save(resourceService, mapStateId);
 
+    //TODO: Possible future caching opportunity?
+
     std::string xml;
     xml.append("<RuntimeMap>\n");
     // ------------------------------ Site Version ----------------------------------//
@@ -163,96 +176,98 @@
     xml.append("<Extents>\n");
     xml.append(sExtents);
     xml.append("</Extents>");
-    // ------------------------------ Groups ---------------------------------- //
-    xml.append("<Groups>\n");
-    Ptr<MgLayerGroupCollection> groups = map->GetLayerGroups();
-    for (INT32 i = 0; i < groups->GetCount(); i++)
+    // ---------------------- Optional things if requested -------------------- //
+    LayerDefinitionMap layerDefinitionMap;
+    if ((m_requestDataMask & REQUEST_LAYER_STRUCTURE) == REQUEST_LAYER_STRUCTURE)
     {
-        Ptr<MgLayerGroup> group = groups->GetItem(i);
-        //We'll deal with you later
-        if (group->GetLayerGroupType() == MgLayerGroupType::BaseMap)
-            continue;
+        //Build our LayerDefinition map for code below that requires it
+        if ((m_requestDataMask & REQUEST_LAYER_ICONS) == REQUEST_LAYER_ICONS)
+        {
+            Ptr<MgResourceService> resourceService = (MgResourceService*)CreateService(MgServiceType::ResourceService);
+            Ptr<MgStringCollection> layerIds = new MgStringCollection();
+            Ptr<MgLayerCollection> layers = map->GetLayers();
+            for (INT32 i = 0; i < layers->GetCount(); i++)
+            {
+                Ptr<MgLayerBase> layer = layers->GetItem(i);
+                Ptr<MgResourceIdentifier> ldfId = layer->GetLayerDefinition();
+                layerIds->Add(ldfId->ToString());
+            }
 
-        xml.append("<Group>\n");
-        xml.append("<Name>");
-        xml.append(MgUtil::WideCharToMultiByte(group->GetName()));
-        xml.append("</Name>\n");
-        xml.append("<LegendLabel>");
-        xml.append(MgUtil::WideCharToMultiByte(group->GetLegendLabel()));
-        xml.append("</LegendLabel>\n");
-        xml.append("<ObjectId>");
-        xml.append(MgUtil::WideCharToMultiByte(group->GetObjectId()));
-        xml.append("</ObjectId>\n");
-        xml.append("<DisplayInLegend>");
-        xml.append(group->GetDisplayInLegend() ? "true" : "false");
-        xml.append("</DisplayInLegend>\n");
-        xml.append("<ExpandInLegend>");
-        xml.append(group->GetExpandInLegend() ? "true" : "false");
-        xml.append("</ExpandInLegend>\n");
-        xml.append("<Visible>");
-        xml.append(group->GetVisible() ? "true" : "false");
-        xml.append("</Visible>\n");
-        xml.append("<ActuallyVisible>");
-        xml.append(group->IsVisible() ? "true" : "false");
-        xml.append("</ActuallyVisible>\n");
-        Ptr<MgLayerGroup> parent = group->GetGroup();
-        if (NULL != parent.p)
+            Ptr<MgStringCollection> layerContents = resourceService->GetResourceContents(layerIds, NULL);
+            for (INT32 i = 0; i < layerIds->GetCount(); i++)
+            {
+                STRING ldfId = layerIds->GetItem(i);
+                STRING content = layerContents->GetItem(i);
+                layerDefinitionMap[ldfId] = MgLayerBase::GetLayerDefinition(content);
+            }
+        }
+
+        // ----------- Some pre-processing before we do groups/layers ------------- //
+        Ptr<MgLayerGroupCollection> groups = map->GetLayerGroups();
+        Ptr<MgLayerCollection> layers = map->GetLayers();
+        for (INT32 i = 0; i < groups->GetCount(); i++)
         {
-            xml.append("<ParentGroupId>");
-            xml.append(MgUtil::WideCharToMultiByte(parent->GetObjectId()));
-            xml.append("</ParentGroupId>\n");
+            Ptr<MgLayerGroup> grp = groups->GetItem(i);
+            STRING grpName = grp->GetName();
+            Ptr<MgLayerGroup> parent = grp->GetGroup();
+            if (NULL == parent.p)
+            {
+                m_topLevelGroups.push_back(grp->GetName());
+            }
+            else
+            {
+                STRING parentName = parent->GetName();
+                if (m_groupParentMap.find(parentName) == m_groupParentMap.end())
+                {
+                    m_groupParentMap[parentName] = GroupNameList();
+                }
+                m_groupParentMap[parentName].push_back(grpName);
+            }
         }
-        xml.append("</Group>");
-    }
-    xml.append("</Groups>");
-    // ------------------------------ Layers ---------------------------------- //
-    xml.append("<Layers>\n");
-    Ptr<MgLayerCollection> layers = map->GetLayers();
-    for (INT32 i = 0; i < layers->GetCount(); i++)
-    {
-        Ptr<MgLayerBase> layer = layers->GetItem(i);
-        Ptr<MgLayerGroup> parent = layer->GetGroup();
-        //We'll deal with you later
-        if (NULL != parent.p && parent->GetLayerGroupType() == MgLayerGroupType::BaseMap)
-            continue;
+        for (INT32 i = 0; i < layers->GetCount(); i++)
+        {
+            Ptr<MgLayerBase> layer = layers->GetItem(i);
+            STRING layerName = layer->GetName();
+            Ptr<MgLayerGroup> parent = layer->GetGroup();
+            if (NULL == parent.p)
+            {
+                m_topLevelLayers.push_back(layerName);
+            }
+            else
+            {
+                STRING parentName = parent->GetName();
+                if (m_layerParentMap.find(parentName) == m_layerParentMap.end())
+                {
+                    m_layerParentMap[parentName] = LayerNameList();
+                }
+                m_layerParentMap[parentName].push_back(layerName);
+            }
+        }
+        // ------------------------------ Groups ---------------------------------- //
+        for (GroupNameList::iterator it = m_topLevelGroups.begin(); it != m_topLevelGroups.end(); it++)
+        {
+            STRING groupName = (*it);
+            Ptr<MgLayerGroup> group = groups->GetItem(groupName);
+            CreateGroupItem(group, xml, layers, groups, layerDefinitionMap);
+        }
 
-        xml.append("<Layer>\n");
-        xml.append("<Name>");
-        xml.append(MgUtil::WideCharToMultiByte(layer->GetName()));
-        xml.append("</Name>\n");
-        xml.append("<LegendLabel>");
-        xml.append(MgUtil::WideCharToMultiByte(layer->GetLegendLabel()));
-        xml.append("</LegendLabel>\n");
-        xml.append("<ObjectId>");
-        xml.append(MgUtil::WideCharToMultiByte(layer->GetObjectId()));
-        xml.append("</ObjectId>\n");
-        xml.append("<DisplayInLegend>");
-        xml.append(layer->GetDisplayInLegend() ? "true" : "false");
-        xml.append("</DisplayInLegend>\n");
-        xml.append("<ExpandInLegend>");
-        xml.append(layer->GetExpandInLegend() ? "true" : "false");
-        xml.append("</ExpandInLegend>\n");
-        xml.append("<Visible>");
-        xml.append(layer->GetVisible() ? "true" : "false");
-        xml.append("</Visible>\n");
-        xml.append("<ActuallyVisible>");
-        xml.append(layer->IsVisible() ? "true" : "false");
-        xml.append("</ActuallyVisible>\n");
-        if (NULL != parent.p)
+        for (LayerNameList::iterator it = m_topLevelLayers.begin(); it != m_topLevelLayers.end(); it++)
         {
-            xml.append("<ParentGroupId>");
-            xml.append(MgUtil::WideCharToMultiByte(parent->GetObjectId()));
-            xml.append("</ParentGroupId>\n");
+            STRING layerName = (*it);
+            Ptr<MgLayerBase> layer = layers->GetItem(layerName);
+            CreateLayerItem(layer, xml, layers, layerDefinitionMap);
         }
-        xml.append("</Layer>");
     }
-    xml.append("</Layers>");
-    // ------------------------------ Tiled Groups ---------------------------------- //
-    xml.append("<BaseMapGroups>\n");
-    xml.append("</BaseMapGroups>");
-
     xml.append("</RuntimeMap>");
 
+    //Cleanup our LayerDefinition pointers
+    for (LayerDefinitionMap::iterator it = layerDefinitionMap.begin(); it != layerDefinitionMap.end(); it++)
+    {
+        MdfModel::LayerDefinition* ldf = it->second;
+        delete ldf;
+    }
+    layerDefinitionMap.clear();
+
     Ptr<MgByteSource> byteSource = new MgByteSource((BYTE_ARRAY_IN)xml.c_str(), (INT32)xml.length());
     byteSource->SetMimeType(MgMimeType::Xml);
     byteReader = byteSource->GetReader();
@@ -260,4 +275,169 @@
     MG_HTTP_HANDLER_CATCH_AND_THROW(L"MgHttpCreateRuntimeMap.BuildRuntimeMapXml")
 
     return byteReader.Detach();
-}
\ No newline at end of file
+}
+
+void MgHttpCreateRuntimeMap::CreateGroupItem(MgLayerGroup* group, std::string& xml, MgLayerCollection* layers, MgLayerGroupCollection* groups, const LayerDefinitionMap& layerDefMap)
+{
+    MG_HTTP_HANDLER_TRY()
+
+    STRING groupName = group->GetName();
+    xml.append("<Group>\n");
+    xml.append("<Name>");
+    xml.append(MgUtil::WideCharToMultiByte(groupName));
+    xml.append("</Name>\n");
+    xml.append("<LegendLabel>");
+    xml.append(MgUtil::WideCharToMultiByte(group->GetLegendLabel()));
+    xml.append("</LegendLabel>\n");
+    xml.append("<ObjectId>");
+    xml.append(MgUtil::WideCharToMultiByte(group->GetObjectId()));
+    xml.append("</ObjectId>\n");
+    xml.append("<DisplayInLegend>");
+    xml.append(group->GetDisplayInLegend() ? "true" : "false");
+    xml.append("</DisplayInLegend>\n");
+    xml.append("<ExpandInLegend>");
+    xml.append(group->GetExpandInLegend() ? "true" : "false");
+    xml.append("</ExpandInLegend>\n");
+    xml.append("<Visible>");
+    xml.append(group->GetVisible() ? "true" : "false");
+    xml.append("</Visible>\n");
+    xml.append("<ActuallyVisible>");
+    xml.append(group->IsVisible() ? "true" : "false");
+    xml.append("</ActuallyVisible>\n");
+    if (m_groupParentMap.find(groupName) != m_groupParentMap.end())
+    {
+        GroupNameList childGroups = m_groupParentMap[groupName];
+        for (GroupNameList::iterator it = childGroups.begin(); it != childGroups.end(); it++)
+        {
+            STRING childGroupName = (*it);
+            Ptr<MgLayerGroup> childGroup = groups->GetItem(childGroupName);
+            //Yes, we're using recursion. Stack overflow would probably only happen
+            //if we have a map with several thousand level deep group hierarchy. So
+            //for all intents and purposes: We're safe.
+            CreateGroupItem(childGroup, xml, layers, groups, layerDefMap);
+        }
+    }
+    if (m_layerParentMap.find(groupName) != m_layerParentMap.end())
+    {
+        LayerNameList childLayers = m_layerParentMap[groupName];
+        for (LayerNameList::iterator it = childLayers.begin(); it != childLayers.end(); it++)
+        {
+            STRING childLayerName = (*it);
+            Ptr<MgLayerBase> childLayer = layers->GetItem(childLayerName);
+            CreateLayerItem(childLayer, xml, layers, layerDefMap);
+        }
+    }
+    xml.append("</Group>");
+
+    MG_HTTP_HANDLER_CATCH_AND_THROW(L"MgHttpCreateRuntimeMap.CreateGroupItem")
+}
+
+void MgHttpCreateRuntimeMap::CreateLayerItem(MgLayerBase* layer, std::string& xml, MgLayerCollection* layers, const LayerDefinitionMap& layerDefMap)
+{
+    MG_HTTP_HANDLER_TRY()
+
+    xml.append("<Layer>\n");
+    xml.append("<Type>");
+    std::string sLayerType;
+    MgUtil::Int32ToString(layer->GetLayerType(), sLayerType);
+    xml.append(sLayerType);
+    xml.append("</Type>\n");
+    xml.append("<LayerDefinition>");
+    Ptr<MgResourceIdentifier> layerDefId = layer->GetLayerDefinition();
+    STRING ldfId = layerDefId->ToString();
+    xml.append(MgUtil::WideCharToMultiByte(ldfId));
+    xml.append("</LayerDefinition>\n");
+    xml.append("<Name>");
+    xml.append(MgUtil::WideCharToMultiByte(layer->GetName()));
+    xml.append("</Name>\n");
+    xml.append("<LegendLabel>");
+    xml.append(MgUtil::WideCharToMultiByte(layer->GetLegendLabel()));
+    xml.append("</LegendLabel>\n");
+    xml.append("<ObjectId>");
+    xml.append(MgUtil::WideCharToMultiByte(layer->GetObjectId()));
+    xml.append("</ObjectId>\n");
+    xml.append("<DisplayInLegend>");
+    xml.append(layer->GetDisplayInLegend() ? "true" : "false");
+    xml.append("</DisplayInLegend>\n");
+    xml.append("<ExpandInLegend>");
+    xml.append(layer->GetExpandInLegend() ? "true" : "false");
+    xml.append("</ExpandInLegend>\n");
+    xml.append("<Visible>");
+    xml.append(layer->GetVisible() ? "true" : "false");
+    xml.append("</Visible>\n");
+    xml.append("<ActuallyVisible>");
+    xml.append(layer->IsVisible() ? "true" : "false");
+    xml.append("</ActuallyVisible>\n");
+    // ----------------------- Optional things if requested ------------------------- //
+    if ((m_requestDataMask & REQUEST_LAYER_FEATURE_SOURCE) == REQUEST_LAYER_FEATURE_SOURCE)
+    {
+        xml.append("<FeatureSource>\n");
+        xml.append("<ResourceId>");
+        xml.append(MgUtil::WideCharToMultiByte(layer->GetFeatureSourceId()));
+        xml.append("</ResourceId>\n");
+        xml.append("<ClassName>");
+        xml.append(MgUtil::WideCharToMultiByte(layer->GetFeatureClassName()));
+        xml.append("</ClassName>\n");
+        xml.append("<Geometry>");
+        xml.append(MgUtil::WideCharToMultiByte(layer->GetFeatureGeometryName()));
+        xml.append("</Geometry>\n");
+        xml.append("</FeatureSource>\n");
+    }
+    if ((m_requestDataMask & REQUEST_LAYER_ICONS) == REQUEST_LAYER_ICONS)
+    {
+        //Our layer def map is already populated if this mask was set
+        if (layerDefMap.find(ldfId) != layerDefMap.end())
+        {
+            MdfModel::VectorLayerDefinition* vl = dynamic_cast<MdfModel::VectorLayerDefinition*>(layerDefMap.at(ldfId));
+            if (NULL != vl)
+            {
+                MdfModel::VectorScaleRangeCollection* vsrs = vl->GetScaleRanges();
+                for (INT32 i = 0; i < vsrs->GetCount(); i++)
+                {
+                    MdfModel::VectorScaleRange* vsr = vsrs->GetAt(i);
+                    xml.append("<ScaleRange>\n");
+                    xml.append("<MinScale>");
+                    std::string sMinScale;
+                    MgUtil::DoubleToString(vsr->GetMinScale(), sMinScale);
+                    xml.append(sMinScale);
+                    xml.append("</MinScale>\n");
+                    xml.append("<MaxScale>");
+                    std::string sMaxScale;
+                    MgUtil::DoubleToString(vsr->GetMaxScale(), sMaxScale);
+                    xml.append(sMaxScale);
+                    xml.append("</MaxScale>\n");
+                    xml.append("</ScaleRange>\n");
+                }
+            }
+            else
+            {
+                xml.append("<ScaleRange/>");
+            }
+        }
+        else
+            xml.append("<ScaleRange/>");
+    }
+    xml.append("</Layer>");
+
+    MG_HTTP_HANDLER_CATCH_AND_THROW(L"MgHttpCreateRuntimeMap.CreateLayerItem")
+}
+
+/// <summary>
+/// This method is responsible for checking if
+/// a valid version was given
+/// </summary>
+/// <returns>Returns nothing</returns>
+void MgHttpCreateRuntimeMap::ValidateOperationVersion()
+{
+    MG_HTTP_HANDLER_TRY()
+
+    // There are multiple supported versions
+    INT32 version = m_userInfo->GetApiVersion();
+    if (version != MG_API_VERSION(2,6,0))
+    {
+        throw new MgInvalidOperationVersionException(
+        L"MgHttpCreateRuntimeMap.ValidateOperationVersion", __LINE__, __WFILE__, NULL, L"", NULL);
+    }
+
+    MG_HTTP_HANDLER_CATCH_AND_THROW(L"MgHttpCreateRuntimeMap.ValidateOperationVersion");
+}

Modified: sandbox/jng/createruntimemap/Web/src/HttpHandler/HttpCreateRuntimeMap.h
===================================================================
--- sandbox/jng/createruntimemap/Web/src/HttpHandler/HttpCreateRuntimeMap.h	2013-05-09 13:41:59 UTC (rev 7488)
+++ sandbox/jng/createruntimemap/Web/src/HttpHandler/HttpCreateRuntimeMap.h	2013-05-10 13:50:13 UTC (rev 7489)
@@ -18,6 +18,12 @@
 #ifndef _HTTP_CREATE_RUNTIME_MAP_
 #define _HTTP_CREATE_RUNTIME_MAP_
 
+typedef std::map<STRING, MdfModel::LayerDefinition*> LayerDefinitionMap;
+typedef std::list<STRING> LayerNameList;
+typedef std::list<STRING> GroupNameList;
+typedef std::map<STRING, LayerNameList> LayerParentMap;
+typedef std::map<STRING, GroupNameList> GroupParentMap;
+
 class MgHttpCreateRuntimeMap : public MgHttpRequestResponseHandler
 {
 HTTP_DECLARE_CREATE_OBJECT()
@@ -51,10 +57,26 @@
     /// </returns>
     MgRequestClassification GetRequestClassification() { return MgHttpRequestResponseHandler::mrcViewer; }
 
+    /// <summary>
+    /// This method is responsible for checking if
+    /// a valid version was given
+    /// </summary>
+    /// <returns>Returns nothing</returns>
+    virtual void ValidateOperationVersion();
+
 private:
     MgByteReader* BuildRuntimeMapXml(MgResourceIdentifier* mdfId, CREFSTRING mapName);
+    void CreateGroupItem(MgLayerGroup* group, std::string& xml, MgLayerCollection* layers, MgLayerGroupCollection* groups, const LayerDefinitionMap& layerDefMap);
+    void CreateLayerItem(MgLayerBase* layer, std::string& xml, MgLayerCollection* layers, const LayerDefinitionMap& layerDefMap);
 
     STRING m_mapDefinition;
+    INT32 m_requestDataMask;
+    INT32 m_iconLimitPerScaleRange;
+
+    LayerParentMap m_layerParentMap;
+    GroupParentMap m_groupParentMap;
+    LayerNameList m_topLevelLayers;
+    GroupNameList m_topLevelGroups;
 };
 
 #endif  // _HTTP_CREATE_RUNTIME_MAP_

Modified: sandbox/jng/createruntimemap/Web/src/HttpHandler/HttpResourceStrings.cpp
===================================================================
--- sandbox/jng/createruntimemap/Web/src/HttpHandler/HttpResourceStrings.cpp	2013-05-09 13:41:59 UTC (rev 7488)
+++ sandbox/jng/createruntimemap/Web/src/HttpHandler/HttpResourceStrings.cpp	2013-05-10 13:50:13 UTC (rev 7489)
@@ -217,6 +217,7 @@
 const STRING MgHttpResourceStrings::reqMappingFormat = L"FORMAT";
 const STRING MgHttpResourceStrings::reqMappingType = L"TYPE";
 const STRING MgHttpResourceStrings::reqMappingThemeCategory = L"THEMECATEGORY";
+const STRING MgHttpResourceStrings::reqMappingRequestedFeatures = L"REQUESTEDFEATURES";
 
 // Predefined Rendering Service Request Parameters
 const STRING MgHttpResourceStrings::reqRenderingMapDefinition = L"MAPDEFINITION";

Modified: sandbox/jng/createruntimemap/Web/src/HttpHandler/HttpResourceStrings.h
===================================================================
--- sandbox/jng/createruntimemap/Web/src/HttpHandler/HttpResourceStrings.h	2013-05-09 13:41:59 UTC (rev 7488)
+++ sandbox/jng/createruntimemap/Web/src/HttpHandler/HttpResourceStrings.h	2013-05-10 13:50:13 UTC (rev 7489)
@@ -153,6 +153,7 @@
     static const STRING reqMappingFormat;
     static const STRING reqMappingType;
     static const STRING reqMappingThemeCategory;
+    static const STRING reqMappingRequestedFeatures;
 
     // PREDEFINED RENDERING REQUEST PARAMETERS
     static const STRING reqRenderingMapDefinition;



More information about the mapguide-commits mailing list