001 /*---------------- FILE HEADER ------------------------------------------
002
003 This file is part of deegree.
004 Copyright (C) 2001-2007 by:
005 EXSE, Department of Geography, University of Bonn
006 http://www.giub.uni-bonn.de/deegree/
007 lat/lon GmbH
008 http://www.lat-lon.de
009
010 This library is free software; you can redistribute it and/or
011 modify it under the terms of the GNU Lesser General Public
012 License as published by the Free Software Foundation; either
013 version 2.1 of the License, or (at your option) any later version.
014
015 This library is distributed in the hope that it will be useful,
016 but WITHOUT ANY WARRANTY; without even the implied warranty of
017 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
018 Lesser General Public License for more details.
019
020 You should have received a copy of the GNU Lesser General Public
021 License along with this library; if not, write to the Free Software
022 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
023
024 Contact:
025
026 Andreas Poth
027 lat/lon GmbH
028 Aennchenstr. 19
029 53177 Bonn
030 Germany
031 E-Mail: poth@lat-lon.de
032
033 Prof. Dr. Klaus Greve
034 Department of Geography
035 University of Bonn
036 Meckenheimer Allee 166
037 53115 Bonn
038 Germany
039 E-Mail: greve@giub.uni-bonn.de
040
041
042 ---------------------------------------------------------------------------*/
043 package org.deegree.ogcwebservices.wpvs.operation;
044
045 import java.awt.Point;
046 import java.awt.Rectangle;
047 import java.util.ArrayList;
048 import java.util.List;
049 import java.util.Map;
050 import java.util.StringTokenizer;
051
052 import org.deegree.framework.log.ILogger;
053 import org.deegree.framework.log.LoggerFactory;
054 import org.deegree.i18n.Messages;
055 import org.deegree.ogcbase.ExceptionCode;
056 import org.deegree.ogcwebservices.AbstractOGCWebServiceRequest;
057 import org.deegree.ogcwebservices.InconsistentRequestException;
058 import org.deegree.ogcwebservices.InvalidParameterValueException;
059 import org.deegree.ogcwebservices.OGCWebServiceException;
060 import org.deegree.ogcwebservices.wpvs.operation.GetView;
061
062 /**
063 * This Class handles a kvp encoded Get3DFeatureInfo-request and stores it's values.
064 *
065 * @version $Revision: $
066 * @author <a href="mailto:cordes@lat-lon.de">Lyn Buesching</a>
067 * @author last edited by: $Author: $
068 *
069 * @version 1.0. $Revision: $, $Date: $
070 *
071 */
072 public class Get3DFeatureInfo extends AbstractOGCWebServiceRequest {
073
074 private static final ILogger LOGGER = LoggerFactory.getLogger( Get3DFeatureInfo.class );
075
076 private GetView getViewRequestCopy = null;
077
078 private Point clickPoint = null;
079
080 private Rectangle queryBox = null;
081
082 private float apexAngle;
083
084 private int radius;
085
086 private float depth;
087
088 private String exceptions = null;
089
090 private String infoFormat;
091
092 private List<String> queryDatasets = null;
093
094 private int featureCount = 0;
095
096 private boolean parent;
097
098 /**
099 * creates a <tt>WPVSFeatureInfoRequest</tt> from a <tt>HashMap</tt> that contains the
100 * request parameters as key-value-pairs.
101 *
102 * @param param
103 * <tt>HashMap</tt> containing the request parameters
104 * @return an instance of <tt>WPVSFeatureInfoRequest</tt>
105 * @throws OGCWebServiceException
106 */
107 public static Get3DFeatureInfo create(Map<String, String> param) throws OGCWebServiceException {
108
109 LOGGER.entering();
110
111 // VERSION
112 String version = param.get( "VERSION" ); //$NON-NLS-1$
113 if ( version == null ) {
114 throw new InconsistentRequestException(
115 Messages.getMessage( "WPVS_INVALID_VERSION" ) ); //$NON-NLS-1$
116 }
117
118 // ID
119 String id = param.get( "ID" ); //$NON-NLS-1$
120 if ( id == null ) {
121 throw new InconsistentRequestException(
122 Messages.getMessage( "WPVS_MISSING_ID" ) ); //$NON-NLS-1$
123 }
124
125 // <view_request_copy>
126 GetView getViewRequestCopy = null;
127 try {
128 getViewRequestCopy = GetView.create( param );
129 } catch( Exception ex ) {
130 throw new InconsistentRequestException(
131 Messages.getMessage( "WPVS_EXCEPTION_GETVIEWREQUESTCOPY" ) //$NON-NLS-1$
132 + ex.getMessage() );
133 }
134
135 // APEXANGLE
136 float apexAngle;
137 if ( param.get( "AA" ) != null ) {
138 try {
139 apexAngle = (float)Math.toRadians( Float.parseFloat( param.remove( "AA" ).trim() ) );
140 } catch ( NumberFormatException nfe ) {
141 throw new InvalidParameterValueException(
142 Messages.getMessage( "WPVS_INVALID_APEXANGLE" ) );
143 }
144 if ( apexAngle < 0 ) {
145 throw new InvalidParameterValueException(
146 Messages.getMessage( "WPVS_INVALID_APEXANGLE_LESS_0" ) );
147 }
148 } else {
149 apexAngle = 0;
150 }
151
152 // I, J
153 Point clickPoint = null;
154 if ( ( param.get( "I" ) != null ) && ( param.get( "J" ) != null ) ) { //$NON-NLS-1$ //$NON-NLS-2$
155 try {
156 int i = Integer.parseInt( param.remove( "I" ) ); //$NON-NLS-1$
157 int j = Integer.parseInt( param.remove( "J" ) ); //$NON-NLS-1$
158 clickPoint = new java.awt.Point( i, j );
159 } catch ( NumberFormatException nfe ) {
160 LOGGER.logError( nfe.getLocalizedMessage(), nfe );
161 throw new OGCWebServiceException(
162 "Get3DFeatureInfo", Messages.getMessage( "WPVS_INVALID_POINT" ), //$NON-NLS-1$ //$NON-NLS-2$
163 ExceptionCode.INVALID_POINT );
164 }
165 }
166
167 // QUERYBOX
168 Rectangle queryBox = null;
169 if ( param.get( "QUERYBOX" ) != null ) {
170 String[] tokens = param.remove( "QUERYBOX" ).split( "," ); //$NON-NLS-1$
171 if ( tokens.length != 4 ) {
172 throw new InconsistentRequestException(
173 Messages.getMessage( "WPVS_INVALID_QUERYBOX" )); //$NON-NLS-1$
174 }
175 int minx;
176 int maxx;
177 int miny;
178 int maxy;
179 try {
180 minx = Integer.parseInt(tokens[0]);
181 maxx = Integer.parseInt(tokens[1]);
182 miny = Integer.parseInt(tokens[2]);
183 maxy = Integer.parseInt(tokens[3]);
184 } catch ( NumberFormatException e ) {
185 throw new InconsistentRequestException(
186 Messages.getMessage( "WPVS_ILLEGAL_QUERYBOX" ) //$NON-NLS-1$
187 + e.getMessage() );
188 }
189 if ( minx >= maxx ) {
190 throw new InvalidParameterValueException(
191 Messages.getMessage( "WPVS_INVALID_MINX_MAXX" ) ); //$NON-NLS-1$
192 }
193 if ( miny >= maxy ) {
194 throw new InvalidParameterValueException(
195 Messages.getMessage( "WPVS_INVALID_MINY_MAXY" ) ); //$NON-NLS-1$
196 }
197 queryBox = new Rectangle( minx, maxx, miny, maxy );
198 }
199
200 // RADIUS
201 int radius = 0;
202 if ( param.get( "RADIUS" ) != null ) {
203 try {
204 radius = Integer.parseInt( param.remove( "RADIUS" ).trim() ) ;
205 } catch ( NumberFormatException nfe ) {
206 throw new InvalidParameterValueException(
207 Messages.getMessage( "WPVS_INVALID_RADIUS" ) );
208 }
209 if ( radius < 0 ) {
210 throw new InvalidParameterValueException(
211 Messages.getMessage( "WPVS_INVALID_RADIUS_LESS_0" ) );
212 }
213 }
214
215 // I,J or QUERYBOX?
216 if ( clickPoint == null && queryBox == null ) {
217 throw new InvalidParameterValueException(
218 Messages.getMessage( "WPVS_INVALID_QUERYTYPE" ) ); //$NON-NLS-1$
219 }
220
221 // DEPTH
222 float depth = 0;
223 if ( param.get("DEPTH" ) != null ) {
224 try {
225 depth = Float.parseFloat( param.remove("DEPTH" ).trim() );
226 } catch ( NumberFormatException nfe ) {
227 throw new InvalidParameterValueException(
228 Messages.getMessage( "WPVS_INVALID_DEPTH" ) );
229 }
230 if ( depth < 0 ){
231 throw new InvalidParameterValueException(
232 Messages.getMessage( "WPVS_INVALID_DEPTH_LESS_0" ) );
233 }
234 }
235
236 // EXCEPTIONS (default=application/vnd.ogc.se_xml)
237 String exceptions = param.remove( "EXCEPTIONS" ); //$NON-NLS-1$
238 if ( exceptions == null ) {
239 exceptions = "application/vnd.ogc.se_xml"; //$NON-NLS-1$
240 }
241
242 // INFO_FORMAT (mime-type)
243 String infoFormat = param.remove( "INFO_FORMAT" ); //$NON-NLS-1$
244 if ( infoFormat == null ) {
245 infoFormat = "application/vnd.ogc.gml"; //$NON-NLS-1$
246 }
247
248 // QUERY_LAYERS
249 List<String> queryDatasets = null;
250 if ( param.get( "QUERY_DATASETS" ) != null ) {
251 StringTokenizer st = new StringTokenizer( param.remove( "QUERY_DATASETS" ), "," ); //$NON-NLS-1$
252 queryDatasets = new ArrayList<String>( st.countTokens() );
253 while ( st.hasMoreTokens() ) {
254 queryDatasets.add( st.nextToken() );
255 }
256 } else {
257 throw new InconsistentRequestException(
258 Messages.getMessage( "WPVS_INVALID_QUERYLAYERS" ) ); //$NON-NLS-1$
259 }
260
261 // FEATURE_COUNT
262 int featureCount = 1 ;
263 if ( param.get( "FEATURE_COUNT" ) != null ) {
264 try {
265 featureCount = Integer.parseInt( param.remove( "FEATURE_COUNT" ) );
266 } catch ( NumberFormatException nfe ) {
267 throw new InvalidParameterValueException(
268 Messages.getMessage( "WPVS_INVALID_FEATURE_COUNT" ) );
269 }
270 if ( featureCount < 0 ) {
271 throw new InvalidParameterValueException(
272 Messages.getMessage( "WPVS_INVALID_FEATURE_COUNT_LESS_0" ) );
273 }
274 }
275
276 // PARENT
277 boolean parent = true;
278 if ( param.get("PARENT") != null ) {
279 if ( param.get("PARENT").toUpperCase().trim().equals( "FALSE" ) ) {
280 parent = false;
281 } else if ( !param.remove("PARENT").toUpperCase().trim().equals( "TRUE" ) ){
282 throw new InvalidParameterValueException(
283 Messages.getMessage( "WPVS_INVALID_PARENT_NOT_BOOLEAN" ) );
284 }
285 }
286
287 // VendorSpecificParameter; because all defined parameters has been
288 // removed from the model the vendorSpecificParameters are what left
289 Map<String, String> vendorSpecificParameter = param;
290
291 LOGGER.exiting();
292
293 return new Get3DFeatureInfo( version, id, vendorSpecificParameter, getViewRequestCopy,
294 clickPoint, queryBox, apexAngle, radius, depth, infoFormat,
295 exceptions, queryDatasets, parent, featureCount );
296
297 }
298
299 /**
300 * creates a new WPVSFeatureInfoRequest_Impl object
301 *
302 * @param version
303 * @param id
304 * @param vendorSpecificParameter
305 * @param getViewRequestCopy
306 * @param clickPoint
307 * @param queryBox
308 * @param aa
309 * @param depth
310 * @param queryLayers
311 * @param infoFormat
312 * @param exceptions
313 */
314
315 private Get3DFeatureInfo( String version, String id, Map<String, String> vendorSpecificParameter,
316 GetView getViewRequestCopy, Point clickPoint, Rectangle queryBox, float apexAngle,
317 int radius, float depth, String infoFormat, String exceptions,
318 List<String> queryDatasets, boolean parent, int featureCount ) {
319
320 super( version, id, vendorSpecificParameter );
321 this.getViewRequestCopy = getViewRequestCopy;
322 this.clickPoint = clickPoint;
323 this.queryBox = queryBox;
324 this.apexAngle = apexAngle;
325 this.radius = radius;
326 this.depth = depth;
327 this.infoFormat = infoFormat;
328 this.exceptions = exceptions;
329 this.queryDatasets = queryDatasets;
330 this.parent = parent;
331 this.featureCount = featureCount;
332 }
333
334 public String getServiceName() {
335 return "WPVS"; //$NON-NLS-1$
336 }
337
338 /**
339 * The AA Parameter indicates the apex angle of a request with a cone
340 *
341 * @return the apex angle
342 */
343 public float getApexAngle() {
344 return apexAngle;
345 }
346
347 /**
348 * The I and J parameters indicate a point of interest on the map. Used by the request with a
349 * line or cone. The origin is set to (0,0) centered in the pixel at the upper left corner; I
350 * increases to the right and J increases downward. I and J are returned as java.awt.Point
351 * class/datastructure.
352 *
353 * @return the point of interest
354 */
355 public Point getClickPoint() {
356 return clickPoint;
357 }
358
359 /**
360 * This optional parameter indicates the depth of a query
361 *
362 * @return the depth
363 */
364 public float getDepth() {
365 return depth;
366 }
367
368 /**
369 * The optional EXCEPTIONS parameter states the manner in which errors are to be reported to the
370 * client. The default value is application/vnd.ogc.se_xml if this parameter is absent from the
371 * request.
372 *
373 * @return the exception format
374 */
375 public String getExceptions() {
376 return exceptions;
377 }
378
379 /**
380 * <view request copy> is not a name/value pair like the other parameters. Instead, most of the
381 * GetView request parameters that generated the original map are repeated. Two are omitted
382 * because Get3DFeatureInfo provides its own values: VERSION and REQUEST. The remainder of the
383 * GetView request shall be embedded contiguously in the Get3DFeatureInfo request.
384 *
385 * @return a copy of the original request
386 */
387 public GetView getGetViewRequestCopy() {
388 return getViewRequestCopy;
389 }
390
391 /**
392 * The optional INFO_FORMAT indicates what format to use when returning the feature information.
393 * Supported values for a Get3DFeatureInfo request on a WPVS instance are listed as MIME types
394 * in one or more <Format>elements inside the <Request><FeatureInfo>element of its Capabilities
395 * XML. The entire MIME type string in <Format>is used as the value of the INFO_FORMAT
396 * parameter. In an HTTP environment, the MIME type shall be set on the returned object using
397 * the Content-type entity header.
398 * <p>
399 * </p>
400 * <b>EXAMPLE: </b> <tt> The parameter INFO_FORMAT=application/vnd.ogc.gml
401 * requests that the feature information be formatted in Geography Markup
402 * Language (GML).</tt>
403 *
404 * @return the format
405 */
406 public String getInfoFormat() {
407 return infoFormat;
408 }
409
410 /**
411 * The required QUERY_LAYERS parameter states the map layer(s) from which feature information is
412 * desired to be retrieved. Its value is a comma- separated list of one or more map layers that
413 * are returned as an array. This parameter shall contain at least one layer name, but may
414 * contain fewer layers than the original GetView request.
415 * <p>
416 * </p>
417 * If any layer in this list is not contained in the Capabilities XML of the WPVS, the results
418 * are undefined and the WPVS shall produce an exception response.
419 *
420 * @return the layer names
421 */
422 public List<String> getQueryDatasets() {
423 return queryDatasets;
424 }
425
426 public boolean getParent() {
427 return parent;
428 }
429
430 public int getFeatureCount() {
431 return featureCount;
432 }
433
434 /**
435 * The parameter QueryBox indicates the rectangle for the Request with a pyramid
436 *
437 * @return the queryBox
438 */
439 public Rectangle getQueryBox() {
440 return queryBox;
441 }
442
443 public int getRadius() {
444 return radius;
445 }
446
447 }