|
/* Copyright (c) 2006-2010 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/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 |
|
*/ |
|
|
|
/** |
|
* 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, |
|
|
|
/** |
|
* 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); |
|
}, |
|
|
|
/** |
|
* APIMethod: destroy |
|
* Clean up the protocol. |
|
*/ |
|
destroy: function() { |
|
this.params = null; |
|
this.headers = null; |
|
OpenLayers.Protocol.prototype.destroy.apply(this); |
|
}, |
|
|
|
/** |
|
* 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 = OpenLayers.Util.applyDefaults(options, this.options); |
|
options.params = OpenLayers.Util.applyDefaults( |
|
options.params, this.options.params); |
|
if(options.filter) { |
|
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); |
|
}, |
|
|
|
/** |
|
* Method: filterToParams |
|
* Convert an <OpenLayers.Filter> object to parameters. |
|
* |
|
* Parameters: |
|
* filter - {OpenLayers.Filter} filter to convert. |
|
* params - {Object} The parameters object. |
|
* |
|
* Returns: |
|
* {Object} The resulting parameters object. |
|
*/ |
|
filterToParams: function(filter, params) { |
|
params = params || {}; |
|
var className = filter.CLASS_NAME; |
|
var filterType = className.substring(className.lastIndexOf(".") + 1); |
|
switch(filterType) { |
|
case "Spatial": |
|
switch(filter.type) { |
|
case OpenLayers.Filter.Spatial.BBOX: |
|
params.bbox = filter.value.toArray(); |
|
break; |
|
case OpenLayers.Filter.Spatial.DWITHIN: |
|
params.tolerance = filter.distance; |
|
// no break here |
|
case OpenLayers.Filter.Spatial.WITHIN: |
|
params.lon = filter.value.x; |
|
params.lat = filter.value.y; |
|
break; |
|
default: |
|
OpenLayers.Console.warn( |
|
"Unknown spatial filter type " + filter.type); |
|
} |
|
break; |
|
case "Comparison": |
|
var op = OpenLayers.Protocol.HTTP.COMP_TYPE_TO_OP_STR[filter.type]; |
|
if(op !== undefined) { |
|
var value = filter.value; |
|
if(filter.type == OpenLayers.Filter.Comparison.LIKE) { |
|
value = this.regex2value(value); |
|
if(this.wildcarded) { |
|
value = "%" + value + "%"; |
|
} |
|
} |
|
params[filter.property + "__" + op] = value; |
|
params.queryable = params.queryable || []; |
|
params.queryable.push(filter.property); |
|
} else { |
|
OpenLayers.Console.warn( |
|
"Unknown comparison filter type " + filter.type); |
|
} |
|
break; |
|
case "Logical": |
|
if(filter.type === OpenLayers.Filter.Logical.AND) { |
|
for(var i=0,len=filter.filters.length; i<len; i++) { |
|
params = this.filterToParams(filter.filters[i], params); |
|
} |
|
} else { |
|
OpenLayers.Console.warn( |
|
"Unsupported logical filter type " + filter.type); |
|
} |
|
break; |
|
default: |
|
OpenLayers.Console.warn("Unknown filter type " + filterType); |
|
} |
|
return params; |
|
}, |
|
|
|
/** |
|
* Method: regex2value |
|
* Convert the value from a regular expression string to a LIKE/ILIKE |
|
* string known to the web service. |
|
* |
|
* Parameters: |
|
* value - {String} The regex string. |
|
* |
|
* Returns: |
|
* {String} The converted string. |
|
*/ |
|
regex2value: function(value) { |
|
|
|
// highly sensitive!! Do not change this without running the |
|
// Protocol/HTTP.html unit tests |
|
|
|
// convert % to \% |
|
value = value.replace(/%/g, "\\%"); |
|
|
|
// convert \\. to \\_ (\\.* occurences converted later) |
|
value = value.replace(/\\\\\.(\*)?/g, function($0, $1) { |
|
return $1 ? $0 : "\\\\_"; |
|
}); |
|
|
|
// convert \\.* to \\% |
|
value = value.replace(/\\\\\.\*/g, "\\\\%"); |
|
|
|
// convert . to _ (\. and .* occurences converted later) |
|
value = value.replace(/(\\)?\.(\*)?/g, function($0, $1, $2) { |
|
return $1 || $2 ? $0 : "_"; |
|
}); |
|
|
|
// convert .* to % (\.* occurnces converted later) |
|
value = value.replace(/(\\)?\.\*/g, function($0, $1) { |
|
return $1 ? $0 : "%"; |
|
}); |
|
|
|
// convert \. to . |
|
value = value.replace(/\\\./g, "."); |
|
|
|
// replace \* with * (watching out for \\*) |
|
value = value.replace(/(\\)?\\\*/g, function($0, $1) { |
|
return $1 ? $0 : "*"; |
|
}); |
|
|
|
return value; |
|
}, |
|
|
|
/** |
|
* 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({ |