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 }