| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564 |
- /* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for
- * full list of contributors). Published under the Clear BSD license.
- * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
- * full text of the license. */
- /**
- * @requires OpenLayers/Console.js
- * @requires OpenLayers/Protocol.js
- * @requires OpenLayers/Feature/Vector.js
- * @requires OpenLayers/Filter/Spatial.js
- * @requires OpenLayers/Filter/Comparison.js
- * @requires OpenLayers/Filter/Logical.js
- * @requires OpenLayers/Request/XMLHttpRequest.js
- */
- /**
- * TODO: remove this dependency in 3.0
- * @requires OpenLayers/Format/QueryStringFilter.js
- */
- /**
- * Class: OpenLayers.Protocol.HTTP
- * A basic HTTP protocol for vector layers. Create a new instance with the
- * <OpenLayers.Protocol.HTTP> constructor.
- *
- * Inherits from:
- * - <OpenLayers.Protocol>
- */
- OpenLayers.Protocol.HTTP = OpenLayers.Class(OpenLayers.Protocol, {
- /**
- * Property: url
- * {String} Service URL, read-only, set through the options
- * passed to constructor.
- */
- url: null,
- /**
- * Property: headers
- * {Object} HTTP request headers, read-only, set through the options
- * passed to the constructor,
- * Example: {'Content-Type': 'plain/text'}
- */
- headers: null,
- /**
- * Property: params
- * {Object} Parameters of GET requests, read-only, set through the options
- * passed to the constructor,
- * Example: {'bbox': '5,5,5,5'}
- */
- params: null,
-
- /**
- * Property: callback
- * {Object} Function to be called when the <read>, <create>,
- * <update>, <delete> or <commit> operation completes, read-only,
- * set through the options passed to the constructor.
- */
- callback: null,
- /**
- * Property: scope
- * {Object} Callback execution scope, read-only, set through the
- * options passed to the constructor.
- */
- scope: null,
- /**
- * Property: readWithPOST
- * {Boolean} true if read operations are done with POST requests
- * instead of GET, defaults to false.
- */
- readWithPOST: false,
- /**
- * Property: wildcarded.
- * {Boolean} If true percent signs are added around values
- * read from LIKE filters, for example if the protocol
- * read method is passed a LIKE filter whose property
- * is "foo" and whose value is "bar" the string
- * "foo__ilike=%bar%" will be sent in the query string;
- * defaults to false.
- */
- wildcarded: false,
- /**
- * APIProperty: srsInBBOX
- * {Boolean} Include the SRS identifier in BBOX query string parameter.
- * Default is false. If true and the layer has a projection object set,
- * any BBOX filter will be serialized with a fifth item identifying the
- * projection. E.g. bbox=-1000,-1000,1000,1000,EPSG:900913
- */
- srsInBBOX: false,
- /**
- * Constructor: OpenLayers.Protocol.HTTP
- * A class for giving layers generic HTTP protocol.
- *
- * Parameters:
- * options - {Object} Optional object whose properties will be set on the
- * instance.
- *
- * Valid options include:
- * url - {String}
- * headers - {Object}
- * params - {Object}
- * format - {<OpenLayers.Format>}
- * callback - {Function}
- * scope - {Object}
- */
- initialize: function(options) {
- options = options || {};
- this.params = {};
- this.headers = {};
- OpenLayers.Protocol.prototype.initialize.apply(this, arguments);
- if (!this.filterToParams && OpenLayers.Format.QueryStringFilter) {
- var format = new OpenLayers.Format.QueryStringFilter({
- wildcarded: this.wildcarded,
- srsInBBOX: this.srsInBBOX
- });
- this.filterToParams = function(filter, params) {
- return format.write(filter, params);
- }
- }
- },
-
- /**
- * APIMethod: destroy
- * Clean up the protocol.
- */
- destroy: function() {
- this.params = null;
- this.headers = null;
- OpenLayers.Protocol.prototype.destroy.apply(this);
- },
- /**
- * APIMethod: filterToParams
- * Optional method to translate an <OpenLayers.Filter> object into an object
- * that can be serialized as request query string provided. If a custom
- * method is not provided, the filter will be serialized using the
- * <OpenLayers.Protocol.simpleFilterSerializer> method.
- *
- * Parameters:
- * filter - {<OpenLayers.Filter>} filter to convert.
- * params - {Object} The parameters object.
- *
- * Returns:
- * {Object} The resulting parameters object.
- */
-
- /**
- * APIMethod: read
- * Construct a request for reading new features.
- *
- * Parameters:
- * options - {Object} Optional object for configuring the request.
- * This object is modified and should not be reused.
- *
- * Valid options:
- * url - {String} Url for the request.
- * params - {Object} Parameters to get serialized as a query string.
- * headers - {Object} Headers to be set on the request.
- * filter - {<OpenLayers.Filter>} Filter to get serialized as a
- * query string.
- * readWithPOST - {Boolean} If the request should be done with POST.
- *
- * Returns:
- * {<OpenLayers.Protocol.Response>} A response object, whose "priv" property
- * references the HTTP request, this object is also passed to the
- * callback function when the request completes, its "features" property
- * is then populated with the the features received from the server.
- */
- read: function(options) {
- OpenLayers.Protocol.prototype.read.apply(this, arguments);
- options = options || {};
- options.params = OpenLayers.Util.applyDefaults(
- options.params, this.options.params);
- options = OpenLayers.Util.applyDefaults(options, this.options);
- if (options.filter && this.filterToParams) {
- options.params = this.filterToParams(
- options.filter, options.params
- );
- }
- var readWithPOST = (options.readWithPOST !== undefined) ?
- options.readWithPOST : this.readWithPOST;
- var resp = new OpenLayers.Protocol.Response({requestType: "read"});
- if(readWithPOST) {
- resp.priv = OpenLayers.Request.POST({
- url: options.url,
- callback: this.createCallback(this.handleRead, resp, options),
- data: OpenLayers.Util.getParameterString(options.params),
- headers: {
- "Content-Type": "application/x-www-form-urlencoded"
- }
- });
- } else {
- resp.priv = OpenLayers.Request.GET({
- url: options.url,
- callback: this.createCallback(this.handleRead, resp, options),
- params: options.params,
- headers: options.headers
- });
- }
- return resp;
- },
- /**
- * Method: handleRead
- * Individual callbacks are created for read, create and update, should
- * a subclass need to override each one separately.
- *
- * Parameters:
- * resp - {<OpenLayers.Protocol.Response>} The response object to pass to
- * the user callback.
- * options - {Object} The user options passed to the read call.
- */
- handleRead: function(resp, options) {
- this.handleResponse(resp, options);
- },
- /**
- * APIMethod: create
- * Construct a request for writing newly created features.
- *
- * Parameters:
- * features - {Array({<OpenLayers.Feature.Vector>})} or
- * {<OpenLayers.Feature.Vector>}
- * options - {Object} Optional object for configuring the request.
- * This object is modified and should not be reused.
- *
- * Returns:
- * {<OpenLayers.Protocol.Response>} An <OpenLayers.Protocol.Response>
- * object, whose "priv" property references the HTTP request, this
- * object is also passed to the callback function when the request
- * completes, its "features" property is then populated with the
- * the features received from the server.
- */
- create: function(features, options) {
- options = OpenLayers.Util.applyDefaults(options, this.options);
- var resp = new OpenLayers.Protocol.Response({
- reqFeatures: features,
- requestType: "create"
- });
- resp.priv = OpenLayers.Request.POST({
- url: options.url,
- callback: this.createCallback(this.handleCreate, resp, options),
- headers: options.headers,
- data: this.format.write(features)
- });
- return resp;
- },
- /**
- * Method: handleCreate
- * Called the the request issued by <create> is complete. May be overridden
- * by subclasses.
- *
- * Parameters:
- * resp - {<OpenLayers.Protocol.Response>} The response object to pass to
- * any user callback.
- * options - {Object} The user options passed to the create call.
- */
- handleCreate: function(resp, options) {
- this.handleResponse(resp, options);
- },
- /**
- * APIMethod: update
- * Construct a request updating modified feature.
- *
- * Parameters:
- * feature - {<OpenLayers.Feature.Vector>}
- * options - {Object} Optional object for configuring the request.
- * This object is modified and should not be reused.
- *
- * Returns:
- * {<OpenLayers.Protocol.Response>} An <OpenLayers.Protocol.Response>
- * object, whose "priv" property references the HTTP request, this
- * object is also passed to the callback function when the request
- * completes, its "features" property is then populated with the
- * the feature received from the server.
- */
- update: function(feature, options) {
- options = options || {};
- var url = options.url ||
- feature.url ||
- this.options.url + "/" + feature.fid;
- options = OpenLayers.Util.applyDefaults(options, this.options);
- var resp = new OpenLayers.Protocol.Response({
- reqFeatures: feature,
- requestType: "update"
- });
- resp.priv = OpenLayers.Request.PUT({
- url: url,
- callback: this.createCallback(this.handleUpdate, resp, options),
- headers: options.headers,
- data: this.format.write(feature)
- });
- return resp;
- },
- /**
- * Method: handleUpdate
- * Called the the request issued by <update> is complete. May be overridden
- * by subclasses.
- *
- * Parameters:
- * resp - {<OpenLayers.Protocol.Response>} The response object to pass to
- * any user callback.
- * options - {Object} The user options passed to the update call.
- */
- handleUpdate: function(resp, options) {
- this.handleResponse(resp, options);
- },
- /**
- * APIMethod: delete
- * Construct a request deleting a removed feature.
- *
- * Parameters:
- * feature - {<OpenLayers.Feature.Vector>}
- * options - {Object} Optional object for configuring the request.
- * This object is modified and should not be reused.
- *
- * Returns:
- * {<OpenLayers.Protocol.Response>} An <OpenLayers.Protocol.Response>
- * object, whose "priv" property references the HTTP request, this
- * object is also passed to the callback function when the request
- * completes.
- */
- "delete": function(feature, options) {
- options = options || {};
- var url = options.url ||
- feature.url ||
- this.options.url + "/" + feature.fid;
- options = OpenLayers.Util.applyDefaults(options, this.options);
- var resp = new OpenLayers.Protocol.Response({
- reqFeatures: feature,
- requestType: "delete"
- });
- resp.priv = OpenLayers.Request.DELETE({
- url: url,
- callback: this.createCallback(this.handleDelete, resp, options),
- headers: options.headers
- });
- return resp;
- },
- /**
- * Method: handleDelete
- * Called the the request issued by <delete> is complete. May be overridden
- * by subclasses.
- *
- * Parameters:
- * resp - {<OpenLayers.Protocol.Response>} The response object to pass to
- * any user callback.
- * options - {Object} The user options passed to the delete call.
- */
- handleDelete: function(resp, options) {
- this.handleResponse(resp, options);
- },
- /**
- * Method: handleResponse
- * Called by CRUD specific handlers.
- *
- * Parameters:
- * resp - {<OpenLayers.Protocol.Response>} The response object to pass to
- * any user callback.
- * options - {Object} The user options passed to the create, read, update,
- * or delete call.
- */
- handleResponse: function(resp, options) {
- var request = resp.priv;
- if(options.callback) {
- if(request.status >= 200 && request.status < 300) {
- // success
- if(resp.requestType != "delete") {
- resp.features = this.parseFeatures(request);
- }
- resp.code = OpenLayers.Protocol.Response.SUCCESS;
- } else {
- // failure
- resp.code = OpenLayers.Protocol.Response.FAILURE;
- }
- options.callback.call(options.scope, resp);
- }
- },
- /**
- * 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);
- },
- /**
- * APIMethod: commit
- * Iterate over each feature and take action based on the feature state.
- * Possible actions are create, update and delete.
- *
- * Parameters:
- * features - {Array({<OpenLayers.Feature.Vector>})}
- * options - {Object} Optional object for setting up intermediate commit
- * callbacks.
- *
- * Valid options:
- * create - {Object} Optional object to be passed to the <create> method.
- * update - {Object} Optional object to be passed to the <update> method.
- * delete - {Object} Optional object to be passed to the <delete> method.
- * callback - {Function} Optional function to be called when the commit
- * is complete.
- * scope - {Object} Optional object to be set as the scope of the callback.
- *
- * Returns:
- * {Array(<OpenLayers.Protocol.Response>)} An array of response objects,
- * one per request made to the server, each object's "priv" property
- * references the corresponding HTTP request.
- */
- commit: function(features, options) {
- options = OpenLayers.Util.applyDefaults(options, this.options);
- var resp = [], nResponses = 0;
-
- // Divide up features before issuing any requests. This properly
- // counts requests in the event that any responses come in before
- // all requests have been issued.
- var types = {};
- types[OpenLayers.State.INSERT] = [];
- types[OpenLayers.State.UPDATE] = [];
- types[OpenLayers.State.DELETE] = [];
- var feature, list, requestFeatures = [];
- for(var i=0, len=features.length; i<len; ++i) {
- feature = features[i];
- list = types[feature.state];
- if(list) {
- list.push(feature);
- requestFeatures.push(feature);
- }
- }
- // tally up number of requests
- var nRequests = (types[OpenLayers.State.INSERT].length > 0 ? 1 : 0) +
- types[OpenLayers.State.UPDATE].length +
- types[OpenLayers.State.DELETE].length;
-
- // This response will be sent to the final callback after all the others
- // have been fired.
- var success = true;
- var finalResponse = new OpenLayers.Protocol.Response({
- reqFeatures: requestFeatures
- });
-
- function insertCallback(response) {
- var len = response.features ? response.features.length : 0;
- var fids = new Array(len);
- for(var i=0; i<len; ++i) {
- fids[i] = response.features[i].fid;
- }
- finalResponse.insertIds = fids;
- callback.apply(this, [response]);
- }
-
- function callback(response) {
- this.callUserCallback(response, options);
- success = success && response.success();
- nResponses++;
- if (nResponses >= nRequests) {
- if (options.callback) {
- finalResponse.code = success ?
- OpenLayers.Protocol.Response.SUCCESS :
- OpenLayers.Protocol.Response.FAILURE;
- options.callback.apply(options.scope, [finalResponse]);
- }
- }
- }
- // start issuing requests
- var queue = types[OpenLayers.State.INSERT];
- if(queue.length > 0) {
- resp.push(this.create(
- queue, OpenLayers.Util.applyDefaults(
- {callback: insertCallback, scope: this}, options.create
- )
- ));
- }
- queue = types[OpenLayers.State.UPDATE];
- for(var i=queue.length-1; i>=0; --i) {
- resp.push(this.update(
- queue[i], OpenLayers.Util.applyDefaults(
- {callback: callback, scope: this}, options.update
- ))
- );
- }
- queue = types[OpenLayers.State.DELETE];
- for(var i=queue.length-1; i>=0; --i) {
- resp.push(this["delete"](
- queue[i], OpenLayers.Util.applyDefaults(
- {callback: callback, scope: this}, options["delete"]
- ))
- );
- }
- return resp;
- },
- /**
- * APIMethod: abort
- * Abort an ongoing request, the response object passed to
- * this method must come from this HTTP protocol (as a result
- * of a create, read, update, delete or commit operation).
- *
- * Parameters:
- * response - {<OpenLayers.Protocol.Response>}
- */
- abort: function(response) {
- if (response) {
- response.priv.abort();
- }
- },
- /**
- * Method: callUserCallback
- * This method is used from within the commit method each time an
- * an HTTP response is received from the server, it is responsible
- * for calling the user-supplied callbacks.
- *
- * Parameters:
- * resp - {<OpenLayers.Protocol.Response>}
- * options - {Object} The map of options passed to the commit call.
- */
- callUserCallback: function(resp, options) {
- var opt = options[resp.requestType];
- if(opt && opt.callback) {
- opt.callback.call(opt.scope, resp);
- }
- },
- CLASS_NAME: "OpenLayers.Protocol.HTTP"
- });
|