001 //$HeadURL: $
002 /*----------------------------------------------------------------------------
003 This file is part of deegree, http://deegree.org/
004 Copyright (C) 2001-2009 by:
005 Department of Geography, University of Bonn
006 and
007 lat/lon GmbH
008
009 This library is free software; you can redistribute it and/or modify it under
010 the terms of the GNU Lesser General Public License as published by the Free
011 Software Foundation; either version 2.1 of the License, or (at your option)
012 any later version.
013 This library is distributed in the hope that it will be useful, but WITHOUT
014 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
015 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
016 details.
017 You should have received a copy of the GNU Lesser General Public License
018 along with this library; if not, write to the Free Software Foundation, Inc.,
019 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
020
021 Contact information:
022
023 lat/lon GmbH
024 Aennchenstr. 19, 53177 Bonn
025 Germany
026 http://lat-lon.de/
027
028 Department of Geography, University of Bonn
029 Prof. Dr. Klaus Greve
030 Postfach 1147, 53001 Bonn
031 Germany
032 http://www.geographie.uni-bonn.de/deegree/
033
034 e-mail: info@deegree.org
035 ----------------------------------------------------------------------------*/
036
037 package org.deegree.ogcwebservices.wcts.operation;
038
039 import java.util.List;
040 import java.util.Map;
041
042 import javax.vecmath.Point3d;
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.model.crs.CRSFactory;
048 import org.deegree.model.crs.CoordinateSystem;
049 import org.deegree.model.crs.UnknownCRSException;
050 import org.deegree.ogcbase.ExceptionCode;
051 import org.deegree.ogcwebservices.OGCWebServiceException;
052 import org.deegree.ogcwebservices.wcts.WCTSExceptionCode;
053 import org.deegree.ogcwebservices.wcts.WCTService;
054 import org.deegree.ogcwebservices.wcts.data.FeatureCollectionData;
055 import org.deegree.ogcwebservices.wcts.data.GeometryData;
056 import org.deegree.ogcwebservices.wcts.data.SimpleData;
057 import org.deegree.ogcwebservices.wcts.data.TransformableData;
058 import org.deegree.owscommon_1_1_0.Manifest;
059
060 /**
061 * <code>Transform</code> is an encapsulation of a Transform request defined in the wcts 0.4.0 specification.
062 *
063 * @author <a href="mailto:bezema@lat-lon.de">Rutger Bezema</a>
064 *
065 * @author last edited by: $Author:$
066 *
067 * @version $Revision:$, $Date:$
068 *
069 */
070 public class Transform extends WCTSRequestBase {
071
072 /**
073 * Signals that the data was presented inline.
074 */
075 public final static int INLINE = 0;
076
077 /**
078 * Signals that the data was presented in multiparts.
079 */
080 public final static int MULTIPART = 1;
081
082 private static ILogger LOG = LoggerFactory.getLogger( Transform.class );
083
084 private static final long serialVersionUID = -7695383750627152056L;
085
086 private final boolean store;
087
088 private final CoordinateSystem sourceCRS;
089
090 private final CoordinateSystem targetCRS;
091
092 private final Manifest inputData;
093
094 private final String inputDataString;
095
096 private final String outputFormat;
097
098 private final TransformableData<?> transformableData;
099
100 private String requestIP = "Unknown IP";
101
102 private final boolean extensiveLogging = false;
103
104 private final int dataPresentation;
105
106 private final TransformationReference transformationReference;
107
108 /**
109 * @param version
110 * of the request (0.4.0)
111 * @param requestID
112 * internal id of the request.
113 * @param store
114 * @param sourceCRS
115 * @param targetCRS
116 * @param transformationReference
117 * a bean holding the reference to a configured (or user defined) reference or
118 * @param inputData
119 * @param transformableData
120 * an encapsulation of all kinds of possible transformable data.
121 * @param outputFormat
122 * @param dataPresentation
123 * a flag signaling the way the data was presented to the wcts. Valid values are {@link #INLINE} and
124 * {@link #MULTIPART}. If another value is given, {@link #MULTIPART} is assumed.
125 * @throws IllegalArgumentException
126 * if the transformableData was <code>null</code>.
127 */
128 public Transform( String version, String requestID, boolean store, CoordinateSystem sourceCRS,
129 CoordinateSystem targetCRS, TransformationReference transformationReference, Manifest inputData,
130 TransformableData<?> transformableData, String outputFormat, int dataPresentation )
131 throws IllegalArgumentException {
132 super( version, requestID, null );
133 this.store = store;
134 this.sourceCRS = sourceCRS;
135 this.targetCRS = targetCRS;
136 this.transformationReference = transformationReference;
137 if ( sourceCRS == null && targetCRS == null && transformationReference == null ) {
138 throw new IllegalArgumentException( Messages.getMessage( "WCTS_INVALID_CONSTRUCT",
139 "Source/Target, TransformationReference" ) );
140 }
141
142 this.inputData = inputData;
143 this.inputDataString = null;
144 this.outputFormat = outputFormat;
145 if ( transformableData == null ) {
146 throw new IllegalArgumentException( Messages.getMessage( "WCTS_MISSING_ARGUMENT", transformableData ) );
147 }
148 this.transformableData = transformableData;
149 if ( dataPresentation != INLINE && dataPresentation != MULTIPART ) {
150 dataPresentation = MULTIPART;
151 }
152 this.dataPresentation = dataPresentation;
153 }
154
155 /**
156 * @return true if the transformed data should be stored.
157 */
158 public final boolean mustStore() {
159 return store;
160 }
161
162 /**
163 * @return the sourceCRS.
164 */
165 public final CoordinateSystem getSourceCRS() {
166 return sourceCRS;
167 }
168
169 /**
170 * @return the targetCRS.
171 */
172 public final CoordinateSystem getTargetCRS() {
173 return targetCRS;
174 }
175
176 /**
177 * @return the inputData, may be <code>null</code>, if so, check {@link #getInputDataString()} to see if the
178 * request defined a location by kvp.
179 */
180 public final Manifest getInputData() {
181 return inputData;
182 }
183
184 /**
185 * @return the inputDataString, supplied by kvp. Maybe <code>null</code>, if so check {@link #getInputData()} to
186 * see if an xml encoded inputdata object was supplied.
187 */
188 public final String getInputDataString() {
189 return inputDataString;
190 }
191
192 /**
193 * @return the outputFormat.
194 */
195 public final String getOutputFormat() {
196 return outputFormat;
197 }
198
199 /**
200 * Create a {@link Transform}-request by extracting the values from the map, and calling the constructor with these
201 * values.
202 *
203 * @param requestID
204 * service internal id for this request.
205 * @param map
206 * to extract requested values from.
207 * @return the bean representation
208 * @throws OGCWebServiceException
209 * if the map is <code>null</code> or has size==0, or the service,request parameters have none
210 * accepted values.
211 */
212 public static Transform create( String requestID, Map<String, String> map )
213 throws OGCWebServiceException {
214 if ( map == null || map.size() == 0 ) {
215 throw new OGCWebServiceException( Messages.getMessage( "WCTS_REQUESTMAP_NULL" ),
216 ExceptionCode.MISSINGPARAMETERVALUE );
217 }
218 String service = map.get( "SERVICE" );
219 if ( service == null || !"WCTS".equals( service ) ) {
220 throw new OGCWebServiceException( Messages.getMessage( "WCTS_NO_SERVICE_KVP", service ),
221 ExceptionCode.MISSINGPARAMETERVALUE );
222 }
223 String request = map.get( "REQUEST" );
224 if ( request == null || !"Transform".equalsIgnoreCase( request ) ) {
225 throw new OGCWebServiceException( Messages.getMessage( "WCTS_NO_REQUEST_KVP", "Transform" ),
226 ( request == null ? ExceptionCode.MISSINGPARAMETERVALUE
227 : ExceptionCode.OPERATIONNOTSUPPORTED ) );
228 }
229 String version = map.get( "VERSION" );
230 if ( version == null || !WCTService.version.equalsIgnoreCase( version ) ) {
231 throw new OGCWebServiceException( Messages.getMessage( "WCTS_NO_VERSION_KVP", version ),
232 ExceptionCode.MISSINGPARAMETERVALUE );
233 }
234
235 String sCRS = map.get( "SOURCECRS" );
236 String tCRS = map.get( "TARGETCRS" );
237 TransformationReference transformationReference = null;
238 if ( ( ( sCRS != null && !"".equals( sCRS.trim() ) ) && ( tCRS == null || "".equals( tCRS.trim() ) ) )
239 || ( ( tCRS != null && !"".equals( tCRS.trim() ) ) && ( sCRS == null || "".equals( sCRS.trim() ) ) ) ) {
240 throw new OGCWebServiceException( Messages.getMessage( "WCTS_MISSING_MUTUAL_KEY_KVP",
241 ( ( sCRS == null ) ? "TargetCRS" : "SourceCRS" ),
242 ( ( sCRS == null ) ? "SourceCRS" : "TargetCRS" ) ),
243 ExceptionCode.INVALIDPARAMETERVALUE );
244 }
245 if ( ( sCRS == null || "".equals( sCRS.trim() ) ) && ( tCRS == null || "".equals( tCRS.trim() ) ) ) {
246 String transformation = map.get( "TRANSFORMATION" );
247 if ( !( transformation == null || "".equals( transformation.trim() ) ) ) {
248 transformationReference = new TransformationReference( transformation );
249 //
250 // throw new OGCWebServiceException(
251 // Messages.getMessage( "WCTS_OPERATION_NOT_SUPPORTED",
252 // "defining of transformations (Transformation key)" ),
253 // ExceptionCode.OPERATIONNOTSUPPORTED );
254 }
255 throw new OGCWebServiceException( Messages.getMessage( "WCTS_TRANSFORMATION_NO_CRS_OR_TRANSFORM_KVP" ),
256 ExceptionCode.MISSINGPARAMETERVALUE );
257
258 }
259 CoordinateSystem sourceCRS = null;
260 CoordinateSystem targetCRS = null;
261 try {
262 sourceCRS = CRSFactory.create( WCTService.CRS_PROVIDER, sCRS );
263 targetCRS = CRSFactory.create( WCTService.CRS_PROVIDER, tCRS );
264 } catch ( UnknownCRSException e ) {
265 throw new OGCWebServiceException( e.getMessage(), WCTSExceptionCode.UNSUPPORTED_COMBINATION );
266 }
267
268 int dataRepresentation = MULTIPART;
269 String inputData = map.get( "INPUTDATA" );
270 if ( inputData == null || "".equals( inputData ) ) {
271 throw new OGCWebServiceException( Messages.getMessage( "WCTS_MISSING_MANDATORY_KEY_KVP", "inputData" ),
272 ExceptionCode.MISSINGPARAMETERVALUE );
273 }
274 TransformableData<?> theData = FeatureCollectionData.parseFeatureCollection( inputData );
275 if ( theData == null ) {
276 dataRepresentation = INLINE;
277 LOG.logDebug( "Could not generate a feature collection, trying GeometryData" );
278 theData = GeometryData.parseGeometryData( sourceCRS, inputData );
279 if ( theData == null ) {
280 LOG.logDebug( "Could not generate a feature collection nor a geometry, trying SimpleData" );
281 String cs = map.get( "CS" );
282 if ( cs == null || "".equals( cs ) ) {
283 LOG.logDebug( "CS is set to a space ' '." );
284 cs = " ";
285 }
286 String ts = map.get( "TS" );
287 if ( ts == null || "".equals( ts ) ) {
288 LOG.logDebug( "TS is set to comma ','." );
289 ts = ",";
290 }
291 String ds = map.get( "DS" );
292 if ( ds == null || "".equals( ds ) ) {
293 LOG.logDebug( "DS is set to point '.'." );
294 ds = ".";
295 }
296 List<Point3d> points = SimpleData.parseData( inputData, sourceCRS.getDimension(), cs, ts, ds );
297 if ( points.size() > 0 ) {
298 theData = new SimpleData( points, cs, ts );
299 } else {
300 LOG.logError( "Didn't find any parsable data, this transform can not be handled." );
301 throw new OGCWebServiceException( Messages.getMessage( "WCTS_TRANSFORM_MISSING_DATA" ),
302 WCTSExceptionCode.NO_INPUT_DATA );
303 }
304 }
305 }
306
307 String interPolationType = map.get( "INTERPOLATIONTYPE" );
308 if ( !( interPolationType == null || "".equals( interPolationType.trim() ) ) ) {
309 throw new OGCWebServiceException( Messages.getMessage( "WCTS_OPERATION_NOT_SUPPORTED",
310 "InterpolationType (key)" ),
311 ExceptionCode.OPERATIONNOTSUPPORTED );
312 }
313
314 String outputFormat = map.get( "OUTPUTFORMAT" );
315
316 String st = map.get( "STORE" );
317 boolean store = false;
318
319 if ( st != null && !"".equals( st.trim() ) ) {
320 store = "true".equalsIgnoreCase( st ) || "yes".equalsIgnoreCase( st ) || "1".equalsIgnoreCase( st );
321 }
322 return new Transform( version, requestID, store, sourceCRS, targetCRS, transformationReference, null, theData,
323 outputFormat, dataRepresentation );
324 }
325
326 /**
327 * @return the transformableData, as an encapsulation of a
328 */
329 public final TransformableData<?> getTransformableData() {
330 return transformableData;
331 }
332
333 /**
334 * @param requestIP
335 * or <code>null</code> if not known.
336 */
337 public void setRequestIP( String requestIP ) {
338 if ( requestIP != null && !"".equals( requestIP.trim() ) ) {
339 this.requestIP = requestIP;
340 }
341
342 }
343
344 /**
345 * @return the requestIP or 'Unknown IP' if the ip-address of the request was not set/known.
346 */
347 public final String getRequestIP() {
348 return requestIP;
349 }
350
351 /**
352 * @return true if the logging should be extensive.
353 */
354 public final boolean extensiveLogging() {
355 return extensiveLogging;
356 }
357
358 /**
359 * @return a flag signaling the way the data was presented to the wcts. Valid values are {@link #INLINE} and
360 * {@link #MULTIPART}.
361 */
362 public final int getDataPresentation() {
363 return dataPresentation;
364 }
365
366 /**
367 * @return the transformationReference which references a transformation, may be <code>null</code>
368 */
369 public final TransformationReference getTransformationReference() {
370 return transformationReference;
371 }
372
373 }