001 //$HeadURL: svn+ssh://rbezema@svn.wald.intevation.org/deegree/base/branches/2.2_testing/src/org/deegree/ogcwebservices/wps/execute/ExecuteRequestHandler.java $
002 /*---------------- FILE HEADER ------------------------------------------
003
004 This file is part of deegree.
005 Copyright (C) 2001-2008 by:
006 EXSE, Department of Geography, University of Bonn
007 http://www.giub.uni-bonn.de/exse/
008 lat/lon GmbH
009 http://www.lat-lon.de
010
011 This library is free software; you can redistribute it and/or
012 modify it under the terms of the GNU Lesser General Public
013 License as published by the Free Software Foundation; either
014 version 2.1 of the License, or (at your option) any later version.
015
016 This library is distributed in the hope that it will be useful,
017 but WITHOUT ANY WARRANTY; without even the implied warranty of
018 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
019 Lesser General Public License for more details.
020
021 You should have received a copy of the GNU Lesser General Public
022 License along with this library; if not, write to the Free Software
023 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
024
025 Contact:
026
027 Andreas Poth
028 lat/lon GmbH
029 Aennchenstraße 19
030 53177 Bonn
031 Germany
032 E-Mail: poth@lat-lon.de
033
034 Prof. Dr. Klaus Greve
035 Department of Geography
036 University of Bonn
037 Meckenheimer Allee 166
038 53115 Bonn
039 Germany
040 E-Mail: greve@giub.uni-bonn.de
041
042 ---------------------------------------------------------------------------*/
043 package org.deegree.ogcwebservices.wps.execute;
044
045 import java.util.HashMap;
046 import java.util.List;
047 import java.util.Map;
048
049 import org.deegree.datatypes.Code;
050 import org.deegree.datatypes.values.TypedLiteral;
051 import org.deegree.framework.log.ILogger;
052 import org.deegree.framework.log.LoggerFactory;
053 import org.deegree.model.spatialschema.Envelope;
054 import org.deegree.ogcwebservices.InvalidParameterValueException;
055 import org.deegree.ogcwebservices.MissingParameterValueException;
056 import org.deegree.ogcwebservices.OGCWebServiceException;
057 import org.deegree.ogcwebservices.wps.ServerBusyException;
058 import org.deegree.ogcwebservices.wps.WPService;
059 import org.deegree.ogcwebservices.wps.configuration.WPSConfiguration;
060 import org.deegree.ogcwebservices.wps.describeprocess.ComplexData;
061 import org.deegree.ogcwebservices.wps.describeprocess.InputDescription;
062 import org.deegree.ogcwebservices.wps.describeprocess.OutputDescription;
063 import org.deegree.ogcwebservices.wps.describeprocess.ProcessDescription;
064 import org.deegree.ogcwebservices.wps.describeprocess.ProcessDescription.DataInputs;
065 import org.deegree.ogcwebservices.wps.describeprocess.ProcessDescription.ProcessOutputs;
066 import org.deegree.ogcwebservices.wps.execute.IOValue.ComplexValueReference;
067
068 /**
069 * WPSExecuteRequestHandler.java
070 *
071 * Created on 10.03.2006. 12:11:28h
072 *
073 * @author <a href="mailto:christian@kiehle.org">Christian Kiehle</a>
074 * @author <a href="mailto:christian.heier@gmx.de">Christian Heier</a>
075 * @author last edited by: $Author: apoth $
076 *
077 * @version $Revision: 9345 $, $Date: 2007-12-27 17:22:25 +0100 (Do, 27 Dez 2007) $
078 */
079 public class ExecuteRequestHandler {
080
081 private static final ILogger LOG = LoggerFactory.getLogger( ExecuteRequestHandler.class );
082
083 private WPService wpService = null;
084
085 private static WPSConfiguration wpsConfiguration = null;
086
087 /**
088 *
089 * @param wpService
090 */
091 public ExecuteRequestHandler( WPService wpService ) {
092 this.wpService = wpService;
093 // Get configuration from current wps instance
094 wpsConfiguration = this.wpService.getConfiguration();
095 }
096
097 /**
098 *
099 * @param executeRequest
100 * @return
101 * @throws OGCWebServiceException
102 */
103 public ExecuteResponse handleRequest( ExecuteRequest executeRequest )
104 throws OGCWebServiceException {
105
106 // Get the map of registered Processes from wps configuration
107 Map<String, Process> registeredProcessesMap = wpsConfiguration.getRegisteredProcesses();
108
109 // Get the identifier of the process to be executed from the
110 // ExecuteRequest
111 Code executeProcessIdentifier = executeRequest.getIdentifier();
112
113 // Get the requested process from the registered processes
114 Process process = registeredProcessesMap.get( executeProcessIdentifier.getCode().toUpperCase() );
115
116 if ( null == process ) {
117
118 // Unknown process was requested
119 String msg = "A process with identifier '" + executeRequest.getIdentifier().getCode()
120 + "' is not known to this wpserver.";
121 LOG.logDebug( msg );
122 throw new InvalidParameterValueException( getClass().getName(), msg );
123 }
124
125 // Get request queue manager from configuration
126 RequestQueueManager requestQueueManager = wpsConfiguration.getDeegreeParams().getRequestQueueManager();
127
128 // add current request to queue
129 boolean success = requestQueueManager.addRequestToQueue( executeRequest );
130
131 Status status = null;
132
133 if ( success ) {
134 status = new Status();
135 String msg = "Your execute request has been successfully added to the RequestQueue. The current length of the RequestQueue is "
136 + requestQueueManager.getLengthOfQueue();
137 LOG.logDebug( msg );
138 status.setProcessAccepted( msg );
139 } else {
140 String msg = "The server is too busy to accept and queue the request at this time.";
141 LOG.logError( msg );
142 throw new ServerBusyException( msg );
143 }
144
145 // TODO implement multiple threads handling
146 if ( 0 < requestQueueManager.getLengthOfQueue() ) {
147 executeRequest = requestQueueManager.getRequestFromQueue();
148 }
149
150 // Instantiate new execute response
151 // this response will be populated during the following workflow
152 ExecuteResponse executeResponse = new ExecuteResponse();
153
154 // Set identifier in response according to requested process
155 executeResponse.setIdentifier( process.getProcessDescription().getIdentifier() );
156
157 // Add current status to response
158 executeResponse.setStatus( status );
159
160 // Set version in response according to configuration
161 executeResponse.setVersion( wpsConfiguration.getVersion() );
162
163 // Copy inputs from request to response
164 ExecuteDataInputs executeDataInputs = executeRequest.getDataInputs();
165 if ( null != executeDataInputs ) {
166 executeResponse.setDataInputs( executeDataInputs );
167 }
168
169 // Copy outputdefinitions from request to response
170 OutputDefinitions outputDefinitions = executeRequest.getOutputDefinitions();
171 if ( null != outputDefinitions ) {
172 executeResponse.setOutputDefinitions( outputDefinitions );
173 }
174
175 handleStoreParameter( process, executeRequest, executeResponse );
176
177 return executeResponse;
178 }
179
180 /**
181 *
182 * @param process
183 * @param executeRequest
184 * @param executeResponse
185 * @throws OGCWebServiceException
186 */
187 private static void handleStoreParameter( Process process, ExecuteRequest executeRequest,
188 ExecuteResponse executeResponse )
189 throws OGCWebServiceException {
190
191 boolean store = executeRequest.isStore();
192
193 if ( store ) {
194
195 // TODO store (optional) currently not supported
196 // @see OGC 05-007r4 Table 27
197 // @see OGC 05-007r4 Subclauses 10.3.1 and 10.3.2
198 throw new InvalidParameterValueException( "store",
199 "Store is not supported by this WPServer instance." );
200 // handleStatusParameter(process, executeRequest, executeResponse);
201
202 }
203
204 // Get configured process outputs
205 ProcessOutputs configuredProcessOutputs = process.getProcessDescription().getProcessOutputs();
206
207 // Get list of outputdescriptions from configured process outputs
208 List<OutputDescription> outputDescriptionsList = configuredProcessOutputs.getOutput();
209
210 /*
211 * @see OGC 05-007r4 Subclauses 10.3.1 and 10.3.2
212 * @see OGC 05-007r4 Table 27: If the store parameter is false, there is only one output,
213 * and that output has a ComplexValue, then this ComplexValue shall be returned to the
214 * client outside of any ExecuteResponse document.
215 *
216 */
217 if ( 1 == outputDescriptionsList.size() ) {
218 OutputDescription outputDescription = outputDescriptionsList.get( 0 );
219
220 ComplexData complexOutput = outputDescription.getComplexOutput();
221
222 if ( null != complexOutput ) {
223 executeResponse.setDirectResponse( true );
224 startProcess( process, executeRequest, executeResponse );
225 } else {
226 handleStatusParameter( process, executeRequest, executeResponse );
227 }
228 } else {
229 handleStatusParameter( process, executeRequest, executeResponse );
230 }
231
232 }
233
234 /**
235 *
236 * @param process
237 * @param executeRequest
238 * @param executeResponse
239 * @throws OGCWebServiceException
240 */
241 private static void handleStatusParameter( Process process, ExecuteRequest executeRequest,
242 ExecuteResponse executeResponse )
243 throws OGCWebServiceException {
244
245 boolean status = executeRequest.isStatus();
246
247 if ( status ) {
248
249 // TODO status currently not supported (optional)
250 // @see OGC 05-007r4 Table 27
251 // @see OGC 05-007r4 Subclauses 10.3.1 and 10.3.2
252
253 throw new InvalidParameterValueException( "status",
254 "Status is not supported by this WPServer instance." );
255
256 // save passed response at web accessible location, get full path
257 // and add it as statuslocation to response
258 // saveExecuteResponse();
259 // executeResponse.setStatusLocation(fullpath);
260
261 // return response to client
262
263 // startProcess(process, executeRequest, executeResponse);
264
265 // update status to process started
266
267 // updateSavedExecuteResponse();
268
269 }
270 startProcess( process, executeRequest, executeResponse );
271
272 }
273
274 /**
275 *
276 * @param process
277 * @param executeRequest
278 * @param executeResponse
279 * @throws OGCWebServiceException
280 */
281 private static void startProcess( Process process, ExecuteRequest executeRequest,
282 ExecuteResponse executeResponse )
283 throws OGCWebServiceException {
284
285 // Extract map of provided inputs from request
286 Map<String, IOValue> inputs = extractProcessInputs( process.getProcessDescription(),
287 executeRequest );
288
289 // Extract outputDefinitions from request
290 OutputDefinitions outputDefinitions = executeRequest.getOutputDefinitions();
291
292 ExecuteResponse.ProcessOutputs processOutputs = process.execute( inputs, outputDefinitions );
293
294 if ( null != processOutputs ) {
295
296 // Update status in response to successfull
297 Status status = executeResponse.getStatus();
298 status.setProcessSucceeded( "The "
299 + process.getProcessDescription().getIdentifier().getCode()
300 + " process has been successfully completed" );
301 executeResponse.setStatus( status );
302
303 // Add processOutputs to response
304 executeResponse.setProcessOutputs( processOutputs );
305 }
306 }
307
308 /**
309 * Extract required process inputs from <code>ExecuteRequest</code>
310 *
311 * @param executeRequest
312 * @return processInputs
313 * @throws MissingParameterValueException
314 * @throws InvalidParameterValueException
315 */
316 private static Map<String, IOValue> extractProcessInputs(
317 ProcessDescription processDescription,
318 ExecuteRequest executeRequest )
319 throws MissingParameterValueException, InvalidParameterValueException {
320
321 // TODO if complexvaluereferences are included --> load data via a new
322 // threaded method
323
324 // Get inputs provided in executerequest
325 ExecuteDataInputs executeDataInputs = executeRequest.getDataInputs();
326 Map<String, IOValue> providedInputs = executeDataInputs.getInputs();
327
328 // Prepare result map
329 Map<String, IOValue> processInputs = null;
330
331 // Get required process inputs from processDescription
332 DataInputs configuredDataInputs = processDescription.getDataInputs();
333 List<InputDescription> inputDescriptions = configuredDataInputs.getInputDescriptions();
334
335 // Get inputDescription for each configured input
336 int size = inputDescriptions.size();
337
338 if ( 0 < size ) {
339 processInputs = new HashMap<String, IOValue>( size );
340
341 for ( int i = 0; i < size; i++ ) {
342
343 InputDescription inputDescription = inputDescriptions.get( i );
344 String identifier = inputDescription.getIdentifier().getCode();
345 int minOccurs = inputDescription.getMinimumOccurs();
346
347 IOValue ioValue = providedInputs.get( identifier );
348
349 if ( null == ioValue && 1 == minOccurs ) {
350 throw new MissingParameterValueException( identifier,
351 "A required process input is missing" );
352 }
353
354 if ( inputDescription.isBoundingBoxData() ) {
355 Envelope boundingBoxValue = ioValue.getBoundingBoxValue();
356 if ( null == boundingBoxValue ) {
357 throw new InvalidParameterValueException( identifier,
358 "The type of the provided process input is wrong" );
359 }
360
361 } else if ( inputDescription.isLiteralData() ) {
362 TypedLiteral literalValue = ioValue.getLiteralValue();
363 if ( null == literalValue ) {
364 throw new InvalidParameterValueException( identifier,
365 "The type of the provided process input is wrong" );
366 }
367
368 } else if ( inputDescription.isComplexData() ) {
369 ComplexValue complexValue = ioValue.getComplexValue();
370 ComplexValueReference complexValuereference = ioValue.getComplexValueReference();
371 if ( null == complexValue && null == complexValuereference ) {
372 throw new InvalidParameterValueException( identifier,
373 "The type of the provided process input is wrong" );
374 }
375 }
376
377 // TODO load complexvaluereference, add as IOValue to
378 // ProcessInputsmap
379
380 LOG.logDebug( "Found required process input '" + identifier
381 + "' in execute request." );
382
383 processInputs.put( identifier, ioValue );
384 }
385 }
386
387 return processInputs;
388 }
389
390 }