From 2ce92ac6a29f53cc162d546418806b103869c662 Mon Sep 17 00:00:00 2001 From: Bart van den Eijnden Date: Fri, 7 Mar 2014 16:44:24 +0100 Subject: [PATCH] Add write support for BBOX filter --- src/objectliterals.jsdoc | 5 +- src/ol/format/gmlformat.js | 70 +++++++++++++++++++++------ src/ol/format/wfsformat.js | 41 +++++++++++++++- test/spec/ol/format/wfsformat.test.js | 28 +++++++++++ 4 files changed, 127 insertions(+), 17 deletions(-) diff --git a/src/objectliterals.jsdoc b/src/objectliterals.jsdoc index 8d6b967eed..1f222add18 100644 --- a/src/objectliterals.jsdoc +++ b/src/objectliterals.jsdoc @@ -340,7 +340,10 @@ * set on geometries when this is not provided. * @property {string|undefined} handle Handle. * @property {string|undefined} outputFormat Output format. - * @property {number} maxFeatures Maximum number of features to fetch. + * @property {number|undefined} maxFeatures Maximum number of features to fetch. + * @property {string|undefined} geometryName Geometry name to use in a BBOX + * filter. + * @property {ol.Extent|undefined} bbox Extent to use for the BBOX filter. */ /** diff --git a/src/ol/format/gmlformat.js b/src/ol/format/gmlformat.js index 65621e014b..291c65c772 100644 --- a/src/ol/format/gmlformat.js +++ b/src/ol/format/gmlformat.js @@ -1117,6 +1117,41 @@ ol.format.GML.writePoint_ = function(node, geometry, objectStack) { }; +/** + * @type {Object.>} + * @private + */ +ol.format.GML.ENVELOPE_SERIALIZERS_ = { + 'http://www.opengis.net/gml': { + 'lowerCorner': ol.xml.makeChildAppender(ol.format.XSD.writeStringTextNode), + 'upperCorner': ol.xml.makeChildAppender(ol.format.XSD.writeStringTextNode) + } +}; + + +/** + * @param {Node} node Node. + * @param {ol.Extent} extent Extent. + * @param {Array.<*>} objectStack Node stack. + */ +ol.format.GML.writeEnvelope = function(node, extent, objectStack) { + goog.asserts.assert(extent.length == 4); + var context = objectStack[objectStack.length - 1]; + goog.asserts.assert(goog.isObject(context)); + var srsName = goog.object.get(context, 'srsName'); + if (goog.isDef(srsName)) { + node.setAttribute('srsName', srsName); + } + var keys = ['lowerCorner', 'upperCorner']; + var values = [extent[0] + ' ' + extent[1], extent[2] + ' ' + extent[3]]; + ol.xml.pushSerializeAndPop(/** @type {ol.xml.NodeStackItem} */ + ({node: node}), ol.format.GML.ENVELOPE_SERIALIZERS_, + ol.xml.OBJECT_PROPERTY_NODE_FACTORY, + values, + objectStack, keys); +}; + + /** * @param {Node} node Node. * @param {ol.geom.LinearRing} geometry LinearRing geometry. @@ -1366,11 +1401,10 @@ ol.format.GML.writeCurveSegments_ = function(node, line, objectStack) { /** * @param {Node} node Node. - * @param {ol.geom.Geometry} geometry Geometry. + * @param {ol.geom.Geometry|ol.Extent} geometry Geometry. * @param {Array.<*>} objectStack Node stack. - * @private */ -ol.format.GML.writeGeometry_ = function(node, geometry, objectStack) { +ol.format.GML.writeGeometry = function(node, geometry, objectStack) { var context = objectStack[objectStack.length - 1]; goog.asserts.assert(goog.isObject(context)); var item = goog.object.clone(context); @@ -1408,7 +1442,7 @@ ol.format.GML.writeFeature_ = function(node, feature, objectStack) { if (key == geometryName) { if (!(key in context.serializers[featureNS])) { context.serializers[featureNS][key] = ol.xml.makeChildAppender( - ol.format.GML.writeGeometry_); + ol.format.GML.writeGeometry); } } else { if (!(key in context.serializers[featureNS])) { @@ -1524,7 +1558,9 @@ ol.format.GML.GEOMETRY_SERIALIZERS_ = { ol.format.GML.writeMultiSurfaceOrPolygon_), 'Surface': ol.xml.makeChildAppender(ol.format.GML.writeSurfaceOrPolygon_), 'MultiSurface': ol.xml.makeChildAppender( - ol.format.GML.writeMultiSurfaceOrPolygon_) + ol.format.GML.writeMultiSurfaceOrPolygon_), + 'Envelope': ol.xml.makeChildAppender( + ol.format.GML.writeEnvelope) } }; @@ -1575,18 +1611,22 @@ ol.format.GML.GEOMETRY_NODE_FACTORY_ = function(value, objectStack, var surface = goog.object.get(context, 'surface'); var curve = goog.object.get(context, 'curve'); var multiCurve = goog.object.get(context, 'multiCurve'); - goog.asserts.assertInstanceof(value, ol.geom.Geometry); var parentNode = objectStack[objectStack.length - 1].node; goog.asserts.assert(ol.xml.isNode(parentNode)); - var nodeName = value.getType(); - if (nodeName === 'MultiPolygon' && multiSurface === true) { - nodeName = 'MultiSurface'; - } else if (nodeName === 'Polygon' && surface === true) { - nodeName = 'Surface'; - } else if (nodeName === 'LineString' && curve === true) { - nodeName = 'Curve'; - } else if (nodeName === 'MultiLineString' && multiCurve === true) { - nodeName = 'MultiCurve'; + if (!goog.isArray(value)) { + goog.asserts.assertInstanceof(value, ol.geom.Geometry); + var nodeName = value.getType(); + if (nodeName === 'MultiPolygon' && multiSurface === true) { + nodeName = 'MultiSurface'; + } else if (nodeName === 'Polygon' && surface === true) { + nodeName = 'Surface'; + } else if (nodeName === 'LineString' && curve === true) { + nodeName = 'Curve'; + } else if (nodeName === 'MultiLineString' && multiCurve === true) { + nodeName = 'MultiCurve'; + } + } else { + nodeName = 'Envelope'; } return ol.xml.createElementNS('http://www.opengis.net/gml', nodeName); diff --git a/src/ol/format/wfsformat.js b/src/ol/format/wfsformat.js index 11109ae724..72ee897470 100644 --- a/src/ol/format/wfsformat.js +++ b/src/ol/format/wfsformat.js @@ -312,6 +312,43 @@ ol.format.WFS.writeQuery_ = function(node, featureType, objectStack) { ol.format.WFS.QUERY_SERIALIZERS_, ol.xml.makeSimpleNodeFactory('PropertyName'), propertyNames, objectStack); + var bbox = goog.object.get(context, 'bbox'); + if (goog.isDef(bbox)) { + var child = ol.xml.createElementNS('http://www.opengis.net/ogc', 'Filter'); + ol.format.WFS.writeBBOX_(child, bbox, objectStack); + node.appendChild(child); + } +}; + + +/** + * @param {Node} node Node. + * @param {string} value PropertyName value. + * @param {Array.<*>} objectStack Node stack. + * @private + */ +ol.format.WFS.writeOgcPropertyName_ = function(node, value, objectStack) { + var property = ol.xml.createElementNS('http://www.opengis.net/ogc', + 'PropertyName'); + ol.format.XSD.writeStringTextNode(property, value); + node.appendChild(property); +}; + + +/** + * @param {Node} node Node. + * @param {ol.Extent} bbox Bounding box. + * @param {Array.<*>} objectStack Node stack. + * @private + */ +ol.format.WFS.writeBBOX_ = function(node, bbox, objectStack) { + var context = objectStack[objectStack.length - 1]; + goog.asserts.assert(goog.isObject(context)); + var geometryName = goog.object.get(context, 'geometryName'); + var bboxNode = ol.xml.createElementNS('http://www.opengis.net/ogc', 'BBOX'); + node.appendChild(bboxNode); + ol.format.WFS.writeOgcPropertyName_(bboxNode, geometryName, objectStack); + ol.format.GML.writeGeometry(bboxNode, bbox, objectStack); }; @@ -337,7 +374,7 @@ ol.format.WFS.writeGetFeature_ = function(node, featureTypes, objectStack) { var context = objectStack[objectStack.length - 1]; goog.asserts.assert(goog.isObject(context)); var item = goog.object.clone(context); - goog.object.set(item, 'node', node); + item.node = node; ol.xml.pushSerializeAndPop(item, ol.format.WFS.GETFEATURE_SERIALIZERS_, ol.xml.makeSimpleNodeFactory('Query'), featureTypes, @@ -382,6 +419,8 @@ ol.format.WFS.prototype.writeGetFeature = function(options) { featureNS: goog.isDef(options.featureNS) ? options.featureNS : this.featureNS_, featurePrefix: options.featurePrefix, + geometryName: options.geometryName, + bbox: options.bbox, propertyNames: goog.isDef(options.propertyNames) ? options.propertyNames : [] }; diff --git a/test/spec/ol/format/wfsformat.test.js b/test/spec/ol/format/wfsformat.test.js index 603e15a388..cb500361c0 100644 --- a/test/spec/ol/format/wfsformat.test.js +++ b/test/spec/ol/format/wfsformat.test.js @@ -146,6 +146,34 @@ describe('ol.format.WFS', function() { }); expect(serialized).to.xmleql(ol.xml.load(text)); }); + + it('creates a BBOX filter', function() { + var text = + '' + + ' ' + + ' ' + + ' the_geom' + + ' ' + + ' 1 2' + + ' 3 4' + + ' ' + + ' ' + + ' ' + + ''; + var serialized = new ol.format.WFS().writeGetFeature({ + srsName: 'urn:ogc:def:crs:EPSG::4326', + featureNS: 'http://www.openplans.org/topp', + featurePrefix: 'topp', + featureTypes: ['states'], + geometryName: 'the_geom', + bbox: [1, 2, 3, 4] + }); + expect(serialized.firstElementChild).to.xmleql(ol.xml.load(text)); + }); + }); });