Merge pull request #632 from ahocevar/wps-client
WPS Client. r=@bartvde,@tschaub
This commit is contained in:
@@ -0,0 +1,31 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
|
||||||
|
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||||
|
<title>OpenLayers WPS Client Example</title>
|
||||||
|
<link rel="stylesheet" href="../theme/default/style.css" type="text/css">
|
||||||
|
<link rel="stylesheet" href="style.css" type="text/css">
|
||||||
|
<script src="../lib/OpenLayers.js"></script>
|
||||||
|
<script src="wps-client.js"></script>
|
||||||
|
</head>
|
||||||
|
<body onload="init()">
|
||||||
|
<h1 id="title">WPS Client Example</h1>
|
||||||
|
|
||||||
|
<div id="tags">
|
||||||
|
wps
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="shortdesc">Shows the usage of the WPS Client</div>
|
||||||
|
|
||||||
|
<div id="map" class="smallmap"></div>
|
||||||
|
|
||||||
|
<div id="docs">
|
||||||
|
<p>This example shows how simple it is to use the WPS Client. It
|
||||||
|
buffers an intersection of a geometry and a feature, which is
|
||||||
|
accomplished by chaining two processes. See
|
||||||
|
<a href="wps-client.js">wps-client.js</a> to see how this is done.</p>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,75 @@
|
|||||||
|
OpenLayers.ProxyHost = 'proxy.cgi?url=';
|
||||||
|
|
||||||
|
var map, client, intersect, buffer;
|
||||||
|
|
||||||
|
function init() {
|
||||||
|
|
||||||
|
map = new OpenLayers.Map('map', {
|
||||||
|
allOverlays: true,
|
||||||
|
center: [114, 16],
|
||||||
|
zoom: 4,
|
||||||
|
layers: [new OpenLayers.Layer.Vector()]
|
||||||
|
});
|
||||||
|
|
||||||
|
var features = [new OpenLayers.Feature.Vector(OpenLayers.Geometry.fromWKT(
|
||||||
|
'LINESTRING(117 22,112 18,118 13, 115 8)'
|
||||||
|
))];
|
||||||
|
var geometry = OpenLayers.Geometry.fromWKT(
|
||||||
|
'POLYGON((110 20,120 20,120 10,110 10,110 20),(112 17,118 18,118 16,112 15,112 17))'
|
||||||
|
);
|
||||||
|
|
||||||
|
map.baseLayer.addFeatures(features);
|
||||||
|
map.baseLayer.addFeatures([new OpenLayers.Feature.Vector(geometry)]);
|
||||||
|
|
||||||
|
client = new OpenLayers.WPSClient({
|
||||||
|
servers: {
|
||||||
|
opengeo: 'http://demo.opengeo.org/geoserver/wps'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Create a process and configure it
|
||||||
|
intersect = client.getProcess('opengeo', 'JTS:intersection');
|
||||||
|
intersect.configure({
|
||||||
|
// spatial input can be a feature or a geometry or an array of
|
||||||
|
// features or geometries
|
||||||
|
inputs: {
|
||||||
|
a: features,
|
||||||
|
b: geometry
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Create another process which chains the previous one and execute it
|
||||||
|
buffer = client.getProcess('opengeo', 'JTS:buffer');
|
||||||
|
buffer.execute({
|
||||||
|
inputs: {
|
||||||
|
geom: intersect.output(),
|
||||||
|
distance: 1
|
||||||
|
},
|
||||||
|
success: function(outputs) {
|
||||||
|
// outputs.result is a feature or an array of features for spatial
|
||||||
|
// processes.
|
||||||
|
map.baseLayer.addFeatures(outputs.result);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Instead of creating a process and executing it, we could call execute on
|
||||||
|
// the client directly if we are only dealing with a single process:
|
||||||
|
/*
|
||||||
|
client.execute({
|
||||||
|
server: "opengeo",
|
||||||
|
process: "JTS:intersection",
|
||||||
|
// spatial input can be a feature or a geometry or an array of
|
||||||
|
// features or geometries
|
||||||
|
inputs: {
|
||||||
|
a: features,
|
||||||
|
b: geometry
|
||||||
|
},
|
||||||
|
success: function(outputs) {
|
||||||
|
// outputs.result is a feature or an array of features for spatial
|
||||||
|
// processes.
|
||||||
|
map.baseLayer.addFeatures(outputs.result);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
*/
|
||||||
|
|
||||||
|
}
|
||||||
+3
-1
@@ -50,7 +50,9 @@
|
|||||||
<p>This example shows WPS in action by using the WPSCapabilities,
|
<p>This example shows WPS in action by using the WPSCapabilities,
|
||||||
WPSDescribeProcess and WPSExecute formats. See
|
WPSDescribeProcess and WPSExecute formats. See
|
||||||
<a target="_blank" href="wps.js">wps.js</a> for the
|
<a target="_blank" href="wps.js">wps.js</a> for the
|
||||||
source code.</p>
|
source code. <b>Note: For applications using WPS, the high level
|
||||||
|
approach shown in the <a href="wps-client.html">wps-client</a> example
|
||||||
|
is recommended instead.</b></p>
|
||||||
<ol>
|
<ol>
|
||||||
<li>Select a process from the list below the map. The list is
|
<li>Select a process from the list below the map. The list is
|
||||||
populated with the result of a WPS GetCapabilities request, parsed
|
populated with the result of a WPS GetCapabilities request, parsed
|
||||||
|
|||||||
+3
-1
@@ -394,7 +394,9 @@
|
|||||||
"OpenLayers/Symbolizer/Raster.js",
|
"OpenLayers/Symbolizer/Raster.js",
|
||||||
"OpenLayers/Lang.js",
|
"OpenLayers/Lang.js",
|
||||||
"OpenLayers/Lang/en.js",
|
"OpenLayers/Lang/en.js",
|
||||||
"OpenLayers/Spherical.js"
|
"OpenLayers/Spherical.js",
|
||||||
|
"OpenLayers/WPSClient.js",
|
||||||
|
"OpenLayers/WPSProcess.js"
|
||||||
]; // etc.
|
]; // etc.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,223 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2006-2012 by OpenLayers Contributors (see authors.txt for
|
||||||
|
* full list of contributors). Published under the 2-clause BSD license.
|
||||||
|
* See license.txt in the OpenLayers distribution or repository for the
|
||||||
|
* full text of the license.
|
||||||
|
*
|
||||||
|
* @requires OpenLayers/SingleFile.js
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @requires OpenLayers/Events.js
|
||||||
|
* @requires OpenLayers/WPSProcess.js
|
||||||
|
* @requires OpenLayers/Format/WPSDescribeProcess.js
|
||||||
|
* @requires OpenLayers/Request.js
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class: OpenLayers.WPSClient
|
||||||
|
* High level API for interaction with Web Processing Services (WPS).
|
||||||
|
* An <OpenLayers.WPSClient> instance is used to create <OpenLayers.WPSProcess>
|
||||||
|
* instances for servers known to the WPSClient. The WPSClient also caches
|
||||||
|
* DescribeProcess responses to reduce the number of requests sent to servers
|
||||||
|
* when processes are created.
|
||||||
|
*/
|
||||||
|
OpenLayers.WPSClient = OpenLayers.Class({
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Property: servers
|
||||||
|
* {Object} Service metadata, keyed by a local identifier.
|
||||||
|
*
|
||||||
|
* Properties:
|
||||||
|
* url - {String} the url of the server
|
||||||
|
* version - {String} WPS version of the server
|
||||||
|
* processDescription - {Object} Cache of raw DescribeProcess
|
||||||
|
* responses, keyed by process identifier.
|
||||||
|
*/
|
||||||
|
servers: null,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Property: version
|
||||||
|
* {String} The default WPS version to use if none is configured. Default
|
||||||
|
* is '1.0.0'.
|
||||||
|
*/
|
||||||
|
version: '1.0.0',
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Property: lazy
|
||||||
|
* {Boolean} Should the DescribeProcess be deferred until a process is
|
||||||
|
* fully configured? Default is false.
|
||||||
|
*/
|
||||||
|
lazy: false,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Property: events
|
||||||
|
* {<OpenLayers.Events>}
|
||||||
|
*
|
||||||
|
* Supported event types:
|
||||||
|
* describeprocess - Fires when the process description is available.
|
||||||
|
* Listeners receive an object with a 'raw' property holding the raw
|
||||||
|
* DescribeProcess response, and an 'identifier' property holding the
|
||||||
|
* process identifier of the described process.
|
||||||
|
*/
|
||||||
|
events: null,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor: OpenLayers.WPSClient
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* options - {Object} Object whose properties will be set on the instance.
|
||||||
|
*
|
||||||
|
* Avaliable options:
|
||||||
|
* servers - {Object} Mandatory. Service metadata, keyed by a local
|
||||||
|
* identifier. Can either be a string with the service url or an
|
||||||
|
* object literal with additional metadata:
|
||||||
|
*
|
||||||
|
* (code)
|
||||||
|
* servers: {
|
||||||
|
* local: '/geoserver/wps'
|
||||||
|
* }, {
|
||||||
|
* opengeo: {
|
||||||
|
* url: 'http://demo.opengeo.org/geoserver/wps',
|
||||||
|
* version: '1.0.0'
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* (end)
|
||||||
|
*
|
||||||
|
* lazy - {Boolean} Optional. Set to true if DescribeProcess should not be
|
||||||
|
* requested until a process is fully configured. Default is false.
|
||||||
|
*/
|
||||||
|
initialize: function(options) {
|
||||||
|
OpenLayers.Util.extend(this, options);
|
||||||
|
this.events = new OpenLayers.Events(this);
|
||||||
|
this.servers = {};
|
||||||
|
for (var s in options.servers) {
|
||||||
|
this.servers[s] = typeof options.servers[s] == 'string' ? {
|
||||||
|
url: options.servers[s],
|
||||||
|
version: this.version,
|
||||||
|
processDescription: {}
|
||||||
|
} : options.servers[s];
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* APIMethod: execute
|
||||||
|
* Shortcut to execute a process with a single function call. This is
|
||||||
|
* equivalent to using <getProcess> and then calling execute on the
|
||||||
|
* process.
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* options - {Object} Options for the execute operation.
|
||||||
|
*
|
||||||
|
* Available options:
|
||||||
|
* server - {String} Mandatory. One of the local identifiers of the
|
||||||
|
* configured servers.
|
||||||
|
* process - {String} Mandatory. A process identifier known to the
|
||||||
|
* server.
|
||||||
|
* inputs - {Object} The inputs for the process, keyed by input identifier.
|
||||||
|
* For spatial data inputs, the value of an input is usually an
|
||||||
|
* <OpenLayers.Geometry>, an <OpenLayers.Feature.Vector> or an array of
|
||||||
|
* geometries or features.
|
||||||
|
* output - {String} The identifier of an output to parse. Optional. If not
|
||||||
|
* provided, the first output will be parsed.
|
||||||
|
* success - {Function} Callback to call when the process is complete.
|
||||||
|
* This function is called with an outputs object as argument, which
|
||||||
|
* will have a property with the identifier of the requested output
|
||||||
|
* (e.g. 'result'). For processes that generate spatial output, the
|
||||||
|
* value will either be a single <OpenLayers.Feature.Vector> or an
|
||||||
|
* array of features.
|
||||||
|
* scope - {Object} Optional scope for the success callback.
|
||||||
|
*/
|
||||||
|
execute: function(options) {
|
||||||
|
var process = this.getProcess(options.server, options.process);
|
||||||
|
process.execute({
|
||||||
|
inputs: options.inputs,
|
||||||
|
success: options.success,
|
||||||
|
scope: options.scope
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* APIMethod: getProcess
|
||||||
|
* Creates an <OpenLayers.WPSProcess>.
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* serverID - {String} Local identifier from the servers that this instance
|
||||||
|
* was constructed with.
|
||||||
|
* processID - {String} Process identifier known to the server.
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
* {<OpenLayers.WPSProcess>}
|
||||||
|
*/
|
||||||
|
getProcess: function(serverID, processID) {
|
||||||
|
var process = new OpenLayers.WPSProcess({
|
||||||
|
client: this,
|
||||||
|
server: serverID,
|
||||||
|
identifier: processID
|
||||||
|
});
|
||||||
|
if (!this.lazy) {
|
||||||
|
process.describe();
|
||||||
|
}
|
||||||
|
return process;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method: describeProcess
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* serverID - {String} Identifier of the server
|
||||||
|
* processID - {String} Identifier of the requested process
|
||||||
|
* callback - {Function} Callback to call when the description is available
|
||||||
|
* scope - {Object} Optional execution scope for the callback function
|
||||||
|
*/
|
||||||
|
describeProcess: function(serverID, processID, callback, scope) {
|
||||||
|
var server = this.servers[serverID];
|
||||||
|
if (!server.processDescription[processID]) {
|
||||||
|
if (!(processID in server.processDescription)) {
|
||||||
|
// set to null so we know a describeFeature request is pending
|
||||||
|
server.processDescription[processID] = null;
|
||||||
|
OpenLayers.Request.GET({
|
||||||
|
url: server.url,
|
||||||
|
params: {
|
||||||
|
SERVICE: 'WPS',
|
||||||
|
VERSION: server.version,
|
||||||
|
REQUEST: 'DescribeProcess',
|
||||||
|
IDENTIFIER: processID
|
||||||
|
},
|
||||||
|
success: function(response) {
|
||||||
|
server.processDescription[processID] = response.responseText;
|
||||||
|
this.events.triggerEvent('describeprocess', {
|
||||||
|
identifier: processID,
|
||||||
|
raw: response.responseText
|
||||||
|
});
|
||||||
|
},
|
||||||
|
scope: this
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// pending request
|
||||||
|
this.events.register('describeprocess', this, function describe(evt) {
|
||||||
|
if (evt.identifier === processID) {
|
||||||
|
this.events.unregister('describeprocess', this, describe);
|
||||||
|
callback.call(scope, evt.raw);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
window.setTimeout(function() {
|
||||||
|
callback.call(scope, server.processDescription[processID]);
|
||||||
|
}, 0);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method: destroy
|
||||||
|
*/
|
||||||
|
destroy: function() {
|
||||||
|
this.events.destroy();
|
||||||
|
this.events = null;
|
||||||
|
this.servers = null;
|
||||||
|
},
|
||||||
|
|
||||||
|
CLASS_NAME: 'OpenLayers.WPSClient'
|
||||||
|
|
||||||
|
});
|
||||||
@@ -0,0 +1,501 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2006-2012 by OpenLayers Contributors (see authors.txt for
|
||||||
|
* full list of contributors). Published under the 2-clause BSD license.
|
||||||
|
* See license.txt in the OpenLayers distribution or repository for the
|
||||||
|
* full text of the license.
|
||||||
|
*
|
||||||
|
* @requires OpenLayers/SingleFile.js
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @requires OpenLayers/Geometry.js
|
||||||
|
* @requires OpenLayers/Feature/Vector.js
|
||||||
|
* @requires OpenLayers/Format/WKT.js
|
||||||
|
* @requires OpenLayers/Format/GeoJSON.js
|
||||||
|
* @requires OpenLayers/Format/WPSExecute.js
|
||||||
|
* @requires OpenLayers/Request.js
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class: OpenLayers.WPSProcess
|
||||||
|
* Representation of a WPS process. Usually instances of
|
||||||
|
* <OpenLayers.WPSProcess> are created by calling 'getProcess' on an
|
||||||
|
* <OpenLayers.WPSClient> instance.
|
||||||
|
*
|
||||||
|
* Currently <OpenLayers.WPSProcess> supports processes that have geometries
|
||||||
|
* or features as output, using WKT or GeoJSON as output format. It also
|
||||||
|
* supports chaining of processes by using the <output> method to create a
|
||||||
|
* handle that is used as process input instead of a static value.
|
||||||
|
*/
|
||||||
|
OpenLayers.WPSProcess = OpenLayers.Class({
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Property: client
|
||||||
|
* {<OpenLayers.WPSClient>} The client that manages this process.
|
||||||
|
*/
|
||||||
|
client: null,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Property: server
|
||||||
|
* {String} Local client identifier for this process's server.
|
||||||
|
*/
|
||||||
|
server: null,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Property: identifier
|
||||||
|
* {String} Process identifier known to the server.
|
||||||
|
*/
|
||||||
|
identifier: null,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Property: description
|
||||||
|
* {Object} DescribeProcess response for this process.
|
||||||
|
*/
|
||||||
|
description: null,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* APIProperty: localWPS
|
||||||
|
* {String} Service endpoint for locally chained WPS processes. Default is
|
||||||
|
* 'http://geoserver/wps'.
|
||||||
|
*/
|
||||||
|
localWPS: 'http://geoserver/wps',
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Property: formats
|
||||||
|
* {Object} OpenLayers.Format instances keyed by mimetype.
|
||||||
|
*/
|
||||||
|
formats: null,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Property: chained
|
||||||
|
* {Integer} Number of chained processes for pending execute requests that
|
||||||
|
* don't have a full configuration yet.
|
||||||
|
*/
|
||||||
|
chained: 0,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Property: executeCallbacks
|
||||||
|
* {Array} Callbacks waiting to be executed until all chained processes
|
||||||
|
* are configured;
|
||||||
|
*/
|
||||||
|
executeCallbacks: null,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor: OpenLayers.WPSProcess
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* options - {Object} Object whose properties will be set on the instance.
|
||||||
|
*
|
||||||
|
* Avaliable options:
|
||||||
|
* client - {<OpenLayers.WPSClient>} Mandatory. Client that manages this
|
||||||
|
* process.
|
||||||
|
* server - {String} Mandatory. Local client identifier of this process's
|
||||||
|
* server.
|
||||||
|
* identifier - {String} Mandatory. Process identifier known to the server.
|
||||||
|
*/
|
||||||
|
initialize: function(options) {
|
||||||
|
OpenLayers.Util.extend(this, options);
|
||||||
|
this.executeCallbacks = [];
|
||||||
|
this.formats = {
|
||||||
|
'application/wkt': new OpenLayers.Format.WKT(),
|
||||||
|
'application/json': new OpenLayers.Format.GeoJSON()
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method: describe
|
||||||
|
* Makes the client issue a DescribeProcess request asynchronously.
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* options - {Object} Configuration for the method call
|
||||||
|
*
|
||||||
|
* Available options:
|
||||||
|
* callback - {Function} Callback to execute when the description is
|
||||||
|
* available. Will be called with the parsed description as argument.
|
||||||
|
* Optional.
|
||||||
|
* scope - {Object} The scope in which the callback will be executed.
|
||||||
|
* Default is the global object.
|
||||||
|
*/
|
||||||
|
describe: function(options) {
|
||||||
|
options = options || {};
|
||||||
|
if (!this.description) {
|
||||||
|
this.client.describeProcess(this.server, this.identifier, function(description) {
|
||||||
|
if (!this.description) {
|
||||||
|
this.parseDescription(description);
|
||||||
|
}
|
||||||
|
if (options.callback) {
|
||||||
|
options.callback.call(options.scope, this.description);
|
||||||
|
}
|
||||||
|
}, this);
|
||||||
|
} else if (options.callback) {
|
||||||
|
var description = this.description;
|
||||||
|
window.setTimeout(function() {
|
||||||
|
options.callback.call(options.scope, description);
|
||||||
|
}, 0);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* APIMethod: configure
|
||||||
|
* Configure the process, but do not execute it. Use this for processes
|
||||||
|
* that are chained as input of a different process by means of the
|
||||||
|
* <output> method.
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* options - {Object}
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
* {<OpenLayers.WPSProcess>} this process.
|
||||||
|
*
|
||||||
|
* Available options:
|
||||||
|
* inputs - {Object} The inputs for the process, keyed by input identifier.
|
||||||
|
* For spatial data inputs, the value of an input is usually an
|
||||||
|
* <OpenLayers.Geometry>, an <OpenLayers.Feature.Vector> or an array of
|
||||||
|
* geometries or features.
|
||||||
|
* callback - {Function} Callback to call when the configuration is
|
||||||
|
* complete. Optional.
|
||||||
|
* scope - {Object} Optional scope for the callback.
|
||||||
|
*/
|
||||||
|
configure: function(options) {
|
||||||
|
this.describe({
|
||||||
|
callback: function() {
|
||||||
|
var description = this.description,
|
||||||
|
inputs = options.inputs,
|
||||||
|
input, i, ii;
|
||||||
|
for (i=0, ii=description.dataInputs.length; i<ii; ++i) {
|
||||||
|
input = description.dataInputs[i];
|
||||||
|
this.setInputData(input, inputs[input.identifier]);
|
||||||
|
}
|
||||||
|
if (options.callback) {
|
||||||
|
options.callback.call(options.scope);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
scope: this
|
||||||
|
});
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* APIMethod: execute
|
||||||
|
* Configures and executes the process
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* options - {Object}
|
||||||
|
*
|
||||||
|
* Available options:
|
||||||
|
* inputs - {Object} The inputs for the process, keyed by input identifier.
|
||||||
|
* For spatial data inputs, the value of an input is usually an
|
||||||
|
* <OpenLayers.Geometry>, an <OpenLayers.Feature.Vector> or an array of
|
||||||
|
* geometries or features.
|
||||||
|
* output - {String} The identifier of the output to request and parse.
|
||||||
|
* Optional. If not provided, the first output will be requested.
|
||||||
|
* success - {Function} Callback to call when the process is complete.
|
||||||
|
* This function is called with an outputs object as argument, which
|
||||||
|
* will have a property with the identifier of the requested output
|
||||||
|
* (or 'result' if output was not configured). For processes that
|
||||||
|
* generate spatial output, the value will be an array of
|
||||||
|
* <OpenLayers.Feature.Vector> instances.
|
||||||
|
* scope - {Object} Optional scope for the success callback.
|
||||||
|
*/
|
||||||
|
execute: function(options) {
|
||||||
|
this.configure({
|
||||||
|
inputs: options.inputs,
|
||||||
|
callback: function() {
|
||||||
|
var me = this;
|
||||||
|
//TODO For now we only deal with a single output
|
||||||
|
var outputIndex = this.getOutputIndex(
|
||||||
|
me.description.processOutputs, options.output
|
||||||
|
);
|
||||||
|
me.setResponseForm({outputIndex: outputIndex});
|
||||||
|
(function callback() {
|
||||||
|
OpenLayers.Util.removeItem(me.executeCallbacks, callback);
|
||||||
|
if (me.chained !== 0) {
|
||||||
|
// need to wait until chained processes have a
|
||||||
|
// description and configuration - see chainProcess
|
||||||
|
me.executeCallbacks.push(callback);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// all chained processes are added as references now, so
|
||||||
|
// let's proceed.
|
||||||
|
OpenLayers.Request.POST({
|
||||||
|
url: me.client.servers[me.server].url,
|
||||||
|
data: new OpenLayers.Format.WPSExecute().write(me.description),
|
||||||
|
success: function(response) {
|
||||||
|
var output = me.description.processOutputs[outputIndex];
|
||||||
|
var mimeType = me.findMimeType(
|
||||||
|
output.complexOutput.supported.formats
|
||||||
|
);
|
||||||
|
//TODO For now we assume a spatial output
|
||||||
|
var features = me.formats[mimeType].read(response.responseText);
|
||||||
|
if (features instanceof OpenLayers.Feature.Vector) {
|
||||||
|
features = [features];
|
||||||
|
}
|
||||||
|
if (options.success) {
|
||||||
|
var outputs = {};
|
||||||
|
outputs[options.output || 'result'] = features;
|
||||||
|
options.success.call(options.scope, outputs);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
scope: me
|
||||||
|
});
|
||||||
|
})();
|
||||||
|
},
|
||||||
|
scope: this
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* APIMethod: output
|
||||||
|
* Chain an output of a configured process (see <configure>) as input to
|
||||||
|
* another process.
|
||||||
|
*
|
||||||
|
* (code)
|
||||||
|
* intersect = client.getProcess('opengeo', 'JTS:intersection');
|
||||||
|
* intersect.configure({
|
||||||
|
* // ...
|
||||||
|
* });
|
||||||
|
* buffer = client.getProcess('opengeo', 'JTS:buffer');
|
||||||
|
* buffer.execute({
|
||||||
|
* inputs: {
|
||||||
|
* geom: intersect.output('result'), // <-- here we're chaining
|
||||||
|
* distance: 1
|
||||||
|
* },
|
||||||
|
* // ...
|
||||||
|
* });
|
||||||
|
* (end)
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* identifier - {String} Identifier of the output that we're chaining. If
|
||||||
|
* not provided, the first output will be used.
|
||||||
|
*/
|
||||||
|
output: function(identifier) {
|
||||||
|
return new OpenLayers.WPSProcess.ChainLink({
|
||||||
|
process: this,
|
||||||
|
output: identifier
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method: parseDescription
|
||||||
|
* Parses the DescribeProcess response
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* description - {Object}
|
||||||
|
*/
|
||||||
|
parseDescription: function(description) {
|
||||||
|
var server = this.client.servers[this.server];
|
||||||
|
this.description = new OpenLayers.Format.WPSDescribeProcess()
|
||||||
|
.read(server.processDescription[this.identifier])
|
||||||
|
.processDescriptions[this.identifier];
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method: setInputData
|
||||||
|
* Sets the data for a single input
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* input - {Object} An entry from the dataInputs array of the process
|
||||||
|
* description.
|
||||||
|
* data - {Mixed} For spatial data inputs, this is usually an
|
||||||
|
* <OpenLayers.Geometry>, an <OpenLayers.Feature.Vector> or an array of
|
||||||
|
* geometries or features.
|
||||||
|
*/
|
||||||
|
setInputData: function(input, data) {
|
||||||
|
// clear any previous data
|
||||||
|
delete input.data;
|
||||||
|
delete input.reference;
|
||||||
|
if (data instanceof OpenLayers.WPSProcess.ChainLink) {
|
||||||
|
++this.chained;
|
||||||
|
input.reference = {
|
||||||
|
method: 'POST',
|
||||||
|
href: data.process.server === this.server ?
|
||||||
|
this.localWPS : this.client.servers[data.process.server].url
|
||||||
|
};
|
||||||
|
data.process.describe({
|
||||||
|
callback: function() {
|
||||||
|
--this.chained;
|
||||||
|
this.chainProcess(input, data);
|
||||||
|
},
|
||||||
|
scope: this
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
input.data = {};
|
||||||
|
var complexData = input.complexData;
|
||||||
|
if (complexData) {
|
||||||
|
var format = this.findMimeType(complexData.supported.formats);
|
||||||
|
input.data.complexData = {
|
||||||
|
mimeType: format,
|
||||||
|
value: this.formats[format].write(this.toFeatures(data))
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
input.data.literalData = {
|
||||||
|
value: data
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method: setResponseForm
|
||||||
|
* Sets the responseForm property of the <execute> payload.
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* options - {Object} See below.
|
||||||
|
*
|
||||||
|
* Available options:
|
||||||
|
* outputIndex - {Integer} The index of the output to use. Optional.
|
||||||
|
* supportedFormats - {Object} Object with supported mime types as key,
|
||||||
|
* and true as value for supported types. Optional.
|
||||||
|
*/
|
||||||
|
setResponseForm: function(options) {
|
||||||
|
options = options || {};
|
||||||
|
output = this.description.processOutputs[options.outputIndex || 0];
|
||||||
|
this.description.responseForm = {
|
||||||
|
rawDataOutput: {
|
||||||
|
identifier: output.identifier,
|
||||||
|
mimeType: this.findMimeType(output.complexOutput.supported.formats, options.supportedFormats)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method: getOutputIndex
|
||||||
|
* Gets the index of a processOutput by its identifier
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* outputs - {Array} The processOutputs array to look at
|
||||||
|
* identifier - {String} The identifier of the output
|
||||||
|
*
|
||||||
|
* Returns
|
||||||
|
* {Integer} The index of the processOutput with the provided identifier
|
||||||
|
* in the outputs array.
|
||||||
|
*/
|
||||||
|
getOutputIndex: function(outputs, identifier) {
|
||||||
|
var output;
|
||||||
|
if (identifier) {
|
||||||
|
for (var i=outputs.length-1; i>=0; --i) {
|
||||||
|
if (outputs[i].identifier === identifier) {
|
||||||
|
output = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
output = 0;
|
||||||
|
}
|
||||||
|
return output;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method: chainProcess
|
||||||
|
* Sets a fully configured chained process as input for this process.
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* input - {Object} The dataInput that the chained process provides.
|
||||||
|
* chainLink - {<OpenLayers.WPSProcess.ChainLink>} The process to chain.
|
||||||
|
*/
|
||||||
|
chainProcess: function(input, chainLink) {
|
||||||
|
var output = this.getOutputIndex(
|
||||||
|
chainLink.process.description.processOutputs, chainLink.output
|
||||||
|
);
|
||||||
|
input.reference.mimeType = this.findMimeType(
|
||||||
|
input.complexData.supported.formats,
|
||||||
|
chainLink.process.description.processOutputs[output].complexOutput.supported.formats
|
||||||
|
);
|
||||||
|
var formats = {};
|
||||||
|
formats[input.reference.mimeType] = true;
|
||||||
|
chainLink.process.setResponseForm({
|
||||||
|
outputIndex: output,
|
||||||
|
supportedFormats: formats
|
||||||
|
});
|
||||||
|
input.reference.body = chainLink.process.description;
|
||||||
|
while (this.executeCallbacks.length > 0) {
|
||||||
|
this.executeCallbacks[0]();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method: toFeatures
|
||||||
|
* Converts spatial input into features so it can be processed by
|
||||||
|
* <OpenLayers.Format> instances.
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* source - {Mixed} An <OpenLayers.Geometry>, an
|
||||||
|
* <OpenLayers.Feature.Vector>, or an array of geometries or features
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
* {Array(<OpenLayers.Feature.Vector>)}
|
||||||
|
*/
|
||||||
|
toFeatures: function(source) {
|
||||||
|
var isArray = OpenLayers.Util.isArray(source);
|
||||||
|
if (!isArray) {
|
||||||
|
source = [source];
|
||||||
|
}
|
||||||
|
var target = new Array(source.length),
|
||||||
|
current;
|
||||||
|
for (var i=0, ii=source.length; i<ii; ++i) {
|
||||||
|
current = source[i];
|
||||||
|
target[i] = current instanceof OpenLayers.Feature.Vector ?
|
||||||
|
current : new OpenLayers.Feature.Vector(current);
|
||||||
|
}
|
||||||
|
return isArray ? target : target[0];
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method: findMimeType
|
||||||
|
* Finds a supported mime type.
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* sourceFormats - {Object} An object literal with mime types as key and
|
||||||
|
* true as value for supported formats.
|
||||||
|
* targetFormats - {Object} Like <sourceFormats>, but optional to check for
|
||||||
|
* supported mime types on a different target than this process.
|
||||||
|
* Default is to check against this process's supported formats.
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
* {String} A supported mime type.
|
||||||
|
*/
|
||||||
|
findMimeType: function(sourceFormats, targetFormats) {
|
||||||
|
targetFormats = targetFormats || this.formats;
|
||||||
|
for (var f in sourceFormats) {
|
||||||
|
if (f in targetFormats) {
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
CLASS_NAME: "OpenLayers.WPSProcess"
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class: OpenLayers.WPSProcess.ChainLink
|
||||||
|
* Type for chaining processes.
|
||||||
|
*/
|
||||||
|
OpenLayers.WPSProcess.ChainLink = OpenLayers.Class({
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Property: process
|
||||||
|
* {<OpenLayers.WPSProcess>} The process to chain
|
||||||
|
*/
|
||||||
|
process: null,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Property: output
|
||||||
|
* {String} The output identifier of the output we are going to use as
|
||||||
|
* input for another process.
|
||||||
|
*/
|
||||||
|
output: null,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor: OpenLayers.WPSProcess.ChainLink
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* options - {Object} Properties to set on the instance.
|
||||||
|
*/
|
||||||
|
initialize: function(options) {
|
||||||
|
OpenLayers.Util.extend(this, options);
|
||||||
|
},
|
||||||
|
|
||||||
|
CLASS_NAME: "OpenLayers.WPSProcess.ChainLink"
|
||||||
|
|
||||||
|
});
|
||||||
@@ -0,0 +1,108 @@
|
|||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<script src="OLLoader.js"></script>
|
||||||
|
<script type="text/javascript">
|
||||||
|
|
||||||
|
var client;
|
||||||
|
|
||||||
|
function test_initialize(t) {
|
||||||
|
t.plan(3);
|
||||||
|
|
||||||
|
client = new OpenLayers.WPSClient({
|
||||||
|
servers: {
|
||||||
|
local: "/geoserver/wps"
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
t.ok(client instanceof OpenLayers.WPSClient, 'creates an instance');
|
||||||
|
t.ok(client.events, 'has an events instance');
|
||||||
|
t.eq(client.servers.local.url, '/geoserver/wps', 'servers stored on instance');
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_getProcess(t) {
|
||||||
|
t.plan(4);
|
||||||
|
|
||||||
|
client = new OpenLayers.WPSClient({
|
||||||
|
servers: {
|
||||||
|
local: "/geoserver/wps"
|
||||||
|
},
|
||||||
|
lazy: true
|
||||||
|
});
|
||||||
|
|
||||||
|
var process = client.getProcess('local', 'gs:splitPolygon');
|
||||||
|
t.ok(process instanceof OpenLayers.WPSProcess, 'creates a process');
|
||||||
|
t.ok(process.client === client, 'process knows about client');
|
||||||
|
t.eq(process.server, 'local', 'process created with correct server');
|
||||||
|
t.eq(process.identifier, 'gs:splitPolygon', 'process created with correct identifier');
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_describeProcess(t) {
|
||||||
|
t.plan(6);
|
||||||
|
var log = {request: [], event: []};
|
||||||
|
var originalGET = OpenLayers.Request.GET;
|
||||||
|
OpenLayers.Request.GET = function(cfg) {
|
||||||
|
log.request.push(cfg);
|
||||||
|
}
|
||||||
|
function describe(evt) {
|
||||||
|
log.event.push(evt);
|
||||||
|
}
|
||||||
|
client.events.register('describeprocess', this, describe);
|
||||||
|
|
||||||
|
process = client.getProcess('local', 'gs:splitPolygon');
|
||||||
|
t.eq(client.servers.local.processDescription['gs:splitPolyon'], null, 'describeProcess pending');
|
||||||
|
process.describe();
|
||||||
|
t.eq(log.request.length, 1, 'describeProcess request only sent once');
|
||||||
|
log.request[0].success.call(client, {
|
||||||
|
responseText: '<?xml version="1.0" encoding="UTF-8"?><wps:ProcessDescriptions xmlns:wps="http://www.opengis.net/wps/1.0.0"></wps:ProcessDescriptions>'
|
||||||
|
});
|
||||||
|
t.eq(log.event[0].type, 'describeprocess', 'describeprocess event triggered');
|
||||||
|
t.ok(client.servers.local.processDescription['gs:splitPolygon'], 'We have a process description!');
|
||||||
|
process.describe();
|
||||||
|
t.eq(log.request.length, 1, 'describeProcess request only sent once');
|
||||||
|
t.eq(log.event.length, 1, 'describeprocess event only triggered once');
|
||||||
|
|
||||||
|
OpenLayers.Request.GET = originalGET;
|
||||||
|
client.events.unregister('describeprocess', this, describe);
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_execute(t) {
|
||||||
|
t.plan(1);
|
||||||
|
|
||||||
|
client = new OpenLayers.WPSClient({
|
||||||
|
servers: {
|
||||||
|
local: "/geoserver/wps"
|
||||||
|
},
|
||||||
|
lazy: true
|
||||||
|
});
|
||||||
|
var log = [];
|
||||||
|
client.getProcess = function() {
|
||||||
|
return {
|
||||||
|
execute: function(options) {
|
||||||
|
log.push(options);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
client.execute({inputs: 'a', success: 'b', scope: 'c'});
|
||||||
|
t.eq(log[0], {inputs: 'a', success: 'b', scope: 'c'}, "process executed with correct options");
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_destroy(t) {
|
||||||
|
t.plan(2);
|
||||||
|
client = new OpenLayers.WPSClient({
|
||||||
|
servers: {
|
||||||
|
local: "/geoserver/wps"
|
||||||
|
},
|
||||||
|
lazy: true
|
||||||
|
});
|
||||||
|
client.destroy();
|
||||||
|
t.eq(client.events, null, "Events nullified");
|
||||||
|
t.eq(client.servers, null, "Servers nullified");
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,188 @@
|
|||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<script src="OLLoader.js"></script>
|
||||||
|
<script type="text/javascript">
|
||||||
|
|
||||||
|
var wkt = new OpenLayers.Format.WKT();
|
||||||
|
var process;
|
||||||
|
var client = new OpenLayers.WPSClient({
|
||||||
|
servers: {
|
||||||
|
local: 'geoserver/wps'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
client.servers.local.processDescription = {
|
||||||
|
'JTS:intersection': '<?xml version="1.0" encoding="UTF-8"?>' +
|
||||||
|
'<wps:ProcessDescriptions xml:lang="en" service="WPS" version="1.0.0" xsi:schemaLocation="http://www.opengis.net/wps/1.0.0 http://schemas.opengis.net/wps/1.0.0/wpsAll.xsd" xmlns:wps="http://www.opengis.net/wps/1.0.0" xmlns:ows="http://www.opengis.net/ows/1.1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xlink="http://www.w3.org/1999/xlink"><ProcessDescription wps:processVersion="1.0.0" statusSupported="true" storeSupported="true"><ows:Identifier>JTS:intersection</ows:Identifier><ows:Title>Returns the intersectoin between a and b (eventually an empty collection if there is no intersection)</ows:Title><ows:Abstract>Returns the intersectoin between a and b (eventually an empty collection if there is no intersection)</ows:Abstract><DataInputs><Input maxOccurs="1" minOccurs="1"><ows:Identifier>a</ows:Identifier><ows:Title>a</ows:Title><ows:Abstract>[undescribed]</ows:Abstract><ComplexData><Default><Format><MimeType>text/xml; subtype=gml/3.1.1</MimeType></Format></Default><Supported><Format><MimeType>text/xml; subtype=gml/3.1.1</MimeType></Format><Format><MimeType>text/xml; subtype=gml/2.1.2</MimeType></Format><Format><MimeType>application/wkt</MimeType></Format><Format><MimeType>application/gml-3.1.1</MimeType></Format><Format><MimeType>application/gml-2.1.2</MimeType></Format></Supported></ComplexData></Input><Input maxOccurs="1" minOccurs="1"><ows:Identifier>b</ows:Identifier><ows:Title>b</ows:Title><ows:Abstract>[undescribed]</ows:Abstract><ComplexData><Default><Format><MimeType>text/xml; subtype=gml/3.1.1</MimeType></Format></Default><Supported><Format><MimeType>text/xml; subtype=gml/3.1.1</MimeType></Format><Format><MimeType>text/xml; subtype=gml/2.1.2</MimeType></Format><Format><MimeType>application/wkt</MimeType></Format><Format><MimeType>application/gml-3.1.1</MimeType></Format><Format><MimeType>application/gml-2.1.2</MimeType></Format></Supported></ComplexData></Input></DataInputs><ProcessOutputs><Output><ows:Identifier>result</ows:Identifier><ows:Title>Process result</ows:Title><ComplexOutput><Default><Format><MimeType>text/xml; subtype=gml/3.1.1</MimeType></Format></Default><Supported><Format><MimeType>text/xml; subtype=gml/3.1.1</MimeType></Format><Format><MimeType>text/xml; subtype=gml/2.1.2</MimeType></Format><Format><MimeType>application/wkt</MimeType></Format><Format><MimeType>application/gml-3.1.1</MimeType></Format><Format><MimeType>application/gml-2.1.2</MimeType></Format></Supported></ComplexOutput></Output></ProcessOutputs></ProcessDescription></wps:ProcessDescriptions>'
|
||||||
|
};
|
||||||
|
|
||||||
|
function test_initialize(t) {
|
||||||
|
t.plan(1);
|
||||||
|
process = new OpenLayers.WPSProcess();
|
||||||
|
t.ok(process instanceof OpenLayers.WPSProcess, 'creates an instance');
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_describe(t) {
|
||||||
|
t.plan(2);
|
||||||
|
process = client.getProcess('local', 'JTS:intersection');
|
||||||
|
var log = [];
|
||||||
|
process.describe({
|
||||||
|
callback: function(description) { log.push(description); }
|
||||||
|
});
|
||||||
|
t.delay_call(0.1, function() {
|
||||||
|
t.eq(log.length, 1, 'callback called');
|
||||||
|
t.eq(log[0].identifier, 'JTS:intersection', 'callback called with correct description');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_execute(t) {
|
||||||
|
t.plan(7);
|
||||||
|
|
||||||
|
var log = [];
|
||||||
|
var originalPOST = OpenLayers.Request.POST;
|
||||||
|
OpenLayers.Request.POST = function(cfg) {
|
||||||
|
log.push(cfg);
|
||||||
|
cfg.success.call(cfg.scope, {responseText: ''});
|
||||||
|
}
|
||||||
|
|
||||||
|
process = new OpenLayers.WPSProcess({
|
||||||
|
client: client,
|
||||||
|
server: 'local',
|
||||||
|
identifier: 'gs:splitPolygon'
|
||||||
|
});
|
||||||
|
process.description = {
|
||||||
|
dataInputs: [{
|
||||||
|
identifier: 'line',
|
||||||
|
complexData: {
|
||||||
|
supported: {
|
||||||
|
formats: {'application/wkt': true}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
identifier: 'polygon',
|
||||||
|
complexData: {
|
||||||
|
supported: {
|
||||||
|
formats: {'application/wkt': true}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}],
|
||||||
|
processOutputs: [{
|
||||||
|
identifier: 'foo',
|
||||||
|
complexOutput: {
|
||||||
|
supported: {
|
||||||
|
formats: {'application/wkt': true}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
};
|
||||||
|
var line = 'LINESTRING(117 22,112 18,118 13,115 8)';
|
||||||
|
var polygon = 'POLYGON((110 20,120 20,120 10,110 10,110 20),(112 17,118 18,118 16,112 15,112 17))';
|
||||||
|
var output = [];
|
||||||
|
function success(result) {
|
||||||
|
output.push(result);
|
||||||
|
}
|
||||||
|
// configured with output identifier
|
||||||
|
process.execute({
|
||||||
|
inputs: {
|
||||||
|
line: wkt.read(line),
|
||||||
|
polygon: wkt.read(polygon)
|
||||||
|
},
|
||||||
|
output: 'foo',
|
||||||
|
success: success
|
||||||
|
});
|
||||||
|
// configured without output identifier
|
||||||
|
process.execute({
|
||||||
|
inputs: {
|
||||||
|
line: wkt.read(line),
|
||||||
|
polygon: wkt.read(polygon)
|
||||||
|
},
|
||||||
|
success: success
|
||||||
|
});
|
||||||
|
|
||||||
|
t.delay_call(0.1, function() {
|
||||||
|
t.eq(log.length, 2, 'Two execute requests sent');
|
||||||
|
t.eq(process.description.dataInputs[0].data.complexData.value, line, 'data for first input correct');
|
||||||
|
t.eq(process.description.dataInputs[0].data.complexData.mimeType, 'application/wkt', 'format for first input correct');
|
||||||
|
t.eq(process.description.responseForm.rawDataOutput.identifier, 'foo', 'correct identifier for responseForm');
|
||||||
|
t.eq(process.description.responseForm.rawDataOutput.mimeType, 'application/wkt', 'correct format for responseForm');
|
||||||
|
t.ok('foo' in output[0], 'process result contains output with correct identifier when configured with output');
|
||||||
|
t.ok('result' in output[1], 'process result contains output with correct identifier when configured without output');
|
||||||
|
|
||||||
|
OpenLayers.Request.POST = originalPOST;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_chainProcess(t) {
|
||||||
|
t.plan(5);
|
||||||
|
|
||||||
|
var originalGET = OpenLayers.Request.GET;
|
||||||
|
OpenLayers.Request.GET = function(cfg) {
|
||||||
|
window.setTimeout(function() {
|
||||||
|
cfg.success.call(cfg.scope, {
|
||||||
|
responseText: '<?xml version="1.0" encoding="UTF-8"?>' +
|
||||||
|
'<wps:ProcessDescriptions xml:lang="en" service="WPS" version="1.0.0" xsi:schemaLocation="http://www.opengis.net/wps/1.0.0 http://schemas.opengis.net/wps/1.0.0/wpsAll.xsd" xmlns:wps="http://www.opengis.net/wps/1.0.0" xmlns:ows="http://www.opengis.net/ows/1.1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xlink="http://www.w3.org/1999/xlink"><ProcessDescription wps:processVersion="1.0.0" statusSupported="true" storeSupported="true"><ows:Identifier>JTS:buffer</ows:Identifier><ows:Title>Buffers a geometry using a certain distance</ows:Title><ows:Abstract>Buffers a geometry using a certain distance</ows:Abstract><DataInputs><Input maxOccurs="1" minOccurs="1"><ows:Identifier>geom</ows:Identifier><ows:Title>geom</ows:Title><ows:Abstract>The geometry to be buffered</ows:Abstract><ComplexData><Default><Format><MimeType>text/xml; subtype=gml/3.1.1</MimeType></Format></Default><Supported><Format><MimeType>text/xml; subtype=gml/3.1.1</MimeType></Format><Format><MimeType>text/xml; subtype=gml/2.1.2</MimeType></Format><Format><MimeType>application/wkt</MimeType></Format><Format><MimeType>application/gml-3.1.1</MimeType></Format><Format><MimeType>application/gml-2.1.2</MimeType></Format></Supported></ComplexData></Input><Input maxOccurs="1" minOccurs="1"><ows:Identifier>distance</ows:Identifier><ows:Title>distance</ows:Title><ows:Abstract>The distance (same unit of measure as the geometry)</ows:Abstract><LiteralData><ows:DataType>xs:double</ows:DataType><ows:AnyValue/></LiteralData></Input><Input maxOccurs="1" minOccurs="0"><ows:Identifier>quadrantSegments</ows:Identifier><ows:Title>quadrantSegments</ows:Title><ows:Abstract>Number of quadrant segments. Use > 0 for round joins, 0 for flat joins, < 0 for mitred joins</ows:Abstract><LiteralData><ows:DataType>xs:int</ows:DataType><ows:AnyValue/></LiteralData></Input><Input maxOccurs="1" minOccurs="0"><ows:Identifier>capStyle</ows:Identifier><ows:Title>capStyle</ows:Title><ows:Abstract>The buffer cap style, round, flat, square</ows:Abstract><LiteralData><ows:AllowedValues><ows:Value>Round</ows:Value><ows:Value>Flat</ows:Value><ows:Value>Square</ows:Value></ows:AllowedValues></LiteralData></Input></DataInputs><ProcessOutputs><Output><ows:Identifier>result</ows:Identifier><ows:Title>result</ows:Title><ComplexOutput><Default><Format><MimeType>text/xml; subtype=gml/3.1.1</MimeType></Format></Default><Supported><Format><MimeType>text/xml; subtype=gml/3.1.1</MimeType></Format><Format><MimeType>text/xml; subtype=gml/2.1.2</MimeType></Format><Format><MimeType>application/wkt</MimeType></Format><Format><MimeType>application/gml-3.1.1</MimeType></Format><Format><MimeType>application/gml-2.1.2</MimeType></Format></Supported></ComplexOutput></Output></ProcessOutputs></ProcessDescription></wps:ProcessDescriptions>'
|
||||||
|
});
|
||||||
|
}, 100);
|
||||||
|
}
|
||||||
|
var originalPOST = OpenLayers.Request.POST;
|
||||||
|
OpenLayers.Request.POST = function(cfg) {
|
||||||
|
cfg.success.call(cfg.scope, {responseText: ''});
|
||||||
|
};
|
||||||
|
|
||||||
|
var intersect = client.getProcess('local', 'JTS:intersection');
|
||||||
|
intersect.configure({
|
||||||
|
inputs: {
|
||||||
|
a: wkt.read(
|
||||||
|
'LINESTRING(117 22,112 18,118 13,115 8)'
|
||||||
|
),
|
||||||
|
b: wkt.read(
|
||||||
|
'POLYGON((110 20,120 20,120 10,110 10,110 20),(112 17,118 18,118 16,112 15,112 17))'
|
||||||
|
)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// one buffer process to make sure chaining works
|
||||||
|
var buffer1 = client.getProcess('local', 'JTS:buffer');
|
||||||
|
// another buffer process to make sure that things work asynchronously
|
||||||
|
var buffer2 = client.getProcess('local', 'JTS:buffer');
|
||||||
|
var log = [];
|
||||||
|
buffer1.chainProcess = buffer2.chainProcess = function() {
|
||||||
|
log.push(this.executeCallbacks.length);
|
||||||
|
OpenLayers.WPSProcess.prototype.chainProcess.apply(this, arguments);
|
||||||
|
};
|
||||||
|
var done1 = done2 = false;
|
||||||
|
buffer1.execute({
|
||||||
|
inputs: {
|
||||||
|
geom: intersect.output(),
|
||||||
|
distance: 1
|
||||||
|
},
|
||||||
|
success: function(outputs) {
|
||||||
|
done1 = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
buffer2.execute({
|
||||||
|
inputs: {
|
||||||
|
geom: intersect.output(),
|
||||||
|
distance: 2
|
||||||
|
},
|
||||||
|
success: function(outputs) {
|
||||||
|
done2 = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
t.delay_call(0.5, function() {
|
||||||
|
t.eq(log.length, 2, 'chainProcess called once for each process');
|
||||||
|
t.eq(log[0], 1, 'executeCallback queued to wait for 1 chained process');
|
||||||
|
t.eq(log[1], 1, 'executeCallback queued to wait for 1 chained process');
|
||||||
|
t.eq(done1, true, 'execute for buffer1 process successfully completed');
|
||||||
|
t.eq(done2, true, 'execute for buffer2 process successfully completed');
|
||||||
|
|
||||||
|
OpenLayers.Request.GET = originalGET;
|
||||||
|
OpenLayers.Request.POST = originalPOST;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -232,6 +232,8 @@
|
|||||||
<li>Kinetic.html</li>
|
<li>Kinetic.html</li>
|
||||||
<li>Util.html</li>
|
<li>Util.html</li>
|
||||||
<li>Util/vendorPrefix.html</li>
|
<li>Util/vendorPrefix.html</li>
|
||||||
|
<li>WPSClient.html</li>
|
||||||
|
<li>WPSProcess.html</li>
|
||||||
<li>deprecated/Ajax.html</li>
|
<li>deprecated/Ajax.html</li>
|
||||||
<li>deprecated/Util.html</li>
|
<li>deprecated/Util.html</li>
|
||||||
<li>deprecated/BaseTypes/Class.html</li>
|
<li>deprecated/BaseTypes/Class.html</li>
|
||||||
@@ -249,4 +251,4 @@
|
|||||||
<li>deprecated/Renderer/SVG2.html</li>
|
<li>deprecated/Renderer/SVG2.html</li>
|
||||||
<li>deprecated/Layer/Yahoo.html</li>
|
<li>deprecated/Layer/Yahoo.html</li>
|
||||||
<li>deprecated/Tile/WFS.html</li>
|
<li>deprecated/Tile/WFS.html</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|||||||
Reference in New Issue
Block a user