Adding a WFS protocol. This allows for creating, reading, updating, and deleting features via WFS. Huge thanks to ahocevar for the test writing and review. r=ahocevar (closes #1648)
git-svn-id: http://svn.openlayers.org/trunk/openlayers@8868 dc9f47b5-9b13-0410-9fdd-eb0c1a62fdaf
This commit is contained in:
328
lib/OpenLayers/Protocol/WFS/v1.js
Normal file
328
lib/OpenLayers/Protocol/WFS/v1.js
Normal file
@@ -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>
|
||||
*/
|
||||
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 - {<OpenLayers.Protocol.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 - {<OpenLayers.Protocol.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({<OpenLayers.Feature.Vector>})} or
|
||||
* {<OpenLayers.Feature.Vector>} 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(<OpenLayers.Feature.Vector>}
|
||||
*
|
||||
* Returns:
|
||||
* {<OpenLayers.Protocol.Response>} 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 - {<OpenLayers.Protocol.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"
|
||||
});
|
||||
Reference in New Issue
Block a user