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 }