001 /*---------------- FILE HEADER ------------------------------------------ 002 003 This file is part of deegree. 004 Copyright (C) 2001-2008 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 /** 075 * the created serial id. 076 */ 077 private static final long serialVersionUID = 4584807898848764192L; 078 079 private static final ILogger LOGGER = LoggerFactory.getLogger( Get3DFeatureInfo.class ); 080 081 private GetView getViewRequestCopy = null; 082 083 private Point clickPoint = null; 084 085 private Rectangle queryBox = null; 086 087 private float apexAngle; 088 089 private int radius; 090 091 private float depth; 092 093 private String exceptions = null; 094 095 private String infoFormat; 096 097 private List<String> queryDatasets = null; 098 099 private int featureCount = 0; 100 101 private boolean parent; 102 103 /** 104 * creates a <tt>WPVSFeatureInfoRequest</tt> from a <tt>HashMap</tt> that contains the 105 * request parameters as key-value-pairs. 106 * 107 * @param param 108 * <tt>HashMap</tt> containing the request parameters 109 * @return an instance of <tt>WPVSFeatureInfoRequest</tt> 110 * @throws OGCWebServiceException 111 */ 112 public static Get3DFeatureInfo create( Map<String, String> param ) 113 throws OGCWebServiceException { 114 115 // VERSION 116 String version = param.get( "VERSION" ); //$NON-NLS-1$ 117 if ( version == null ) { 118 throw new InconsistentRequestException( Messages.getMessage( "WPVS_INVALID_VERSION" ) ); //$NON-NLS-1$ 119 } 120 121 // ID 122 String id = param.get( "ID" ); //$NON-NLS-1$ 123 if ( id == null ) { 124 throw new InconsistentRequestException( Messages.getMessage( "WPVS_MISSING_ID" ) ); //$NON-NLS-1$ 125 } 126 127 // <view_request_copy> 128 GetView getViewRequestCopy = null; 129 try { 130 getViewRequestCopy = GetView.create( param ); 131 } catch ( Exception ex ) { 132 throw new InconsistentRequestException( Messages.getMessage( "WPVS_EXCEPTION_GETVIEWREQUESTCOPY" ) //$NON-NLS-1$ 133 + ex.getMessage() ); 134 } 135 136 // APEXANGLE 137 float apexAngle; 138 if ( param.get( "AA" ) != null ) { 139 try { 140 apexAngle = (float) Math.toRadians( Float.parseFloat( param.remove( "AA" ).trim() ) ); 141 } catch ( NumberFormatException nfe ) { 142 throw new InvalidParameterValueException( Messages.getMessage( "WPVS_INVALID_APEXANGLE" ) ); 143 } 144 if ( apexAngle < 0 ) { 145 throw new InvalidParameterValueException( Messages.getMessage( "WPVS_INVALID_APEXANGLE_LESS_0" ) ); 146 } 147 } else { 148 apexAngle = 0; 149 } 150 151 // I, J 152 Point clickPoint = null; 153 if ( ( param.get( "I" ) != null ) && ( param.get( "J" ) != null ) ) { //$NON-NLS-1$ //$NON-NLS-2$ 154 try { 155 int i = Integer.parseInt( param.remove( "I" ) ); //$NON-NLS-1$ 156 int j = Integer.parseInt( param.remove( "J" ) ); //$NON-NLS-1$ 157 clickPoint = new java.awt.Point( i, j ); 158 } catch ( NumberFormatException nfe ) { 159 LOGGER.logError( nfe.getLocalizedMessage(), nfe ); 160 throw new OGCWebServiceException( "Get3DFeatureInfo", Messages.getMessage( "WPVS_INVALID_POINT" ), //$NON-NLS-1$ //$NON-NLS-2$ 161 ExceptionCode.INVALID_POINT ); 162 } 163 } 164 165 // QUERYBOX 166 Rectangle queryBox = null; 167 if ( param.get( "QUERYBOX" ) != null ) { 168 String[] tokens = param.remove( "QUERYBOX" ).split( "," ); //$NON-NLS-1$ 169 if ( tokens.length != 4 ) { 170 throw new InconsistentRequestException( Messages.getMessage( "WPVS_INVALID_QUERYBOX" ) ); //$NON-NLS-1$ 171 } 172 int minx; 173 int maxx; 174 int miny; 175 int maxy; 176 try { 177 minx = Integer.parseInt( tokens[0] ); 178 maxx = Integer.parseInt( tokens[1] ); 179 miny = Integer.parseInt( tokens[2] ); 180 maxy = Integer.parseInt( tokens[3] ); 181 } catch ( NumberFormatException e ) { 182 throw new InconsistentRequestException( Messages.getMessage( "WPVS_ILLEGAL_QUERYBOX" ) //$NON-NLS-1$ 183 + e.getMessage() ); 184 } 185 if ( minx >= maxx ) { 186 throw new InvalidParameterValueException( Messages.getMessage( "WPVS_INVALID_MINX_MAXX" ) ); //$NON-NLS-1$ 187 } 188 if ( miny >= maxy ) { 189 throw new InvalidParameterValueException( Messages.getMessage( "WPVS_INVALID_MINY_MAXY" ) ); //$NON-NLS-1$ 190 } 191 queryBox = new Rectangle( minx, maxx, miny, maxy ); 192 } 193 194 // RADIUS 195 int radius = 0; 196 if ( param.get( "RADIUS" ) != null ) { 197 try { 198 radius = Integer.parseInt( param.remove( "RADIUS" ).trim() ); 199 } catch ( NumberFormatException nfe ) { 200 throw new InvalidParameterValueException( Messages.getMessage( "WPVS_INVALID_RADIUS" ) ); 201 } 202 if ( radius < 0 ) { 203 throw new InvalidParameterValueException( Messages.getMessage( "WPVS_INVALID_RADIUS_LESS_0" ) ); 204 } 205 } 206 207 // I,J or QUERYBOX? 208 if ( clickPoint == null && queryBox == null ) { 209 throw new InvalidParameterValueException( Messages.getMessage( "WPVS_INVALID_QUERYTYPE" ) ); //$NON-NLS-1$ 210 } 211 212 // DEPTH 213 float depth = 0; 214 if ( param.get( "DEPTH" ) != null ) { 215 try { 216 depth = Float.parseFloat( param.remove( "DEPTH" ).trim() ); 217 } catch ( NumberFormatException nfe ) { 218 throw new InvalidParameterValueException( Messages.getMessage( "WPVS_INVALID_DEPTH" ) ); 219 } 220 if ( depth < 0 ) { 221 throw new InvalidParameterValueException( Messages.getMessage( "WPVS_INVALID_DEPTH_LESS_0" ) ); 222 } 223 } 224 225 // EXCEPTIONS (default=application/vnd.ogc.se_xml) 226 String exceptions = param.remove( "EXCEPTIONS" ); //$NON-NLS-1$ 227 if ( exceptions == null ) { 228 exceptions = "application/vnd.ogc.se_xml"; //$NON-NLS-1$ 229 } 230 231 // INFO_FORMAT (mime-type) 232 String infoFormat = param.remove( "INFO_FORMAT" ); //$NON-NLS-1$ 233 if ( infoFormat == null ) { 234 infoFormat = "application/vnd.ogc.gml"; //$NON-NLS-1$ 235 } 236 237 // QUERY_LAYERS 238 List<String> queryDatasets = null; 239 if ( param.get( "QUERY_DATASETS" ) != null ) { 240 StringTokenizer st = new StringTokenizer( param.remove( "QUERY_DATASETS" ), "," ); //$NON-NLS-1$ 241 queryDatasets = new ArrayList<String>( st.countTokens() ); 242 while ( st.hasMoreTokens() ) { 243 queryDatasets.add( st.nextToken() ); 244 } 245 } else { 246 throw new InconsistentRequestException( Messages.getMessage( "WPVS_INVALID_QUERYLAYERS" ) ); //$NON-NLS-1$ 247 } 248 249 // FEATURE_COUNT 250 int featureCount = 1; 251 if ( param.get( "FEATURE_COUNT" ) != null ) { 252 try { 253 featureCount = Integer.parseInt( param.remove( "FEATURE_COUNT" ) ); 254 } catch ( NumberFormatException nfe ) { 255 throw new InvalidParameterValueException( Messages.getMessage( "WPVS_INVALID_FEATURE_COUNT" ) ); 256 } 257 if ( featureCount < 0 ) { 258 throw new InvalidParameterValueException( Messages.getMessage( "WPVS_INVALID_FEATURE_COUNT_LESS_0" ) ); 259 } 260 } 261 262 // PARENT 263 boolean parent = true; 264 if ( param.get( "PARENT" ) != null ) { 265 if ( param.get( "PARENT" ).toUpperCase().trim().equals( "FALSE" ) ) { 266 parent = false; 267 } else if ( !param.remove( "PARENT" ).toUpperCase().trim().equals( "TRUE" ) ) { 268 throw new InvalidParameterValueException( Messages.getMessage( "WPVS_INVALID_PARENT_NOT_BOOLEAN" ) ); 269 } 270 } 271 272 // VendorSpecificParameter; because all defined parameters has been 273 // removed from the model the vendorSpecificParameters are what left 274 Map<String, String> vendorSpecificParameter = param; 275 276 return new Get3DFeatureInfo( version, id, vendorSpecificParameter, getViewRequestCopy, clickPoint, queryBox, 277 apexAngle, radius, depth, infoFormat, exceptions, queryDatasets, parent, 278 featureCount ); 279 280 } 281 282 /** 283 * creates a new WPVSFeatureInfoRequest_Impl object 284 * 285 * @param version 286 * @param id 287 * @param vendorSpecificParameter 288 * @param getViewRequestCopy 289 * @param clickPoint 290 * @param queryBox 291 * @param aa 292 * @param depth 293 * @param queryLayers 294 * @param infoFormat 295 * @param exceptions 296 */ 297 298 private Get3DFeatureInfo( String version, String id, Map<String, String> vendorSpecificParameter, 299 GetView getViewRequestCopy, Point clickPoint, Rectangle queryBox, float apexAngle, 300 int radius, float depth, String infoFormat, String exceptions, 301 List<String> queryDatasets, boolean parent, int featureCount ) { 302 303 super( version, id, vendorSpecificParameter ); 304 this.getViewRequestCopy = getViewRequestCopy; 305 this.clickPoint = clickPoint; 306 this.queryBox = queryBox; 307 this.apexAngle = apexAngle; 308 this.radius = radius; 309 this.depth = depth; 310 this.infoFormat = infoFormat; 311 this.exceptions = exceptions; 312 this.queryDatasets = queryDatasets; 313 this.parent = parent; 314 this.featureCount = featureCount; 315 } 316 317 public String getServiceName() { 318 return "WPVS"; //$NON-NLS-1$ 319 } 320 321 /** 322 * The AA Parameter indicates the apex angle of a request with a cone 323 * 324 * @return the apex angle 325 */ 326 public float getApexAngle() { 327 return apexAngle; 328 } 329 330 /** 331 * The I and J parameters indicate a point of interest on the map. Used by the request with a 332 * line or cone. The origin is set to (0,0) centered in the pixel at the upper left corner; I 333 * increases to the right and J increases downward. I and J are returned as java.awt.Point 334 * class/datastructure. 335 * 336 * @return the point of interest 337 */ 338 public Point getClickPoint() { 339 return clickPoint; 340 } 341 342 /** 343 * This optional parameter indicates the depth of a query 344 * 345 * @return the depth 346 */ 347 public float getDepth() { 348 return depth; 349 } 350 351 /** 352 * The optional EXCEPTIONS parameter states the manner in which errors are to be reported to the 353 * client. The default value is application/vnd.ogc.se_xml if this parameter is absent from the 354 * request. 355 * 356 * @return the exception format 357 */ 358 public String getExceptions() { 359 return exceptions; 360 } 361 362 /** 363 * <view request copy> is not a name/value pair like the other parameters. Instead, most of the 364 * GetView request parameters that generated the original map are repeated. Two are omitted 365 * because Get3DFeatureInfo provides its own values: VERSION and REQUEST. The remainder of the 366 * GetView request shall be embedded contiguously in the Get3DFeatureInfo request. 367 * 368 * @return a copy of the original request 369 */ 370 public GetView getGetViewRequestCopy() { 371 return getViewRequestCopy; 372 } 373 374 /** 375 * The optional INFO_FORMAT indicates what format to use when returning the feature information. 376 * Supported values for a Get3DFeatureInfo request on a WPVS instance are listed as MIME types 377 * in one or more <Format>elements inside the <Request><FeatureInfo>element of its Capabilities 378 * XML. The entire MIME type string in <Format>is used as the value of the INFO_FORMAT 379 * parameter. In an HTTP environment, the MIME type shall be set on the returned object using 380 * the Content-type entity header. 381 * <p> 382 * </p> 383 * <b>EXAMPLE: </b> <tt> The parameter INFO_FORMAT=application/vnd.ogc.gml 384 * requests that the feature information be formatted in Geography Markup 385 * Language (GML).</tt> 386 * 387 * @return the format 388 */ 389 public String getInfoFormat() { 390 return infoFormat; 391 } 392 393 /** 394 * The required QUERY_LAYERS parameter states the map layer(s) from which feature information is 395 * desired to be retrieved. Its value is a comma- separated list of one or more map layers that 396 * are returned as an array. This parameter shall contain at least one layer name, but may 397 * contain fewer layers than the original GetView request. 398 * <p> 399 * </p> 400 * If any layer in this list is not contained in the Capabilities XML of the WPVS, the results 401 * are undefined and the WPVS shall produce an exception response. 402 * 403 * @return the layer names 404 */ 405 public List<String> getQueryDatasets() { 406 return queryDatasets; 407 } 408 409 /** 410 * @return true if a parent is available. 411 */ 412 public boolean getParent() { 413 return parent; 414 } 415 416 /** 417 * @return the number of features. 418 */ 419 public int getFeatureCount() { 420 return featureCount; 421 } 422 423 /** 424 * The parameter QueryBox indicates the rectangle for the Request with a pyramid 425 * 426 * @return the queryBox 427 */ 428 public Rectangle getQueryBox() { 429 return queryBox; 430 } 431 432 /** 433 * @return the radius of a feature info request. 434 */ 435 public int getRadius() { 436 return radius; 437 } 438 439 }