[fusion-commits] r2725 - in trunk: layers/MapGuide lib

svn_fusion at osgeo.org svn_fusion at osgeo.org
Thu May 30 00:37:05 PDT 2013


Author: jng
Date: 2013-05-30 00:37:05 -0700 (Thu, 30 May 2013)
New Revision: 2725

Modified:
   trunk/layers/MapGuide/MapGuide.js
   trunk/lib/MGBroker.js
Log:
MapGuide RFC 126: Merge QUERYMAPFEATURES v2.6 sandbox

Modified: trunk/layers/MapGuide/MapGuide.js
===================================================================
--- trunk/layers/MapGuide/MapGuide.js	2013-05-29 08:25:25 UTC (rev 2724)
+++ trunk/layers/MapGuide/MapGuide.js	2013-05-30 07:37:05 UTC (rev 2725)
@@ -971,26 +971,28 @@
      *        given, all the elemsnts will be returned.
      */
     getSelection: function(userFunc, layers, startcount) {
-
-      /*for now always go back to server to fetch selection */
-
-      if (userFunc)
-      {
-          //this.aSelectionCallbacks.push(userFunc);
-
-
-          //this.mapWidget._addWorker();
-          // this._bSelectionIsLoading = true;
-          var s = 'layers/' + this.arch + '/' + Fusion.getScriptLanguage() + "/Selection." + Fusion.getScriptLanguage() ;
-          var options = {
-              parameters: {'session': this.getSessionID(),
-                          'mapname': this._sMapname,
-                          'layers': layers,
-                          'startcount': startcount},
-              onSuccess: OpenLayers.Function.bind(this.getSelectionCB, this, userFunc)
-          };
-          Fusion.ajaxRequest(s, options);
-      }
+        /*for now always go back to server to fetch selection */
+        if (userFunc)
+        {
+            if (this.previousAttributes) {
+                userFunc(new Fusion.SelectionObject(this.previousAttributes));
+            } else {
+                //this.aSelectionCallbacks.push(userFunc);
+                //this.mapWidget._addWorker();
+                // this._bSelectionIsLoading = true;
+                var s = 'layers/' + this.arch + '/' + Fusion.getScriptLanguage() + "/Selection." + Fusion.getScriptLanguage() ;
+                var options = {
+                    parameters: {
+                        'session': this.getSessionID(),
+                        'mapname': this._sMapname,
+                        'layers': layers,
+                        'startcount': startcount
+                    },
+                    onSuccess: OpenLayers.Function.bind(this.getSelectionCB, this, userFunc)
+                };
+                Fusion.ajaxRequest(s, options);
+            }
+        }
     },
 
     /**
@@ -1049,6 +1051,14 @@
         this.processSelectedFeatureProperties(r);
     },
 
+    processSelectedFeaturePropertiesNode: function(oNode) {
+        if (oNode.hasSelection) {
+            this.newSelection();
+        } else {
+            this.clearSelection();
+        }
+    },
+
     /**
        Call back function when select functions are called (eg queryRect)
        to handle feature attributes
@@ -1057,13 +1067,7 @@
         this.mapWidget._removeWorker();
         if (r.responseText) {   //TODO: make the equivalent change to MapServer.js
             var oNode = Fusion.parseJSON(r.responseText);
-
-            if (oNode.hasSelection) {
-              this.newSelection();
-            } else {
-              this.clearSelection();
-              return;
-            }
+            this.processSelectedFeaturePropertiesNode(oNode);
         }
     },
 
@@ -1117,6 +1121,25 @@
             }
         }
     },
+    /**
+     * Checks if we can perform a v2.6.0 QUERYMAPFEATURES request. A v2.6.0 QUERYMAPFEATURES request gives us
+     *  - All attributes of selected features if requested (bypassing several follow-up requests to PHP scripts to get this data)
+     *  - Slimmer maptip requests.
+     * A much better option, if it is available to us.
+     */
+    supportsExtendedQuery: function() {
+        var bSupportsExtended = false;
+        if (this.siteVersion[0] >= 2) { //2.x or higher
+            if (this.siteVersion[0] == 2) { //Major is 2
+                if (this.siteVersion[1] >= 6) { //2.6 or higher 2.x
+                    bSupportsExtended = true;
+                }
+            } else { //3.x, 4.x, etc
+                bSupportsExtended = true;
+            }
+        }
+        return bSupportsExtended;
+    },
 
     /**
        Do a query on the map
@@ -1140,7 +1163,13 @@
         {
             options.filter = '';
         }
-        var r = new Fusion.Lib.MGRequest.MGQueryMapFeatures(this.getSessionID(),
+        
+        if (this.supportsExtendedQuery()) {
+            var reqData = 1; //attributes
+            //TODO: Can't use inline selection image yet as we'll have to modify OpenLayers to accept an inline selection
+            //over doing a GETDYNAMICMAPOVERLAYIMAGE request. When we can, or the value of 2 into the mask for inline 
+            //selection as well
+            var r = new Fusion.Lib.MGRequest.MGQueryMapFeatures2(this.getSessionID(),
                                                                 this._sMapname,
                                                                 options.geometry,
                                                                 maxFeatures,
@@ -1148,9 +1177,25 @@
                                                                 options.selectionType || this.selectionType,
                                                                 options.filter,
                                                                 options.layers,
+                                                                layerAttributeFilter,
+                                                                reqData,
+                                                                this.selectionColor,
+                                                                this.selectionImageFormat);
+            var callback = (options.extendSelection == true) ? OpenLayers.Function.bind(this.processAndMergeExtendedFeatureInfo, this) : OpenLayers.Function.bind(this.processExtendedFeatureInfo, this);
+            Fusion.oBroker.dispatchRequest(r, callback);
+        } else {
+            var r = new Fusion.Lib.MGRequest.MGQueryMapFeatures(this.getSessionID(),
+                                                                this._sMapname,
+                                                                options.geometry,
+                                                                maxFeatures,
+                                                                persist,
+                                                                options.selectionType || this.selectionType,
+                                                                options.filter,
+                                                                options.layers,
                                                                 layerAttributeFilter);
-        var callback = (options.extendSelection == true) ? OpenLayers.Function.bind(this.processAndMergeFeatureInfo, this) : OpenLayers.Function.bind(this.processFeatureInfo, this);
-        Fusion.oBroker.dispatchRequest(r, callback);
+            var callback = (options.extendSelection == true) ? OpenLayers.Function.bind(this.processAndMergeFeatureInfo, this) : OpenLayers.Function.bind(this.processFeatureInfo, this);
+            Fusion.oBroker.dispatchRequest(r, callback);
+        }
     },
 
     showLayer: function( layer, noDraw ) {
@@ -1210,7 +1255,7 @@
         this.drawMap();
     },
 
-  /**
+    /**
      * called when there is a click on the map holding the CTRL key: query features at that postion.
      **/
     mouseUpCRTLClick: function(evt) {
@@ -1353,12 +1398,25 @@
         var layerAttributeFilter = 5;
         //TODO: possibly make the layer names configurable?
         var layerNames = mapTipWidget.aLayers.toString();
-        var r = new Fusion.Lib.MGRequest.MGQueryMapFeatures(this.getSessionID(),
-                                        this._sMapname,
-                                        sGeometry,
-                                        maxFeatures, persist, selection, filter, layerNames,
-                                        layerAttributeFilter);
-        oBroker.dispatchRequest(r, OpenLayers.Function.bind(this.parseMapTip, this));
+        if (this.supportsExtendedQuery()) {
+            var reqData = (4 | 8); //Tooltips and hyperlinks
+            var r = new Fusion.Lib.MGRequest.MGQueryMapFeatures2(this.getSessionID(),
+                                            this._sMapname,
+                                            sGeometry,
+                                            maxFeatures, persist, selection, filter, layerNames,
+                                            layerAttributeFilter,
+                                            reqData,
+                                            this.selectionColor,
+                                            this.selectionImageFormat);
+            oBroker.dispatchRequest(r, OpenLayers.Function.bind(this.parseMapTip, this));
+        } else {
+            var r = new Fusion.Lib.MGRequest.MGQueryMapFeatures(this.getSessionID(),
+                                            this._sMapname,
+                                            sGeometry,
+                                            maxFeatures, persist, selection, filter, layerNames,
+                                            layerAttributeFilter);
+            oBroker.dispatchRequest(r, OpenLayers.Function.bind(this.parseMapTip, this));
+        }
     },
     
     parseMapTip: function(xhr) {
@@ -1408,10 +1466,138 @@
             }
             return url;
         }
+    },
+    
+    typeNameToValue: function(name) {
+        switch(name) { //Values from MgPropertyType
+            case "byte":
+                return 2;
+            case "boolean":
+                return 1;
+            case "blob":
+                return 10;
+            case "clob":
+                return 11;
+            case "datetime":
+                return 3;
+            case "double":
+                return 5;
+            case "int16":
+                return 6;
+            case "int32":
+                return 7;
+            case "int64":
+                return 8;
+            case "single":
+                return 4;
+            case "string":
+                return 9;
+        }
+        return -1;
+    },
+    
+    convertExtendedFeatureInfo: function(efi) {
+        var bHasSelection = false;
+        var result = {};
+        var layerNames = [];
+        var featuresByLayer = {};
+        if (efi.FeatureInformation.SelectedFeatures) {
+            var selLayers = efi.FeatureInformation.SelectedFeatures[0].SelectedLayer;
+            bHasSelection = (selLayers.length > 0);
+            var box = new OpenLayers.Bounds();
+            
+            for (var i = 0; i < selLayers.length; i++) {
+                var selLayer = selLayers[i];
+                var layerName = selLayer["@name"];
+                if (!result[layerName]) {
+                    var layerMeta = selLayer.LayerMetadata[0];
+                    var pnames = [];
+                    var ptypes = [];
+                    var pvals = [];
+                    for (var j = 0; j < layerMeta.Property.length; j++) {
+                        var metaProp = layerMeta.Property[j];
+                        pnames.push(metaProp.Name[0]);
+                        ptypes.push(metaProp.Type[0]);
+                        pvals.push(metaProp.DisplayName[0]);
+                    }
+                    result[layerName] = {
+                        metadata: [],  //NOTE: Probably a defect, but regular code path is putting blank string arrays here too
+                        metadatanames: ["dimension", "bbox", "center", "area", "length"],
+                        numelements: selLayer.Feature.length,
+                        propertynames: pnames,
+                        propertytypes: ptypes,
+                        propertyvalues: pvals,
+                        values: []
+                    };
+                    layerNames.push(layerName);
+                }
+                
+                for (var j = 0; j < selLayer.Feature.length; j++) {
+                    var feat = selLayer.Feature[j];
+                    var featVals = [];
+                    for (var k = 0; k < feat.Property.length; k++) {
+                        //Fusion represents null as empty string. Don't think that's right but we'll run with whatever
+                        //the old code path produces
+                        featVals.push(feat.Property[k].Value == null ? "" : feat.Property[k].Value[0]);
+                    }
+                    result[layerName].values.push(featVals);
+                    //NOTE: Probably a defect, but regular code path is putting blank string arrays here too, so let's do the same
+                    result[layerName].metadata.push(["","","","",""]);
+                    var bounds = feat.Bounds[0].split(" "); //minx miny maxx maxy
+                    box.extend(new OpenLayers.LonLat(parseFloat(bounds[0]), parseFloat(bounds[1])));
+                    box.extend(new OpenLayers.LonLat(parseFloat(bounds[2]), parseFloat(bounds[3])));
+                }
+            }
+            return OpenLayers.Util.extend(result, {
+                hasSelection: bHasSelection,
+                extents: {
+                    minx: box.left,
+                    miny: box.bottom,
+                    maxx: box.right,
+                    maxy: box.top
+                },
+                layers: layerNames
+            });
+        } else {
+            result.hasSelection = false;
+            return result;
+        }
+    },
 
+    processAndMergeExtendedFeatureInfo: function(r) {
+        this.processSelectedExtendedFeatureInfo(r, true);
+        //this.processSelectedFeatureInfo(r, true);
     },
-
-
+    
+    processExtendedFeatureInfo: function(r) {
+        this.processSelectedExtendedFeatureInfo(r, false);
+        //this.processSelectedFeatureInfo(r, false);
+    },
+    
+    processSelectedExtendedFeatureInfo: function(r, mergeSelection) {
+        var o = Fusion.parseJSON(r.responseText);
+        var sel = new Fusion.SimpleSelectionObject(o);
+        var attributes = this.convertExtendedFeatureInfo(o);
+        var selText = sel.getSelectionXml();
+        if (mergeSelection == true)
+        {
+            sel.merge(this.previousSelection);
+        }
+        this.previousSelection = sel;
+        //Because the QUERYMAPFEATURES 2.6.0 response contains mostly everything we need, we cut down
+        //on lots of async request ping-pong. So we can just update the selection image and notify any
+        //interested parties of the new selection attributes
+        if (selText != "" && selText != null) {
+            this.previousAttributes = attributes;
+            this.updateMapSelection(selText, false);
+            this.processSelectedFeaturePropertiesNode(attributes);
+        } else {
+            this.previousAttributes = null;
+            this.clearSelection();
+        }
+        this.mapWidget._removeWorker();
+    },
+    
     processAndMergeFeatureInfo: function (r) {
         this.processSelectedFeatureInfo(r, true);
     },

Modified: trunk/lib/MGBroker.js
===================================================================
--- trunk/lib/MGBroker.js	2013-05-29 08:25:25 UTC (rev 2724)
+++ trunk/lib/MGBroker.js	2013-05-30 07:37:05 UTC (rev 2725)
@@ -641,6 +641,59 @@
 });
 
 /****************************************************************************
+ * Class: Fusion.Lib.MGRequest.MGQueryMapFeatures2
+ *
+ * encapsulate a request to the server to query map features on 
+ * selectable layers
+ * 
+ * Inherits from:
+ *  - <Fusion.Lib.MGRequest>
+ */
+Fusion.Lib.MGRequest.MGQueryMapFeatures2 = OpenLayers.Class(Fusion.Lib.MGRequest, {
+    /**
+     * Constructor: Fusion.Lib.MGRequest.MGQueryMapFeatures2
+     * 
+     * initialize a new instance of Fusion.Lib.MGRequest.MGQueryMapFeatures2
+     *
+     * Parameters:
+     * sessionId - {String} the id of the session to restore
+     * mapName - {String} the id of the session to restore
+     * geometry (sting wkt} gemetry to use for selection.  Example : POLYGON(x1 y1, x2,y2)
+     * maxFeatures - {integer} number of maximum results (-1 to indicate no maximum)
+     * selectionPersist - {boolean} save the selection (valid values are 0 and 1) 
+     * selectionVariant - {String} indicates the spatial operation. Valid values are 'INTERSECTS', ...
+     * featureFilter - {String} filter crieteria to be applied for selection.
+     * layerNames - {String} comma separated list of layer names to include in the query
+     * layerAttributeFilter - {integer} bitmask determining layer selection behaviour (1=visible layers,
+     *          2=selectable layers, 4=layers with tooltips)
+     * requestData - {integer} a bitmask of the desired information to return (Attributes = 1 InlineSelection? = 2 Tooltip = 4 Hyperlink = 8)
+     * selectionColor - {String} the html color for the inline selection image (if requested)
+     * selectionFormat - {String} the format of the inline selection image (if requested)
+     */
+    initialize : function( sessionId, mapName, geometry, maxFeatures, persist, selectionVariant, featureFilter, layerNames, layerAttributeFilter, requestData, selectionColor, selectionFormat) 
+    {
+        this.initializeRequest();
+        this.setParams( {
+            operation : 'QUERYMAPFEATURES',
+            format: "application/json",
+            version: "2.6.0",
+            session: sessionId,
+            mapname: mapName,
+            geometry: geometry,
+            maxFeatures: maxFeatures,
+            persist: persist,
+            selectionVariant: selectionVariant,
+            featureFilter: featureFilter,
+            layerNames: layerNames,
+            layerAttributeFilter: layerAttributeFilter,
+            requestData: requestData,
+            selectionColor: selectionColor,
+            selectionFormat: selectionFormat
+        } );
+    }
+});
+
+/****************************************************************************
  * Class: Fusion.Lib.MGRequest.MGGetFeatureSetEnvelope
  *
  * encapsulate a request to the server to query map features on 



More information about the fusion-commits mailing list