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