diff --git a/examples/wfs-protocol-transactions.html b/examples/wfs-protocol-transactions.html new file mode 100644 index 0000000000..552e23f160 --- /dev/null +++ b/examples/wfs-protocol-transactions.html @@ -0,0 +1,197 @@ + + + + + + + + + + + +

WFS Transaction Example

+ +
+
+

+ Shows the use of the WFS Transactions (WFS-T). +

+ +
+ +
+

The WFS protocol allows for creation of new features and reading, + updating, or deleting of existing features.

+

Use the tools to create, modify, and delete (in order from left + to right) features. Use the save tool (picture of a disk) to + save your changes. Use the navigation tool (hand) to stop editing + and use the mouse for map navigation.

+
+ + + + + + + diff --git a/examples/wfs-protocol.html b/examples/wfs-protocol.html new file mode 100644 index 0000000000..7a2362d6b5 --- /dev/null +++ b/examples/wfs-protocol.html @@ -0,0 +1,48 @@ + + + OpenLayers Vector Behavior Example + + + + + + + +

Vector Behavior Example

+

+ Uses a BBOX strategy, WFS protocol, and GML format. +

+
+
+

The vector layer shown uses the BBOX strategy, the WFS protocol, + and the GML format. The BBOX strategy fetches features within a + bounding box. When the map bounds invalidate the data bounds, + another request is triggered. The WFS protocol gets features + through a WFS request. The GML format is used to serialize + features.

+
+ + diff --git a/lib/OpenLayers.js b/lib/OpenLayers.js index 783feec5db..3b8b0cc614 100644 --- a/lib/OpenLayers.js +++ b/lib/OpenLayers.js @@ -193,6 +193,10 @@ "OpenLayers/Protocol/HTTP.js", "OpenLayers/Protocol/SQL.js", "OpenLayers/Protocol/SQL/Gears.js", + "OpenLayers/Protocol/WFS.js", + "OpenLayers/Protocol/WFS/v1.js", + "OpenLayers/Protocol/WFS/v1_0_0.js", + "OpenLayers/Protocol/WFS/v1_1_0.js", "OpenLayers/Layer/PointTrack.js", "OpenLayers/Layer/GML.js", "OpenLayers/Style.js", @@ -224,6 +228,10 @@ "OpenLayers/Format/SLD/v1.js", "OpenLayers/Format/SLD/v1_0_0.js", "OpenLayers/Format/SLD/v1.js", + "OpenLayers/Format/WFST.js", + "OpenLayers/Format/WFST/v1.js", + "OpenLayers/Format/WFST/v1_0_0.js", + "OpenLayers/Format/WFST/v1_1_0.js", "OpenLayers/Format/Text.js", "OpenLayers/Format/JSON.js", "OpenLayers/Format/GeoJSON.js", diff --git a/lib/OpenLayers/Format/WFST.js b/lib/OpenLayers/Format/WFST.js new file mode 100644 index 0000000000..58bf469e35 --- /dev/null +++ b/lib/OpenLayers/Format/WFST.js @@ -0,0 +1,29 @@ +/** + * @requires OpenLayers/Format.js + */ + +/** + * Function: OpenLayers.Format.WFST + * Used to create a versioned WFS protocol. Default version is 1.0.0. + * + * Returns: + * {} A WFST format of the given version. + */ +OpenLayers.Format.WFST = function(options) { + options = OpenLayers.Util.applyDefaults( + options, OpenLayers.Format.WFST.DEFAULTS + ); + var cls = OpenLayers.Format.WFST["v"+options.version.replace(/\./g, "_")]; + if(!cls) { + throw "Unsupported WFST version: " + options.version; + } + return new cls(options); +} + +/** + * Constant: OpenLayers.Format.WFST.DEFAULTS + * {Object} Default properties for the WFST format. + */ +OpenLayers.Format.WFST.DEFAULTS = { + "version": "1.0.0" +}; diff --git a/lib/OpenLayers/Format/WFST/v1.js b/lib/OpenLayers/Format/WFST/v1.js new file mode 100644 index 0000000000..cf377ae07e --- /dev/null +++ b/lib/OpenLayers/Format/WFST/v1.js @@ -0,0 +1,373 @@ +/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD + * license. See http://svn.openlayers.org/trunk/openlayers/license.txt for the + * full text of the license. */ + +/** + * @requires OpenLayers/Format/XML.js + * @requires OpenLayers/Format/WFST.js + */ + +/** + * Class: OpenLayers.Format.WFST.v1 + * Superclass for WFST parsers. + * + * Inherits from: + * - + */ +OpenLayers.Format.WFST.v1 = OpenLayers.Class(OpenLayers.Format.XML, { + + /** + * Property: namespaces + * {Object} Mapping of namespace aliases to namespace URIs. + */ + namespaces: { + xlink: "http://www.w3.org/1999/xlink", + xsi: "http://www.w3.org/2001/XMLSchema-instance", + wfs: "http://www.opengis.net/wfs", + gml: "http://www.opengis.net/gml", + ogc: "http://www.opengis.net/ogc" + }, + + /** + * Property: defaultPrefix + */ + defaultPrefix: "wfs", + + /** + * Property: version + * {String} WFS version number. + */ + version: null, + + /** + * Property: schemaLocation + * {String} Schema location for a particular minor version. + */ + schemaLocations: null, + + /** + * APIProperty: srsName + * {String} URI for spatial reference system. + */ + srsName: null, + + /** + * APIProperty: extractAttributes + * {Boolean} Extract attributes from GML. Default is true. + */ + extractAttributes: true, + + /** + * APIProperty: xy + * {Boolean} Order of the GML coordinate true:(x,y) or false:(y,x) + * Changing is not recommended, a new Format should be instantiated. + */ + xy: true, + + /** + * Property: stateName + * {Object} Maps feature states to node names. + */ + stateName: null, + + /** + * Constructor: OpenLayers.Format.WFST.v1 + * Instances of this class are not created directly. Use the + * or + * constructor instead. + * + * Parameters: + * options - {Object} An optional object whose properties will be set on + * this instance. + */ + initialize: function(options) { + if(options.featureNS) { + this.namespaces = OpenLayers.Util.extend( + {feature: options.featureNS}, + OpenLayers.Format.WFST.v1.prototype.namespaces + ); + } + // set state name mapping + this.stateName = {}; + this.stateName[OpenLayers.State.INSERT] = "wfs:Insert"; + this.stateName[OpenLayers.State.UPDATE] = "wfs:Update"; + this.stateName[OpenLayers.State.DELETE] = "wfs:Delete"; + // extend format with misc properties from filter and gml formats + var filterProto = OpenLayers.Format.Filter.v1.prototype; + var gmlProto = OpenLayers.Format.GML.Base.prototype; + OpenLayers.Util.extend(this, { + readOgcExpression: filterProto.readOgcExpression, + getFilterType: filterProto.getFilterType, + filterMap: filterProto.filterMap, + regExes: gmlProto.regExes + }); + OpenLayers.Format.XML.prototype.initialize.apply(this, [options]); + }, + + /** + * Method: getSrsName + */ + getSrsName: function(feature, options) { + var srsName = options && options.srsName; + if(!srsName) { + if(feature && feature.layer) { + srsName = feature.layer.projection.getCode(); + } else { + srsName = this.srsName; + } + } + return srsName; + }, + + /** + * Method: read + * Parse the response from a transaction. Because WFS is split into + * Transaction requests (create, update, and delete) and GetFeature + * requests (read), this method handles parsing of both types of + * responses. + */ + read: function(data) { + if(typeof data == "string") { + data = OpenLayers.Format.XML.prototype.read.apply(this, [data]); + } + if(data && data.nodeType == 9) { + data = data.documentElement; + } + var obj = {}; + this.readNode(data, obj); + if(obj.features) { + obj = obj.features; + } + return obj; + }, + + /** + * Property: readers + * Contains public functions, grouped by namespace prefix, that will + * be applied when a namespaced node is found matching the function + * name. The function will be applied in the scope of this parser + * with two arguments: the node being read and a context object passed + * from the parent. + */ + readers: { + "wfs": { + "FeatureCollection": function(node, obj) { + obj.features = []; + this.readChildNodes(node, obj); + } + } + }, + + /** + * Method: write + * Given an array of features, write a WFS transaction. This assumes + * the features have a state property that determines the operation + * type - insert, update, or delete. + * + * Parameters: + * features - {Array()} A list of features. + * + * Returns: + * {String} A serialized WFS transaction. + */ + write: function(features) { + var node = this.writeNode("wfs:Transaction", features); + var value = this.schemaLocationAttr(); + if(value) { + this.setAttributeNS( + node, this.namespaces["xsi"], "xsi:schemaLocation", value + ) + } + return OpenLayers.Format.XML.prototype.write.apply(this, [node]); + }, + + /** + * Property: writers + * As a compliment to the readers property, this structure contains public + * writing functions grouped by namespace alias and named like the + * node names they produce. + */ + writers: { + "wfs": { + "GetFeature": function(options) { + var node = this.createElementNSPlus("wfs:GetFeature", { + attributes: { + service: "WFS", + version: this.version, + maxFeatures: options && options.maxFeatures, + "xsi:schemaLocation": this.schemaLocationAttr(options) + } + }); + this.writeNode("Query", options, node); + return node; + }, + "Query": function(options) { + options = OpenLayers.Util.extend({ + featureNS: this.featureNS, + featurePrefix: this.featurePrefix, + featureType: this.featureType, + srsName: this.srsName + }, options); + // TODO: this is still version specific and should be separated out + // v1.0.0 does not allow srsName on wfs:Query + var node = this.createElementNSPlus("wfs:Query", { + attributes: { + typeName: (options.featureNS ? options.featurePrefix + ":" : "") + + options.featureType, + srsName: options.srsName + } + }); + if(options.featureNS) { + node.setAttribute("xmlns:" + options.featurePrefix, options.featureNS); + } + if(options.filter) { + this.setFilterProperty(options.filter); + this.writeNode("ogc:Filter", options.filter, node); + } + return node; + }, + "Transaction": function(features) { + var node = this.createElementNSPlus("wfs:Transaction", { + attributes: { + service: "WFS", + version: this.version + } + }); + if(features) { + var name, feature; + for(var i=0, len=features.length; i} + */ + setFilterProperty: function(filter) { + if(filter.filters) { + for(var i=0, len=filter.filters.length; i constructor. + * + * Inherits from: + * - + */ +OpenLayers.Format.WFST.v1_0_0 = OpenLayers.Class(OpenLayers.Format.WFST.v1, { + + /** + * Property: version + * {String} WFS version number. + */ + version: "1.0.0", + + /** + * Property: schemaLocations + * {Object} Properties are namespace aliases, values are schema locations. + */ + schemaLocations: { + "wfs": "http://schemas.opengis.net/wfs/1.0.0/WFS-transaction.xsd" + }, + + /** + * Constructor: OpenLayers.Format.WFST.v1_0_0 + * A class for parsing and generating WFS v1.0.0 transactions. + * + * Parameters: + * options - {Object} Optional object whose properties will be set on the + * instance. + * + * Valid options properties: + * featureType - {String} Local (without prefix) feature typeName (required). + * featureNS - {String} Feature namespace (optional). + * featurePrefix - {String} Feature namespace alias (optional - only used + * if featureNS is provided). Default is 'feature'. + * geometryName - {String} Name of geometry attribute. Default is 'the_geom'. + */ + initialize: function(options) { + OpenLayers.Format.WFST.v1.prototype.initialize.apply(this, [options]); + OpenLayers.Format.GML.v2.prototype.setGeometryTypes.call(this); + }, + + /** + * Property: readers + * Contains public functions, grouped by namespace prefix, that will + * be applied when a namespaced node is found matching the function + * name. The function will be applied in the scope of this parser + * with two arguments: the node being read and a context object passed + * from the parent. + */ + readers: { + "wfs": OpenLayers.Util.applyDefaults({ + "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); + container.insertIds.push(obj.fids[0]); + }, + "TransactionResult": function(node, obj) { + this.readChildNodes(node, obj); + }, + "Status": function(node, obj) { + this.readChildNodes(node, obj); + }, + "SUCCESS": function(node, obj) { + obj.success = true; + } + }, OpenLayers.Format.WFST.v1.prototype.readers["wfs"]), + "gml": OpenLayers.Format.GML.v2.prototype.readers["gml"], + "feature": OpenLayers.Format.GML.v2.prototype.readers["feature"], + "ogc": OpenLayers.Format.Filter.v1_0_0.prototype.readers["ogc"] + }, + + /** + * Property: writers + * As a compliment to the readers property, this structure contains public + * writing functions grouped by namespace alias and named like the + * node names they produce. + */ + writers: { + "wfs": OpenLayers.Util.applyDefaults({ + "Query": function(options) { + options = OpenLayers.Util.extend({ + featureNS: this.featureNS, + featurePrefix: this.featurePrefix, + featureType: this.featureType, + srsName: this.srsName + }, options); + var node = this.createElementNSPlus("wfs:Query", { + attributes: { + typeName: (options.featureNS ? options.featurePrefix + ":" : "") + + options.featureType + } + }); + if(options.featureNS) { + node.setAttribute("xmlns:" + options.featurePrefix, options.featureNS); + } + if(options.filter) { + this.setFilterProperty(options.filter); + this.writeNode("ogc:Filter", options.filter, node); + } + return node; + } + }, OpenLayers.Format.WFST.v1.prototype.writers["wfs"]), + "gml": OpenLayers.Format.GML.v2.prototype.writers["gml"], + "feature": OpenLayers.Format.GML.v2.prototype.writers["feature"], + "ogc": OpenLayers.Format.Filter.v1_0_0.prototype.writers["ogc"] + }, + + CLASS_NAME: "OpenLayers.Format.WFST.v1_0_0" +}); diff --git a/lib/OpenLayers/Format/WFST/v1_1_0.js b/lib/OpenLayers/Format/WFST/v1_1_0.js new file mode 100644 index 0000000000..a616015348 --- /dev/null +++ b/lib/OpenLayers/Format/WFST/v1_1_0.js @@ -0,0 +1,122 @@ +/** + * @requires OpenLayers/Format/WFST/v1.js + * @requires OpenLayers/Format/GML/v3.js + * @requires OpenLayers/Format/Filter/v1_1_0.js + */ + +/** + * Class: OpenLayers.Format.WFST.v1_1_0 + * A format for creating WFS v1.1.0 transactions. Create a new instance with the + * constructor. + * + * Inherits from: + * - + */ +OpenLayers.Format.WFST.v1_1_0 = OpenLayers.Class(OpenLayers.Format.WFST.v1, { + + /** + * Property: version + * {String} WFS version number. + */ + version: "1.1.0", + + /** + * Property: schemaLocations + * {Object} Properties are namespace aliases, values are schema locations. + */ + schemaLocations: { + "wfs": "http://schemas.opengis.net/wfs/1.1.0/wfs.xsd" + }, + + /** + * Constructor: OpenLayers.Format.WFST.v1_1_0 + * A class for parsing and generating WFS v1.1.0 transactions. + * + * Parameters: + * options - {Object} Optional object whose properties will be set on the + * instance. + * + * Valid options properties: + * featureType - {String} Local (without prefix) feature typeName (required). + * featureNS - {String} Feature namespace (optional). + * featurePrefix - {String} Feature namespace alias (optional - only used + * if featureNS is provided). Default is 'feature'. + * geometryName - {String} Name of geometry attribute. Default is 'the_geom'. + */ + initialize: function(options) { + OpenLayers.Format.WFST.v1.prototype.initialize.apply(this, [options]); + OpenLayers.Format.GML.v3.prototype.setGeometryTypes.call(this); + }, + + /** + * Property: readers + * Contains public functions, grouped by namespace prefix, that will + * be applied when a namespaced node is found matching the function + * name. The function will be applied in the scope of this parser + * with two arguments: the node being read and a context object passed + * from the parent. + */ + readers: { + "wfs": OpenLayers.Util.applyDefaults({ + "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]); + } + }, OpenLayers.Format.WFST.v1.prototype.readers["wfs"]), + "gml": OpenLayers.Format.GML.v3.prototype.readers["gml"], + "feature": OpenLayers.Format.GML.v3.prototype.readers["feature"], + "ogc": OpenLayers.Format.Filter.v1_1_0.prototype.readers["ogc"] + }, + + /** + * Property: writers + * As a compliment to the readers property, this structure contains public + * writing functions grouped by namespace alias and named like the + * node names they produce. + */ + writers: { + "wfs": OpenLayers.Util.applyDefaults({ + "Query": function(options) { + options = OpenLayers.Util.extend({ + featureNS: this.featureNS, + featurePrefix: this.featurePrefix, + featureType: this.featureType, + srsName: this.srsName + }, options); + var node = this.createElementNSPlus("wfs:Query", { + attributes: { + typeName: (options.featureNS ? options.featurePrefix + ":" : "") + + options.featureType, + srsName: options.srsName + } + }); + if(options.featureNS) { + node.setAttribute("xmlns:" + options.featurePrefix, options.featureNS); + } + if(options.filter) { + this.setFilterProperty(options.filter); + this.writeNode("ogc:Filter", options.filter, node); + } + return node; + } + }, OpenLayers.Format.WFST.v1.prototype.writers["wfs"]), + "gml": OpenLayers.Format.GML.v3.prototype.writers["gml"], + "feature": OpenLayers.Format.GML.v3.prototype.writers["feature"], + "ogc": OpenLayers.Format.Filter.v1_1_0.prototype.writers["ogc"] + }, + + CLASS_NAME: "OpenLayers.Format.WFST.v1_1_0" +}); diff --git a/lib/OpenLayers/Protocol/WFS.js b/lib/OpenLayers/Protocol/WFS.js new file mode 100644 index 0000000000..3a2fcc05a8 --- /dev/null +++ b/lib/OpenLayers/Protocol/WFS.js @@ -0,0 +1,28 @@ +/** + * @requires OpenLayers/Protocol.js + */ + +/** + * Function: OpenLayers.Protocol.WFS + * Used to create a versioned WFS protocol. Default version is 1.0.0. + * + * Returns: + * {} A WFS protocol of the given version. + */ +OpenLayers.Protocol.WFS = function(options) { + options = OpenLayers.Util.applyDefaults( + options, OpenLayers.Protocol.WFS.DEFAULTS + ); + var cls = OpenLayers.Protocol.WFS["v"+options.version.replace(/\./g, "_")]; + if(!cls) { + throw "Unsupported WFS version: " + options.version; + } + return new cls(options); +} + +/** + * Constant: OpenLayers.Protocol.WFS.DEFAULTS + */ +OpenLayers.Protocol.WFS.DEFAULTS = { + "version": "1.0.0" +}; diff --git a/lib/OpenLayers/Protocol/WFS/v1.js b/lib/OpenLayers/Protocol/WFS/v1.js new file mode 100644 index 0000000000..4957bf2a7e --- /dev/null +++ b/lib/OpenLayers/Protocol/WFS/v1.js @@ -0,0 +1,328 @@ +/** + * @requires OpenLayers/Protocol/WFS.js + */ + +/** + * Class: OpenLayers.Protocol.WFS.v1 + * Abstract class for for v1.0.0 and v1.1.0 protocol. + * + * Inherits from: + * - + */ +OpenLayers.Protocol.WFS.v1 = new OpenLayers.Class(OpenLayers.Protocol, { + + /** + * Property: version + * {String} WFS version number. + */ + version: null, + + /** + * Property: srsName + * {String} Name of spatial reference system. Default is "EPSG:4326". + */ + srsName: "EPSG:4326", + + /** + * Property: featureType + * {String} Local feature typeName. + */ + featureType: null, + + /** + * Property: featureNS + * {String} Feature namespace. + */ + featureNS: null, + + /** + * Property: geometryName + * {String} Name of the geometry attribute for features. Default is + * "the_geom". + */ + geometryName: "the_geom", + + /** + * Property: schema + * {String} Optional schema location that will be included in the + * schemaLocation attribute value. Note that the feature type schema + * is required for a strict XML validator (on transactions with an + * insert for example), but is *not* required by the WFS specification + * (since the server is supposed to know about feature type schemas). + */ + schema: null, + + /** + * Property: featurePrefix + * {String} Namespace alias for feature type. Default is "feature". + */ + featurePrefix: "feature", + + /** + * Property: formatOptions + * {Object} Optional options for the format. If a format is not provided, + * this property can be used to extend the default format options. + */ + formatOptions: null, + + /** + * Constructor: OpenLayers.Protocol.WFS + * A class for giving layers WFS protocol. + * + * Parameters: + * options - {Object} Optional object whose properties will be set on the + * instance. + * + * Valid options properties: + * url - {String} URL to send requests to (required). + * featureType - {String} Local (without prefix) feature typeName (required). + * featureNS - {String} Feature namespace (required, but can be autodetected + * for reading if featurePrefix is provided and identical to the prefix + * in the server response). + * featurePrefix - {String} Feature namespace alias (optional - only used + * for writing if featureNS is provided). Default is 'feature'. + * geometryName - {String} Name of geometry attribute. Default is 'the_geom'. + */ + initialize: function(options) { + OpenLayers.Protocol.prototype.initialize.apply(this, [options]); + if(!options.format) { + this.format = OpenLayers.Format.WFST(OpenLayers.Util.extend({ + version: this.version, + featureType: this.featureType, + featureNS: this.featureNS, + featurePrefix: this.featurePrefix, + geometryName: this.geometryName, + srsName: this.srsName, + schema: this.schema + }, this.formatOptions)); + } + if(!this.featureNS) { + // featureNS autodetection + var readNode = this.format.readNode; + this.format.readNode = function(node, obj) { + if(!this.featureNS && node.prefix == this.featurePrefix) { + this.featureNS = node.namespaceURI; + this.setNamespace("feature", this.featureNS); + } + return readNode.apply(this, arguments); + } + } + }, + + /** + * APIMethod: destroy + * Clean up the protocol. + */ + destroy: function() { + if(this.options && !this.options.format) { + this.format.destroy(); + } + this.format = null; + OpenLayers.Protocol.prototype.destroy.apply(this); + }, + + /** + * Method: createCallback + * Returns a function that applies the given public method with resp and + * options arguments. + * + * Parameters: + * method - {Function} The method to be applied by the callback. + * response - {} The protocol response object. + * options - {Object} Options sent to the protocol method (read, create, + * update, or delete). + */ + createCallback: function(method, response, options) { + return OpenLayers.Function.bind(function() { + method.apply(this, [response, options]); + }, this); + }, + + /** + * Method: read + * Construct a request for reading new features. Since WFS splits the + * basic CRUD operations into GetFeature requests (for read) and + * Transactions (for all others), this method does not make use of the + * format's read method (that is only about reading transaction + * responses). + */ + read: function(options) { + options = OpenLayers.Util.extend({}, options); + OpenLayers.Util.applyDefaults(options, this.options || {}); + var response = new OpenLayers.Protocol.Response({requestType: "read"}); + + var data = OpenLayers.Format.XML.prototype.write.apply( + this.format, [this.format.writeNode("wfs:GetFeature", options)] + ); + + response.priv = OpenLayers.Request.POST({ + url: options.url, + callback: this.createCallback(this.handleRead, response, options), + params: options.params, + headers: options.headers, + data: data + }); + + return response; + }, + + /** + * Method: handleRead + * Deal with response from the read request. + * + * Parameters: + * response - {} The response object to pass + * to the user callback. + * options - {Object} The user options passed to the read call. + */ + handleRead: function(response, options) { + if(options.callback) { + var request = response.priv; + if(request.status >= 200 && request.status < 300) { + // success + response.features = this.parseFeatures(request); + response.code = OpenLayers.Protocol.Response.SUCCESS; + } else { + // failure + response.code = OpenLayers.Protocol.Response.FAILURE; + } + options.callback.call(options.scope, response); + }; + }, + + /** + * Method: parseFeatures + * Read HTTP response body and return features + * + * Parameters: + * request - {XMLHttpRequest} The request object + * + * Returns: + * {Array({})} or + * {} Array of features or a single feature. + */ + parseFeatures: function(request) { + var doc = request.responseXML; + if(!doc || !doc.documentElement) { + doc = request.responseText; + } + if(!doc || doc.length <= 0) { + return null; + } + return this.format.read(doc); + }, + + /** + * Method: commit + * Given a list of feature, assemble a batch request for update, create, + * and delete transactions. A commit call on the prototype amounts + * to writing a WFS transaction - so the write method on the format + * is used. + * + * Parameters: + * features - {Array(} + * + * Returns: + * {} A response object with a features + * property containing any insertIds and a priv property referencing + * the XMLHttpRequest object. + */ + commit: function(features, options) { + + options = OpenLayers.Util.extend({}, options); + OpenLayers.Util.applyDefaults(options, this.options); + + var response = new OpenLayers.Protocol.Response({ + requestType: "commit", + reqFeatures: features + }); + response.priv = OpenLayers.Request.POST({ + url: options.url, + data: this.format.write(features, options), + callback: this.createCallback(this.handleCommit, response, options) + }); + + return response; + }, + + /** + * Method: handleCommit + * Called when the commit request returns. + * + * Parameters: + * response - {} The response object to pass + * to the user callback. + * options - {Object} The user options passed to the commit call. + */ + handleCommit: function(response, options) { + if(options.callback) { + var request = response.priv; + + // ensure that we have an xml doc + var data = request.responseXML; + if(!data || !data.documentElement) { + data = request.responseText; + } + + var obj = this.format.read(data) || {}; + + response.insertIds = obj.insertIds || []; + response.code = (obj.success) ? + OpenLayers.Protocol.Response.SUCCESS : + OpenLayers.Protocol.Response.FAILURE; + options.callback.call(options.scope, response); + } + }, + + /** + * Method: filterDelete + * Send a request that deletes all features by their filter. + * + * Parameters: + * filter - {OpenLayers.Filter} filter + */ + filterDelete: function(filter, options) { + options = OpenLayers.Util.extend({}, options); + OpenLayers.Util.applyDefaults(options, this.options); + + var response = new OpenLayers.Protocol.Response({ + requestType: "commit" + }); + + var root = this.format.createElementNSPlus("wfs:Transaction", { + attributes: { + service: "WFS", + version: this.version + } + }); + + var deleteNode = this.format.createElementNSPlus("wfs:Delete", { + attributes: { + typeName: (options.featureNS ? this.featurePrefix + ":" : "") + + options.featureType + } + }); + + if(options.featureNS) { + deleteNode.setAttribute("xmlns:" + this.featurePrefix, options.featureNS); + } + var filterNode = this.format.writeNode("ogc:Filter", filter); + + deleteNode.appendChild(filterNode); + + root.appendChild(deleteNode); + + var data = OpenLayers.Format.XML.prototype.write.apply( + this.format, [root] + ); + + return OpenLayers.Request.POST({ + url: this.url, + callback : options.callback || function(){}, + data: data + }); + + }, + + CLASS_NAME: "OpenLayers.Protocol.WFS.v1" +}); diff --git a/lib/OpenLayers/Protocol/WFS/v1_0_0.js b/lib/OpenLayers/Protocol/WFS/v1_0_0.js new file mode 100644 index 0000000000..81c9ab4e3d --- /dev/null +++ b/lib/OpenLayers/Protocol/WFS/v1_0_0.js @@ -0,0 +1,39 @@ +/** + * @requires OpenLayers/Protocol/WFS/v1.js + * @requires OpenLayers/Format/WFST/v1_0_0.js + */ + +/** + * Class: OpenLayers.Protocol.WFS.v1_0_0 + * A WFS v1.0.0 protocol for vector layers. Create a new instance with the + * constructor. + * + * Inherits from: + * - + */ +OpenLayers.Protocol.WFS.v1_0_0 = OpenLayers.Class(OpenLayers.Protocol.WFS.v1, { + + /** + * Property: version + * {String} WFS version number. + */ + version: "1.0.0", + + /** + * Constructor: OpenLayers.Protocol.WFS.v1_0_0 + * A class for giving layers WFS v1.0.0 protocol. + * + * Parameters: + * options - {Object} Optional object whose properties will be set on the + * instance. + * + * Valid options properties: + * featureType - {String} Local (without prefix) feature typeName (required). + * featureNS - {String} Feature namespace (optional). + * featurePrefix - {String} Feature namespace alias (optional - only used + * if featureNS is provided). Default is 'feature'. + * geometryName - {String} Name of geometry attribute. Default is 'the_geom'. + */ + + CLASS_NAME: "OpenLayers.Protocol.WFS.v1_0_0" +}); diff --git a/lib/OpenLayers/Protocol/WFS/v1_1_0.js b/lib/OpenLayers/Protocol/WFS/v1_1_0.js new file mode 100644 index 0000000000..f9f95868e1 --- /dev/null +++ b/lib/OpenLayers/Protocol/WFS/v1_1_0.js @@ -0,0 +1,43 @@ +/** + * @requires OpenLayers/Protocol/WFS/v1.js + * @requires OpenLayers/Format/WFST/v1_1_0.js + */ + +/** + * Class: OpenLayers.Protocol.WFS.v1_1_0 + * A WFS v1.1.0 protocol for vector layers. Create a new instance with the + * constructor. + * + * Differences from the v1.0.0 protocol: + * - uses Filter Encoding 1.1.0 instead of 1.0.0 + * - uses GML 3 instead of 2 if no format is provided + * + * Inherits from: + * - + */ +OpenLayers.Protocol.WFS.v1_1_0 = OpenLayers.Class(OpenLayers.Protocol.WFS.v1, { + + /** + * Property: version + * {String} WFS version number. + */ + version: "1.1.0", + + /** + * Constructor: OpenLayers.Protocol.WFS.v1_1_0 + * A class for giving layers WFS v1.1.0 protocol. + * + * Parameters: + * options - {Object} Optional object whose properties will be set on the + * instance. + * + * Valid options properties: + * featureType - {String} Local (without prefix) feature typeName (required). + * featureNS - {String} Feature namespace (optional). + * featurePrefix - {String} Feature namespace alias (optional - only used + * if featureNS is provided). Default is 'feature'. + * geometryName - {String} Name of geometry attribute. Default is 'the_geom'. + */ + + CLASS_NAME: "OpenLayers.Protocol.WFS.v1_1_0" +}); diff --git a/tests/Format/WFST.html b/tests/Format/WFST.html new file mode 100644 index 0000000000..e6793c0f85 --- /dev/null +++ b/tests/Format/WFST.html @@ -0,0 +1,23 @@ + + + + + + +
+ + diff --git a/tests/Format/WFST/v1.html b/tests/Format/WFST/v1.html new file mode 100644 index 0000000000..eb0f8cedc9 --- /dev/null +++ b/tests/Format/WFST/v1.html @@ -0,0 +1,160 @@ + + + + + + +
+ +
+ +
+
+
+
+
+ + diff --git a/tests/Format/WFST/v1_0_0.html b/tests/Format/WFST/v1_0_0.html new file mode 100644 index 0000000000..6dca1c9f83 --- /dev/null +++ b/tests/Format/WFST/v1_0_0.html @@ -0,0 +1,87 @@ + + + + + + +
+
+
+ + diff --git a/tests/Format/WFST/v1_1_0.html b/tests/Format/WFST/v1_1_0.html new file mode 100644 index 0000000000..a9ec9cea70 --- /dev/null +++ b/tests/Format/WFST/v1_1_0.html @@ -0,0 +1,91 @@ + + + + + + +
+
+
+ + diff --git a/tests/Protocol/WFS.html b/tests/Protocol/WFS.html new file mode 100644 index 0000000000..aa3dc5b9f8 --- /dev/null +++ b/tests/Protocol/WFS.html @@ -0,0 +1,238 @@ + + + + + + +
+
+
+
+
+ + diff --git a/tests/list-tests.html b/tests/list-tests.html index 790d8077aa..15dfddb24d 100644 --- a/tests/list-tests.html +++ b/tests/list-tests.html @@ -55,6 +55,10 @@
  • Format/Filter/v1_0_0.html
  • Format/Filter/v1_1_0.html
  • Format/WFSDescribeFeatureType.html
  • +
  • Format/WFST.html
  • +
  • Format/WFST/v1.html
  • +
  • Format/WFST/v1_0_0.html
  • +
  • Format/WFST/v1_1_0.html
  • Format/WKT.html
  • Format/WMC.html
  • Format/WMC/v1_1_0.html
  • @@ -121,6 +125,7 @@
  • Protocol/HTTP.html
  • Protocol/SQL.html
  • Protocol/SQL/Gears.html
  • +
  • Protocol/WFS.html
  • Renderer.html
  • Renderer/Canvas.html
  • Renderer/Elements.html