From dc58d4e5621aa32baf858e1a0a361cc44d8bb97e Mon Sep 17 00:00:00 2001 From: Bart van den Eijnden Date: Tue, 22 Oct 2013 16:24:07 +0200 Subject: [PATCH 01/13] srsName should be optional in BBOX --- src/ol/parser/ogc/filterparser_v1_0_0.js | 6 ++++-- src/ol/parser/ogc/gmlparser_v2.js | 3 ++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/ol/parser/ogc/filterparser_v1_0_0.js b/src/ol/parser/ogc/filterparser_v1_0_0.js index e9b3a22bac..0b14d01eb6 100644 --- a/src/ol/parser/ogc/filterparser_v1_0_0.js +++ b/src/ol/parser/ogc/filterparser_v1_0_0.js @@ -91,12 +91,14 @@ ol.parser.ogc.Filter_v1_0_0 = function() { goog.asserts.assert(args[1] instanceof ol.expr.Literal); goog.asserts.assert(args[2] instanceof ol.expr.Literal); goog.asserts.assert(args[3] instanceof ol.expr.Literal); - goog.asserts.assert(args[4] instanceof ol.expr.Literal); var bbox = [ args[0].getValue(), args[1].getValue(), args[2].getValue(), args[3].getValue() ]; - var projection = args[4].getValue(); + var projection; + if (args[4] instanceof ol.expr.Literal) { + projection = args[4].getValue(); + } var property = args[5]; // PropertyName is mandatory in 1.0.0, but e.g. GeoServer also // accepts filters without it. diff --git a/src/ol/parser/ogc/gmlparser_v2.js b/src/ol/parser/ogc/gmlparser_v2.js index 837b5d844e..37bdd9d191 100644 --- a/src/ol/parser/ogc/gmlparser_v2.js +++ b/src/ol/parser/ogc/gmlparser_v2.js @@ -54,7 +54,8 @@ ol.parser.ogc.GML_v2 = function(opt_options) { for (var i = 0; i < numCoordinates; ++i) { var coord = coordinates[i]; var part = goog.array.concat(coord); - if (this.axisOrientation.substr(0, 2) !== 'en') { + if (goog.isDef(this.axisOrientation) && + this.axisOrientation.substr(0, 2) !== 'en') { part[0] = coord[1]; part[1] = coord[0]; } From 557390f2add7e7dc07fd3643871eedd6d179b12d Mon Sep 17 00:00:00 2001 From: Bart van den Eijnden Date: Tue, 22 Oct 2013 16:24:27 +0200 Subject: [PATCH 02/13] initial version of the WFS parser for 1.0.0 and 1.1.0 --- src/objectliterals.jsdoc | 7 ++ src/ol/parser/ogc/wfsparser.js | 38 +++++++ src/ol/parser/ogc/wfsparser_v1.js | 87 ++++++++++++++++ src/ol/parser/ogc/wfsparser_v1_0_0.js | 99 +++++++++++++++++++ src/ol/parser/ogc/wfsparser_v1_1_0.js | 94 ++++++++++++++++++ test/spec/ol/parser/ogc/wfs_v1_0_0.test.js | 49 +++++++++ .../xml/wfs_v1_0_0/Transaction_Response.xml | 11 +++ .../ol/parser/ogc/xml/wfs_v1_0_0/query0.xml | 10 ++ 8 files changed, 395 insertions(+) create mode 100644 src/ol/parser/ogc/wfsparser.js create mode 100644 src/ol/parser/ogc/wfsparser_v1.js create mode 100644 src/ol/parser/ogc/wfsparser_v1_0_0.js create mode 100644 src/ol/parser/ogc/wfsparser_v1_1_0.js create mode 100644 test/spec/ol/parser/ogc/wfs_v1_0_0.test.js create mode 100644 test/spec/ol/parser/ogc/xml/wfs_v1_0_0/Transaction_Response.xml create mode 100644 test/spec/ol/parser/ogc/xml/wfs_v1_0_0/query0.xml diff --git a/src/objectliterals.jsdoc b/src/objectliterals.jsdoc index d416c8b63e..ef153d8169 100644 --- a/src/objectliterals.jsdoc +++ b/src/objectliterals.jsdoc @@ -595,6 +595,13 @@ * calculations. */ +/** + * @typedef {Object} ol.parser.WFSOptions + * @property {Array.} featureTypes The feature types to use. + * @property {string} featureNS The featureNS to use. + * @property {string} featurePrefix The prefix to use for the featureNS. + */ + /** * @typedef {Object} ol.source.BingMapsOptions * @property {string|undefined} culture Culture code. Default is `en-us`. diff --git a/src/ol/parser/ogc/wfsparser.js b/src/ol/parser/ogc/wfsparser.js new file mode 100644 index 0000000000..68e3141326 --- /dev/null +++ b/src/ol/parser/ogc/wfsparser.js @@ -0,0 +1,38 @@ +goog.require('ol.parser.ogc.Versioned'); +goog.provide('ol.parser.ogc.WFS'); +goog.require('ol.parser.ogc.WFS_v1_0_0'); +goog.require('ol.parser.ogc.WFS_v1_1_0'); + + +/** + * @define {boolean} Whether to enable OGC WFS version 1.0.0. + */ +ol.ENABLE_WFS_1_0_0 = true; + + +/** + * @define {boolean} Whether to enable OGC WFS version 1.1.0. + */ +ol.ENABLE_WFS_1_1_0 = true; + + + +/** + * @constructor + * @param {ol.parser.WFSOptions=} opt_options + * Optional configuration object. + * @extends {ol.parser.ogc.Versioned} + */ +ol.parser.ogc.WFS = function(opt_options) { + var options = opt_options || {}; + options['defaultVersion'] = '1.0.0'; + this.parsers = {}; + if (ol.ENABLE_WFS_1_0_0) { + this.parsers['v1_0_0'] = ol.parser.ogc.WFS_v1_0_0; + } + if (ol.ENABLE_WFS_1_1_0) { + this.parsers['v1_1_0'] = ol.parser.ogc.WFS_v1_1_0; + } + goog.base(this, options); +}; +goog.inherits(ol.parser.ogc.WFS, ol.parser.ogc.Versioned); diff --git a/src/ol/parser/ogc/wfsparser_v1.js b/src/ol/parser/ogc/wfsparser_v1.js new file mode 100644 index 0000000000..ddee7c2079 --- /dev/null +++ b/src/ol/parser/ogc/wfsparser_v1.js @@ -0,0 +1,87 @@ +goog.provide('ol.parser.ogc.WFS_v1'); +goog.require('goog.dom.xml'); +goog.require('ol.parser.XML'); + + + +/** + * @constructor + * @param {ol.parser.WFSOptions=} opt_options + * Optional configuration object. + * @extends {ol.parser.XML} + */ +ol.parser.ogc.WFS_v1 = function(opt_options) { + if (goog.isDef(opt_options)) { + this.featureTypes = opt_options.featureTypes; + this.featurePrefix = opt_options.featurePrefix; + this.featureNS = opt_options.featureNS; + } + this.defaultNamespaceURI = 'http://www.opengis.net/wfs'; + // TODO set errorProperty + this.readers = {}; + this.readers[this.defaultNamespaceURI] = { + 'FeatureCollection': function(node, obj) { + obj.features = []; + this.readChildNodes(node, obj); + } + }; + this.writers = {}; + this.writers[this.defaultNamespaceURI] = { + 'GetFeature': function(options) { + var node = this.createElementNS('wfs:GetFeature'); + node.setAttribute('service', 'WFS'); + node.setAttribute('version', this.version); + if (goog.isDef(options)) { + if (goog.isDef(options.handle)) { + node.setAttribute('handle', options.handle); + } + if (goog.isDef(options.outputFormat)) { + node.setAttribute('outputFormat', options.outputFormat); + } + if (goog.isDef(options.maxFeatures)) { + node.setAttribute('maxFeatures', options.maxFeatures); + } + } + // TODO set xsi:schemaLocation + for (var i = 0, ii = this.featureTypes.length; i < ii; i++) { + options.featureType = this.featureTypes[i]; + this.writeNode('Query', options, null, node); + } + return node; + } + }; + goog.base(this); +}; +goog.inherits(ol.parser.ogc.WFS_v1, ol.parser.XML); + + +/** + * @param {string|Document|Element} data Data to read. + * @return {Object} An object representing the document. + */ +ol.parser.ogc.WFS_v1.prototype.read = function(data) { + if (goog.isString(data)) { + data = goog.dom.xml.loadXml(data); + } + if (data && data.nodeType == 9) { + data = data.documentElement; + } + var obj = {}; + this.readNode(data, obj); + return obj; +}; + + +/** + * @param {Array.} features The features to write out. + * @param {Object} options Write options. + * @return {string} A serialized WFS transaction. + */ +ol.parser.ogc.WFS_v1.prototype.write = function(features, options) { + var root = this.writeNode('wfs:Transaction', {features: features, + options: options}); + this.setAttributeNS( + root, 'http://www.w3.org/2001/XMLSchema-instance', + 'xsi:schemaLocation', this.schemaLocation); + return this.serialize(root); +}; diff --git a/src/ol/parser/ogc/wfsparser_v1_0_0.js b/src/ol/parser/ogc/wfsparser_v1_0_0.js new file mode 100644 index 0000000000..0387940f67 --- /dev/null +++ b/src/ol/parser/ogc/wfsparser_v1_0_0.js @@ -0,0 +1,99 @@ +goog.provide('ol.parser.ogc.WFS_v1_0_0'); + +goog.require('goog.array'); +goog.require('goog.object'); +goog.require('ol.parser.ogc.Filter_v1_0_0'); +goog.require('ol.parser.ogc.WFS_v1'); + + + +/** + * @constructor + * @param {ol.parser.WFSOptions=} opt_options + * Optional configuration object. + * @extends {ol.parser.ogc.WFS_v1} + */ +ol.parser.ogc.WFS_v1_0_0 = function(opt_options) { + goog.base(this, opt_options); + this.version = '1.0.0'; + this.schemaLocation = this.defaultNamespaceURI + ' ' + + 'http://schemas.opengis.net/wfs/1.0.0/WFS-transaction.xsd'; + goog.object.extend(this.readers[this.defaultNamespaceURI], { + 'WFS_TransactionResponse': function(node, obj) { + obj.insertIds = []; + obj.success = false; + this.readChildNodes(node, obj); + }, + 'InsertResult': function(node, container) { + var obj = {fids: []}; + this.readChildNodes(node, obj); + for (var key in obj.fids) { + container.insertIds.push(key); + } + }, + 'TransactionResult': function(node, obj) { + this.readChildNodes(node, obj); + }, + 'Status': function(node, obj) { + this.readChildNodes(node, obj); + }, + 'SUCCESS': function(node, obj) { + obj.success = true; + } + }); + goog.object.extend(this.writers[this.defaultNamespaceURI], { + 'Query': function(options) { + // TODO see if we really need properties on the instance + /*goog.object.extend(options, { + featureNS: this.featureNS, + featurePrefix: this.featurePrefix, + featureType: this.featureType, + srsName: this.srsName, + srsNameInQuery: this.srsNameInQuery + });*/ + var prefix = goog.isDef(this.featurePrefix) ? this.featurePrefix + + ':' : ''; + var node = this.createElementNS('wfs:Query'); + node.setAttribute('typeName', prefix + options.featureType); + if (goog.isDef(options.srsNameInQuery) && goog.isDef(options.srsName)) { + node.setAttribute('srsName', options.srsName); + } + if (goog.isDef(this.featureNS)) { + node.setAttribute('xmlns:' + this.featurePrefix, this.featureNS); + } + if (goog.isDef(options.propertyNames)) { + for (var i = 0, ii = options.propertyNames.length; i < ii; i++) { + this.writeNode('ogc:PropertyName', { + property: options.propertyNames[i] + }, 'http://www.opengis.net/ogc', node); + } + } + if (goog.isDef(options.filter)) { + this.writeNode('Filter', options.filter, + 'http://www.opengis.net/ogc', node); + } + return node; + } + }); + this.filter_ = new ol.parser.ogc.Filter_v1_0_0(); + for (var uri in this.filter_.readers) { + for (var key in this.filter_.readers[uri]) { + if (!goog.isDef(this.readers[uri])) { + this.readers[uri] = {}; + } + this.readers[uri][key] = goog.bind(this.filter_.readers[uri][key], + this.filter_); + } + } + for (uri in this.filter_.writers) { + for (key in this.filter_.writers[uri]) { + if (!goog.isDef(this.writers[uri])) { + this.writers[uri] = {}; + } + this.writers[uri][key] = goog.bind(this.filter_.writers[uri][key], + this.filter_); + } + } +}; +goog.inherits(ol.parser.ogc.WFS_v1_0_0, + ol.parser.ogc.WFS_v1); diff --git a/src/ol/parser/ogc/wfsparser_v1_1_0.js b/src/ol/parser/ogc/wfsparser_v1_1_0.js new file mode 100644 index 0000000000..fee3992e66 --- /dev/null +++ b/src/ol/parser/ogc/wfsparser_v1_1_0.js @@ -0,0 +1,94 @@ +goog.provide('ol.parser.ogc.WFS_v1_1_0'); + +goog.require('goog.functions'); +goog.require('goog.object'); +goog.require('ol.parser.ogc.WFS_v1'); + + + +/** + * @constructor + * @extends {ol.parser.ogc.WFS_v1} + */ +ol.parser.ogc.WFS_v1_1_0 = function() { + goog.base(this); + this.version = '1.1.0'; + this.schemaLocation = this.defaultNamespaceURI + ' ' + + 'http://schemas.opengis.net/wfs/1.1.0/wfs.xsd'; + goog.object.extend(this.readers[this.defaultNamespaceURI], { + 'FeatureCollection': goog.functions.sequence( + function(node, obj) { + obj.numberOfFeatures = parseInt( + node.getAttribute('numberOfFeatures'), 10); + }, + this.readers['http://www.opengis.net/wfs']['FeatureCollection'] + ), + 'TransactionResponse': function(node, obj) { + obj.insertIds = []; + obj.success = false; + this.readChildNodes(node, obj); + }, + 'TransactionSummary': function(node, obj) { + // this is a limited test of success + obj.success = true; + }, + 'InsertResults': function(node, obj) { + this.readChildNodes(node, obj); + }, + 'Feature': function(node, container) { + var obj = {fids: []}; + this.readChildNodes(node, obj); + container.insertIds.push(obj.fids[0]); + } + }); + goog.object.extend(this.writers[this.defaultNamespaceURI], { + 'GetFeature': function(options) { + var node = this.writers['http://www.opengis.net/wfs']['GetFeature']. + apply(this, arguments); + if (goog.isDef(options)) { + node.setAttribute('resultType', options.resultType); + if (goog.isDef(options.startIndex)) { + node.setAttribute('startIndex', options.startIndex); + } + node.setAttribute('count', options.count); + } + return node; + }, + 'Query': function(options) { + goog.object.extend(options, { + featureNS: this.featureNS, + featurePrefix: this.featurePrefix, + featureType: this.featureType, + srsName: this.srsName + }); + var prefix = goog.isDef(options.featurePrefix) ? options.prefix + ':' : + ''; + var node = this.createElementNS('wfs:Query'); + node.setAttribute('typeName', prefix + options.featureType); + node.setAttribute('srsName', options.srsName); + if (goog.isDef(options.featureNS)) { + node.setAttribute('xmlns:' + options.prefix, options.featureNS); + } + if (goog.isDef(options.propertyNames)) { + for (var i = 0, ii = options.propertyNames.length; i < ii; i++) { + this.writeNode('wfs:PropertyName', { + property: options.propertyNames[i] + }, null, node); + } + } + if (goog.isDef(options.filter)) { + this.writeNode('ogc:Filter', options.filter, + 'http://www.opengis.net/ogc', node); + } + return node; + }, + 'PropertyName': function(obj) { + var node = this.createElementNS('wfs:PropertyName'); + node.appendChild(this.createTextNode(obj.property)); + return node; + } + }); + // TODO ogc and gml namespaces +}; +goog.inherits(ol.parser.ogc.WFS_v1_1_0, + ol.parser.ogc.WFS_v1); diff --git a/test/spec/ol/parser/ogc/wfs_v1_0_0.test.js b/test/spec/ol/parser/ogc/wfs_v1_0_0.test.js new file mode 100644 index 0000000000..716d95f644 --- /dev/null +++ b/test/spec/ol/parser/ogc/wfs_v1_0_0.test.js @@ -0,0 +1,49 @@ +goog.provide('ol.test.parser.ogc.WFS_v1_0_0'); + +describe('ol.parser.ogc.WFS_v1_0_0', function() { + + var parser = new ol.parser.ogc.WFS(); + + describe('reading and writing', function() { + + it('handles read of transaction response', function(done) { + var url = 'spec/ol/parser/ogc/xml/wfs_v1_0_0/Transaction_Response.xml'; + afterLoadXml(url, function(xml) { + var obj = parser.read(xml); + expect(obj.insertIds.length).to.equal(2); + expect(obj.insertIds[0]).to.equal('parcelle.40'); + expect(obj.insertIds[1]).to.equal('parcelle.41'); + expect(obj.version).to.equal('1.0.0'); + expect(obj.success).to.be(true); + done(); + }); + }); + + it('handles writing Query with BBOX Filter', function(done) { + var url = 'spec/ol/parser/ogc/xml/wfs_v1_0_0/query0.xml'; + afterLoadXml(url, function(xml) { + var p = new ol.parser.ogc.WFS_v1_0_0({featureTypes: ['states'], + featurePrefix: 'topp', featureNS: 'http://www.openplans.org/topp'}); + var filter = new ol.expr.Call( + new ol.expr.Identifier(ol.expr.functions.EXTENT), + [new ol.expr.Literal(1), new ol.expr.Literal(2), + new ol.expr.Literal(3), new ol.expr.Literal(4), + undefined, + new ol.expr.Identifier('the_geom')]); + var output = p.writers[p.defaultNamespaceURI]['Query'].apply( + p, [{filter: filter, featureType: 'states'}]); + expect(goog.dom.xml.loadXml(p.serialize(output))).to.xmleql(xml); + done(); + }); + }); + + }); + +}); + +goog.require('goog.dom.xml'); +goog.require('ol.expr.Call'); +goog.require('ol.expr.Identifier'); +goog.require('ol.expr.Literal'); +goog.require('ol.parser.ogc.WFS'); +goog.require('ol.parser.ogc.WFS_v1_0_0'); diff --git a/test/spec/ol/parser/ogc/xml/wfs_v1_0_0/Transaction_Response.xml b/test/spec/ol/parser/ogc/xml/wfs_v1_0_0/Transaction_Response.xml new file mode 100644 index 0000000000..5d178b8124 --- /dev/null +++ b/test/spec/ol/parser/ogc/xml/wfs_v1_0_0/Transaction_Response.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/test/spec/ol/parser/ogc/xml/wfs_v1_0_0/query0.xml b/test/spec/ol/parser/ogc/xml/wfs_v1_0_0/query0.xml new file mode 100644 index 0000000000..d5fdc88cfa --- /dev/null +++ b/test/spec/ol/parser/ogc/xml/wfs_v1_0_0/query0.xml @@ -0,0 +1,10 @@ + + + + the_geom + + 1,2 3,4 + + + + From 0581a49378c5951f5893dc73cfe81e978c71cb0c Mon Sep 17 00:00:00 2001 From: Bart van den Eijnden Date: Tue, 22 Oct 2013 17:26:55 +0200 Subject: [PATCH 03/13] ability to write out PropertyNames in a GetFeature request --- src/ol/parser/ogc/wfsparser_v1.js | 4 +++- src/ol/parser/ogc/wfsparser_v1_0_0.js | 5 ++--- src/ol/parser/ogc/wfsparser_v1_1_0.js | 2 +- test/spec/ol/parser/ogc/wfs_v1_0_0.test.js | 14 ++++++++++++++ .../ol/parser/ogc/xml/wfs_v1_0_0/getfeature0.xml | 11 +++++++++++ 5 files changed, 31 insertions(+), 5 deletions(-) create mode 100644 test/spec/ol/parser/ogc/xml/wfs_v1_0_0/getfeature0.xml diff --git a/src/ol/parser/ogc/wfsparser_v1.js b/src/ol/parser/ogc/wfsparser_v1.js index ddee7c2079..dd1acc1f9e 100644 --- a/src/ol/parser/ogc/wfsparser_v1.js +++ b/src/ol/parser/ogc/wfsparser_v1.js @@ -42,11 +42,13 @@ ol.parser.ogc.WFS_v1 = function(opt_options) { node.setAttribute('maxFeatures', options.maxFeatures); } } - // TODO set xsi:schemaLocation for (var i = 0, ii = this.featureTypes.length; i < ii; i++) { options.featureType = this.featureTypes[i]; this.writeNode('Query', options, null, node); } + this.setAttributeNS( + node, 'http://www.w3.org/2001/XMLSchema-instance', + 'xsi:schemaLocation', this.schemaLocation); return node; } }; diff --git a/src/ol/parser/ogc/wfsparser_v1_0_0.js b/src/ol/parser/ogc/wfsparser_v1_0_0.js index 0387940f67..f2b55fe5ac 100644 --- a/src/ol/parser/ogc/wfsparser_v1_0_0.js +++ b/src/ol/parser/ogc/wfsparser_v1_0_0.js @@ -63,9 +63,8 @@ ol.parser.ogc.WFS_v1_0_0 = function(opt_options) { } if (goog.isDef(options.propertyNames)) { for (var i = 0, ii = options.propertyNames.length; i < ii; i++) { - this.writeNode('ogc:PropertyName', { - property: options.propertyNames[i] - }, 'http://www.opengis.net/ogc', node); + this.writeNode('PropertyName', options.propertyNames[i], + 'http://www.opengis.net/ogc', node); } } if (goog.isDef(options.filter)) { diff --git a/src/ol/parser/ogc/wfsparser_v1_1_0.js b/src/ol/parser/ogc/wfsparser_v1_1_0.js index fee3992e66..d44ec90dc8 100644 --- a/src/ol/parser/ogc/wfsparser_v1_1_0.js +++ b/src/ol/parser/ogc/wfsparser_v1_1_0.js @@ -77,7 +77,7 @@ ol.parser.ogc.WFS_v1_1_0 = function() { } } if (goog.isDef(options.filter)) { - this.writeNode('ogc:Filter', options.filter, + this.writeNode('Filter', options.filter, 'http://www.opengis.net/ogc', node); } return node; diff --git a/test/spec/ol/parser/ogc/wfs_v1_0_0.test.js b/test/spec/ol/parser/ogc/wfs_v1_0_0.test.js index 716d95f644..c611aab39e 100644 --- a/test/spec/ol/parser/ogc/wfs_v1_0_0.test.js +++ b/test/spec/ol/parser/ogc/wfs_v1_0_0.test.js @@ -37,6 +37,20 @@ describe('ol.parser.ogc.WFS_v1_0_0', function() { }); }); + it('handles writing GetFeature with PropertyName', function(done) { + var url = 'spec/ol/parser/ogc/xml/wfs_v1_0_0/getfeature0.xml'; + afterLoadXml(url, function(xml) { + var p = new ol.parser.ogc.WFS_v1_0_0({featureTypes: ['states'], + featurePrefix: 'topp', featureNS: 'http://www.openplans.org/topp'}); + var output = p.writers[p.defaultNamespaceURI]['GetFeature'].apply( + p, [{propertyNames: [new ol.expr.Identifier('STATE_NAME'), + new ol.expr.Identifier('STATE_FIPS'), + new ol.expr.Identifier('STATE_ABBR')]}]); + expect(goog.dom.xml.loadXml(p.serialize(output))).to.xmleql(xml); + done(); + }); + }); + }); }); diff --git a/test/spec/ol/parser/ogc/xml/wfs_v1_0_0/getfeature0.xml b/test/spec/ol/parser/ogc/xml/wfs_v1_0_0/getfeature0.xml new file mode 100644 index 0000000000..8d7e136cea --- /dev/null +++ b/test/spec/ol/parser/ogc/xml/wfs_v1_0_0/getfeature0.xml @@ -0,0 +1,11 @@ + + + STATE_NAME + STATE_FIPS + STATE_ABBR + + From d2ac206ca3bf617a339bfd7a57177ec4533faae4 Mon Sep 17 00:00:00 2001 From: Bart van den Eijnden Date: Tue, 22 Oct 2013 20:34:55 +0200 Subject: [PATCH 04/13] starting to add tests for WFS 1.1.0 make sure we don't override the wfs:FeatureCollection reader with the one from GML --- src/ol/parser/ogc/wfsparser_v1.js | 34 +++++++++++++++++ src/ol/parser/ogc/wfsparser_v1_0_0.js | 20 +--------- src/ol/parser/ogc/wfsparser_v1_1_0.js | 9 +++-- test/spec/ol/parser/ogc/wfs_v1_1_0.test.js | 38 +++++++++++++++++++ .../ogc/xml/wfs_v1_1_0/NumberOfFeatures.xml | 9 +++++ .../xml/wfs_v1_1_0/TransactionResponse.xml | 16 ++++++++ 6 files changed, 104 insertions(+), 22 deletions(-) create mode 100644 test/spec/ol/parser/ogc/wfs_v1_1_0.test.js create mode 100644 test/spec/ol/parser/ogc/xml/wfs_v1_1_0/NumberOfFeatures.xml create mode 100644 test/spec/ol/parser/ogc/xml/wfs_v1_1_0/TransactionResponse.xml diff --git a/src/ol/parser/ogc/wfsparser_v1.js b/src/ol/parser/ogc/wfsparser_v1.js index dd1acc1f9e..531287c5ab 100644 --- a/src/ol/parser/ogc/wfsparser_v1.js +++ b/src/ol/parser/ogc/wfsparser_v1.js @@ -57,6 +57,40 @@ ol.parser.ogc.WFS_v1 = function(opt_options) { goog.inherits(ol.parser.ogc.WFS_v1, ol.parser.XML); +/** + * @param {ol.parser.ogc.Filter_v1_0_0|ol.parser.ogc.Filter_v1_1_0} filter The + * Filter parser to use. + * @protected + */ +ol.parser.ogc.WFS_v1.prototype.setFilterParser = function(filter) { + this.filter_ = filter; + for (var uri in this.filter_.readers) { + for (var key in this.filter_.readers[uri]) { + if (!goog.isDef(this.readers[uri])) { + this.readers[uri] = {}; + } + // do not overwrite any readers + if (!goog.isDef(this.readers[uri][key])) { + this.readers[uri][key] = goog.bind(this.filter_.readers[uri][key], + this.filter_); + } + } + } + for (uri in this.filter_.writers) { + for (key in this.filter_.writers[uri]) { + if (!goog.isDef(this.writers[uri])) { + this.writers[uri] = {}; + } + // do not overwrite any writers + if (!goog.isDef(this.writers[uri][key])) { + this.writers[uri][key] = goog.bind(this.filter_.writers[uri][key], + this.filter_); + } + } + } +}; + + /** * @param {string|Document|Element} data Data to read. * @return {Object} An object representing the document. diff --git a/src/ol/parser/ogc/wfsparser_v1_0_0.js b/src/ol/parser/ogc/wfsparser_v1_0_0.js index f2b55fe5ac..df2e93f691 100644 --- a/src/ol/parser/ogc/wfsparser_v1_0_0.js +++ b/src/ol/parser/ogc/wfsparser_v1_0_0.js @@ -74,25 +74,7 @@ ol.parser.ogc.WFS_v1_0_0 = function(opt_options) { return node; } }); - this.filter_ = new ol.parser.ogc.Filter_v1_0_0(); - for (var uri in this.filter_.readers) { - for (var key in this.filter_.readers[uri]) { - if (!goog.isDef(this.readers[uri])) { - this.readers[uri] = {}; - } - this.readers[uri][key] = goog.bind(this.filter_.readers[uri][key], - this.filter_); - } - } - for (uri in this.filter_.writers) { - for (key in this.filter_.writers[uri]) { - if (!goog.isDef(this.writers[uri])) { - this.writers[uri] = {}; - } - this.writers[uri][key] = goog.bind(this.filter_.writers[uri][key], - this.filter_); - } - } + this.setFilterParser(new ol.parser.ogc.Filter_v1_0_0()); }; goog.inherits(ol.parser.ogc.WFS_v1_0_0, ol.parser.ogc.WFS_v1); diff --git a/src/ol/parser/ogc/wfsparser_v1_1_0.js b/src/ol/parser/ogc/wfsparser_v1_1_0.js index d44ec90dc8..016fd10a7d 100644 --- a/src/ol/parser/ogc/wfsparser_v1_1_0.js +++ b/src/ol/parser/ogc/wfsparser_v1_1_0.js @@ -2,6 +2,7 @@ goog.provide('ol.parser.ogc.WFS_v1_1_0'); goog.require('goog.functions'); goog.require('goog.object'); +goog.require('ol.parser.ogc.Filter_v1_1_0'); goog.require('ol.parser.ogc.WFS_v1'); @@ -36,9 +37,11 @@ ol.parser.ogc.WFS_v1_1_0 = function() { this.readChildNodes(node, obj); }, 'Feature': function(node, container) { - var obj = {fids: []}; + var obj = {}; this.readChildNodes(node, obj); - container.insertIds.push(obj.fids[0]); + for (var key in obj.fids) { + container.insertIds.push(key); + } } }); goog.object.extend(this.writers[this.defaultNamespaceURI], { @@ -88,7 +91,7 @@ ol.parser.ogc.WFS_v1_1_0 = function() { return node; } }); - // TODO ogc and gml namespaces + this.setFilterParser(new ol.parser.ogc.Filter_v1_1_0()); }; goog.inherits(ol.parser.ogc.WFS_v1_1_0, ol.parser.ogc.WFS_v1); diff --git a/test/spec/ol/parser/ogc/wfs_v1_1_0.test.js b/test/spec/ol/parser/ogc/wfs_v1_1_0.test.js new file mode 100644 index 0000000000..2af072d81a --- /dev/null +++ b/test/spec/ol/parser/ogc/wfs_v1_1_0.test.js @@ -0,0 +1,38 @@ +goog.provide('ol.test.parser.ogc.WFS_v1_1_0'); + +describe('ol.parser.ogc.WFS_v1_1_0', function() { + + var parser = new ol.parser.ogc.WFS(); + + describe('reading and writing', function() { + + it('handles read of transaction response', function(done) { + var url = 'spec/ol/parser/ogc/xml/wfs_v1_1_0/TransactionResponse.xml'; + afterLoadXml(url, function(xml) { + var obj = parser.read(xml); + expect(obj.insertIds.length).to.equal(2); + expect(obj.insertIds[0]).to.equal('parcelle.40'); + expect(obj.insertIds[1]).to.equal('parcelle.41'); + expect(obj.version).to.equal('1.1.0'); + expect(obj.success).to.be(true); + done(); + }); + }); + + it('handles read of number of features', function(done) { + var url = 'spec/ol/parser/ogc/xml/wfs_v1_1_0/NumberOfFeatures.xml'; + afterLoadXml(url, function(xml) { + // the XML does not contain a version attribute on the root node + var p = new ol.parser.ogc.WFS_v1_1_0(); + var obj = p.read(xml); + expect(obj.numberOfFeatures).to.equal(625); + done(); + }); + }); + }); + +}); + +goog.require('goog.dom.xml'); +goog.require('ol.parser.ogc.WFS'); +goog.require('ol.parser.ogc.WFS_v1_1_0'); diff --git a/test/spec/ol/parser/ogc/xml/wfs_v1_1_0/NumberOfFeatures.xml b/test/spec/ol/parser/ogc/xml/wfs_v1_1_0/NumberOfFeatures.xml new file mode 100644 index 0000000000..dcc67c37d7 --- /dev/null +++ b/test/spec/ol/parser/ogc/xml/wfs_v1_1_0/NumberOfFeatures.xml @@ -0,0 +1,9 @@ + + + diff --git a/test/spec/ol/parser/ogc/xml/wfs_v1_1_0/TransactionResponse.xml b/test/spec/ol/parser/ogc/xml/wfs_v1_1_0/TransactionResponse.xml new file mode 100644 index 0000000000..6a64bddeca --- /dev/null +++ b/test/spec/ol/parser/ogc/xml/wfs_v1_1_0/TransactionResponse.xml @@ -0,0 +1,16 @@ + + + 0 + 1 + 0 + + + + + + + + + + + From 3184fb02e551062924166f1999b4c1f2349a6002 Mon Sep 17 00:00:00 2001 From: Bart van den Eijnden Date: Wed, 23 Oct 2013 11:46:57 +0200 Subject: [PATCH 05/13] ability to read boundedBy from FeatureCollection --- src/ol/parser/ogc/gmlparser.js | 3 ++ src/ol/parser/ogc/wfsparser_v1_1_0.js | 12 +++-- test/spec/ol/parser/ogc/wfs_v1_1_0.test.js | 15 ++++++ .../parser/ogc/xml/wfs_v1_1_0/boundedBy.xml | 47 +++++++++++++++++++ 4 files changed, 73 insertions(+), 4 deletions(-) create mode 100644 test/spec/ol/parser/ogc/xml/wfs_v1_1_0/boundedBy.xml diff --git a/src/ol/parser/ogc/gmlparser.js b/src/ol/parser/ogc/gmlparser.js index 088cfe13ac..6431298975 100644 --- a/src/ol/parser/ogc/gmlparser.js +++ b/src/ol/parser/ogc/gmlparser.js @@ -148,6 +148,9 @@ ol.parser.ogc.GML = function(opt_options) { 'polygonMember': function(node, obj) { this.readChildNodes(node, obj); }, + 'boundedBy': function(node, obj) { + this.readChildNodes(node, obj); + }, 'Point': function(node, container) { var coordinates = []; this.readers[this.defaultNamespaceURI]['_inherit'].apply(this, diff --git a/src/ol/parser/ogc/wfsparser_v1_1_0.js b/src/ol/parser/ogc/wfsparser_v1_1_0.js index 016fd10a7d..e788cd4b5b 100644 --- a/src/ol/parser/ogc/wfsparser_v1_1_0.js +++ b/src/ol/parser/ogc/wfsparser_v1_1_0.js @@ -9,18 +9,22 @@ goog.require('ol.parser.ogc.WFS_v1'); /** * @constructor +* @param {ol.parser.WFSOptions=} opt_options + * Optional configuration object. * @extends {ol.parser.ogc.WFS_v1} */ -ol.parser.ogc.WFS_v1_1_0 = function() { - goog.base(this); +ol.parser.ogc.WFS_v1_1_0 = function(opt_options) { + goog.base(this, opt_options); this.version = '1.1.0'; this.schemaLocation = this.defaultNamespaceURI + ' ' + 'http://schemas.opengis.net/wfs/1.1.0/wfs.xsd'; goog.object.extend(this.readers[this.defaultNamespaceURI], { 'FeatureCollection': goog.functions.sequence( function(node, obj) { - obj.numberOfFeatures = parseInt( - node.getAttribute('numberOfFeatures'), 10); + var numberOfFeatures = node.getAttribute('numberOfFeatures'); + if (!goog.isNull(numberOfFeatures)) { + obj.numberOfFeatures = parseInt(numberOfFeatures, 10); + } }, this.readers['http://www.opengis.net/wfs']['FeatureCollection'] ), diff --git a/test/spec/ol/parser/ogc/wfs_v1_1_0.test.js b/test/spec/ol/parser/ogc/wfs_v1_1_0.test.js index 2af072d81a..5027f1d4f6 100644 --- a/test/spec/ol/parser/ogc/wfs_v1_1_0.test.js +++ b/test/spec/ol/parser/ogc/wfs_v1_1_0.test.js @@ -29,6 +29,21 @@ describe('ol.parser.ogc.WFS_v1_1_0', function() { done(); }); }); + + it('handles read of boundedBy on the FeatureCollection', function(done) { + var url = 'spec/ol/parser/ogc/xml/wfs_v1_1_0/boundedBy.xml'; + afterLoadXml(url, function(xml) { + // the XML does not contain a version attribute on the root node + var p = new ol.parser.ogc.WFS_v1_1_0(); + var obj = p.read(xml); + expect(obj.bounds[0]).to.equal(3197.88); + expect(obj.bounds[1]).to.equal(306457.313); + expect(obj.bounds[2]).to.equal(280339.156); + expect(obj.bounds[3]).to.equal(613850.438); + done(); + }); + }); + }); }); diff --git a/test/spec/ol/parser/ogc/xml/wfs_v1_1_0/boundedBy.xml b/test/spec/ol/parser/ogc/xml/wfs_v1_1_0/boundedBy.xml new file mode 100644 index 0000000000..4daeb2eadc --- /dev/null +++ b/test/spec/ol/parser/ogc/xml/wfs_v1_1_0/boundedBy.xml @@ -0,0 +1,47 @@ + + + + 3197.880000 306457.313000 + 280339.156000 613850.438000 + + + + + + + + 196507.469000 502347.938000 + 202430.844000 510383.719000 + + + + + + + + + + 200448.047000 510383.719000 198475.031000 509253.875000 198477.422000 507339.688000 196507.469000 505841.969000 196507.625000 504980.281000 196621.359000 505029.969000 196825.328000 505114.000000 197310.031000 505183.469000 197636.609000 505148.750000 197837.594000 505061.563000 197941.031000 504953.688000 198003.094000 504817.719000 198023.781000 504721.688000 198016.391000 504597.531000 197907.234000 504363.219000 197716.734000 504013.969000 197700.156000 503567.563000 197775.531000 503373.969000 197930.688000 503153.781000 198034.234000 503045.594000 198170.078000 502932.125000 198504.047000 502725.250000 198858.719000 502550.875000 199138.000000 502460.719000 199336.000000 502347.938000 199044.125000 504910.969000 199549.359000 507065.781000 200280.594000 506878.938000 202430.844000 507474.625000 202430.844000 508850.906000 200448.047000 510383.719000 + + + + + + + + 791 + 1800.89 + 4620 + + + 0 + 24305.1 + + + From 4df848fae001f5490eef5aad4ee6261b354dc00a Mon Sep 17 00:00:00 2001 From: Bart van den Eijnden Date: Wed, 23 Oct 2013 13:15:16 +0200 Subject: [PATCH 06/13] need the ability to set axisOrientation We need to be able to set axisOrientation on the underlying GML parser of the Filter subparser of ol.parser.WFS*, also only options and no properties on the instance anymore --- src/ol/parser/ogc/filterparser_v1.js | 8 +++++ src/ol/parser/ogc/wfsparser.js | 3 +- src/ol/parser/ogc/wfsparser_v1.js | 21 ++++++------- src/ol/parser/ogc/wfsparser_v1_0_0.js | 20 ++++--------- src/ol/parser/ogc/wfsparser_v1_1_0.js | 18 ++++------- test/spec/ol/parser/ogc/wfs_v1_0_0.test.js | 24 ++++++++++----- test/spec/ol/parser/ogc/wfs_v1_1_0.test.js | 30 +++++++++++++++++++ .../ol/parser/ogc/xml/wfs_v1_1_0/query0.xml | 11 +++++++ 8 files changed, 87 insertions(+), 48 deletions(-) create mode 100644 test/spec/ol/parser/ogc/xml/wfs_v1_1_0/query0.xml diff --git a/src/ol/parser/ogc/filterparser_v1.js b/src/ol/parser/ogc/filterparser_v1.js index f0a21995ab..38bd33d2c4 100644 --- a/src/ol/parser/ogc/filterparser_v1.js +++ b/src/ol/parser/ogc/filterparser_v1.js @@ -580,6 +580,14 @@ ol.parser.ogc.Filter_v1.prototype.aggregateLogical_ = function(filters, }; +/** + * @return {ol.parser.ogc.GML_v2|ol.parser.ogc.GML_v3} + */ +ol.parser.ogc.Filter_v1.prototype.getGmlParser = function() { + return this.gml_; +}; + + /** * @param {ol.parser.ogc.GML_v2|ol.parser.ogc.GML_v3} gml The GML parser to * use. diff --git a/src/ol/parser/ogc/wfsparser.js b/src/ol/parser/ogc/wfsparser.js index 68e3141326..33625798bd 100644 --- a/src/ol/parser/ogc/wfsparser.js +++ b/src/ol/parser/ogc/wfsparser.js @@ -19,8 +19,7 @@ ol.ENABLE_WFS_1_1_0 = true; /** * @constructor - * @param {ol.parser.WFSOptions=} opt_options - * Optional configuration object. + * @param {Object=} opt_options Options which will be set on this object. * @extends {ol.parser.ogc.Versioned} */ ol.parser.ogc.WFS = function(opt_options) { diff --git a/src/ol/parser/ogc/wfsparser_v1.js b/src/ol/parser/ogc/wfsparser_v1.js index 531287c5ab..73b12f4ff3 100644 --- a/src/ol/parser/ogc/wfsparser_v1.js +++ b/src/ol/parser/ogc/wfsparser_v1.js @@ -6,16 +6,9 @@ goog.require('ol.parser.XML'); /** * @constructor - * @param {ol.parser.WFSOptions=} opt_options - * Optional configuration object. * @extends {ol.parser.XML} */ -ol.parser.ogc.WFS_v1 = function(opt_options) { - if (goog.isDef(opt_options)) { - this.featureTypes = opt_options.featureTypes; - this.featurePrefix = opt_options.featurePrefix; - this.featureNS = opt_options.featureNS; - } +ol.parser.ogc.WFS_v1 = function() { this.defaultNamespaceURI = 'http://www.opengis.net/wfs'; // TODO set errorProperty this.readers = {}; @@ -42,8 +35,8 @@ ol.parser.ogc.WFS_v1 = function(opt_options) { node.setAttribute('maxFeatures', options.maxFeatures); } } - for (var i = 0, ii = this.featureTypes.length; i < ii; i++) { - options.featureType = this.featureTypes[i]; + for (var i = 0, ii = options.featureTypes.length; i < ii; i++) { + options.featureType = options.featureTypes[i]; this.writeNode('Query', options, null, node); } this.setAttributeNS( @@ -57,6 +50,14 @@ ol.parser.ogc.WFS_v1 = function(opt_options) { goog.inherits(ol.parser.ogc.WFS_v1, ol.parser.XML); +/** + * @return {ol.parser.ogc.Filter_v1_0_0|ol.parser.ogc.Filter_v1_1_0} + */ +ol.parser.ogc.WFS_v1.prototype.getFilterParser = function() { + return this.filter_; +}; + + /** * @param {ol.parser.ogc.Filter_v1_0_0|ol.parser.ogc.Filter_v1_1_0} filter The * Filter parser to use. diff --git a/src/ol/parser/ogc/wfsparser_v1_0_0.js b/src/ol/parser/ogc/wfsparser_v1_0_0.js index df2e93f691..1fc20a5bb4 100644 --- a/src/ol/parser/ogc/wfsparser_v1_0_0.js +++ b/src/ol/parser/ogc/wfsparser_v1_0_0.js @@ -9,12 +9,10 @@ goog.require('ol.parser.ogc.WFS_v1'); /** * @constructor - * @param {ol.parser.WFSOptions=} opt_options - * Optional configuration object. * @extends {ol.parser.ogc.WFS_v1} */ -ol.parser.ogc.WFS_v1_0_0 = function(opt_options) { - goog.base(this, opt_options); +ol.parser.ogc.WFS_v1_0_0 = function() { + goog.base(this); this.version = '1.0.0'; this.schemaLocation = this.defaultNamespaceURI + ' ' + 'http://schemas.opengis.net/wfs/1.0.0/WFS-transaction.xsd'; @@ -43,23 +41,15 @@ ol.parser.ogc.WFS_v1_0_0 = function(opt_options) { }); goog.object.extend(this.writers[this.defaultNamespaceURI], { 'Query': function(options) { - // TODO see if we really need properties on the instance - /*goog.object.extend(options, { - featureNS: this.featureNS, - featurePrefix: this.featurePrefix, - featureType: this.featureType, - srsName: this.srsName, - srsNameInQuery: this.srsNameInQuery - });*/ - var prefix = goog.isDef(this.featurePrefix) ? this.featurePrefix + + var prefix = goog.isDef(options.featurePrefix) ? options.featurePrefix + ':' : ''; var node = this.createElementNS('wfs:Query'); node.setAttribute('typeName', prefix + options.featureType); if (goog.isDef(options.srsNameInQuery) && goog.isDef(options.srsName)) { node.setAttribute('srsName', options.srsName); } - if (goog.isDef(this.featureNS)) { - node.setAttribute('xmlns:' + this.featurePrefix, this.featureNS); + if (goog.isDef(options.featureNS)) { + node.setAttribute('xmlns:' + options.featurePrefix, options.featureNS); } if (goog.isDef(options.propertyNames)) { for (var i = 0, ii = options.propertyNames.length; i < ii; i++) { diff --git a/src/ol/parser/ogc/wfsparser_v1_1_0.js b/src/ol/parser/ogc/wfsparser_v1_1_0.js index e788cd4b5b..4889ccf1aa 100644 --- a/src/ol/parser/ogc/wfsparser_v1_1_0.js +++ b/src/ol/parser/ogc/wfsparser_v1_1_0.js @@ -9,12 +9,10 @@ goog.require('ol.parser.ogc.WFS_v1'); /** * @constructor -* @param {ol.parser.WFSOptions=} opt_options - * Optional configuration object. * @extends {ol.parser.ogc.WFS_v1} */ -ol.parser.ogc.WFS_v1_1_0 = function(opt_options) { - goog.base(this, opt_options); +ol.parser.ogc.WFS_v1_1_0 = function() { + goog.base(this); this.version = '1.1.0'; this.schemaLocation = this.defaultNamespaceURI + ' ' + 'http://schemas.opengis.net/wfs/1.1.0/wfs.xsd'; @@ -62,19 +60,13 @@ ol.parser.ogc.WFS_v1_1_0 = function(opt_options) { return node; }, 'Query': function(options) { - goog.object.extend(options, { - featureNS: this.featureNS, - featurePrefix: this.featurePrefix, - featureType: this.featureType, - srsName: this.srsName - }); - var prefix = goog.isDef(options.featurePrefix) ? options.prefix + ':' : - ''; + var prefix = goog.isDef(options.featurePrefix) ? options.featurePrefix + + ':' : ''; var node = this.createElementNS('wfs:Query'); node.setAttribute('typeName', prefix + options.featureType); node.setAttribute('srsName', options.srsName); if (goog.isDef(options.featureNS)) { - node.setAttribute('xmlns:' + options.prefix, options.featureNS); + node.setAttribute('xmlns:' + options.featurePrefix, options.featureNS); } if (goog.isDef(options.propertyNames)) { for (var i = 0, ii = options.propertyNames.length; i < ii; i++) { diff --git a/test/spec/ol/parser/ogc/wfs_v1_0_0.test.js b/test/spec/ol/parser/ogc/wfs_v1_0_0.test.js index c611aab39e..bab4dd44dc 100644 --- a/test/spec/ol/parser/ogc/wfs_v1_0_0.test.js +++ b/test/spec/ol/parser/ogc/wfs_v1_0_0.test.js @@ -22,8 +22,7 @@ describe('ol.parser.ogc.WFS_v1_0_0', function() { it('handles writing Query with BBOX Filter', function(done) { var url = 'spec/ol/parser/ogc/xml/wfs_v1_0_0/query0.xml'; afterLoadXml(url, function(xml) { - var p = new ol.parser.ogc.WFS_v1_0_0({featureTypes: ['states'], - featurePrefix: 'topp', featureNS: 'http://www.openplans.org/topp'}); + var p = new ol.parser.ogc.WFS_v1_0_0(); var filter = new ol.expr.Call( new ol.expr.Identifier(ol.expr.functions.EXTENT), [new ol.expr.Literal(1), new ol.expr.Literal(2), @@ -31,7 +30,12 @@ describe('ol.parser.ogc.WFS_v1_0_0', function() { undefined, new ol.expr.Identifier('the_geom')]); var output = p.writers[p.defaultNamespaceURI]['Query'].apply( - p, [{filter: filter, featureType: 'states'}]); + p, [{ + filter: filter, + featureType: 'states', + featureNS: 'http://www.openplans.org/topp', + featurePrefix: 'topp' + }]); expect(goog.dom.xml.loadXml(p.serialize(output))).to.xmleql(xml); done(); }); @@ -40,12 +44,16 @@ describe('ol.parser.ogc.WFS_v1_0_0', function() { it('handles writing GetFeature with PropertyName', function(done) { var url = 'spec/ol/parser/ogc/xml/wfs_v1_0_0/getfeature0.xml'; afterLoadXml(url, function(xml) { - var p = new ol.parser.ogc.WFS_v1_0_0({featureTypes: ['states'], - featurePrefix: 'topp', featureNS: 'http://www.openplans.org/topp'}); + var p = new ol.parser.ogc.WFS_v1_0_0(); var output = p.writers[p.defaultNamespaceURI]['GetFeature'].apply( - p, [{propertyNames: [new ol.expr.Identifier('STATE_NAME'), - new ol.expr.Identifier('STATE_FIPS'), - new ol.expr.Identifier('STATE_ABBR')]}]); + p, [{ + propertyNames: [new ol.expr.Identifier('STATE_NAME'), + new ol.expr.Identifier('STATE_FIPS'), + new ol.expr.Identifier('STATE_ABBR')], + featureNS: 'http://www.openplans.org/topp', + featurePrefix: 'topp', + featureTypes: ['states'] + }]); expect(goog.dom.xml.loadXml(p.serialize(output))).to.xmleql(xml); done(); }); diff --git a/test/spec/ol/parser/ogc/wfs_v1_1_0.test.js b/test/spec/ol/parser/ogc/wfs_v1_1_0.test.js index 5027f1d4f6..4ae4b1b672 100644 --- a/test/spec/ol/parser/ogc/wfs_v1_1_0.test.js +++ b/test/spec/ol/parser/ogc/wfs_v1_1_0.test.js @@ -44,10 +44,40 @@ describe('ol.parser.ogc.WFS_v1_1_0', function() { }); }); + it('handles writing Query with BBOX Filter', function(done) { + var url = 'spec/ol/parser/ogc/xml/wfs_v1_1_0/query0.xml'; + afterLoadXml(url, function(xml) { + var p = new ol.parser.ogc.WFS_v1_1_0(); + var srs = 'urn:ogc:def:crs:EPSG::4326'; + var filter = new ol.expr.Call( + new ol.expr.Identifier(ol.expr.functions.EXTENT), + [new ol.expr.Literal(1), new ol.expr.Literal(2), + new ol.expr.Literal(3), new ol.expr.Literal(4), + new ol.expr.Literal(srs), + new ol.expr.Identifier('the_geom')]); + p.getFilterParser().getGmlParser().axisOrientation = + ol.proj.get(srs).getAxisOrientation(); + var output = p.writers[p.defaultNamespaceURI]['Query'].apply( + p, [{ + srsName: srs, + filter: filter, + featureType: 'states', + featureNS: 'http://www.openplans.org/topp', + featurePrefix: 'topp' + }]); + expect(goog.dom.xml.loadXml(p.serialize(output))).to.xmleql(xml); + done(); + }); + }); + }); }); goog.require('goog.dom.xml'); +goog.require('ol.expr.Call'); +goog.require('ol.expr.Identifier'); +goog.require('ol.expr.Literal'); goog.require('ol.parser.ogc.WFS'); goog.require('ol.parser.ogc.WFS_v1_1_0'); +goog.require('ol.proj'); diff --git a/test/spec/ol/parser/ogc/xml/wfs_v1_1_0/query0.xml b/test/spec/ol/parser/ogc/xml/wfs_v1_1_0/query0.xml new file mode 100644 index 0000000000..30be0808f7 --- /dev/null +++ b/test/spec/ol/parser/ogc/xml/wfs_v1_1_0/query0.xml @@ -0,0 +1,11 @@ + + + + the_geom + + 1 2 + 3 4 + + + + From a77632a88cd6a49ef77a2579d7f7dab96d5bbdcb Mon Sep 17 00:00:00 2001 From: Bart van den Eijnden Date: Wed, 23 Oct 2013 14:54:21 +0200 Subject: [PATCH 07/13] write out GetFeature in WFS 1.1 --- src/ol/parser/ogc/wfsparser_v1.js | 2 +- src/ol/parser/ogc/wfsparser_v1_0_0.js | 7 ++++ src/ol/parser/ogc/wfsparser_v1_1_0.js | 38 +++++++++++-------- test/spec/ol/parser/ogc/wfs_v1_1_0.test.js | 21 ++++++++++ .../parser/ogc/xml/wfs_v1_1_0/getfeature0.xml | 11 ++++++ 5 files changed, 62 insertions(+), 17 deletions(-) create mode 100644 test/spec/ol/parser/ogc/xml/wfs_v1_1_0/getfeature0.xml diff --git a/src/ol/parser/ogc/wfsparser_v1.js b/src/ol/parser/ogc/wfsparser_v1.js index 73b12f4ff3..d4ea23f0d1 100644 --- a/src/ol/parser/ogc/wfsparser_v1.js +++ b/src/ol/parser/ogc/wfsparser_v1.js @@ -42,7 +42,7 @@ ol.parser.ogc.WFS_v1 = function() { this.setAttributeNS( node, 'http://www.w3.org/2001/XMLSchema-instance', 'xsi:schemaLocation', this.schemaLocation); - return node; + return {node: node, options: options}; } }; goog.base(this); diff --git a/src/ol/parser/ogc/wfsparser_v1_0_0.js b/src/ol/parser/ogc/wfsparser_v1_0_0.js index 1fc20a5bb4..602817f5a4 100644 --- a/src/ol/parser/ogc/wfsparser_v1_0_0.js +++ b/src/ol/parser/ogc/wfsparser_v1_0_0.js @@ -1,6 +1,7 @@ goog.provide('ol.parser.ogc.WFS_v1_0_0'); goog.require('goog.array'); +goog.require('goog.functions'); goog.require('goog.object'); goog.require('ol.parser.ogc.Filter_v1_0_0'); goog.require('ol.parser.ogc.WFS_v1'); @@ -40,6 +41,12 @@ ol.parser.ogc.WFS_v1_0_0 = function() { } }); goog.object.extend(this.writers[this.defaultNamespaceURI], { + 'GetFeature': goog.functions.compose( + function(obj) { + return obj.node; + }, + this.writers['http://www.opengis.net/wfs']['GetFeature'] + ), 'Query': function(options) { var prefix = goog.isDef(options.featurePrefix) ? options.featurePrefix + ':' : ''; diff --git a/src/ol/parser/ogc/wfsparser_v1_1_0.js b/src/ol/parser/ogc/wfsparser_v1_1_0.js index 4889ccf1aa..b17488b1d7 100644 --- a/src/ol/parser/ogc/wfsparser_v1_1_0.js +++ b/src/ol/parser/ogc/wfsparser_v1_1_0.js @@ -1,7 +1,9 @@ goog.provide('ol.parser.ogc.WFS_v1_1_0'); +goog.require('goog.asserts'); goog.require('goog.functions'); goog.require('goog.object'); +goog.require('ol.expr.Identifier'); goog.require('ol.parser.ogc.Filter_v1_1_0'); goog.require('ol.parser.ogc.WFS_v1'); @@ -47,18 +49,23 @@ ol.parser.ogc.WFS_v1_1_0 = function() { } }); goog.object.extend(this.writers[this.defaultNamespaceURI], { - 'GetFeature': function(options) { - var node = this.writers['http://www.opengis.net/wfs']['GetFeature']. - apply(this, arguments); - if (goog.isDef(options)) { - node.setAttribute('resultType', options.resultType); - if (goog.isDef(options.startIndex)) { - node.setAttribute('startIndex', options.startIndex); - } - node.setAttribute('count', options.count); - } - return node; - }, + 'GetFeature': goog.functions.compose( + function(obj) { + var options = obj.options; + var node = obj.node; + if (goog.isDef(options)) { + node.setAttribute('resultType', options.resultType); + if (goog.isDef(options.startIndex)) { + node.setAttribute('startIndex', options.startIndex); + } + if (goog.isDef(options.count)) { + node.setAttribute('count', options.count); + } + } + return node; + }, + this.writers['http://www.opengis.net/wfs']['GetFeature'] + ), 'Query': function(options) { var prefix = goog.isDef(options.featurePrefix) ? options.featurePrefix + ':' : ''; @@ -70,9 +77,7 @@ ol.parser.ogc.WFS_v1_1_0 = function() { } if (goog.isDef(options.propertyNames)) { for (var i = 0, ii = options.propertyNames.length; i < ii; i++) { - this.writeNode('wfs:PropertyName', { - property: options.propertyNames[i] - }, null, node); + this.writeNode('PropertyName', options.propertyNames[i], null, node); } } if (goog.isDef(options.filter)) { @@ -82,8 +87,9 @@ ol.parser.ogc.WFS_v1_1_0 = function() { return node; }, 'PropertyName': function(obj) { + goog.asserts.assertInstanceof(obj, ol.expr.Identifier); var node = this.createElementNS('wfs:PropertyName'); - node.appendChild(this.createTextNode(obj.property)); + node.appendChild(this.createTextNode(obj.getName())); return node; } }); diff --git a/test/spec/ol/parser/ogc/wfs_v1_1_0.test.js b/test/spec/ol/parser/ogc/wfs_v1_1_0.test.js index 4ae4b1b672..c92d02eeea 100644 --- a/test/spec/ol/parser/ogc/wfs_v1_1_0.test.js +++ b/test/spec/ol/parser/ogc/wfs_v1_1_0.test.js @@ -68,6 +68,27 @@ describe('ol.parser.ogc.WFS_v1_1_0', function() { expect(goog.dom.xml.loadXml(p.serialize(output))).to.xmleql(xml); done(); }); + + }); + + it('handles writing GetFeature with PropertyName', function(done) { + var url = 'spec/ol/parser/ogc/xml/wfs_v1_1_0/getfeature0.xml'; + afterLoadXml(url, function(xml) { + var p = new ol.parser.ogc.WFS_v1_1_0(); + var output = p.writers[p.defaultNamespaceURI]['GetFeature'].apply( + p, [{ + resultType: 'hits', + srsName: 'urn:ogc:def:crs:EPSG::4326', + propertyNames: [new ol.expr.Identifier('STATE_NAME'), + new ol.expr.Identifier('STATE_FIPS'), + new ol.expr.Identifier('STATE_ABBR')], + featureNS: 'http://www.openplans.org/topp', + featurePrefix: 'topp', + featureTypes: ['states'] + }]); + expect(goog.dom.xml.loadXml(p.serialize(output))).to.xmleql(xml); + done(); + }); }); }); diff --git a/test/spec/ol/parser/ogc/xml/wfs_v1_1_0/getfeature0.xml b/test/spec/ol/parser/ogc/xml/wfs_v1_1_0/getfeature0.xml new file mode 100644 index 0000000000..7449d7d826 --- /dev/null +++ b/test/spec/ol/parser/ogc/xml/wfs_v1_1_0/getfeature0.xml @@ -0,0 +1,11 @@ + + + STATE_NAME + STATE_FIPS + STATE_ABBR + + From c4e7d4437cb87a7302c65aaf45ad068150948093 Mon Sep 17 00:00:00 2001 From: Bart van den Eijnden Date: Wed, 23 Oct 2013 15:24:23 +0200 Subject: [PATCH 08/13] port over another WFS 1.1 testcase --- src/ol/parser/ogc/wfsparser_v1_1_0.js | 4 +++- test/spec/ol/parser/ogc/wfs_v1_1_0.test.js | 20 ++++++++++++++++++- .../parser/ogc/xml/wfs_v1_1_0/getfeature1.xml | 8 ++++++++ 3 files changed, 30 insertions(+), 2 deletions(-) create mode 100644 test/spec/ol/parser/ogc/xml/wfs_v1_1_0/getfeature1.xml diff --git a/src/ol/parser/ogc/wfsparser_v1_1_0.js b/src/ol/parser/ogc/wfsparser_v1_1_0.js index b17488b1d7..02452be120 100644 --- a/src/ol/parser/ogc/wfsparser_v1_1_0.js +++ b/src/ol/parser/ogc/wfsparser_v1_1_0.js @@ -54,7 +54,9 @@ ol.parser.ogc.WFS_v1_1_0 = function() { var options = obj.options; var node = obj.node; if (goog.isDef(options)) { - node.setAttribute('resultType', options.resultType); + if (goog.isDef(options.resultType)) { + node.setAttribute('resultType', options.resultType); + } if (goog.isDef(options.startIndex)) { node.setAttribute('startIndex', options.startIndex); } diff --git a/test/spec/ol/parser/ogc/wfs_v1_1_0.test.js b/test/spec/ol/parser/ogc/wfs_v1_1_0.test.js index c92d02eeea..1e24d2ccbc 100644 --- a/test/spec/ol/parser/ogc/wfs_v1_1_0.test.js +++ b/test/spec/ol/parser/ogc/wfs_v1_1_0.test.js @@ -71,7 +71,7 @@ describe('ol.parser.ogc.WFS_v1_1_0', function() { }); - it('handles writing GetFeature with PropertyName', function(done) { + it('handles writing GetFeature with resultType hits', function(done) { var url = 'spec/ol/parser/ogc/xml/wfs_v1_1_0/getfeature0.xml'; afterLoadXml(url, function(xml) { var p = new ol.parser.ogc.WFS_v1_1_0(); @@ -91,6 +91,24 @@ describe('ol.parser.ogc.WFS_v1_1_0', function() { }); }); + it('handles writing GetFeature with paging info', function(done) { + var url = 'spec/ol/parser/ogc/xml/wfs_v1_1_0/getfeature1.xml'; + afterLoadXml(url, function(xml) { + var p = new ol.parser.ogc.WFS_v1_1_0(); + var output = p.writers[p.defaultNamespaceURI]['GetFeature'].apply( + p, [{ + count: 10, + startIndex: 20, + srsName: 'urn:ogc:def:crs:EPSG::4326', + featureNS: 'http://www.openplans.org/topp', + featurePrefix: 'topp', + featureTypes: ['states'] + }]); + expect(goog.dom.xml.loadXml(p.serialize(output))).to.xmleql(xml); + done(); + }); + }); + }); }); diff --git a/test/spec/ol/parser/ogc/xml/wfs_v1_1_0/getfeature1.xml b/test/spec/ol/parser/ogc/xml/wfs_v1_1_0/getfeature1.xml new file mode 100644 index 0000000000..f79e579d08 --- /dev/null +++ b/test/spec/ol/parser/ogc/xml/wfs_v1_1_0/getfeature1.xml @@ -0,0 +1,8 @@ + + + + From 46b79d88f88dc2a24708619f8ad851f2a947741d Mon Sep 17 00:00:00 2001 From: Bart van den Eijnden Date: Wed, 23 Oct 2013 17:04:20 +0200 Subject: [PATCH 09/13] ability to parse a FeatureCollection The trick here was to delete featureNS so autoConfig would kick in --- src/ol/parser/ogc/wfsparser_v1_0_0.js | 4 +- test/spec/ol/parser/ogc/wfs_v1.test.js | 23 +++++++++++ .../ogc/xml/wfs_v1/FeatureCollection.xml | 41 +++++++++++++++++++ 3 files changed, 67 insertions(+), 1 deletion(-) create mode 100644 test/spec/ol/parser/ogc/wfs_v1.test.js create mode 100644 test/spec/ol/parser/ogc/xml/wfs_v1/FeatureCollection.xml diff --git a/src/ol/parser/ogc/wfsparser_v1_0_0.js b/src/ol/parser/ogc/wfsparser_v1_0_0.js index 602817f5a4..28e64c98b8 100644 --- a/src/ol/parser/ogc/wfsparser_v1_0_0.js +++ b/src/ol/parser/ogc/wfsparser_v1_0_0.js @@ -71,7 +71,9 @@ ol.parser.ogc.WFS_v1_0_0 = function() { return node; } }); - this.setFilterParser(new ol.parser.ogc.Filter_v1_0_0()); + var filter = new ol.parser.ogc.Filter_v1_0_0(); + delete filter.getGmlParser().featureNS; + this.setFilterParser(filter); }; goog.inherits(ol.parser.ogc.WFS_v1_0_0, ol.parser.ogc.WFS_v1); diff --git a/test/spec/ol/parser/ogc/wfs_v1.test.js b/test/spec/ol/parser/ogc/wfs_v1.test.js new file mode 100644 index 0000000000..db767e5fc0 --- /dev/null +++ b/test/spec/ol/parser/ogc/wfs_v1.test.js @@ -0,0 +1,23 @@ +goog.provide('ol.test.parser.ogc.WFS_v1'); + +describe('ol.parser.ogc.WFS', function() { + + var parser = new ol.parser.ogc.WFS(); + + describe('reading and writing', function() { + + it('handles read of FeatureCollection', function(done) { + var url = 'spec/ol/parser/ogc/xml/wfs_v1/FeatureCollection.xml'; + afterLoadXml(url, function(xml) { + var obj = parser.read(xml); + expect(obj.features.length).to.equal(1); + done(); + }); + }); + + }); + +}); + +goog.require('goog.dom.xml'); +goog.require('ol.parser.ogc.WFS'); diff --git a/test/spec/ol/parser/ogc/xml/wfs_v1/FeatureCollection.xml b/test/spec/ol/parser/ogc/xml/wfs_v1/FeatureCollection.xml new file mode 100644 index 0000000000..bb7f9d2ad0 --- /dev/null +++ b/test/spec/ol/parser/ogc/xml/wfs_v1/FeatureCollection.xml @@ -0,0 +1,41 @@ + + + + + + + + + + -75.70742,38.557476 -75.71106,38.649551 -75.724937,38.83017 -75.752922,39.141548 -75.761658,39.247753 -75.764664,39.295849 -75.772697,39.383007 -75.791435,39.723755 -75.775269,39.724442 -75.745934,39.774818 -75.695114,39.820347 -75.644341,39.838196 -75.583794,39.840008 -75.470345,39.826435 -75.42083,39.79887 -75.412117,39.789658 -75.428009,39.77813 -75.460754,39.763248 -75.475128,39.741718 -75.476334,39.719971 -75.489639,39.714745 -75.610725,39.612793 -75.562996,39.566723 -75.590187,39.463768 -75.515572,39.36694 -75.402481,39.257637 -75.397728,39.073036 -75.324852,39.012386 -75.307899,38.945911 -75.190941,38.80867 -75.083138,38.799812 -75.045998,38.44949 -75.068298,38.449963 -75.093094,38.450451 -75.350204,38.455208 -75.69915,38.463066 -75.70742,38.557476 + + + + + + + Delaware + 10 + S Atl + DE + 5062.456 + 1385.022 + 666168.0 + 175867.0 + 247497.0 + 322968.0 + 343200.0 + 247566.0 + 258087.0 + 42968.0 + 8069.0 + 335147.0 + 13945.0 + 87973.0 + 44140.0 + 0.485 + 0.515 + 102776.0 + + + From c9569ed9e240d2af6f27b7b82b025b9e63472d2b Mon Sep 17 00:00:00 2001 From: Bart van den Eijnden Date: Thu, 24 Oct 2013 14:51:04 +0200 Subject: [PATCH 10/13] more tests and typedefs. Once feature editing is more stable, this format can be extended with Update, Delete and Insert --- src/objectliterals.jsdoc | 11 ++- src/ol/parser/ogc/wfsparser_v1.js | 43 ++++++++++- test/spec/ol/parser/ogc/wfs_v1.test.js | 71 +++++++++++++++++++ .../ol/parser/ogc/xml/wfs_v1/GetFeature.xml | 3 + .../ogc/xml/wfs_v1/GetFeatureMultiple.xml | 4 ++ test/spec/ol/parser/ogc/xml/wfs_v1/Native.xml | 1 + .../ol/parser/ogc/xml/wfs_v1/Transaction.xml | 1 + 7 files changed, 131 insertions(+), 3 deletions(-) create mode 100644 test/spec/ol/parser/ogc/xml/wfs_v1/GetFeature.xml create mode 100644 test/spec/ol/parser/ogc/xml/wfs_v1/GetFeatureMultiple.xml create mode 100644 test/spec/ol/parser/ogc/xml/wfs_v1/Native.xml create mode 100644 test/spec/ol/parser/ogc/xml/wfs_v1/Transaction.xml diff --git a/src/objectliterals.jsdoc b/src/objectliterals.jsdoc index ef153d8169..1de0782977 100644 --- a/src/objectliterals.jsdoc +++ b/src/objectliterals.jsdoc @@ -597,9 +597,16 @@ /** * @typedef {Object} ol.parser.WFSOptions + * @property {string} featureNS The feature namespace to use. + * @property {string} featurePrefix The prefix for the namespace. * @property {Array.} featureTypes The feature types to use. - * @property {string} featureNS The featureNS to use. - * @property {string} featurePrefix The prefix to use for the featureNS. + */ + +/** + * @typedef {Object} ol.parser.WFSNative + * @property {string} vendorId The vendor id to use. + * @property {boolean} safeToIgnore Is it safe to ignore? + * @property {string} value The value of the Native element. */ /** diff --git a/src/ol/parser/ogc/wfsparser_v1.js b/src/ol/parser/ogc/wfsparser_v1.js index d4ea23f0d1..fff9f4fba2 100644 --- a/src/ol/parser/ogc/wfsparser_v1.js +++ b/src/ol/parser/ogc/wfsparser_v1.js @@ -21,6 +21,7 @@ ol.parser.ogc.WFS_v1 = function() { this.writers = {}; this.writers[this.defaultNamespaceURI] = { 'GetFeature': function(options) { + options = /** @type {ol.parser.WFSOptions} */(options); var node = this.createElementNS('wfs:GetFeature'); node.setAttribute('service', 'WFS'); node.setAttribute('version', this.version); @@ -43,6 +44,46 @@ ol.parser.ogc.WFS_v1 = function() { node, 'http://www.w3.org/2001/XMLSchema-instance', 'xsi:schemaLocation', this.schemaLocation); return {node: node, options: options}; + }, + 'Transaction': function(obj) { + obj = obj || {}; + var options = obj.options || {}; + var node = this.createElementNS('wfs:Transaction'); + node.setAttribute('service', 'WFS'); + node.setAttribute('version', this.version); + if (goog.isDef(options.handle)) { + node.setAttribute('handle', options.handle); + } + var i, ii; + var features = obj.features; + if (goog.isDefAndNotNull(features)) { + // TODO implement multi option for geometry types + var name, feature; + for (i = 0, ii = features.length; i < ii; ++i) { + feature = features[i]; + // TODO Update (use feature.getOriginal()) + // TODO Insert and Delete + if (goog.isDef(name)) { + this.writeNode(name, { + feature: feature, + options: options + }, null, node); + } + } + } + if (goog.isDef(options.nativeElements)) { + for (i = 0, ii = options.nativeElements.length; i < ii; ++i) { + this.writeNode('Native', options.nativeElements[i], null, node); + } + } + return node; + }, + 'Native': function(nativeElement) { + var node = this.createElementNS('wfs:Native'); + node.setAttribute('vendorId', nativeElement.vendorId); + node.setAttribute('safeToIgnore', nativeElement.safeToIgnore); + node.appendChild(this.createTextNode(nativeElement.value)); + return node; } }; goog.base(this); @@ -115,7 +156,7 @@ ol.parser.ogc.WFS_v1.prototype.read = function(data) { * @return {string} A serialized WFS transaction. */ ol.parser.ogc.WFS_v1.prototype.write = function(features, options) { - var root = this.writeNode('wfs:Transaction', {features: features, + var root = this.writeNode('Transaction', {features: features, options: options}); this.setAttributeNS( root, 'http://www.w3.org/2001/XMLSchema-instance', diff --git a/test/spec/ol/parser/ogc/wfs_v1.test.js b/test/spec/ol/parser/ogc/wfs_v1.test.js index db767e5fc0..a64b00b203 100644 --- a/test/spec/ol/parser/ogc/wfs_v1.test.js +++ b/test/spec/ol/parser/ogc/wfs_v1.test.js @@ -15,9 +15,80 @@ describe('ol.parser.ogc.WFS', function() { }); }); + it('handles writing out GetFeature with a handle', function(done) { + var url = 'spec/ol/parser/ogc/xml/wfs_v1/GetFeature.xml'; + afterLoadXml(url, function(xml) { + var p = new ol.parser.ogc.WFS_v1_0_0(); + var output = p.writers[p.defaultNamespaceURI]['GetFeature']. + apply(p, [{ + featureNS: 'http://www.openplans.org/topp', + featureTypes: ['states'], + featurePrefix: 'topp', + handle: 'handle_g', + maxFeatures: 1, + outputFormat: 'json' + } + ]); + expect(goog.dom.xml.loadXml(p.serialize(output))).to.xmleql(xml); + done(); + }); + }); + + it('handles writing out Transaction with a handle', function(done) { + var url = 'spec/ol/parser/ogc/xml/wfs_v1/Transaction.xml'; + afterLoadXml(url, function(xml) { + var p = new ol.parser.ogc.WFS_v1_0_0(); + var output = p.writers[p.defaultNamespaceURI]['Transaction']. + apply(p, [{ + options: {handle: 'handle_t'} + } + ]); + expect(goog.dom.xml.loadXml(p.serialize(output))).to.xmleql(xml); + done(); + }); + }); + + it('handles writing out Native', function(done) { + var url = 'spec/ol/parser/ogc/xml/wfs_v1/Native.xml'; + afterLoadXml(url, function(xml) { + var p = new ol.parser.ogc.WFS_v1_1_0(); + var output = p.write(null, { + nativeElements: [{ + vendorId: 'ORACLE', + safeToIgnore: true, + value: 'ALTER SESSION ENABLE PARALLEL DML' + }, { + vendorId: 'ORACLE', + safeToIgnore: false, + value: 'Another native line goes here' + }] + }); + expect(goog.dom.xml.loadXml(output)).to.xmleql(xml); + done(); + }); + }); + + it('handles writing out GetFeature with > 1 typename', function(done) { + var url = 'spec/ol/parser/ogc/xml/wfs_v1/GetFeatureMultiple.xml'; + afterLoadXml(url, function(xml) { + var p = new ol.parser.ogc.WFS_v1_0_0(); + var output = p.writers[p.defaultNamespaceURI]['GetFeature']. + apply(p, [{ + featureNS: 'http://www.openplans.org/topp', + featureTypes: ['states', 'cities'], + featurePrefix: 'topp' + } + ]); + expect(goog.dom.xml.loadXml(p.serialize(output))).to.xmleql(xml); + done(); + }); + }); + }); }); goog.require('goog.dom.xml'); goog.require('ol.parser.ogc.WFS'); +goog.require('ol.parser.ogc.WFS_v1_0_0'); +goog.require('ol.parser.ogc.WFS_v1_1_0'); diff --git a/test/spec/ol/parser/ogc/xml/wfs_v1/GetFeature.xml b/test/spec/ol/parser/ogc/xml/wfs_v1/GetFeature.xml new file mode 100644 index 0000000000..8d597268c0 --- /dev/null +++ b/test/spec/ol/parser/ogc/xml/wfs_v1/GetFeature.xml @@ -0,0 +1,3 @@ + + + diff --git a/test/spec/ol/parser/ogc/xml/wfs_v1/GetFeatureMultiple.xml b/test/spec/ol/parser/ogc/xml/wfs_v1/GetFeatureMultiple.xml new file mode 100644 index 0000000000..e1717ddc38 --- /dev/null +++ b/test/spec/ol/parser/ogc/xml/wfs_v1/GetFeatureMultiple.xml @@ -0,0 +1,4 @@ + + + + diff --git a/test/spec/ol/parser/ogc/xml/wfs_v1/Native.xml b/test/spec/ol/parser/ogc/xml/wfs_v1/Native.xml new file mode 100644 index 0000000000..d3ff10f227 --- /dev/null +++ b/test/spec/ol/parser/ogc/xml/wfs_v1/Native.xml @@ -0,0 +1 @@ +ALTER SESSION ENABLE PARALLEL DMLAnother native line goes here diff --git a/test/spec/ol/parser/ogc/xml/wfs_v1/Transaction.xml b/test/spec/ol/parser/ogc/xml/wfs_v1/Transaction.xml new file mode 100644 index 0000000000..b147dc07f4 --- /dev/null +++ b/test/spec/ol/parser/ogc/xml/wfs_v1/Transaction.xml @@ -0,0 +1 @@ + From 279c358af2b4fa5e80794f5d59f56380e62cdbae Mon Sep 17 00:00:00 2001 From: Bart van den Eijnden Date: Thu, 24 Oct 2013 15:02:15 +0200 Subject: [PATCH 11/13] same solution for axisOrientation as for WFS 1.1.0 --- src/ol/parser/ogc/gmlparser_v2.js | 3 +-- test/spec/ol/parser/ogc/wfs_v1_0_0.test.js | 1 + 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ol/parser/ogc/gmlparser_v2.js b/src/ol/parser/ogc/gmlparser_v2.js index 37bdd9d191..837b5d844e 100644 --- a/src/ol/parser/ogc/gmlparser_v2.js +++ b/src/ol/parser/ogc/gmlparser_v2.js @@ -54,8 +54,7 @@ ol.parser.ogc.GML_v2 = function(opt_options) { for (var i = 0; i < numCoordinates; ++i) { var coord = coordinates[i]; var part = goog.array.concat(coord); - if (goog.isDef(this.axisOrientation) && - this.axisOrientation.substr(0, 2) !== 'en') { + if (this.axisOrientation.substr(0, 2) !== 'en') { part[0] = coord[1]; part[1] = coord[0]; } diff --git a/test/spec/ol/parser/ogc/wfs_v1_0_0.test.js b/test/spec/ol/parser/ogc/wfs_v1_0_0.test.js index bab4dd44dc..c616061602 100644 --- a/test/spec/ol/parser/ogc/wfs_v1_0_0.test.js +++ b/test/spec/ol/parser/ogc/wfs_v1_0_0.test.js @@ -29,6 +29,7 @@ describe('ol.parser.ogc.WFS_v1_0_0', function() { new ol.expr.Literal(3), new ol.expr.Literal(4), undefined, new ol.expr.Identifier('the_geom')]); + p.getFilterParser().getGmlParser().axisOrientation = 'enu'; var output = p.writers[p.defaultNamespaceURI]['Query'].apply( p, [{ filter: filter, From d564b5170cd24488de88ecfb4e3bf57d6db51f2e Mon Sep 17 00:00:00 2001 From: Bart van den Eijnden Date: Mon, 25 Nov 2013 14:29:00 +0100 Subject: [PATCH 12/13] move the typedefs out of objectliterals --- src/objectliterals.jsdoc | 14 -------------- src/ol/parser/ogc/wfsparser_v1.js | 22 +++++++++++++++++++--- test/spec/ol/parser/ogc/wfs_v1.test.js | 20 +++++++++----------- 3 files changed, 28 insertions(+), 28 deletions(-) diff --git a/src/objectliterals.jsdoc b/src/objectliterals.jsdoc index 1de0782977..d416c8b63e 100644 --- a/src/objectliterals.jsdoc +++ b/src/objectliterals.jsdoc @@ -595,20 +595,6 @@ * calculations. */ -/** - * @typedef {Object} ol.parser.WFSOptions - * @property {string} featureNS The feature namespace to use. - * @property {string} featurePrefix The prefix for the namespace. - * @property {Array.} featureTypes The feature types to use. - */ - -/** - * @typedef {Object} ol.parser.WFSNative - * @property {string} vendorId The vendor id to use. - * @property {boolean} safeToIgnore Is it safe to ignore? - * @property {string} value The value of the Native element. - */ - /** * @typedef {Object} ol.source.BingMapsOptions * @property {string|undefined} culture Culture code. Default is `en-us`. diff --git a/src/ol/parser/ogc/wfsparser_v1.js b/src/ol/parser/ogc/wfsparser_v1.js index fff9f4fba2..892e7a851f 100644 --- a/src/ol/parser/ogc/wfsparser_v1.js +++ b/src/ol/parser/ogc/wfsparser_v1.js @@ -3,6 +3,22 @@ goog.require('goog.dom.xml'); goog.require('ol.parser.XML'); +/** + * @typedef {{featureNS: string, + featurePrefix: string, + featureTypes: Array., + handle: string, + outputFormat: string, + nativeElements: Array.<{ + vendorId: string, + safeToIgnore: boolean, + value: string + }>, + maxFeatures: number}} + */ +ol.parser.WFSWriteOptions; + + /** * @constructor @@ -21,7 +37,7 @@ ol.parser.ogc.WFS_v1 = function() { this.writers = {}; this.writers[this.defaultNamespaceURI] = { 'GetFeature': function(options) { - options = /** @type {ol.parser.WFSOptions} */(options); + options = /** @type {ol.parser.WFSWriteOptions} */(options); var node = this.createElementNS('wfs:GetFeature'); node.setAttribute('service', 'WFS'); node.setAttribute('version', this.version); @@ -47,7 +63,7 @@ ol.parser.ogc.WFS_v1 = function() { }, 'Transaction': function(obj) { obj = obj || {}; - var options = obj.options || {}; + var options = /** {ol.parser.WFSWriteOptions} */(obj.options || {}); var node = this.createElementNS('wfs:Transaction'); node.setAttribute('service', 'WFS'); node.setAttribute('version', this.version); @@ -152,7 +168,7 @@ ol.parser.ogc.WFS_v1.prototype.read = function(data) { /** * @param {Array.} features The features to write out. - * @param {Object} options Write options. + * @param {ol.parser.WFSWriteOptions} options Write options. * @return {string} A serialized WFS transaction. */ ol.parser.ogc.WFS_v1.prototype.write = function(features, options) { diff --git a/test/spec/ol/parser/ogc/wfs_v1.test.js b/test/spec/ol/parser/ogc/wfs_v1.test.js index a64b00b203..22bf07fc01 100644 --- a/test/spec/ol/parser/ogc/wfs_v1.test.js +++ b/test/spec/ol/parser/ogc/wfs_v1.test.js @@ -52,17 +52,15 @@ describe('ol.parser.ogc.WFS', function() { var url = 'spec/ol/parser/ogc/xml/wfs_v1/Native.xml'; afterLoadXml(url, function(xml) { var p = new ol.parser.ogc.WFS_v1_1_0(); - var output = p.write(null, { - nativeElements: [{ - vendorId: 'ORACLE', - safeToIgnore: true, - value: 'ALTER SESSION ENABLE PARALLEL DML' - }, { - vendorId: 'ORACLE', - safeToIgnore: false, - value: 'Another native line goes here' - }] - }); + var output = p.write(null, {nativeElements: [{ + vendorId: 'ORACLE', + safeToIgnore: true, + value: 'ALTER SESSION ENABLE PARALLEL DML' + }, { + vendorId: 'ORACLE', + safeToIgnore: false, + value: 'Another native line goes here' + }]}); expect(goog.dom.xml.loadXml(output)).to.xmleql(xml); done(); }); From 9ed5004aa6f5cdd9f1d142b997db7f22eb8dce7f Mon Sep 17 00:00:00 2001 From: Bart van den Eijnden Date: Mon, 25 Nov 2013 15:46:38 +0100 Subject: [PATCH 13/13] rename this.gml_ to this.gmlParser_ --- src/ol/parser/ogc/filterparser_v1.js | 23 ++++++++++++----------- src/ol/parser/ogc/filterparser_v1_0_0.js | 2 +- src/ol/parser/ogc/filterparser_v1_1_0.js | 2 +- 3 files changed, 14 insertions(+), 13 deletions(-) diff --git a/src/ol/parser/ogc/filterparser_v1.js b/src/ol/parser/ogc/filterparser_v1.js index 38bd33d2c4..b141c98279 100644 --- a/src/ol/parser/ogc/filterparser_v1.js +++ b/src/ol/parser/ogc/filterparser_v1.js @@ -182,7 +182,8 @@ ol.parser.ogc.Filter_v1 = function() { var args = [], container = {}; this.readChildNodes(node, container); if (goog.isDef(container.geometry)) { - args.push(new ol.expr.Literal(this.gml_.createGeometry(container))); + args.push(new ol.expr.Literal(this.gmlParser_.createGeometry( + container))); } else { args = [new ol.expr.Literal(container.bounds[0]), new ol.expr.Literal(container.bounds[1]), @@ -584,7 +585,7 @@ ol.parser.ogc.Filter_v1.prototype.aggregateLogical_ = function(filters, * @return {ol.parser.ogc.GML_v2|ol.parser.ogc.GML_v3} */ ol.parser.ogc.Filter_v1.prototype.getGmlParser = function() { - return this.gml_; + return this.gmlParser_; }; @@ -594,23 +595,23 @@ ol.parser.ogc.Filter_v1.prototype.getGmlParser = function() { * @protected */ ol.parser.ogc.Filter_v1.prototype.setGmlParser = function(gml) { - this.gml_ = gml; - for (var uri in this.gml_.readers) { - for (var key in this.gml_.readers[uri]) { + this.gmlParser_ = gml; + for (var uri in this.gmlParser_.readers) { + for (var key in this.gmlParser_.readers[uri]) { if (!goog.isDef(this.readers[uri])) { this.readers[uri] = {}; } - this.readers[uri][key] = goog.bind(this.gml_.readers[uri][key], - this.gml_); + this.readers[uri][key] = goog.bind(this.gmlParser_.readers[uri][key], + this.gmlParser_); } } - for (uri in this.gml_.writers) { - for (key in this.gml_.writers[uri]) { + for (uri in this.gmlParser_.writers) { + for (key in this.gmlParser_.writers[uri]) { if (!goog.isDef(this.writers[uri])) { this.writers[uri] = {}; } - this.writers[uri][key] = goog.bind(this.gml_.writers[uri][key], - this.gml_); + this.writers[uri][key] = goog.bind(this.gmlParser_.writers[uri][key], + this.gmlParser_); } } }; diff --git a/src/ol/parser/ogc/filterparser_v1_0_0.js b/src/ol/parser/ogc/filterparser_v1_0_0.js index 0b14d01eb6..eecebe2504 100644 --- a/src/ol/parser/ogc/filterparser_v1_0_0.js +++ b/src/ol/parser/ogc/filterparser_v1_0_0.js @@ -169,7 +169,7 @@ ol.parser.ogc.Filter_v1_0_0.prototype.writeSpatial_ = function(filter, name) { var child; if (geom !== null) { child = this.writeNode('_geometry', {value: geom}, - this.gml_.featureNS).firstChild; + this.gmlParser_.featureNS).firstChild; } else if (bbox.length === 4) { child = this.writeNode('Box', bbox, 'http://www.opengis.net/gml'); diff --git a/src/ol/parser/ogc/filterparser_v1_1_0.js b/src/ol/parser/ogc/filterparser_v1_1_0.js index 77423733fa..42c8388fdc 100644 --- a/src/ol/parser/ogc/filterparser_v1_1_0.js +++ b/src/ol/parser/ogc/filterparser_v1_1_0.js @@ -225,7 +225,7 @@ ol.parser.ogc.Filter_v1_1_0.prototype.writeSpatial_ = function(filter, name) { var child; if (geom !== null) { child = this.writeNode('_geometry', {value: geom}, - this.gml_.featureNS).firstChild; + this.gmlParser_.featureNS).firstChild; } else if (bbox.length === 4) { child = this.writeNode('Envelope', bbox, 'http://www.opengis.net/gml');