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.data;
038
039 import java.io.IOException;
040 import java.net.MalformedURLException;
041 import java.net.URL;
042 import java.util.ArrayList;
043 import java.util.List;
044
045 import org.deegree.crs.transformations.Transformation;
046 import org.deegree.framework.log.ILogger;
047 import org.deegree.framework.log.LoggerFactory;
048 import org.deegree.framework.xml.XMLParsingException;
049 import org.deegree.i18n.Messages;
050 import org.deegree.model.crs.CRSFactory;
051 import org.deegree.model.crs.CRSTransformationException;
052 import org.deegree.model.crs.CoordinateSystem;
053 import org.deegree.model.crs.GeoTransformer;
054 import org.deegree.model.feature.Feature;
055 import org.deegree.model.feature.FeatureCollection;
056 import org.deegree.model.feature.FeatureProperty;
057 import org.deegree.model.feature.GMLFeatureCollectionDocument;
058 import org.deegree.model.spatialschema.Geometry;
059 import org.deegree.ogcbase.ExceptionCode;
060 import org.deegree.ogcwebservices.OGCWebServiceException;
061 import org.xml.sax.SAXException;
062
063 /**
064 * <code>FeatureCollectionData</code> encapsulates a list of FeatureCollections which can be transformed using the
065 * {@link #doTransform(Transformation, boolean)} or {@link #doTransform(CoordinateSystem, CoordinateSystem, boolean)}
066 * methods.
067 *
068 * @author <a href="mailto:bezema@lat-lon.de">Rutger Bezema</a>
069 *
070 * @author last edited by: $Author:$
071 *
072 * @version $Revision:$, $Date:$
073 *
074 */
075 public class FeatureCollectionData extends TransformableData<FeatureCollection> {
076
077 private static ILogger LOG = LoggerFactory.getLogger( FeatureCollectionData.class );
078
079 private List<FeatureCollection> sourceData;
080
081 private List<FeatureCollection> transformedData;
082
083 /**
084 * Creates a data instance which handles feature collections.
085 *
086 * @param transformableData
087 * to transform
088 * @throws IllegalArgumentException
089 * if either one of the crs's are <code>null</code>.
090 */
091 public FeatureCollectionData( List<FeatureCollection> transformableData ) throws IllegalArgumentException {
092 if ( transformableData == null ) {
093 transformableData = new ArrayList<FeatureCollection>();
094 }
095 this.sourceData = transformableData;
096 this.transformedData = new ArrayList<FeatureCollection>( this.sourceData.size() );
097
098 }
099
100 private void doTransform( CoordinateSystem sourceCRS, GeoTransformer transformer, @SuppressWarnings("unused")
101 boolean enableLogging )
102 throws OGCWebServiceException {
103 for ( FeatureCollection fc : sourceData ) {
104 try {
105 FeatureCollection result = transform( fc, transformer, sourceCRS );
106 if ( result != null && result.size() != 0 ) {
107 transformedData.add( result );
108 }
109 } catch ( CRSTransformationException e ) {
110 LOG.logError( e.getMessage(), e );
111 throw new OGCWebServiceException( e.getMessage(), ExceptionCode.NOAPPLICABLECODE );
112 }
113 }
114 }
115
116 @Override
117 public void doTransform( CoordinateSystem sourceCRS, CoordinateSystem targetCRS, boolean enableLogging )
118 throws OGCWebServiceException {
119 doTransform( sourceCRS, getGeotransformer( targetCRS ), enableLogging );
120 }
121
122 @Override
123 public void doTransform( Transformation transformation, boolean enableLogging )
124 throws OGCWebServiceException {
125 doTransform( CRSFactory.create( transformation.getSourceCRS() ), getGeotransformer( transformation ),
126 enableLogging );
127 }
128
129 /*
130 * (non-Javadoc)
131 *
132 * @see org.deegree.ogcwebservices.wcts.operation.TransformableData#getResult()
133 */
134 @Override
135 public List<FeatureCollection> getTransformedData() {
136 return transformedData;
137 }
138
139 /**
140 * Transforms all geometries contained within the passed {@link FeatureCollection} into the given target CRS.
141 *
142 * @param fc
143 * the collection to transform
144 * @param transformer
145 * which will do the transforming
146 * @param sourceCRS
147 * in which the data is referenced.
148 * @return the transformed geometries in the FeatureCollection
149 * @throws CRSTransformationException
150 * if the transformation cannot be created or processed.
151 * @throws OGCWebServiceException
152 * if the crs of the geom does not match the requested crs
153 */
154 private FeatureCollection transform( FeatureCollection fc, GeoTransformer transformer, CoordinateSystem sourceCRS )
155 throws CRSTransformationException, OGCWebServiceException {
156 for ( int i = 0; i < fc.size(); i++ ) {
157 transform( fc.getFeature( i ), transformer, sourceCRS );
158 }
159 return fc;
160 }
161
162 /**
163 * Sort of a copy of the {@link GeoTransformer#transform(Feature)} but is able to log everything per geometry.
164 * Transforms all geometries contained within the passed {@link Feature} into the given target CRS. If a geometry
165 * was transformed the {@link Feature#setEnvelopesUpdated()} method will be called.
166 *
167 * @param feature
168 * @param transformer
169 * which does the transforming.
170 * @param sourceCRS
171 * to transform from
172 * @return the transformed geometries in the given Feature.
173 * @throws CRSTransformationException
174 * @throws OGCWebServiceException
175 * if the crs of the geom does not match the requested crs
176 */
177 private Feature transform( Feature feature, GeoTransformer transformer, CoordinateSystem sourceCRS )
178 throws CRSTransformationException, OGCWebServiceException {
179 if ( feature != null ) {
180 FeatureProperty[] featureProperties = feature.getProperties();
181 if ( featureProperties != null ) {
182 for ( FeatureProperty fp : featureProperties ) {
183 if ( fp != null ) {
184 Object value = fp.getValue();
185 if ( value != null ) {
186 if ( value instanceof Geometry ) {
187 Geometry geom = (Geometry) value;
188 if ( !sourceCRS.equals( geom.getCoordinateSystem() ) ) {
189 throw new OGCWebServiceException(
190 Messages.getMessage(
191 "WCTS_MISMATCHING_CRS_DEFINITIONS",
192 sourceCRS.getIdentifier(),
193 geom.getCoordinateSystem().getIdentifier() ),
194 ExceptionCode.INVALIDPARAMETERVALUE );
195 }
196 fp.setValue( transformer.transform( geom ) );
197 feature.setEnvelopesUpdated();
198 } else if ( value instanceof Feature ) {
199 transform( (Feature) value, transformer, sourceCRS );
200 }
201 }
202 }
203 }
204 }
205 }
206 return feature;
207 }
208
209 /**
210 * Try to load the featureCollection from a given url, and puts the result into a FeatureCollectionData object.
211 *
212 * @param url
213 * to load the data from.
214 * @return a loaded feature collection or <code>null</code> if no file could be loaded.
215 */
216 public static FeatureCollectionData parseFeatureCollection( String url ) {
217 if ( url == null ) {
218 return null;
219 }
220 GMLFeatureCollectionDocument fd = new GMLFeatureCollectionDocument( true, true );
221 FeatureCollectionData result = null;
222 URL theFile = null;
223 try {
224 theFile = new URL( url );
225 fd.load( theFile );
226 FeatureCollection fc = fd.parse();
227 List<FeatureCollection> geometries = new ArrayList<FeatureCollection>();
228 geometries.add( fc );
229 result = new FeatureCollectionData( geometries );
230 } catch ( MalformedURLException e ) {
231 LOG.logDebug( "Probably not a featureCollection: ", e.getMessage() );
232 } catch ( IOException e ) {
233 LOG.logDebug( "Probably not a featureCollection: ", e.getMessage() );
234 } catch ( SAXException e ) {
235 LOG.logDebug( "Probably not a featureCollection: ", e.getMessage() );
236 } catch ( XMLParsingException e ) {
237 LOG.logDebug( "Probably not a featureCollection: ", e.getMessage() );
238 }
239 return result;
240
241 }
242
243 }