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 }