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 }