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 }